/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef AAPT_STRING_PIECE_H #define AAPT_STRING_PIECE_H #include #include #include #include namespace aapt { /** * Read only wrapper around basic C strings. * Prevents excessive copying. * * WARNING: When creating from std::basic_string<>, moving the original * std::basic_string<> will invalidate the data held in a BasicStringPiece<>. * BasicStringPiece<> should only be used transitively. */ template class BasicStringPiece { public: using const_iterator = const TChar*; using difference_type = size_t; BasicStringPiece(); BasicStringPiece(const BasicStringPiece& str); BasicStringPiece(const std::basic_string& str); BasicStringPiece(const TChar* str); BasicStringPiece(const TChar* str, size_t len); BasicStringPiece& operator=(const BasicStringPiece& rhs); BasicStringPiece& assign(const TChar* str, size_t len); BasicStringPiece substr(size_t start, size_t len) const; BasicStringPiece substr(BasicStringPiece::const_iterator begin, BasicStringPiece::const_iterator end) const; const TChar* data() const; size_t length() const; size_t size() const; bool empty() const; std::basic_string toString() const; bool contains(const BasicStringPiece& rhs) const; int compare(const BasicStringPiece& rhs) const; bool operator<(const BasicStringPiece& rhs) const; bool operator>(const BasicStringPiece& rhs) const; bool operator==(const BasicStringPiece& rhs) const; bool operator!=(const BasicStringPiece& rhs) const; const_iterator begin() const; const_iterator end() const; private: const TChar* mData; size_t mLength; }; using StringPiece = BasicStringPiece; using StringPiece16 = BasicStringPiece; // // BasicStringPiece implementation. // template inline BasicStringPiece::BasicStringPiece() : mData(nullptr) , mLength(0) { } template inline BasicStringPiece::BasicStringPiece(const BasicStringPiece& str) : mData(str.mData), mLength(str.mLength) { } template inline BasicStringPiece::BasicStringPiece(const std::basic_string& str) : mData(str.data()), mLength(str.length()) { } template <> inline BasicStringPiece::BasicStringPiece(const char* str) : mData(str), mLength(str != nullptr ? strlen(str) : 0) { } template <> inline BasicStringPiece::BasicStringPiece(const char16_t* str) : mData(str), mLength(str != nullptr ? strlen16(str) : 0) { } template inline BasicStringPiece::BasicStringPiece(const TChar* str, size_t len) : mData(str), mLength(len) { } template inline BasicStringPiece& BasicStringPiece::operator=( const BasicStringPiece& rhs) { mData = rhs.mData; mLength = rhs.mLength; return *this; } template inline BasicStringPiece& BasicStringPiece::assign(const TChar* str, size_t len) { mData = str; mLength = len; return *this; } template inline BasicStringPiece BasicStringPiece::substr(size_t start, size_t len) const { if (start + len > mLength) { return BasicStringPiece(); } return BasicStringPiece(mData + start, len); } template inline BasicStringPiece BasicStringPiece::substr( BasicStringPiece::const_iterator begin, BasicStringPiece::const_iterator end) const { return BasicStringPiece(begin, end - begin); } template inline const TChar* BasicStringPiece::data() const { return mData; } template inline size_t BasicStringPiece::length() const { return mLength; } template inline size_t BasicStringPiece::size() const { return mLength; } template inline bool BasicStringPiece::empty() const { return mLength == 0; } template inline std::basic_string BasicStringPiece::toString() const { return std::basic_string(mData, mLength); } template <> inline bool BasicStringPiece::contains(const BasicStringPiece& rhs) const { if (!mData || !rhs.mData) { return false; } if (rhs.mLength > mLength) { return false; } return strstr(mData, rhs.mData) != nullptr; } template <> inline int BasicStringPiece::compare(const BasicStringPiece& rhs) const { const char nullStr = '\0'; const char* b1 = mData != nullptr ? mData : &nullStr; const char* e1 = b1 + mLength; const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr; const char* e2 = b2 + rhs.mLength; while (b1 < e1 && b2 < e2) { const int d = static_cast(*b1++) - static_cast(*b2++); if (d) { return d; } } return static_cast(mLength - rhs.mLength); } inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece& str) { android::String8 utf8(str.data(), str.size()); return out.write(utf8.string(), utf8.size()); } template <> inline bool BasicStringPiece::contains(const BasicStringPiece& rhs) const { if (!mData || !rhs.mData) { return false; } if (rhs.mLength > mLength) { return false; } return strstr16(mData, rhs.mData) != nullptr; } template <> inline int BasicStringPiece::compare(const BasicStringPiece& rhs) const { const char16_t nullStr = u'\0'; const char16_t* b1 = mData != nullptr ? mData : &nullStr; const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr; return strzcmp16(b1, mLength, b2, rhs.mLength); } template inline bool BasicStringPiece::operator<(const BasicStringPiece& rhs) const { return compare(rhs) < 0; } template inline bool BasicStringPiece::operator>(const BasicStringPiece& rhs) const { return compare(rhs) > 0; } template inline bool BasicStringPiece::operator==(const BasicStringPiece& rhs) const { return compare(rhs) == 0; } template inline bool BasicStringPiece::operator!=(const BasicStringPiece& rhs) const { return compare(rhs) != 0; } template inline typename BasicStringPiece::const_iterator BasicStringPiece::begin() const { return mData; } template inline typename BasicStringPiece::const_iterator BasicStringPiece::end() const { return mData + mLength; } inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece& str) { return out.write(str.data(), str.size()); } } // namespace aapt inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) { android::String8 utf8(str.data(), str.size()); return out.write(utf8.string(), utf8.size()); } #endif // AAPT_STRING_PIECE_H