• 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 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 && mData != kEmptyString) {
129         free(mData);
130         mData = NULL;
131     }
132 
133     mData = (char *)kEmptyString;
134     mSize = 0;
135     mAllocSize = 1;
136 }
137 
hash() const138 size_t AString::hash() const {
139     size_t x = 0;
140     for (size_t i = 0; i < mSize; ++i) {
141         x = (x * 31) + mData[i];
142     }
143 
144     return x;
145 }
146 
operator ==(const AString & other) const147 bool AString::operator==(const AString &other) const {
148     return mSize == other.mSize && !memcmp(mData, other.mData, mSize);
149 }
150 
trim()151 void AString::trim() {
152     makeMutable();
153 
154     size_t i = 0;
155     while (i < mSize && isspace(mData[i])) {
156         ++i;
157     }
158 
159     size_t j = mSize;
160     while (j > i && isspace(mData[j - 1])) {
161         --j;
162     }
163 
164     memmove(mData, &mData[i], j - i);
165     mSize = j - i;
166     mData[mSize] = '\0';
167 }
168 
erase(size_t start,size_t n)169 void AString::erase(size_t start, size_t n) {
170     CHECK_LT(start, mSize);
171     CHECK_LE(start + n, mSize);
172 
173     makeMutable();
174 
175     memmove(&mData[start], &mData[start + n], mSize - start - n);
176     mSize -= n;
177     mData[mSize] = '\0';
178 }
179 
makeMutable()180 void AString::makeMutable() {
181     if (mData == kEmptyString) {
182         mData = strdup(kEmptyString);
183     }
184 }
185 
append(const char * s)186 void AString::append(const char *s) {
187     append(s, strlen(s));
188 }
189 
append(const char * s,size_t size)190 void AString::append(const char *s, size_t size) {
191     makeMutable();
192 
193     if (mSize + size + 1 > mAllocSize) {
194         mAllocSize = (mAllocSize + size + 31) & -32;
195         mData = (char *)realloc(mData, mAllocSize);
196         CHECK(mData != NULL);
197     }
198 
199     memcpy(&mData[mSize], s, size);
200     mSize += size;
201     mData[mSize] = '\0';
202 }
203 
append(const AString & from)204 void AString::append(const AString &from) {
205     append(from.c_str(), from.size());
206 }
207 
append(const AString & from,size_t offset,size_t n)208 void AString::append(const AString &from, size_t offset, size_t n) {
209     append(from.c_str() + offset, n);
210 }
211 
append(int x)212 void AString::append(int x) {
213     char s[16];
214     int result = snprintf(s, sizeof(s), "%d", x);
215     CHECK((result > 0) && ((size_t) result) < sizeof(s));
216     append(s);
217 }
218 
append(unsigned x)219 void AString::append(unsigned x) {
220     char s[16];
221     int result = snprintf(s, sizeof(s), "%u", x);
222     CHECK((result > 0) && ((size_t) result) < sizeof(s));
223     append(s);
224 }
225 
append(long x)226 void AString::append(long x) {
227     char s[32];
228     int result = snprintf(s, sizeof(s), "%ld", x);
229     CHECK((result > 0) && ((size_t) result) < sizeof(s));
230     append(s);
231 }
232 
append(unsigned long x)233 void AString::append(unsigned long x) {
234     char s[32];
235     int result = snprintf(s, sizeof(s), "%lu", x);
236     CHECK((result > 0) && ((size_t) result) < sizeof(s));
237     append(s);
238 }
239 
append(long long x)240 void AString::append(long long x) {
241     char s[32];
242     int result = snprintf(s, sizeof(s), "%lld", x);
243     CHECK((result > 0) && ((size_t) result) < sizeof(s));
244     append(s);
245 }
246 
append(unsigned long long x)247 void AString::append(unsigned long long x) {
248     char s[32];
249     int result = snprintf(s, sizeof(s), "%llu", x);
250     CHECK((result > 0) && ((size_t) result) < sizeof(s));
251     append(s);
252 }
253 
append(float x)254 void AString::append(float x) {
255     char s[16];
256     int result = snprintf(s, sizeof(s), "%f", x);
257     CHECK((result > 0) && ((size_t) result) < sizeof(s));
258     append(s);
259 }
260 
append(double x)261 void AString::append(double x) {
262     char s[16];
263     int result = snprintf(s, sizeof(s), "%f", x);
264     CHECK((result > 0) && ((size_t) result) < sizeof(s));
265     append(s);
266 }
267 
append(void * x)268 void AString::append(void *x) {
269     char s[32];
270     int result = snprintf(s, sizeof(s), "%p", x);
271     CHECK((result > 0) && ((size_t) result) < sizeof(s));
272     append(s);
273 }
274 
find(const char * substring,size_t start) const275 ssize_t AString::find(const char *substring, size_t start) const {
276     CHECK_LE(start, size());
277 
278     const char *match = strstr(mData + start, substring);
279 
280     if (match == NULL) {
281         return -1;
282     }
283 
284     return match - mData;
285 }
286 
insert(const AString & from,size_t insertionPos)287 void AString::insert(const AString &from, size_t insertionPos) {
288     insert(from.c_str(), from.size(), insertionPos);
289 }
290 
insert(const char * from,size_t size,size_t insertionPos)291 void AString::insert(const char *from, size_t size, size_t insertionPos) {
292     CHECK_GE(insertionPos, 0u);
293     CHECK_LE(insertionPos, mSize);
294 
295     makeMutable();
296 
297     if (mSize + size + 1 > mAllocSize) {
298         mAllocSize = (mAllocSize + size + 31) & -32;
299         mData = (char *)realloc(mData, mAllocSize);
300         CHECK(mData != NULL);
301     }
302 
303     memmove(&mData[insertionPos + size],
304             &mData[insertionPos], mSize - insertionPos + 1);
305 
306     memcpy(&mData[insertionPos], from, size);
307 
308     mSize += size;
309 }
310 
operator <(const AString & other) const311 bool AString::operator<(const AString &other) const {
312     return compare(other) < 0;
313 }
314 
operator >(const AString & other) const315 bool AString::operator>(const AString &other) const {
316     return compare(other) > 0;
317 }
318 
compare(const AString & other) const319 int AString::compare(const AString &other) const {
320     return strcmp(mData, other.mData);
321 }
322 
compareIgnoreCase(const AString & other) const323 int AString::compareIgnoreCase(const AString &other) const {
324     return strcasecmp(mData, other.mData);
325 }
326 
equalsIgnoreCase(const AString & other) const327 bool AString::equalsIgnoreCase(const AString &other) const {
328     return compareIgnoreCase(other) == 0;
329 }
330 
tolower()331 void AString::tolower() {
332     makeMutable();
333 
334     for (size_t i = 0; i < mSize; ++i) {
335         mData[i] = ::tolower(mData[i]);
336     }
337 }
338 
startsWith(const char * prefix) const339 bool AString::startsWith(const char *prefix) const {
340     return !strncmp(mData, prefix, strlen(prefix));
341 }
342 
endsWith(const char * suffix) const343 bool AString::endsWith(const char *suffix) const {
344     size_t suffixLen = strlen(suffix);
345 
346     if (mSize < suffixLen) {
347         return false;
348     }
349 
350     return !strcmp(mData + mSize - suffixLen, suffix);
351 }
352 
startsWithIgnoreCase(const char * prefix) const353 bool AString::startsWithIgnoreCase(const char *prefix) const {
354     return !strncasecmp(mData, prefix, strlen(prefix));
355 }
356 
endsWithIgnoreCase(const char * suffix) const357 bool AString::endsWithIgnoreCase(const char *suffix) const {
358     size_t suffixLen = strlen(suffix);
359 
360     if (mSize < suffixLen) {
361         return false;
362     }
363 
364     return !strcasecmp(mData + mSize - suffixLen, suffix);
365 }
366 
367 // static
FromParcel(const Parcel & parcel)368 AString AString::FromParcel(const Parcel &parcel) {
369     size_t size = static_cast<size_t>(parcel.readInt32());
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