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 // A string-like object that points to a sized piece of memory. 18 // 19 // Functions or methods may use const StringPiece& parameters to accept either 20 // a "const char*" or a "string" value that will be implicitly converted to 21 // a StringPiece. The implicit conversion means that it is often appropriate 22 // to include this .h file in other files rather than forward-declaring 23 // StringPiece as would be appropriate for most other Google classes. 24 // 25 // Systematic usage of StringPiece is encouraged as it will reduce unnecessary 26 // conversions from "const char*" to "string" and back again. 27 28 #ifndef ART_RUNTIME_BASE_STRINGPIECE_H_ 29 #define ART_RUNTIME_BASE_STRINGPIECE_H_ 30 31 #include <string.h> 32 #include <algorithm> 33 #include <cstddef> 34 #include <iosfwd> 35 #include <string> 36 37 namespace art { 38 39 class StringPiece { 40 private: 41 const char* ptr_; 42 int length_; 43 44 public: 45 // We provide non-explicit singleton constructors so users can pass 46 // in a "const char*" or a "string" wherever a "StringPiece" is 47 // expected. StringPiece()48 StringPiece() : ptr_(NULL), length_(0) { } StringPiece(const char * str)49 StringPiece(const char* str) // NOLINT 50 : ptr_(str), length_((str == NULL) ? 0 : static_cast<int>(strlen(str))) { } StringPiece(const std::string & str)51 StringPiece(const std::string& str) // NOLINT 52 : ptr_(str.data()), length_(static_cast<int>(str.size())) { } StringPiece(const char * offset,int len)53 StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { } 54 55 // data() may return a pointer to a buffer with embedded NULs, and the 56 // returned buffer may or may not be null terminated. Therefore it is 57 // typically a mistake to pass data() to a routine that expects a NUL 58 // terminated string. data()59 const char* data() const { return ptr_; } size()60 int size() const { return length_; } length()61 int length() const { return length_; } empty()62 bool empty() const { return length_ == 0; } 63 clear()64 void clear() { 65 ptr_ = NULL; 66 length_ = 0; 67 } set(const char * data,int len)68 void set(const char* data, int len) { 69 ptr_ = data; 70 length_ = len; 71 } set(const char * str)72 void set(const char* str) { 73 ptr_ = str; 74 if (str != NULL) 75 length_ = static_cast<int>(strlen(str)); 76 else 77 length_ = 0; 78 } set(const void * data,int len)79 void set(const void* data, int len) { 80 ptr_ = reinterpret_cast<const char*>(data); 81 length_ = len; 82 } 83 84 char operator[](int i) const { return ptr_[i]; } 85 remove_prefix(int n)86 void remove_prefix(int n) { 87 ptr_ += n; 88 length_ -= n; 89 } 90 remove_suffix(int n)91 void remove_suffix(int n) { 92 length_ -= n; 93 } 94 95 int compare(const StringPiece& x) const; 96 as_string()97 std::string as_string() const { 98 return std::string(data(), size()); 99 } 100 // We also define ToString() here, since many other string-like 101 // interfaces name the routine that converts to a C++ string 102 // "ToString", and it's confusing to have the method that does that 103 // for a StringPiece be called "as_string()". We also leave the 104 // "as_string()" method defined here for existing code. ToString()105 std::string ToString() const { 106 return std::string(data(), size()); 107 } 108 109 void CopyToString(std::string* target) const; 110 void AppendToString(std::string* target) const; 111 112 // Does "this" start with "x" starts_with(const StringPiece & x)113 bool starts_with(const StringPiece& x) const { 114 return ((length_ >= x.length_) && 115 (memcmp(ptr_, x.ptr_, x.length_) == 0)); 116 } 117 118 // Does "this" end with "x" ends_with(const StringPiece & x)119 bool ends_with(const StringPiece& x) const { 120 return ((length_ >= x.length_) && 121 (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); 122 } 123 124 // standard STL container boilerplate 125 typedef char value_type; 126 typedef const char* pointer; 127 typedef const char& reference; 128 typedef const char& const_reference; 129 typedef size_t size_type; 130 typedef ptrdiff_t difference_type; 131 static const size_type npos; 132 typedef const char* const_iterator; 133 typedef const char* iterator; 134 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 135 typedef std::reverse_iterator<iterator> reverse_iterator; begin()136 iterator begin() const { return ptr_; } end()137 iterator end() const { return ptr_ + length_; } rbegin()138 const_reverse_iterator rbegin() const { 139 return const_reverse_iterator(ptr_ + length_); 140 } rend()141 const_reverse_iterator rend() const { 142 return const_reverse_iterator(ptr_); 143 } 144 // STLS says return size_type, but Google says return int max_size()145 int max_size() const { return length_; } capacity()146 int capacity() const { return length_; } 147 148 int copy(char* buf, size_type n, size_type pos = 0) const; 149 150 size_type find(const StringPiece& s, size_type pos = 0) const; 151 size_type find(char c, size_type pos = 0) const; 152 size_type rfind(const StringPiece& s, size_type pos = npos) const; 153 size_type rfind(char c, size_type pos = npos) const; 154 155 StringPiece substr(size_type pos, size_type n = npos) const; 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 int 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 StringPiece& y) { 188 return !(x == y); 189 } 190 191 inline bool operator<(const StringPiece& x, const StringPiece& y) { 192 const int r = memcmp(x.data(), y.data(), 193 std::min(x.size(), y.size())); 194 return ((r < 0) || ((r == 0) && (x.size() < y.size()))); 195 } 196 197 inline bool operator>(const StringPiece& x, const StringPiece& y) { 198 return y < x; 199 } 200 201 inline bool operator<=(const StringPiece& x, const StringPiece& y) { 202 return !(x > y); 203 } 204 205 inline bool operator>=(const StringPiece& x, const StringPiece& y) { 206 return !(x < y); 207 } 208 209 extern std::ostream& operator<<(std::ostream& o, const StringPiece& piece); 210 211 } // namespace art 212 213 #endif // ART_RUNTIME_BASE_STRINGPIECE_H_ 214