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