/hphp/runtime/base/string-buffer.h
C Header | 307 lines | 107 code | 39 blank | 161 comment | 7 complexity | 484a46c7a3c25acc9d86bd202c497450 MD5 | raw file
- /*
- +----------------------------------------------------------------------+
- | HipHop for PHP |
- +----------------------------------------------------------------------+
- | Copyright (c) 2010-2015 Facebook, Inc. (http://www.facebook.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- */
- #ifndef incl_HPHP_STRING_BUFFER_H_
- #define incl_HPHP_STRING_BUFFER_H_
- #include "hphp/runtime/base/exceptions.h"
- #include "hphp/runtime/base/type-string.h"
- namespace HPHP {
- ///////////////////////////////////////////////////////////////////////////////
- class File;
- struct StringBufferLimitException : FatalErrorException {
- StringBufferLimitException(int size, const String& partialResult)
- : FatalErrorException(0, "StringBuffer exceeded %d bytes of memory", size),
- m_result(partialResult) {}
- void vscan(IMarker& mark) const override;
- String m_result;
- };
- /*
- * Efficient string concatenation.
- *
- * StringBuffer is designed not to contain any malloc()d memory (only
- * per-request allocated memory) based on sweeping-related assumptions.
- */
- struct StringBuffer {
- static constexpr uint32_t kDefaultOutputLimit = StringData::MaxSize;
- /*
- * Construct a string buffer with some initial size, subsequent allocation
- * will geometrically grow the size when needed.
- */
- explicit StringBuffer(uint32_t initialSize = SmallStringReserve);
- ~StringBuffer();
- StringBuffer(const StringBuffer& sb) = delete;
- StringBuffer& operator=(const StringBuffer& sb) = delete;
- /*
- * Set an "output limit" for this string buffer. If any append goes
- * over this size, the StringBuffer will throw an exception.
- *
- * Pre: size() < maxBytes
- */
- void setOutputLimit(int maxBytes) {
- m_maxBytes = maxBytes > 0 ? maxBytes : kDefaultOutputLimit;
- }
- /*
- * Access the current state of the string.
- *
- * data() has the following semantics:
- *
- * if size() > 0:
- *
- * the pointer returned by to data() is a string of length
- * size(), and is guaranteed to be null terminated.
- *
- * if size() == 0:
- *
- * the return value of data() may *either* be nullptr or a
- * pointer to a zero-length string. Calling code may assume it
- * will not be null if it can guarantee detach() or release()
- * have never been called.
- *
- * The pointer and size should be considered invalidated after any
- * call to a non-const member function on this class.
- */
- uint32_t size() const { return m_len; }
- const char* data() const;
- /*
- * Returns whether this string has length zero.
- */
- bool empty() const { return m_len == 0; }
- /*
- * Detach buffer and yield a String.
- *
- * Post: empty()
- */
- String detach();
- /*
- * Copy this buffer into a String. The contents of this buffer
- * object are unchanged.
- */
- String copy() const;
- /*
- * Set the length of this string to zero.
- *
- * Post: empty()
- */
- void clear();
- /*
- * Set the size of this string to `size'.
- *
- * This function may only be used to reduce the size of the string,
- * or increase the size of the string to a value in range after a
- * call to appendCursor().
- *
- * Post: size() == size
- */
- void resize(uint32_t size);
- /*
- * Release all memory associated with this string buffer.
- *
- * Post: empty()
- */
- void release();
- /*
- * Return a pointer for writing up to `additionalBytes' more bytes.
- * The caller may write fewer bytes than this, and should call
- * resize() as appropriate or the new bytes will not be considered
- * part of the string.
- *
- * The caller *may* write one more byte than `additionalBytes', but
- * only if it is a null terminator.
- *
- * The returned pointer is invalidated after any call to a non-const
- * member function.
- */
- char* appendCursor(int additionalBytes);
- /*
- * Mutate a character in existing buffer.
- */
- void set(uint32_t offset, char c) {
- assert(offset < m_len);
- m_buffer[offset] = c;
- }
- /*
- * Append various types of things to this string.
- */
- void append(char c) {
- if (m_buffer && m_len < m_cap) {
- m_buffer[m_len++] = c;
- return;
- }
- appendHelper(c);
- }
- void append(unsigned char c) { append((char)c);}
- void append(const char* s) { assert(s); append(s, strlen(s)); }
- void append(const String& s) { append(s.data(), s.size()); }
- void append(const std::string& s) { append(s.data(), s.size()); }
- void append(const StringData* s) { append(s->data(), s->size()); }
- void append(folly::StringPiece s) { append(s.data(), s.size()); }
- void append(const char* s, int len) {
- assert(len >= 0);
- if (m_buffer && len <= m_cap - m_len) {
- memcpy(m_buffer + m_len, s, len);
- m_len += len;
- return;
- }
- appendHelper(s, len);
- }
- void append(const Variant& s);
- void append(int n);
- void append(int64_t n);
- /*
- * Take ownership of the string being built by buf.
- *
- * Post: buf.size() == 0
- */
- void absorb(StringBuffer& buf);
- /*
- * Append to this string using a printf-style format specification.
- */
- void printf(ATTRIBUTE_PRINTF_STRING const char* format, ...)
- ATTRIBUTE_PRINTF(2,3);
- /*
- * Read a file into this buffer. Use a larger page size to read more bytes
- * a time for large files.
- */
- void read(FILE *in, int page_size = 1024);
- void read(File *in, int page_size = 1024);
- template<class F> void scan(F& mark) const {
- mark(m_str);
- }
- private:
- void appendHelper(const char* s, int len);
- void appendHelper(char c);
- void growBy(int spaceRequired);
- void makeValid(uint32_t minCap);
- bool valid() const { return m_buffer != nullptr; }
- private:
- StringData* m_str;
- char *m_buffer;
- uint32_t m_initialCap;
- uint32_t m_maxBytes;
- uint32_t m_cap; // doesn't include null terminator
- uint32_t m_len;
- };
- /*
- * StringBuffer-like wrapper for a malloc'd, null-terminated C-style
- * string.
- */
- struct CstrBuffer {
- static const unsigned kMaxCap = INT_MAX;
- /*
- * Create a buffer with enough space for a string of length `len'.
- * (I.e. an allocation of size len + 1.)
- *
- * Pre: len <= kMaxCap
- */
- explicit CstrBuffer(int len);
- /*
- * Take ownership of an existing malloc'd buffer containing a
- * null-terminated string of length `len'. It is assumed the
- * capacity is also len.
- *
- * Pre: len < kMaxCap
- */
- CstrBuffer(char* data, int len);
- /*
- * Create a CstrBuffer, attempting to read the contents of a given
- * file.
- *
- * I/O errors are not reported. size() will just be zero in that
- * case.
- *
- * Post: valid()
- */
- explicit CstrBuffer(const char* filename);
- CstrBuffer(const CstrBuffer&) = delete;
- CstrBuffer& operator=(const CstrBuffer&) = delete;
- ~CstrBuffer();
- /*
- * Read-only access to the data this buffer contains. Guaranteed to
- * be null-terminated.
- *
- * Pre: valid()
- */
- const char* data() const;
- unsigned size() const { return m_len; }
- /*
- * Returns whether this CstrBuffer contains a buffer. This can only
- * return false if detach() has been called.
- */
- bool valid() const { return m_buffer != nullptr; }
- /*
- * Append the supplied data to this string.
- *
- * Pre: valid()
- */
- void append(folly::StringPiece);
- /*
- * Create a request-local string from this buffer.
- *
- * Pre: valid()
- * Post: !valid()
- */
- String detach();
- private:
- char* m_buffer;
- unsigned m_len;
- unsigned m_cap; // doesn't include the space for the \0
- };
- inline const char* CstrBuffer::data() const {
- assert(m_len <= m_cap);
- m_buffer[m_len] = 0;
- return m_buffer;
- }
- ///////////////////////////////////////////////////////////////////////////////
- }
- #endif // incl_HPHP_STRING_BUFFER_H_