1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // A StringPiece points to part or all of a string, Cord, double-quoted string 32 // literal, or other string-like object. A StringPiece does *not* own the 33 // string to which it points. A StringPiece is not null-terminated. 34 // 35 // You can use StringPiece as a function or method parameter. A StringPiece 36 // parameter can receive a double-quoted string literal argument, a "const 37 // char*" argument, a string argument, or a StringPiece argument with no data 38 // copying. Systematic use of StringPiece for arguments reduces data 39 // copies and strlen() calls. 40 // 41 // Prefer passing StringPieces by value: 42 // void MyFunction(StringPiece arg); 43 // If circumstances require, you may also pass by const reference: 44 // void MyFunction(const StringPiece& arg); // not preferred 45 // Both of these have the same lifetime semantics. Passing by value 46 // generates slightly smaller code. For more discussion, see the thread 47 // go/stringpiecebyvalue on c-users. 48 // 49 // StringPiece is also suitable for local variables if you know that 50 // the lifetime of the underlying object is longer than the lifetime 51 // of your StringPiece variable. 52 // 53 // Beware of binding a StringPiece to a temporary: 54 // StringPiece sp = obj.MethodReturningString(); // BAD: lifetime problem 55 // 56 // This code is okay: 57 // string str = obj.MethodReturningString(); // str owns its contents 58 // StringPiece sp(str); // GOOD, because str outlives sp 59 // 60 // StringPiece is sometimes a poor choice for a return value and usually a poor 61 // choice for a data member. If you do use a StringPiece this way, it is your 62 // responsibility to ensure that the object pointed to by the StringPiece 63 // outlives the StringPiece. 64 // 65 // A StringPiece may represent just part of a string; thus the name "Piece". 66 // For example, when splitting a string, vector<StringPiece> is a natural data 67 // type for the output. For another example, a Cord is a non-contiguous, 68 // potentially very long string-like object. The Cord class has an interface 69 // that iteratively provides StringPiece objects that point to the 70 // successive pieces of a Cord object. 71 // 72 // A StringPiece is not null-terminated. If you write code that scans a 73 // StringPiece, you must check its length before reading any characters. 74 // Common idioms that work on null-terminated strings do not work on 75 // StringPiece objects. 76 // 77 // There are several ways to create a null StringPiece: 78 // StringPiece() 79 // StringPiece(nullptr) 80 // StringPiece(nullptr, 0) 81 // For all of the above, sp.data() == nullptr, sp.length() == 0, 82 // and sp.empty() == true. Also, if you create a StringPiece with 83 // a non-null pointer then sp.data() != nullptr. Once created, 84 // sp.data() will stay either nullptr or not-nullptr, except if you call 85 // sp.clear() or sp.set(). 86 // 87 // Thus, you can use StringPiece(nullptr) to signal an out-of-band value 88 // that is different from other StringPiece values. This is similar 89 // to the way that const char* p1 = nullptr; is different from 90 // const char* p2 = "";. 91 // 92 // There are many ways to create an empty StringPiece: 93 // StringPiece() 94 // StringPiece(nullptr) 95 // StringPiece(nullptr, 0) 96 // StringPiece("") 97 // StringPiece("", 0) 98 // StringPiece("abcdef", 0) 99 // StringPiece("abcdef"+6, 0) 100 // For all of the above, sp.length() will be 0 and sp.empty() will be true. 101 // For some empty StringPiece values, sp.data() will be nullptr. 102 // For some empty StringPiece values, sp.data() will not be nullptr. 103 // 104 // Be careful not to confuse: null StringPiece and empty StringPiece. 105 // The set of empty StringPieces properly includes the set of null StringPieces. 106 // That is, every null StringPiece is an empty StringPiece, 107 // but some non-null StringPieces are empty Stringpieces too. 108 // 109 // All empty StringPiece values compare equal to each other. 110 // Even a null StringPieces compares equal to a non-null empty StringPiece: 111 // StringPiece() == StringPiece("", 0) 112 // StringPiece(nullptr) == StringPiece("abc", 0) 113 // StringPiece(nullptr, 0) == StringPiece("abcdef"+6, 0) 114 // 115 // Look carefully at this example: 116 // StringPiece("") == nullptr 117 // True or false? TRUE, because StringPiece::operator== converts 118 // the right-hand side from nullptr to StringPiece(nullptr), 119 // and then compares two zero-length spans of characters. 120 // However, we are working to make this example produce a compile error. 121 // 122 // Suppose you want to write: 123 // bool TestWhat?(StringPiece sp) { return sp == nullptr; } // BAD 124 // Do not do that. Write one of these instead: 125 // bool TestNull(StringPiece sp) { return sp.data() == nullptr; } 126 // bool TestEmpty(StringPiece sp) { return sp.empty(); } 127 // The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty? 128 // Right now, TestWhat? behaves likes TestEmpty. 129 // We are working to make TestWhat? produce a compile error. 130 // TestNull is good to test for an out-of-band signal. 131 // TestEmpty is good to test for an empty StringPiece. 132 // 133 // Caveats (again): 134 // (1) The lifetime of the pointed-to string (or piece of a string) 135 // must be longer than the lifetime of the StringPiece. 136 // (2) There may or may not be a '\0' character after the end of 137 // StringPiece data. 138 // (3) A null StringPiece is empty. 139 // An empty StringPiece may or may not be a null StringPiece. 140 141 #ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ 142 #define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ 143 144 #include <assert.h> 145 #include <stddef.h> 146 #include <string.h> 147 #include <iosfwd> 148 #include <limits> 149 #include <string> 150 151 #include <google/protobuf/stubs/hash.h> 152 153 #include <google/protobuf/port_def.inc> 154 155 namespace google { 156 namespace protobuf { 157 // StringPiece has *two* size types. 158 // StringPiece::size_type 159 // is unsigned 160 // is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 161 // no future changes intended 162 // stringpiece_ssize_type 163 // is signed 164 // is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 165 // future changes intended: http://go/64BitStringPiece 166 // 167 typedef std::string::difference_type stringpiece_ssize_type; 168 169 // STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows. 170 // TODO(mec): delete this after stringpiece_ssize_type goes 64 bit. 171 #if !defined(NDEBUG) 172 #define STRINGPIECE_CHECK_SIZE 1 173 #elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 174 #define STRINGPIECE_CHECK_SIZE 1 175 #else 176 #define STRINGPIECE_CHECK_SIZE 0 177 #endif 178 179 class PROTOBUF_EXPORT StringPiece { 180 private: 181 const char* ptr_; 182 stringpiece_ssize_type length_; 183 184 // Prevent overflow in debug mode or fortified mode. 185 // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t). CheckedSsizeTFromSizeT(size_t size)186 static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) { 187 #if STRINGPIECE_CHECK_SIZE > 0 188 #ifdef max 189 #undef max 190 #endif 191 if (size > static_cast<size_t>( 192 std::numeric_limits<stringpiece_ssize_type>::max())) { 193 // Some people grep for this message in logs 194 // so take care if you ever change it. 195 LogFatalSizeTooBig(size, "size_t to int conversion"); 196 } 197 #endif 198 return static_cast<stringpiece_ssize_type>(size); 199 } 200 201 // Out-of-line error path. 202 static void LogFatalSizeTooBig(size_t size, const char* details); 203 204 public: 205 // We provide non-explicit singleton constructors so users can pass 206 // in a "const char*" or a "string" wherever a "StringPiece" is 207 // expected. 208 // 209 // Style guide exception granted: 210 // http://goto/style-guide-exception-20978288 StringPiece()211 StringPiece() : ptr_(nullptr), length_(0) {} 212 StringPiece(const char * str)213 StringPiece(const char* str) // NOLINT(runtime/explicit) 214 : ptr_(str), length_(0) { 215 if (str != nullptr) { 216 length_ = CheckedSsizeTFromSizeT(strlen(str)); 217 } 218 } 219 220 template <class Allocator> StringPiece(const std::basic_string<char,std::char_traits<char>,Allocator> & str)221 StringPiece( // NOLINT(runtime/explicit) 222 const std::basic_string<char, std::char_traits<char>, Allocator>& str) 223 : ptr_(str.data()), length_(0) { 224 length_ = CheckedSsizeTFromSizeT(str.size()); 225 } 226 StringPiece(const char * offset,stringpiece_ssize_type len)227 StringPiece(const char* offset, stringpiece_ssize_type len) 228 : ptr_(offset), length_(len) { 229 assert(len >= 0); 230 } 231 232 // Substring of another StringPiece. 233 // pos must be non-negative and <= x.length(). 234 StringPiece(StringPiece x, stringpiece_ssize_type pos); 235 // Substring of another StringPiece. 236 // pos must be non-negative and <= x.length(). 237 // len must be non-negative and will be pinned to at most x.length() - pos. 238 StringPiece(StringPiece x, 239 stringpiece_ssize_type pos, 240 stringpiece_ssize_type len); 241 242 // data() may return a pointer to a buffer with embedded NULs, and the 243 // returned buffer may or may not be null terminated. Therefore it is 244 // typically a mistake to pass data() to a routine that expects a NUL 245 // terminated string. data()246 const char* data() const { return ptr_; } size()247 stringpiece_ssize_type size() const { return length_; } length()248 stringpiece_ssize_type length() const { return length_; } empty()249 bool empty() const { return length_ == 0; } 250 clear()251 void clear() { 252 ptr_ = nullptr; 253 length_ = 0; 254 } 255 set(const char * data,stringpiece_ssize_type len)256 void set(const char* data, stringpiece_ssize_type len) { 257 assert(len >= 0); 258 ptr_ = data; 259 length_ = len; 260 } 261 set(const char * str)262 void set(const char* str) { 263 ptr_ = str; 264 if (str != nullptr) 265 length_ = CheckedSsizeTFromSizeT(strlen(str)); 266 else 267 length_ = 0; 268 } 269 set(const void * data,stringpiece_ssize_type len)270 void set(const void* data, stringpiece_ssize_type len) { 271 ptr_ = reinterpret_cast<const char*>(data); 272 length_ = len; 273 } 274 275 char operator[](stringpiece_ssize_type i) const { 276 assert(0 <= i); 277 assert(i < length_); 278 return ptr_[i]; 279 } 280 remove_prefix(stringpiece_ssize_type n)281 void remove_prefix(stringpiece_ssize_type n) { 282 assert(length_ >= n); 283 ptr_ += n; 284 length_ -= n; 285 } 286 remove_suffix(stringpiece_ssize_type n)287 void remove_suffix(stringpiece_ssize_type n) { 288 assert(length_ >= n); 289 length_ -= n; 290 } 291 292 // returns {-1, 0, 1} compare(StringPiece x)293 int compare(StringPiece x) const { 294 const stringpiece_ssize_type min_size = 295 length_ < x.length_ ? length_ : x.length_; 296 int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size)); 297 if (r < 0) return -1; 298 if (r > 0) return 1; 299 if (length_ < x.length_) return -1; 300 if (length_ > x.length_) return 1; 301 return 0; 302 } 303 as_string()304 std::string as_string() const { return ToString(); } 305 // We also define ToString() here, since many other string-like 306 // interfaces name the routine that converts to a C++ string 307 // "ToString", and it's confusing to have the method that does that 308 // for a StringPiece be called "as_string()". We also leave the 309 // "as_string()" method defined here for existing code. ToString()310 std::string ToString() const { 311 if (ptr_ == nullptr) return ""; 312 return std::string(data(), static_cast<size_type>(size())); 313 } 314 string()315 explicit operator std::string() const { return ToString(); } 316 317 void CopyToString(std::string* target) const; 318 void AppendToString(std::string* target) const; 319 starts_with(StringPiece x)320 bool starts_with(StringPiece x) const { 321 return (length_ >= x.length_) && 322 (memcmp(ptr_, x.ptr_, static_cast<size_t>(x.length_)) == 0); 323 } 324 ends_with(StringPiece x)325 bool ends_with(StringPiece x) const { 326 return ((length_ >= x.length_) && 327 (memcmp(ptr_ + (length_-x.length_), x.ptr_, 328 static_cast<size_t>(x.length_)) == 0)); 329 } 330 331 // Checks whether StringPiece starts with x and if so advances the beginning 332 // of it to past the match. It's basically a shortcut for starts_with 333 // followed by remove_prefix. 334 bool Consume(StringPiece x); 335 // Like above but for the end of the string. 336 bool ConsumeFromEnd(StringPiece x); 337 338 // standard STL container boilerplate 339 typedef char value_type; 340 typedef const char* pointer; 341 typedef const char& reference; 342 typedef const char& const_reference; 343 typedef size_t size_type; 344 typedef ptrdiff_t difference_type; 345 static const size_type npos; 346 typedef const char* const_iterator; 347 typedef const char* iterator; 348 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 349 typedef std::reverse_iterator<iterator> reverse_iterator; begin()350 iterator begin() const { return ptr_; } end()351 iterator end() const { return ptr_ + length_; } rbegin()352 const_reverse_iterator rbegin() const { 353 return const_reverse_iterator(ptr_ + length_); 354 } rend()355 const_reverse_iterator rend() const { 356 return const_reverse_iterator(ptr_); 357 } max_size()358 stringpiece_ssize_type max_size() const { return length_; } capacity()359 stringpiece_ssize_type capacity() const { return length_; } 360 361 // cpplint.py emits a false positive [build/include_what_you_use] 362 stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT 363 364 bool contains(StringPiece s) const; 365 366 stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const; 367 stringpiece_ssize_type find(char c, size_type pos = 0) const; 368 stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const; 369 stringpiece_ssize_type rfind(char c, size_type pos = npos) const; 370 371 stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const; 372 stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const { 373 return find(c, pos); 374 } 375 stringpiece_ssize_type find_first_not_of(StringPiece s, 376 size_type pos = 0) const; 377 stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const; 378 stringpiece_ssize_type find_last_of(StringPiece s, 379 size_type pos = npos) const; 380 stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const { 381 return rfind(c, pos); 382 } 383 stringpiece_ssize_type find_last_not_of(StringPiece s, 384 size_type pos = npos) const; 385 stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const; 386 387 StringPiece substr(size_type pos, size_type n = npos) const; 388 }; 389 390 // This large function is defined inline so that in a fairly common case where 391 // one of the arguments is a literal, the compiler can elide a lot of the 392 // following comparisons. 393 inline bool operator==(StringPiece x, StringPiece y) { 394 stringpiece_ssize_type len = x.size(); 395 if (len != y.size()) { 396 return false; 397 } 398 399 return x.data() == y.data() || len <= 0 || 400 memcmp(x.data(), y.data(), static_cast<size_t>(len)) == 0; 401 } 402 403 inline bool operator!=(StringPiece x, StringPiece y) { 404 return !(x == y); 405 } 406 407 inline bool operator<(StringPiece x, StringPiece y) { 408 const stringpiece_ssize_type min_size = 409 x.size() < y.size() ? x.size() : y.size(); 410 const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size)); 411 return (r < 0) || (r == 0 && x.size() < y.size()); 412 } 413 414 inline bool operator>(StringPiece x, StringPiece y) { 415 return y < x; 416 } 417 418 inline bool operator<=(StringPiece x, StringPiece y) { 419 return !(x > y); 420 } 421 422 inline bool operator>=(StringPiece x, StringPiece y) { 423 return !(x < y); 424 } 425 426 // allow StringPiece to be logged 427 extern std::ostream& operator<<(std::ostream& o, StringPiece piece); 428 429 namespace internal { 430 // StringPiece is not a POD and can not be used in an union (pre C++11). We 431 // need a POD version of it. 432 struct StringPiecePod { 433 // Create from a StringPiece. CreateFromStringPieceStringPiecePod434 static StringPiecePod CreateFromStringPiece(StringPiece str) { 435 StringPiecePod pod; 436 pod.data_ = str.data(); 437 pod.size_ = str.size(); 438 return pod; 439 } 440 441 // Cast to StringPiece. StringPieceStringPiecePod442 operator StringPiece() const { return StringPiece(data_, size_); } 443 444 bool operator==(const char* value) const { 445 return StringPiece(data_, size_) == StringPiece(value); 446 } 447 448 char operator[](stringpiece_ssize_type i) const { 449 assert(0 <= i); 450 assert(i < size_); 451 return data_[i]; 452 } 453 dataStringPiecePod454 const char* data() const { return data_; } 455 sizeStringPiecePod456 stringpiece_ssize_type size() const { 457 return size_; 458 } 459 ToStringStringPiecePod460 std::string ToString() const { 461 return std::string(data_, static_cast<size_t>(size_)); 462 } 463 stringStringPiecePod464 explicit operator std::string() const { return ToString(); } 465 466 private: 467 const char* data_; 468 stringpiece_ssize_type size_; 469 }; 470 471 } // namespace internal 472 } // namespace protobuf 473 } // namespace google 474 475 GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START 476 template<> struct hash<StringPiece> { 477 size_t operator()(const StringPiece& s) const { 478 size_t result = 0; 479 for (const char *str = s.data(), *end = str + s.size(); str < end; str++) { 480 result = 5 * result + static_cast<size_t>(*str); 481 } 482 return result; 483 } 484 }; 485 GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END 486 487 #include <google/protobuf/port_undef.inc> 488 489 #endif // STRINGS_STRINGPIECE_H_ 490