PageRenderTime 32ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/runtime/base/string-buffer.h

https://gitlab.com/alvinahmadov2/hhvm
C Header | 307 lines | 107 code | 39 blank | 161 comment | 7 complexity | 484a46c7a3c25acc9d86bd202c497450 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2015 Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifndef incl_HPHP_STRING_BUFFER_H_
  17. #define incl_HPHP_STRING_BUFFER_H_
  18. #include "hphp/runtime/base/exceptions.h"
  19. #include "hphp/runtime/base/type-string.h"
  20. namespace HPHP {
  21. ///////////////////////////////////////////////////////////////////////////////
  22. class File;
  23. struct StringBufferLimitException : FatalErrorException {
  24. StringBufferLimitException(int size, const String& partialResult)
  25. : FatalErrorException(0, "StringBuffer exceeded %d bytes of memory", size),
  26. m_result(partialResult) {}
  27. void vscan(IMarker& mark) const override;
  28. String m_result;
  29. };
  30. /*
  31. * Efficient string concatenation.
  32. *
  33. * StringBuffer is designed not to contain any malloc()d memory (only
  34. * per-request allocated memory) based on sweeping-related assumptions.
  35. */
  36. struct StringBuffer {
  37. static constexpr uint32_t kDefaultOutputLimit = StringData::MaxSize;
  38. /*
  39. * Construct a string buffer with some initial size, subsequent allocation
  40. * will geometrically grow the size when needed.
  41. */
  42. explicit StringBuffer(uint32_t initialSize = SmallStringReserve);
  43. ~StringBuffer();
  44. StringBuffer(const StringBuffer& sb) = delete;
  45. StringBuffer& operator=(const StringBuffer& sb) = delete;
  46. /*
  47. * Set an "output limit" for this string buffer. If any append goes
  48. * over this size, the StringBuffer will throw an exception.
  49. *
  50. * Pre: size() < maxBytes
  51. */
  52. void setOutputLimit(int maxBytes) {
  53. m_maxBytes = maxBytes > 0 ? maxBytes : kDefaultOutputLimit;
  54. }
  55. /*
  56. * Access the current state of the string.
  57. *
  58. * data() has the following semantics:
  59. *
  60. * if size() > 0:
  61. *
  62. * the pointer returned by to data() is a string of length
  63. * size(), and is guaranteed to be null terminated.
  64. *
  65. * if size() == 0:
  66. *
  67. * the return value of data() may *either* be nullptr or a
  68. * pointer to a zero-length string. Calling code may assume it
  69. * will not be null if it can guarantee detach() or release()
  70. * have never been called.
  71. *
  72. * The pointer and size should be considered invalidated after any
  73. * call to a non-const member function on this class.
  74. */
  75. uint32_t size() const { return m_len; }
  76. const char* data() const;
  77. /*
  78. * Returns whether this string has length zero.
  79. */
  80. bool empty() const { return m_len == 0; }
  81. /*
  82. * Detach buffer and yield a String.
  83. *
  84. * Post: empty()
  85. */
  86. String detach();
  87. /*
  88. * Copy this buffer into a String. The contents of this buffer
  89. * object are unchanged.
  90. */
  91. String copy() const;
  92. /*
  93. * Set the length of this string to zero.
  94. *
  95. * Post: empty()
  96. */
  97. void clear();
  98. /*
  99. * Set the size of this string to `size'.
  100. *
  101. * This function may only be used to reduce the size of the string,
  102. * or increase the size of the string to a value in range after a
  103. * call to appendCursor().
  104. *
  105. * Post: size() == size
  106. */
  107. void resize(uint32_t size);
  108. /*
  109. * Release all memory associated with this string buffer.
  110. *
  111. * Post: empty()
  112. */
  113. void release();
  114. /*
  115. * Return a pointer for writing up to `additionalBytes' more bytes.
  116. * The caller may write fewer bytes than this, and should call
  117. * resize() as appropriate or the new bytes will not be considered
  118. * part of the string.
  119. *
  120. * The caller *may* write one more byte than `additionalBytes', but
  121. * only if it is a null terminator.
  122. *
  123. * The returned pointer is invalidated after any call to a non-const
  124. * member function.
  125. */
  126. char* appendCursor(int additionalBytes);
  127. /*
  128. * Mutate a character in existing buffer.
  129. */
  130. void set(uint32_t offset, char c) {
  131. assert(offset < m_len);
  132. m_buffer[offset] = c;
  133. }
  134. /*
  135. * Append various types of things to this string.
  136. */
  137. void append(char c) {
  138. if (m_buffer && m_len < m_cap) {
  139. m_buffer[m_len++] = c;
  140. return;
  141. }
  142. appendHelper(c);
  143. }
  144. void append(unsigned char c) { append((char)c);}
  145. void append(const char* s) { assert(s); append(s, strlen(s)); }
  146. void append(const String& s) { append(s.data(), s.size()); }
  147. void append(const std::string& s) { append(s.data(), s.size()); }
  148. void append(const StringData* s) { append(s->data(), s->size()); }
  149. void append(folly::StringPiece s) { append(s.data(), s.size()); }
  150. void append(const char* s, int len) {
  151. assert(len >= 0);
  152. if (m_buffer && len <= m_cap - m_len) {
  153. memcpy(m_buffer + m_len, s, len);
  154. m_len += len;
  155. return;
  156. }
  157. appendHelper(s, len);
  158. }
  159. void append(const Variant& s);
  160. void append(int n);
  161. void append(int64_t n);
  162. /*
  163. * Take ownership of the string being built by buf.
  164. *
  165. * Post: buf.size() == 0
  166. */
  167. void absorb(StringBuffer& buf);
  168. /*
  169. * Append to this string using a printf-style format specification.
  170. */
  171. void printf(ATTRIBUTE_PRINTF_STRING const char* format, ...)
  172. ATTRIBUTE_PRINTF(2,3);
  173. /*
  174. * Read a file into this buffer. Use a larger page size to read more bytes
  175. * a time for large files.
  176. */
  177. void read(FILE *in, int page_size = 1024);
  178. void read(File *in, int page_size = 1024);
  179. template<class F> void scan(F& mark) const {
  180. mark(m_str);
  181. }
  182. private:
  183. void appendHelper(const char* s, int len);
  184. void appendHelper(char c);
  185. void growBy(int spaceRequired);
  186. void makeValid(uint32_t minCap);
  187. bool valid() const { return m_buffer != nullptr; }
  188. private:
  189. StringData* m_str;
  190. char *m_buffer;
  191. uint32_t m_initialCap;
  192. uint32_t m_maxBytes;
  193. uint32_t m_cap; // doesn't include null terminator
  194. uint32_t m_len;
  195. };
  196. /*
  197. * StringBuffer-like wrapper for a malloc'd, null-terminated C-style
  198. * string.
  199. */
  200. struct CstrBuffer {
  201. static const unsigned kMaxCap = INT_MAX;
  202. /*
  203. * Create a buffer with enough space for a string of length `len'.
  204. * (I.e. an allocation of size len + 1.)
  205. *
  206. * Pre: len <= kMaxCap
  207. */
  208. explicit CstrBuffer(int len);
  209. /*
  210. * Take ownership of an existing malloc'd buffer containing a
  211. * null-terminated string of length `len'. It is assumed the
  212. * capacity is also len.
  213. *
  214. * Pre: len < kMaxCap
  215. */
  216. CstrBuffer(char* data, int len);
  217. /*
  218. * Create a CstrBuffer, attempting to read the contents of a given
  219. * file.
  220. *
  221. * I/O errors are not reported. size() will just be zero in that
  222. * case.
  223. *
  224. * Post: valid()
  225. */
  226. explicit CstrBuffer(const char* filename);
  227. CstrBuffer(const CstrBuffer&) = delete;
  228. CstrBuffer& operator=(const CstrBuffer&) = delete;
  229. ~CstrBuffer();
  230. /*
  231. * Read-only access to the data this buffer contains. Guaranteed to
  232. * be null-terminated.
  233. *
  234. * Pre: valid()
  235. */
  236. const char* data() const;
  237. unsigned size() const { return m_len; }
  238. /*
  239. * Returns whether this CstrBuffer contains a buffer. This can only
  240. * return false if detach() has been called.
  241. */
  242. bool valid() const { return m_buffer != nullptr; }
  243. /*
  244. * Append the supplied data to this string.
  245. *
  246. * Pre: valid()
  247. */
  248. void append(folly::StringPiece);
  249. /*
  250. * Create a request-local string from this buffer.
  251. *
  252. * Pre: valid()
  253. * Post: !valid()
  254. */
  255. String detach();
  256. private:
  257. char* m_buffer;
  258. unsigned m_len;
  259. unsigned m_cap; // doesn't include the space for the \0
  260. };
  261. inline const char* CstrBuffer::data() const {
  262. assert(m_len <= m_cap);
  263. m_buffer[m_len] = 0;
  264. return m_buffer;
  265. }
  266. ///////////////////////////////////////////////////////////////////////////////
  267. }
  268. #endif // incl_HPHP_STRING_BUFFER_H_