blob: 2f8011df69e78ec6eb22515976caf7eb24eaaff8 [file] [log] [blame]
Andreas Huber72961232010-06-07 10:18:57 -07001/*
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
Marco Nelissen89b2a0a2016-05-03 11:10:42 -070017#define LOG_TAG "AString"
18#include <utils/Log.h>
19
Andreas Huber72961232010-06-07 10:18:57 -070020#include <ctype.h>
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
Lajos Molnarbcf08562014-04-04 18:09:35 -070026#include <utils/String8.h>
Andreas Huber72961232010-06-07 10:18:57 -070027#include "ADebug.h"
28#include "AString.h"
29
Colin Crossf8b5fe22021-12-15 14:59:00 -080030#if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
S Vasudev Prasad08ce0dc2020-05-05 11:39:34 +053031#include <binder/Parcel.h>
32#endif
33
Andreas Huber72961232010-06-07 10:18:57 -070034namespace android {
35
36// static
George Burgess IV3098ae52018-05-15 13:15:20 -070037constexpr const char *AString::kEmptyString;
Andreas Huber72961232010-06-07 10:18:57 -070038
39AString::AString()
40 : mData((char *)kEmptyString),
41 mSize(0),
42 mAllocSize(1) {
43}
44
45AString::AString(const char *s)
46 : mData(NULL),
47 mSize(0),
48 mAllocSize(1) {
Marco Nelissen89b2a0a2016-05-03 11:10:42 -070049 if (!s) {
50 ALOGW("ctor got NULL, using empty string instead");
51 clear();
52 } else {
53 setTo(s);
54 }
Andreas Huber72961232010-06-07 10:18:57 -070055}
56
57AString::AString(const char *s, size_t size)
58 : mData(NULL),
59 mSize(0),
60 mAllocSize(1) {
Marco Nelissen89b2a0a2016-05-03 11:10:42 -070061 if (!s) {
62 ALOGW("ctor got NULL, using empty string instead");
63 clear();
64 } else {
65 setTo(s, size);
66 }
Andreas Huber72961232010-06-07 10:18:57 -070067}
68
Lajos Molnarbcf08562014-04-04 18:09:35 -070069AString::AString(const String8 &from)
70 : mData(NULL),
71 mSize(0),
72 mAllocSize(1) {
Tomasz Wasilczyk03fc55f2023-08-11 17:05:05 +000073 setTo(from.c_str(), from.length());
Lajos Molnarbcf08562014-04-04 18:09:35 -070074}
75
Andreas Huber72961232010-06-07 10:18:57 -070076AString::AString(const AString &from)
77 : mData(NULL),
78 mSize(0),
79 mAllocSize(1) {
80 setTo(from, 0, from.size());
81}
82
83AString::AString(const AString &from, size_t offset, size_t n)
84 : mData(NULL),
85 mSize(0),
86 mAllocSize(1) {
87 setTo(from, offset, n);
88}
89
90AString::~AString() {
91 clear();
92}
93
94AString &AString::operator=(const AString &from) {
95 if (&from != this) {
96 setTo(from, 0, from.size());
97 }
98
99 return *this;
100}
101
102size_t AString::size() const {
103 return mSize;
104}
105
106const char *AString::c_str() const {
107 return mData;
108}
109
110bool AString::empty() const {
111 return mSize == 0;
112}
113
114void AString::setTo(const char *s) {
115 setTo(s, strlen(s));
116}
117
118void AString::setTo(const char *s, size_t size) {
119 clear();
120 append(s, size);
121}
122
123void AString::setTo(const AString &from, size_t offset, size_t n) {
124 CHECK(&from != this);
125
126 clear();
127 setTo(from.mData + offset, n);
128}
129
130void AString::clear() {
Chih-Hung Hsiehb37668e2018-08-30 16:22:52 -0700131 if (mData != kEmptyString) {
Andreas Huber72961232010-06-07 10:18:57 -0700132 free(mData);
Chih-Hung Hsiehb37668e2018-08-30 16:22:52 -0700133 mData = (char *)kEmptyString;
Andreas Huber72961232010-06-07 10:18:57 -0700134 }
Andreas Huber72961232010-06-07 10:18:57 -0700135 mSize = 0;
136 mAllocSize = 1;
137}
138
139size_t AString::hash() const {
140 size_t x = 0;
141 for (size_t i = 0; i < mSize; ++i) {
142 x = (x * 31) + mData[i];
143 }
144
145 return x;
146}
147
148bool AString::operator==(const AString &other) const {
149 return mSize == other.mSize && !memcmp(mData, other.mData, mSize);
150}
151
152void AString::trim() {
153 makeMutable();
154
155 size_t i = 0;
156 while (i < mSize && isspace(mData[i])) {
157 ++i;
158 }
159
160 size_t j = mSize;
161 while (j > i && isspace(mData[j - 1])) {
162 --j;
163 }
164
165 memmove(mData, &mData[i], j - i);
166 mSize = j - i;
167 mData[mSize] = '\0';
168}
169
170void AString::erase(size_t start, size_t n) {
171 CHECK_LT(start, mSize);
172 CHECK_LE(start + n, mSize);
173
174 makeMutable();
175
176 memmove(&mData[start], &mData[start + n], mSize - start - n);
177 mSize -= n;
178 mData[mSize] = '\0';
179}
180
181void AString::makeMutable() {
182 if (mData == kEmptyString) {
183 mData = strdup(kEmptyString);
184 }
185}
186
187void AString::append(const char *s) {
188 append(s, strlen(s));
189}
190
191void AString::append(const char *s, size_t size) {
192 makeMutable();
193
194 if (mSize + size + 1 > mAllocSize) {
195 mAllocSize = (mAllocSize + size + 31) & -32;
196 mData = (char *)realloc(mData, mAllocSize);
197 CHECK(mData != NULL);
198 }
199
200 memcpy(&mData[mSize], s, size);
201 mSize += size;
202 mData[mSize] = '\0';
203}
204
205void AString::append(const AString &from) {
206 append(from.c_str(), from.size());
207}
208
209void AString::append(const AString &from, size_t offset, size_t n) {
210 append(from.c_str() + offset, n);
211}
212
213void AString::append(int x) {
214 char s[16];
Marcus Oaklandef807642014-03-25 17:32:00 +0000215 int result = snprintf(s, sizeof(s), "%d", x);
216 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700217 append(s);
218}
219
220void AString::append(unsigned x) {
221 char s[16];
Marcus Oaklandef807642014-03-25 17:32:00 +0000222 int result = snprintf(s, sizeof(s), "%u", x);
223 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700224 append(s);
225}
226
227void AString::append(long x) {
Marcus Oaklandef807642014-03-25 17:32:00 +0000228 char s[32];
229 int result = snprintf(s, sizeof(s), "%ld", x);
230 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700231 append(s);
232}
233
234void AString::append(unsigned long x) {
Marcus Oaklandef807642014-03-25 17:32:00 +0000235 char s[32];
236 int result = snprintf(s, sizeof(s), "%lu", x);
237 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700238 append(s);
239}
240
241void AString::append(long long x) {
242 char s[32];
Marcus Oaklandef807642014-03-25 17:32:00 +0000243 int result = snprintf(s, sizeof(s), "%lld", x);
244 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700245 append(s);
246}
247
248void AString::append(unsigned long long x) {
249 char s[32];
Marcus Oaklandef807642014-03-25 17:32:00 +0000250 int result = snprintf(s, sizeof(s), "%llu", x);
251 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700252 append(s);
253}
254
255void AString::append(float x) {
256 char s[16];
Marcus Oaklandef807642014-03-25 17:32:00 +0000257 int result = snprintf(s, sizeof(s), "%f", x);
258 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700259 append(s);
260}
261
262void AString::append(double x) {
263 char s[16];
Marcus Oaklandef807642014-03-25 17:32:00 +0000264 int result = snprintf(s, sizeof(s), "%f", x);
265 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700266 append(s);
267}
268
269void AString::append(void *x) {
Marcus Oaklandef807642014-03-25 17:32:00 +0000270 char s[32];
271 int result = snprintf(s, sizeof(s), "%p", x);
272 CHECK((result > 0) && ((size_t) result) < sizeof(s));
Andreas Huber72961232010-06-07 10:18:57 -0700273 append(s);
274}
275
276ssize_t AString::find(const char *substring, size_t start) const {
277 CHECK_LE(start, size());
278
279 const char *match = strstr(mData + start, substring);
280
281 if (match == NULL) {
282 return -1;
283 }
284
285 return match - mData;
286}
287
288void AString::insert(const AString &from, size_t insertionPos) {
289 insert(from.c_str(), from.size(), insertionPos);
290}
291
292void AString::insert(const char *from, size_t size, size_t insertionPos) {
293 CHECK_GE(insertionPos, 0u);
294 CHECK_LE(insertionPos, mSize);
295
296 makeMutable();
297
298 if (mSize + size + 1 > mAllocSize) {
299 mAllocSize = (mAllocSize + size + 31) & -32;
300 mData = (char *)realloc(mData, mAllocSize);
301 CHECK(mData != NULL);
302 }
303
304 memmove(&mData[insertionPos + size],
305 &mData[insertionPos], mSize - insertionPos + 1);
306
307 memcpy(&mData[insertionPos], from, size);
308
309 mSize += size;
310}
311
312bool AString::operator<(const AString &other) const {
313 return compare(other) < 0;
314}
315
316bool AString::operator>(const AString &other) const {
317 return compare(other) > 0;
318}
319
320int AString::compare(const AString &other) const {
321 return strcmp(mData, other.mData);
322}
323
Lajos Molnar8accee42014-08-06 11:32:00 -0700324int AString::compareIgnoreCase(const AString &other) const {
325 return strcasecmp(mData, other.mData);
326}
327
328bool AString::equalsIgnoreCase(const AString &other) const {
329 return compareIgnoreCase(other) == 0;
330}
331
Andreas Huber72961232010-06-07 10:18:57 -0700332void AString::tolower() {
333 makeMutable();
334
335 for (size_t i = 0; i < mSize; ++i) {
336 mData[i] = ::tolower(mData[i]);
337 }
338}
339
340bool AString::startsWith(const char *prefix) const {
341 return !strncmp(mData, prefix, strlen(prefix));
342}
343
Andreas Hubered3e3e02012-03-26 11:13:27 -0700344bool AString::endsWith(const char *suffix) const {
345 size_t suffixLen = strlen(suffix);
346
347 if (mSize < suffixLen) {
348 return false;
349 }
350
351 return !strcmp(mData + mSize - suffixLen, suffix);
352}
353
Lajos Molnar3c1da722014-06-18 12:29:28 -0700354bool AString::startsWithIgnoreCase(const char *prefix) const {
355 return !strncasecmp(mData, prefix, strlen(prefix));
356}
357
358bool AString::endsWithIgnoreCase(const char *suffix) const {
359 size_t suffixLen = strlen(suffix);
360
361 if (mSize < suffixLen) {
362 return false;
363 }
364
365 return !strcasecmp(mData + mSize - suffixLen, suffix);
366}
367
Colin Crossf8b5fe22021-12-15 14:59:00 -0800368#if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
Lajos Molnar8accee42014-08-06 11:32:00 -0700369// static
370AString AString::FromParcel(const Parcel &parcel) {
371 size_t size = static_cast<size_t>(parcel.readInt32());
372 return AString(static_cast<const char *>(parcel.readInplace(size)), size);
373}
374
375status_t AString::writeToParcel(Parcel *parcel) const {
Sasha Levitskiy55971df2014-08-08 09:47:37 -0700376 CHECK_LE(mSize, static_cast<size_t>(INT32_MAX));
Lajos Molnar8accee42014-08-06 11:32:00 -0700377 status_t err = parcel->writeInt32(mSize);
378 if (err == OK) {
379 err = parcel->write(mData, mSize);
380 }
381 return err;
382}
Colin Crossf8b5fe22021-12-15 14:59:00 -0800383#endif // defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
Lajos Molnar8accee42014-08-06 11:32:00 -0700384
Elliott Hughesa1e89442015-02-04 11:54:28 -0800385AString AStringPrintf(const char *format, ...) {
Andreas Huber72961232010-06-07 10:18:57 -0700386 va_list ap;
387 va_start(ap, format);
388
389 char *buffer;
S Vasudev Prasadc2f146f2020-04-21 14:41:39 +0530390 int bufferSize = vasprintf(&buffer, format, ap);
Andreas Huber72961232010-06-07 10:18:57 -0700391
392 va_end(ap);
393
S Vasudev Prasadc2f146f2020-04-21 14:41:39 +0530394 if(bufferSize < 0) {
395 return AString();
396 }
397
Andreas Huber72961232010-06-07 10:18:57 -0700398 AString result(buffer);
399
400 free(buffer);
401 buffer = NULL;
402
403 return result;
404}
405
406} // namespace android
407