1/* 2 * Copyright (C) 2015 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 AAPT_STRING_PIECE_H 18#define AAPT_STRING_PIECE_H 19 20#include <ostream> 21#include <string> 22#include <utils/String8.h> 23#include <utils/Unicode.h> 24 25namespace aapt { 26 27/** 28 * Read only wrapper around basic C strings. 29 * Prevents excessive copying. 30 * 31 * WARNING: When creating from std::basic_string<>, moving the original 32 * std::basic_string<> will invalidate the data held in a BasicStringPiece<>. 33 * BasicStringPiece<> should only be used transitively. 34 */ 35template <typename TChar> 36class BasicStringPiece { 37public: 38 using const_iterator = const TChar*; 39 using difference_type = size_t; 40 41 BasicStringPiece(); 42 BasicStringPiece(const BasicStringPiece<TChar>& str); 43 BasicStringPiece(const std::basic_string<TChar>& str); 44 BasicStringPiece(const TChar* str); 45 BasicStringPiece(const TChar* str, size_t len); 46 47 BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs); 48 BasicStringPiece<TChar>& assign(const TChar* str, size_t len); 49 50 BasicStringPiece<TChar> substr(size_t start, size_t len) const; 51 BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin, 52 BasicStringPiece<TChar>::const_iterator end) const; 53 54 const TChar* data() const; 55 size_t length() const; 56 size_t size() const; 57 bool empty() const; 58 std::basic_string<TChar> toString() const; 59 60 bool contains(const BasicStringPiece<TChar>& rhs) const; 61 int compare(const BasicStringPiece<TChar>& rhs) const; 62 bool operator<(const BasicStringPiece<TChar>& rhs) const; 63 bool operator>(const BasicStringPiece<TChar>& rhs) const; 64 bool operator==(const BasicStringPiece<TChar>& rhs) const; 65 bool operator!=(const BasicStringPiece<TChar>& rhs) const; 66 67 const_iterator begin() const; 68 const_iterator end() const; 69 70private: 71 const TChar* mData; 72 size_t mLength; 73}; 74 75using StringPiece = BasicStringPiece<char>; 76using StringPiece16 = BasicStringPiece<char16_t>; 77 78// 79// BasicStringPiece implementation. 80// 81 82template <typename TChar> 83inline BasicStringPiece<TChar>::BasicStringPiece() : mData(nullptr) , mLength(0) { 84} 85 86template <typename TChar> 87inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str) : 88 mData(str.mData), mLength(str.mLength) { 89} 90 91template <typename TChar> 92inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str) : 93 mData(str.data()), mLength(str.length()) { 94} 95 96template <> 97inline BasicStringPiece<char>::BasicStringPiece(const char* str) : 98 mData(str), mLength(str != nullptr ? strlen(str) : 0) { 99} 100 101template <> 102inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str) : 103 mData(str), mLength(str != nullptr ? strlen16(str) : 0) { 104} 105 106template <typename TChar> 107inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len) : 108 mData(str), mLength(len) { 109} 110 111template <typename TChar> 112inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=( 113 const BasicStringPiece<TChar>& rhs) { 114 mData = rhs.mData; 115 mLength = rhs.mLength; 116 return *this; 117} 118 119template <typename TChar> 120inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) { 121 mData = str; 122 mLength = len; 123 return *this; 124} 125 126 127template <typename TChar> 128inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const { 129 if (start + len > mLength) { 130 return BasicStringPiece<TChar>(); 131 } 132 return BasicStringPiece<TChar>(mData + start, len); 133} 134 135template <typename TChar> 136inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr( 137 BasicStringPiece<TChar>::const_iterator begin, 138 BasicStringPiece<TChar>::const_iterator end) const { 139 return BasicStringPiece<TChar>(begin, end - begin); 140} 141 142template <typename TChar> 143inline const TChar* BasicStringPiece<TChar>::data() const { 144 return mData; 145} 146 147template <typename TChar> 148inline size_t BasicStringPiece<TChar>::length() const { 149 return mLength; 150} 151 152template <typename TChar> 153inline size_t BasicStringPiece<TChar>::size() const { 154 return mLength; 155} 156 157template <typename TChar> 158inline bool BasicStringPiece<TChar>::empty() const { 159 return mLength == 0; 160} 161 162template <typename TChar> 163inline std::basic_string<TChar> BasicStringPiece<TChar>::toString() const { 164 return std::basic_string<TChar>(mData, mLength); 165} 166 167template <> 168inline bool BasicStringPiece<char>::contains(const BasicStringPiece<char>& rhs) const { 169 if (!mData || !rhs.mData) { 170 return false; 171 } 172 if (rhs.mLength > mLength) { 173 return false; 174 } 175 return strstr(mData, rhs.mData) != nullptr; 176} 177 178template <> 179inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const { 180 const char nullStr = '\0'; 181 const char* b1 = mData != nullptr ? mData : &nullStr; 182 const char* e1 = b1 + mLength; 183 const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr; 184 const char* e2 = b2 + rhs.mLength; 185 186 while (b1 < e1 && b2 < e2) { 187 const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++); 188 if (d) { 189 return d; 190 } 191 } 192 return static_cast<int>(mLength - rhs.mLength); 193} 194 195inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) { 196 android::String8 utf8(str.data(), str.size()); 197 return out.write(utf8.string(), utf8.size()); 198} 199 200template <> 201inline bool BasicStringPiece<char16_t>::contains(const BasicStringPiece<char16_t>& rhs) const { 202 if (!mData || !rhs.mData) { 203 return false; 204 } 205 if (rhs.mLength > mLength) { 206 return false; 207 } 208 return strstr16(mData, rhs.mData) != nullptr; 209} 210 211template <> 212inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const { 213 const char16_t nullStr = u'\0'; 214 const char16_t* b1 = mData != nullptr ? mData : &nullStr; 215 const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr; 216 return strzcmp16(b1, mLength, b2, rhs.mLength); 217} 218 219template <typename TChar> 220inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const { 221 return compare(rhs) < 0; 222} 223 224template <typename TChar> 225inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const { 226 return compare(rhs) > 0; 227} 228 229template <typename TChar> 230inline bool BasicStringPiece<TChar>::operator==(const BasicStringPiece<TChar>& rhs) const { 231 return compare(rhs) == 0; 232} 233 234template <typename TChar> 235inline bool BasicStringPiece<TChar>::operator!=(const BasicStringPiece<TChar>& rhs) const { 236 return compare(rhs) != 0; 237} 238 239template <typename TChar> 240inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const { 241 return mData; 242} 243 244template <typename TChar> 245inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const { 246 return mData + mLength; 247} 248 249inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) { 250 return out.write(str.data(), str.size()); 251} 252 253} // namespace aapt 254 255inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) { 256 android::String8 utf8(str.data(), str.size()); 257 return out.write(utf8.string(), utf8.size()); 258} 259 260#endif // AAPT_STRING_PIECE_H 261