1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_BASE_STRINGPIECE_H_ 18 #define ART_RUNTIME_BASE_STRINGPIECE_H_ 19 20 #include <string.h> 21 #include <string> 22 23 namespace art { 24 25 // A string-like object that points to a sized piece of memory. 26 // 27 // Functions or methods may use const StringPiece& parameters to accept either 28 // a "const char*" or a "string" value that will be implicitly converted to 29 // a StringPiece. The implicit conversion means that it is often appropriate 30 // to include this .h file in other files rather than forward-declaring 31 // StringPiece as would be appropriate for most other Google classes. 32 class StringPiece { 33 public: 34 // standard STL container boilerplate 35 typedef char value_type; 36 typedef const char* pointer; 37 typedef const char& reference; 38 typedef const char& const_reference; 39 typedef size_t size_type; 40 typedef ptrdiff_t difference_type; 41 static constexpr size_type npos = size_type(-1); 42 typedef const char* const_iterator; 43 typedef const char* iterator; 44 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 45 typedef std::reverse_iterator<iterator> reverse_iterator; 46 47 // We provide non-explicit singleton constructors so users can pass 48 // in a "const char*" or a "string" wherever a "StringPiece" is 49 // expected. StringPiece()50 StringPiece() : ptr_(nullptr), length_(0) { } StringPiece(const char * str)51 StringPiece(const char* str) // NOLINT implicit constructor desired 52 : ptr_(str), length_((str == nullptr) ? 0 : strlen(str)) { } StringPiece(const std::string & str)53 StringPiece(const std::string& str) // NOLINT implicit constructor desired 54 : ptr_(str.data()), length_(str.size()) { } StringPiece(const char * offset,size_t len)55 StringPiece(const char* offset, size_t len) : ptr_(offset), length_(len) { } 56 57 // data() may return a pointer to a buffer with embedded NULs, and the 58 // returned buffer may or may not be null terminated. Therefore it is 59 // typically a mistake to pass data() to a routine that expects a NUL 60 // terminated string. data()61 const char* data() const { return ptr_; } size()62 size_type size() const { return length_; } length()63 size_type length() const { return length_; } empty()64 bool empty() const { return length_ == 0; } 65 clear()66 void clear() { 67 ptr_ = nullptr; 68 length_ = 0; 69 } set(const char * data_in,size_type len)70 void set(const char* data_in, size_type len) { 71 ptr_ = data_in; 72 length_ = len; 73 } set(const char * str)74 void set(const char* str) { 75 ptr_ = str; 76 if (str != nullptr) { 77 length_ = strlen(str); 78 } else { 79 length_ = 0; 80 } 81 } set(const void * data_in,size_type len)82 void set(const void* data_in, size_type len) { 83 ptr_ = reinterpret_cast<const char*>(data_in); 84 length_ = len; 85 } 86 87 #if defined(NDEBUG) 88 char operator[](size_type i) const { 89 return ptr_[i]; 90 } 91 #else 92 char operator[](size_type i) const; 93 #endif 94 remove_prefix(size_type n)95 void remove_prefix(size_type n) { 96 ptr_ += n; 97 length_ -= n; 98 } 99 remove_suffix(size_type n)100 void remove_suffix(size_type n) { 101 length_ -= n; 102 } 103 104 int compare(const StringPiece& x) const; 105 as_string()106 std::string as_string() const { 107 return std::string(data(), size()); 108 } 109 // We also define ToString() here, since many other string-like 110 // interfaces name the routine that converts to a C++ string 111 // "ToString", and it's confusing to have the method that does that 112 // for a StringPiece be called "as_string()". We also leave the 113 // "as_string()" method defined here for existing code. ToString()114 std::string ToString() const { 115 return std::string(data(), size()); 116 } 117 118 void CopyToString(std::string* target) const; 119 void AppendToString(std::string* target) const; 120 121 // Does "this" start with "x" starts_with(const StringPiece & x)122 bool starts_with(const StringPiece& x) const { 123 return ((length_ >= x.length_) && 124 (memcmp(ptr_, x.ptr_, x.length_) == 0)); 125 } 126 127 // Does "this" end with "x" ends_with(const StringPiece & x)128 bool ends_with(const StringPiece& x) const { 129 return ((length_ >= x.length_) && 130 (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); 131 } 132 begin()133 iterator begin() const { return ptr_; } end()134 iterator end() const { return ptr_ + length_; } rbegin()135 const_reverse_iterator rbegin() const { 136 return const_reverse_iterator(ptr_ + length_); 137 } rend()138 const_reverse_iterator rend() const { 139 return const_reverse_iterator(ptr_); 140 } 141 142 size_type copy(char* buf, size_type n, size_type pos = 0) const; 143 144 size_type find(const StringPiece& s, size_type pos = 0) const; 145 size_type find(char c, size_type pos = 0) const; 146 size_type rfind(const StringPiece& s, size_type pos = npos) const; 147 size_type rfind(char c, size_type pos = npos) const; 148 149 StringPiece substr(size_type pos, size_type n = npos) const; 150 151 private: 152 // Pointer to char data, not necessarily zero terminated. 153 const char* ptr_; 154 // Length of data. 155 size_type length_; 156 }; 157 158 // This large function is defined inline so that in a fairly common case where 159 // one of the arguments is a literal, the compiler can elide a lot of the 160 // following comparisons. 161 inline bool operator==(const StringPiece& x, const StringPiece& y) { 162 StringPiece::size_type len = x.size(); 163 if (len != y.size()) { 164 return false; 165 } 166 167 const char* p1 = x.data(); 168 const char* p2 = y.data(); 169 if (p1 == p2) { 170 return true; 171 } 172 if (len == 0) { 173 return true; 174 } 175 176 // Test last byte in case strings share large common prefix 177 if (p1[len-1] != p2[len-1]) return false; 178 if (len == 1) return true; 179 180 // At this point we can, but don't have to, ignore the last byte. We use 181 // this observation to fold the odd-length case into the even-length case. 182 len &= ~1; 183 184 return memcmp(p1, p2, len) == 0; 185 } 186 187 inline bool operator==(const StringPiece& x, const char* y) { 188 if (y == nullptr) { 189 return x.size() == 0; 190 } else { 191 return strncmp(x.data(), y, x.size()) == 0 && y[x.size()] == '\0'; 192 } 193 } 194 195 inline bool operator!=(const StringPiece& x, const StringPiece& y) { 196 return !(x == y); 197 } 198 199 inline bool operator!=(const StringPiece& x, const char* y) { 200 return !(x == y); 201 } 202 203 inline bool operator<(const StringPiece& x, const StringPiece& y) { 204 const int r = memcmp(x.data(), y.data(), 205 std::min(x.size(), y.size())); 206 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 207 } 208 209 inline bool operator>(const StringPiece& x, const StringPiece& y) { 210 return y < x; 211 } 212 213 inline bool operator<=(const StringPiece& x, const StringPiece& y) { 214 return !(x > y); 215 } 216 217 inline bool operator>=(const StringPiece& x, const StringPiece& y) { 218 return !(x < y); 219 } 220 221 extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece); 222 223 } // namespace art 224 225 #endif // ART_RUNTIME_BASE_STRINGPIECE_H_ 226