• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "AString"
18 #include <utils/Log.h>
19 
20 #include <ctype.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include <binder/Parcel.h>
27 #include <utils/String8.h>
28 #include "ADebug.h"
29 #include "AString.h"
30 
31 namespace android {
32 
33 // static
34 constexpr const char *AString::kEmptyString;
35 
AString()36 AString::AString()
37     : mData((char *)kEmptyString),
38       mSize(0),
39       mAllocSize(1) {
40 }
41 
AString(const char * s)42 AString::AString(const char *s)
43     : mData(NULL),
44       mSize(0),
45       mAllocSize(1) {
46     if (!s) {
47         ALOGW("ctor got NULL, using empty string instead");
48         clear();
49     } else {
50         setTo(s);
51     }
52 }
53 
AString(const char * s,size_t size)54 AString::AString(const char *s, size_t size)
55     : mData(NULL),
56       mSize(0),
57       mAllocSize(1) {
58     if (!s) {
59         ALOGW("ctor got NULL, using empty string instead");
60         clear();
61     } else {
62         setTo(s, size);
63     }
64 }
65 
AString(const String8 & from)66 AString::AString(const String8 &from)
67     : mData(NULL),
68       mSize(0),
69       mAllocSize(1) {
70     setTo(from.string(), from.length());
71 }
72 
AString(const AString & from)73 AString::AString(const AString &from)
74     : mData(NULL),
75       mSize(0),
76       mAllocSize(1) {
77     setTo(from, 0, from.size());
78 }
79 
AString(const AString & from,size_t offset,size_t n)80 AString::AString(const AString &from, size_t offset, size_t n)
81     : mData(NULL),
82       mSize(0),
83       mAllocSize(1) {
84     setTo(from, offset, n);
85 }
86 
~AString()87 AString::~AString() {
88     clear();
89 }
90 
operator =(const AString & from)91 AString &AString::operator=(const AString &from) {
92     if (&from != this) {
93         setTo(from, 0, from.size());
94     }
95 
96     return *this;
97 }
98 
size() const99 size_t AString::size() const {
100     return mSize;
101 }
102 
c_str() const103 const char *AString::c_str() const {
104     return mData;
105 }
106 
empty() const107 bool AString::empty() const {
108     return mSize == 0;
109 }
110 
setTo(const char * s)111 void AString::setTo(const char *s) {
112     setTo(s, strlen(s));
113 }
114 
setTo(const char * s,size_t size)115 void AString::setTo(const char *s, size_t size) {
116     clear();
117     append(s, size);
118 }
119 
setTo(const AString & from,size_t offset,size_t n)120 void AString::setTo(const AString &from, size_t offset, size_t n) {
121     CHECK(&from != this);
122 
123     clear();
124     setTo(from.mData + offset, n);
125 }
126 
clear()127 void AString::clear() {
128     if (mData != kEmptyString) {
129         free(mData);
130         mData = (char *)kEmptyString;
131     }
132     mSize = 0;
133     mAllocSize = 1;
134 }
135 
hash() const136 size_t AString::hash() const {
137     size_t x = 0;
138     for (size_t i = 0; i < mSize; ++i) {
139         x = (x * 31) + mData[i];
140     }
141 
142     return x;
143 }
144 
operator ==(const AString & other) const145 bool AString::operator==(const AString &other) const {
146     return mSize == other.mSize && !memcmp(mData, other.mData, mSize);
147 }
148 
trim()149 void AString::trim() {
150     makeMutable();
151 
152     size_t i = 0;
153     while (i < mSize && isspace(mData[i])) {
154         ++i;
155     }
156 
157     size_t j = mSize;
158     while (j > i && isspace(mData[j - 1])) {
159         --j;
160     }
161 
162     memmove(mData, &mData[i], j - i);
163     mSize = j - i;
164     mData[mSize] = '\0';
165 }
166 
erase(size_t start,size_t n)167 void AString::erase(size_t start, size_t n) {
168     CHECK_LT(start, mSize);
169     CHECK_LE(start + n, mSize);
170 
171     makeMutable();
172 
173     memmove(&mData[start], &mData[start + n], mSize - start - n);
174     mSize -= n;
175     mData[mSize] = '\0';
176 }
177 
makeMutable()178 void AString::makeMutable() {
179     if (mData == kEmptyString) {
180         mData = strdup(kEmptyString);
181     }
182 }
183 
append(const char * s)184 void AString::append(const char *s) {
185     append(s, strlen(s));
186 }
187 
append(const char * s,size_t size)188 void AString::append(const char *s, size_t size) {
189     makeMutable();
190 
191     if (mSize + size + 1 > mAllocSize) {
192         mAllocSize = (mAllocSize + size + 31) & -32;
193         mData = (char *)realloc(mData, mAllocSize);
194         CHECK(mData != NULL);
195     }
196 
197     memcpy(&mData[mSize], s, size);
198     mSize += size;
199     mData[mSize] = '\0';
200 }
201 
append(const AString & from)202 void AString::append(const AString &from) {
203     append(from.c_str(), from.size());
204 }
205 
append(const AString & from,size_t offset,size_t n)206 void AString::append(const AString &from, size_t offset, size_t n) {
207     append(from.c_str() + offset, n);
208 }
209 
append(int x)210 void AString::append(int x) {
211     char s[16];
212     int result = snprintf(s, sizeof(s), "%d", x);
213     CHECK((result > 0) && ((size_t) result) < sizeof(s));
214     append(s);
215 }
216 
append(unsigned x)217 void AString::append(unsigned x) {
218     char s[16];
219     int result = snprintf(s, sizeof(s), "%u", x);
220     CHECK((result > 0) && ((size_t) result) < sizeof(s));
221     append(s);
222 }
223 
append(long x)224 void AString::append(long x) {
225     char s[32];
226     int result = snprintf(s, sizeof(s), "%ld", x);
227     CHECK((result > 0) && ((size_t) result) < sizeof(s));
228     append(s);
229 }
230 
append(unsigned long x)231 void AString::append(unsigned long x) {
232     char s[32];
233     int result = snprintf(s, sizeof(s), "%lu", x);
234     CHECK((result > 0) && ((size_t) result) < sizeof(s));
235     append(s);
236 }
237 
append(long long x)238 void AString::append(long long x) {
239     char s[32];
240     int result = snprintf(s, sizeof(s), "%lld", x);
241     CHECK((result > 0) && ((size_t) result) < sizeof(s));
242     append(s);
243 }
244 
append(unsigned long long x)245 void AString::append(unsigned long long x) {
246     char s[32];
247     int result = snprintf(s, sizeof(s), "%llu", x);
248     CHECK((result > 0) && ((size_t) result) < sizeof(s));
249     append(s);
250 }
251 
append(float x)252 void AString::append(float x) {
253     char s[16];
254     int result = snprintf(s, sizeof(s), "%f", x);
255     CHECK((result > 0) && ((size_t) result) < sizeof(s));
256     append(s);
257 }
258 
append(double x)259 void AString::append(double x) {
260     char s[16];
261     int result = snprintf(s, sizeof(s), "%f", x);
262     CHECK((result > 0) && ((size_t) result) < sizeof(s));
263     append(s);
264 }
265 
append(void * x)266 void AString::append(void *x) {
267     char s[32];
268     int result = snprintf(s, sizeof(s), "%p", x);
269     CHECK((result > 0) && ((size_t) result) < sizeof(s));
270     append(s);
271 }
272 
find(const char * substring,size_t start) const273 ssize_t AString::find(const char *substring, size_t start) const {
274     CHECK_LE(start, size());
275 
276     const char *match = strstr(mData + start, substring);
277 
278     if (match == NULL) {
279         return -1;
280     }
281 
282     return match - mData;
283 }
284 
insert(const AString & from,size_t insertionPos)285 void AString::insert(const AString &from, size_t insertionPos) {
286     insert(from.c_str(), from.size(), insertionPos);
287 }
288 
insert(const char * from,size_t size,size_t insertionPos)289 void AString::insert(const char *from, size_t size, size_t insertionPos) {
290     CHECK_GE(insertionPos, 0u);
291     CHECK_LE(insertionPos, mSize);
292 
293     makeMutable();
294 
295     if (mSize + size + 1 > mAllocSize) {
296         mAllocSize = (mAllocSize + size + 31) & -32;
297         mData = (char *)realloc(mData, mAllocSize);
298         CHECK(mData != NULL);
299     }
300 
301     memmove(&mData[insertionPos + size],
302             &mData[insertionPos], mSize - insertionPos + 1);
303 
304     memcpy(&mData[insertionPos], from, size);
305 
306     mSize += size;
307 }
308 
operator <(const AString & other) const309 bool AString::operator<(const AString &other) const {
310     return compare(other) < 0;
311 }
312 
operator >(const AString & other) const313 bool AString::operator>(const AString &other) const {
314     return compare(other) > 0;
315 }
316 
compare(const AString & other) const317 int AString::compare(const AString &other) const {
318     return strcmp(mData, other.mData);
319 }
320 
compareIgnoreCase(const AString & other) const321 int AString::compareIgnoreCase(const AString &other) const {
322     return strcasecmp(mData, other.mData);
323 }
324 
equalsIgnoreCase(const AString & other) const325 bool AString::equalsIgnoreCase(const AString &other) const {
326     return compareIgnoreCase(other) == 0;
327 }
328 
tolower()329 void AString::tolower() {
330     makeMutable();
331 
332     for (size_t i = 0; i < mSize; ++i) {
333         mData[i] = ::tolower(mData[i]);
334     }
335 }
336 
startsWith(const char * prefix) const337 bool AString::startsWith(const char *prefix) const {
338     return !strncmp(mData, prefix, strlen(prefix));
339 }
340 
endsWith(const char * suffix) const341 bool AString::endsWith(const char *suffix) const {
342     size_t suffixLen = strlen(suffix);
343 
344     if (mSize < suffixLen) {
345         return false;
346     }
347 
348     return !strcmp(mData + mSize - suffixLen, suffix);
349 }
350 
startsWithIgnoreCase(const char * prefix) const351 bool AString::startsWithIgnoreCase(const char *prefix) const {
352     return !strncasecmp(mData, prefix, strlen(prefix));
353 }
354 
endsWithIgnoreCase(const char * suffix) const355 bool AString::endsWithIgnoreCase(const char *suffix) const {
356     size_t suffixLen = strlen(suffix);
357 
358     if (mSize < suffixLen) {
359         return false;
360     }
361 
362     return !strcasecmp(mData + mSize - suffixLen, suffix);
363 }
364 
365 // static
FromParcel(const Parcel & parcel)366 AString AString::FromParcel(const Parcel &parcel) {
367     size_t size = static_cast<size_t>(parcel.readInt32());
368     // The static analyzer incorrectly reports a false-positive here in c++17.
369     // https://bugs.llvm.org/show_bug.cgi?id=38176 . NOLINTNEXTLINE
370     return AString(static_cast<const char *>(parcel.readInplace(size)), size);
371 }
372 
writeToParcel(Parcel * parcel) const373 status_t AString::writeToParcel(Parcel *parcel) const {
374     CHECK_LE(mSize, static_cast<size_t>(INT32_MAX));
375     status_t err = parcel->writeInt32(mSize);
376     if (err == OK) {
377         err = parcel->write(mData, mSize);
378     }
379     return err;
380 }
381 
AStringPrintf(const char * format,...)382 AString AStringPrintf(const char *format, ...) {
383     va_list ap;
384     va_start(ap, format);
385 
386     char *buffer;
387     vasprintf(&buffer, format, ap);
388 
389     va_end(ap);
390 
391     AString result(buffer);
392 
393     free(buffer);
394     buffer = NULL;
395 
396     return result;
397 }
398 
399 }  // namespace android
400 
401