/hphp/runtime/base/string-data-inl.h

https://gitlab.com/0072016/0072016-PHP.LLC · C Header · 221 lines · 145 code · 42 blank · 34 comment · 27 complexity · ca6e623abfc5d049e94ab000170f3c70 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_RUNTIME_BASE_STRING_DATA_INL_H_
  17. #define incl_HPHP_RUNTIME_BASE_STRING_DATA_INL_H_
  18. namespace HPHP {
  19. //////////////////////////////////////////////////////////////////////
  20. // CopyString
  21. inline StringData* StringData::Make(const char* data) {
  22. return Make(data, CopyString);
  23. }
  24. inline StringData* StringData::Make(const std::string& data) {
  25. return Make(data.data(), data.length(), CopyString);
  26. }
  27. inline StringData* StringData::Make(const char* data, CopyStringMode) {
  28. return Make(data, strlen(data), CopyString);
  29. }
  30. //////////////////////////////////////////////////////////////////////
  31. // AttachString
  32. inline StringData* StringData::Make(char* data, AttachStringMode) {
  33. auto const sd = Make(data, CopyString);
  34. free(data);
  35. assert(sd->checkSane());
  36. return sd;
  37. }
  38. //////////////////////////////////////////////////////////////////////
  39. // Concat creation
  40. inline StringData* StringData::Make(const StringData* s1, StringSlice s2) {
  41. return Make(s1->slice(), s2);
  42. }
  43. inline StringData* StringData::Make(const StringData* s1, const char* lit2) {
  44. return Make(s1->slice(), lit2);
  45. }
  46. //////////////////////////////////////////////////////////////////////
  47. inline bool StringData::isStatic() const {
  48. return m_hdr.count == StaticValue;
  49. }
  50. inline bool StringData::isUncounted() const {
  51. return m_hdr.count == UncountedValue;
  52. }
  53. inline StringSlice StringData::slice() const {
  54. return StringSlice(m_data, m_len);
  55. }
  56. inline MutableSlice StringData::bufferSlice() {
  57. assert(!isImmutable());
  58. return MutableSlice(m_data, capacity());
  59. }
  60. inline void StringData::invalidateHash() {
  61. assert(!isImmutable());
  62. assert(!hasMultipleRefs());
  63. m_hash = 0;
  64. assert(checkSane());
  65. }
  66. inline void StringData::setSize(int len) {
  67. assert(len >= 0 && len <= capacity() && !isImmutable());
  68. assert(!hasMultipleRefs());
  69. m_data[len] = 0;
  70. m_lenAndHash = len;
  71. assert(m_hash == 0);
  72. assert(checkSane());
  73. }
  74. inline void StringData::checkStack() const {
  75. assert(uintptr_t(this) - s_stackLimit >= s_stackSize);
  76. }
  77. inline const char* StringData::data() const {
  78. // TODO: t1800106: re-enable this assert
  79. // assert(m_data[size()] == 0); // all strings must be null-terminated
  80. return m_data;
  81. }
  82. inline char* StringData::mutableData() const {
  83. assert(!isImmutable());
  84. return m_data;
  85. }
  86. inline int StringData::size() const { return m_len; }
  87. inline bool StringData::empty() const { return size() == 0; }
  88. inline uint32_t StringData::capacity() const {
  89. return m_hdr.aux.decode();
  90. }
  91. inline size_t StringData::heapSize() const {
  92. return isFlat() ? sizeof(StringData) + 1 + capacity() :
  93. sizeof(StringData) + sizeof(SharedPayload);
  94. }
  95. inline bool StringData::isStrictlyInteger(int64_t& res) const {
  96. // Exploit the NUL terminator and unsigned comparison. This single comparison
  97. // checks whether the string is empty or if the first byte is greater than '9'
  98. // or less than '-'. Note that '-' == 45 and '0' == 48, which makes this
  99. // valid. (46 == '.' and 47 == '/', so if one of those is the first byte, this
  100. // check will be a false positive, but it will still be caught later.)
  101. if ((unsigned char)(data()[0] - '-') > ('9' - '-')) {
  102. return false;
  103. }
  104. if (isStatic() && m_hash < 0) return false;
  105. auto const s = slice();
  106. return is_strictly_integer(s.ptr, s.len, res);
  107. }
  108. inline bool StringData::isZero() const {
  109. return size() == 1 && data()[0] == '0';
  110. }
  111. inline StringData* StringData::modifyChar(int offset, char c) {
  112. assert(offset >= 0 && offset < size());
  113. assert(!hasMultipleRefs());
  114. auto const sd = isShared() ? escalate(size()) : this;
  115. sd->m_data[offset] = c;
  116. sd->m_hash = 0;
  117. return sd;
  118. }
  119. inline strhash_t StringData::hash() const {
  120. strhash_t h = m_hash & STRHASH_MASK;
  121. return h ? h : hashHelper();
  122. }
  123. inline bool StringData::same(const StringData* s) const {
  124. assert(s);
  125. if (m_len != s->m_len) return false;
  126. // The underlying buffer and its length are 8-byte aligned, ensured by
  127. // StringData layout, req::malloc, or malloc. So compare words.
  128. assert(uintptr_t(data()) % 8 == 0);
  129. assert(uintptr_t(s->data()) % 8 == 0);
  130. return wordsame(data(), s->data(), m_len);
  131. }
  132. inline bool StringData::isame(const StringData* s) const {
  133. assert(s);
  134. if (m_len != s->m_len) return false;
  135. return bstrcaseeq(data(), s->data(), m_len);
  136. }
  137. //////////////////////////////////////////////////////////////////////
  138. inline const void* StringData::voidPayload() const { return this + 1; }
  139. inline void* StringData::voidPayload() { return this + 1; }
  140. inline const StringData::SharedPayload* StringData::sharedPayload() const {
  141. return static_cast<const SharedPayload*>(voidPayload());
  142. }
  143. inline StringData::SharedPayload* StringData::sharedPayload() {
  144. return static_cast<SharedPayload*>(voidPayload());
  145. }
  146. inline bool StringData::isFlat() const { return m_data == voidPayload(); }
  147. inline bool StringData::isShared() const { return m_data != voidPayload(); }
  148. inline bool StringData::isImmutable() const {
  149. return isStatic() || isShared() || isUncounted();
  150. }
  151. //////////////////////////////////////////////////////////////////////
  152. ALWAYS_INLINE void decRefStr(StringData* s) {
  153. s->decRefAndRelease();
  154. }
  155. struct string_data_hash {
  156. size_t operator()(const StringData *s) const {
  157. return s->hash();
  158. }
  159. };
  160. struct string_data_same {
  161. bool operator()(const StringData *s1, const StringData *s2) const {
  162. assert(s1 && s2);
  163. return s1->same(s2);
  164. }
  165. };
  166. struct string_data_eq_same {
  167. bool operator()(const StringData* a, const StringData* b) const {
  168. return a == b || a->same(b);
  169. }
  170. };
  171. struct string_data_isame {
  172. bool operator()(const StringData *s1, const StringData *s2) const {
  173. assert(s1 && s2);
  174. return s1->isame(s2);
  175. }
  176. };
  177. //////////////////////////////////////////////////////////////////////
  178. }
  179. #endif