StringPiece.h revision 1ab598f46c3ff520a67f9d80194847741f3467ab
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
40    BasicStringPiece();
41    BasicStringPiece(const BasicStringPiece<TChar>& str);
42    BasicStringPiece(const std::basic_string<TChar>& str);
43    BasicStringPiece(const TChar* str);
44    BasicStringPiece(const TChar* str, size_t len);
45
46    BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
47    BasicStringPiece<TChar>& assign(const TChar* str, size_t len);
48
49    BasicStringPiece<TChar> substr(size_t start, size_t len) const;
50    BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin,
51                                   BasicStringPiece<TChar>::const_iterator end) const;
52
53    const TChar* data() const;
54    size_t length() const;
55    size_t size() const;
56    bool empty() const;
57    std::basic_string<TChar> toString() const;
58
59    int compare(const BasicStringPiece<TChar>& rhs) const;
60    bool operator<(const BasicStringPiece<TChar>& rhs) const;
61    bool operator>(const BasicStringPiece<TChar>& rhs) const;
62    bool operator==(const BasicStringPiece<TChar>& rhs) const;
63    bool operator!=(const BasicStringPiece<TChar>& rhs) const;
64
65    const_iterator begin() const;
66    const_iterator end() const;
67
68private:
69    const TChar* mData;
70    size_t mLength;
71};
72
73using StringPiece = BasicStringPiece<char>;
74using StringPiece16 = BasicStringPiece<char16_t>;
75
76//
77// BasicStringPiece implementation.
78//
79
80template <typename TChar>
81inline BasicStringPiece<TChar>::BasicStringPiece() : mData(nullptr) , mLength(0) {
82}
83
84template <typename TChar>
85inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str) :
86        mData(str.mData), mLength(str.mLength) {
87}
88
89template <typename TChar>
90inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str) :
91        mData(str.data()), mLength(str.length()) {
92}
93
94template <>
95inline BasicStringPiece<char>::BasicStringPiece(const char* str) :
96        mData(str), mLength(str != nullptr ? strlen(str) : 0) {
97}
98
99template <>
100inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str) :
101        mData(str), mLength(str != nullptr ? strlen16(str) : 0) {
102}
103
104template <typename TChar>
105inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len) :
106        mData(str), mLength(len) {
107}
108
109template <typename TChar>
110inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=(
111        const BasicStringPiece<TChar>& rhs) {
112    mData = rhs.mData;
113    mLength = rhs.mLength;
114    return *this;
115}
116
117template <typename TChar>
118inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) {
119    mData = str;
120    mLength = len;
121    return *this;
122}
123
124
125template <typename TChar>
126inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const {
127    if (start + len > mLength) {
128        return BasicStringPiece<TChar>();
129    }
130    return BasicStringPiece<TChar>(mData + start, len);
131}
132
133template <typename TChar>
134inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
135        BasicStringPiece<TChar>::const_iterator begin,
136        BasicStringPiece<TChar>::const_iterator end) const {
137    return BasicStringPiece<TChar>(begin, end - begin);
138}
139
140template <typename TChar>
141inline const TChar* BasicStringPiece<TChar>::data() const {
142    return mData;
143}
144
145template <typename TChar>
146inline size_t BasicStringPiece<TChar>::length() const {
147    return mLength;
148}
149
150template <typename TChar>
151inline size_t BasicStringPiece<TChar>::size() const {
152    return mLength;
153}
154
155template <typename TChar>
156inline bool BasicStringPiece<TChar>::empty() const {
157    return mLength == 0;
158}
159
160template <typename TChar>
161inline std::basic_string<TChar> BasicStringPiece<TChar>::toString() const {
162    return std::basic_string<TChar>(mData, mLength);
163}
164
165template <>
166inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const {
167    const char nullStr = '\0';
168    const char* b1 = mData != nullptr ? mData : &nullStr;
169    const char* e1 = b1 + mLength;
170    const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
171    const char* e2 = b2 + rhs.mLength;
172
173    while (b1 < e1 && b2 < e2) {
174        const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++);
175        if (d) {
176            return d;
177        }
178    }
179    return static_cast<int>(mLength - rhs.mLength);
180}
181
182inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) {
183    android::String8 utf8(str.data(), str.size());
184    return out.write(utf8.string(), utf8.size());
185}
186
187
188template <>
189inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const {
190    const char16_t nullStr = u'\0';
191    const char16_t* b1 = mData != nullptr ? mData : &nullStr;
192    const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
193    return strzcmp16(b1, mLength, b2, rhs.mLength);
194}
195
196template <typename TChar>
197inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const {
198    return compare(rhs) < 0;
199}
200
201template <typename TChar>
202inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const {
203    return compare(rhs) > 0;
204}
205
206template <typename TChar>
207inline bool BasicStringPiece<TChar>::operator==(const BasicStringPiece<TChar>& rhs) const {
208    return compare(rhs) == 0;
209}
210
211template <typename TChar>
212inline bool BasicStringPiece<TChar>::operator!=(const BasicStringPiece<TChar>& rhs) const {
213    return compare(rhs) != 0;
214}
215
216template <typename TChar>
217inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const {
218    return mData;
219}
220
221template <typename TChar>
222inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const {
223    return mData + mLength;
224}
225
226inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
227    return out.write(str.data(), str.size());
228}
229
230} // namespace aapt
231
232inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) {
233    android::String8 utf8(str.data(), str.size());
234    return out.write(utf8.string(), utf8.size());
235}
236
237#endif // AAPT_STRING_PIECE_H
238