2
* Copyright (C) 2005 The Android Open Source Project
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
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
#include <utils/String8.h>
19
#include <utils/Log.h>
20
#include <utils/Unicode.h>
21
#include <utils/SharedBuffer.h>
22
#include <utils/String16.h>
23
#include <utils/TextOutput.h>
24
#include <utils/threads.h>
26
#include <private/utils/Static.h>
31
* Functions outside android is below the namespace android, since they use
32
* functions and constants in android namespace.
35
// ---------------------------------------------------------------------------
39
// Separator used by resource paths. This is not platform dependent contrary
40
// to OS_PATH_SEPARATOR.
41
#define RES_PATH_SEPARATOR '/'
43
static SharedBuffer* gEmptyStringBuf = NULL;
44
static char* gEmptyString = NULL;
46
extern int gDarwinCantLoadAllObjects;
47
int gDarwinIsReallyAnnoying;
49
static inline char* getEmptyString()
51
gEmptyStringBuf->acquire();
55
void initialize_string8()
57
// HACK: This dummy dependency forces linking libutils Static.cpp,
58
// which is needed to initialize String8/String16 classes.
59
// These variables are named for Darwin, but are needed elsewhere too,
60
// including static linking on any platform.
61
gDarwinIsReallyAnnoying = gDarwinCantLoadAllObjects;
63
SharedBuffer* buf = SharedBuffer::alloc(1);
64
char* str = (char*)buf->data();
66
gEmptyStringBuf = buf;
70
void terminate_string8()
72
SharedBuffer::bufferFromData(gEmptyString)->release();
73
gEmptyStringBuf = NULL;
77
// ---------------------------------------------------------------------------
79
static char* allocFromUTF8(const char* in, size_t len)
82
SharedBuffer* buf = SharedBuffer::alloc(len+1);
83
ALOG_ASSERT(buf, "Unable to allocate shared buffer");
85
char* str = (char*)buf->data();
93
return getEmptyString();
96
static char* allocFromUTF16(const char16_t* in, size_t len)
98
if (len == 0) return getEmptyString();
100
const ssize_t bytes = utf16_to_utf8_length(in, len);
102
return getEmptyString();
105
SharedBuffer* buf = SharedBuffer::alloc(bytes+1);
106
ALOG_ASSERT(buf, "Unable to allocate shared buffer");
108
return getEmptyString();
111
char* str = (char*)buf->data();
112
utf16_to_utf8(in, len, str);
116
static char* allocFromUTF32(const char32_t* in, size_t len)
119
return getEmptyString();
122
const ssize_t bytes = utf32_to_utf8_length(in, len);
124
return getEmptyString();
127
SharedBuffer* buf = SharedBuffer::alloc(bytes+1);
128
ALOG_ASSERT(buf, "Unable to allocate shared buffer");
130
return getEmptyString();
133
char* str = (char*) buf->data();
134
utf32_to_utf8(in, len, str);
139
// ---------------------------------------------------------------------------
142
: mString(getEmptyString())
146
String8::String8(const String8& o)
149
SharedBuffer::bufferFromData(mString)->acquire();
152
String8::String8(const char* o)
153
: mString(allocFromUTF8(o, strlen(o)))
155
if (mString == NULL) {
156
mString = getEmptyString();
160
String8::String8(const char* o, size_t len)
161
: mString(allocFromUTF8(o, len))
163
if (mString == NULL) {
164
mString = getEmptyString();
168
String8::String8(const String16& o)
169
: mString(allocFromUTF16(o.string(), o.size()))
173
String8::String8(const char16_t* o)
174
: mString(allocFromUTF16(o, strlen16(o)))
178
String8::String8(const char16_t* o, size_t len)
179
: mString(allocFromUTF16(o, len))
183
String8::String8(const char32_t* o)
184
: mString(allocFromUTF32(o, strlen32(o)))
188
String8::String8(const char32_t* o, size_t len)
189
: mString(allocFromUTF32(o, len))
195
SharedBuffer::bufferFromData(mString)->release();
198
String8 String8::format(const char* fmt, ...)
203
String8 result(formatV(fmt, args));
209
String8 String8::formatV(const char* fmt, va_list args)
212
result.appendFormatV(fmt, args);
216
void String8::clear() {
217
SharedBuffer::bufferFromData(mString)->release();
218
mString = getEmptyString();
221
void String8::setTo(const String8& other)
223
SharedBuffer::bufferFromData(other.mString)->acquire();
224
SharedBuffer::bufferFromData(mString)->release();
225
mString = other.mString;
228
status_t String8::setTo(const char* other)
230
const char *newString = allocFromUTF8(other, strlen(other));
231
SharedBuffer::bufferFromData(mString)->release();
233
if (mString) return NO_ERROR;
235
mString = getEmptyString();
239
status_t String8::setTo(const char* other, size_t len)
241
const char *newString = allocFromUTF8(other, len);
242
SharedBuffer::bufferFromData(mString)->release();
244
if (mString) return NO_ERROR;
246
mString = getEmptyString();
250
status_t String8::setTo(const char16_t* other, size_t len)
252
const char *newString = allocFromUTF16(other, len);
253
SharedBuffer::bufferFromData(mString)->release();
255
if (mString) return NO_ERROR;
257
mString = getEmptyString();
261
status_t String8::setTo(const char32_t* other, size_t len)
263
const char *newString = allocFromUTF32(other, len);
264
SharedBuffer::bufferFromData(mString)->release();
266
if (mString) return NO_ERROR;
268
mString = getEmptyString();
272
status_t String8::append(const String8& other)
274
const size_t otherLen = other.bytes();
278
} else if (otherLen == 0) {
282
return real_append(other.string(), otherLen);
285
status_t String8::append(const char* other)
287
return append(other, strlen(other));
290
status_t String8::append(const char* other, size_t otherLen)
293
return setTo(other, otherLen);
294
} else if (otherLen == 0) {
298
return real_append(other, otherLen);
301
status_t String8::appendFormat(const char* fmt, ...)
306
status_t result = appendFormatV(fmt, args);
312
status_t String8::appendFormatV(const char* fmt, va_list args)
314
int result = NO_ERROR;
315
int n = vsnprintf(NULL, 0, fmt, args);
317
size_t oldLength = length();
318
char* buf = lockBuffer(oldLength + n);
320
vsnprintf(buf + oldLength, n + 1, fmt, args);
328
status_t String8::real_append(const char* other, size_t otherLen)
330
const size_t myLen = bytes();
332
SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
333
->editResize(myLen+otherLen+1);
335
char* str = (char*)buf->data();
338
memcpy(str, other, otherLen);
339
str[otherLen] = '\0';
345
char* String8::lockBuffer(size_t size)
347
SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
348
->editResize(size+1);
350
char* str = (char*)buf->data();
357
void String8::unlockBuffer()
359
unlockBuffer(strlen(mString));
362
status_t String8::unlockBuffer(size_t size)
364
if (size != this->size()) {
365
SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
366
->editResize(size+1);
371
char* str = (char*)buf->data();
379
ssize_t String8::find(const char* other, size_t start) const
385
const char* s = mString+start;
386
const char* p = strstr(s, other);
387
return p ? p-mString : -1;
390
void String8::toLower()
395
void String8::toLower(size_t start, size_t length)
397
const size_t len = size();
401
if (start+length > len) {
404
char* buf = lockBuffer(len);
407
*buf = tolower(*buf);
414
void String8::toUpper()
419
void String8::toUpper(size_t start, size_t length)
421
const size_t len = size();
425
if (start+length > len) {
428
char* buf = lockBuffer(len);
431
*buf = toupper(*buf);
438
size_t String8::getUtf32Length() const
440
return utf8_to_utf32_length(mString, length());
443
int32_t String8::getUtf32At(size_t index, size_t *next_index) const
445
return utf32_from_utf8_at(mString, length(), index, next_index);
448
void String8::getUtf32(char32_t* dst) const
450
utf8_to_utf32(mString, length(), dst);
453
TextOutput& operator<<(TextOutput& to, const String8& val)
459
// ---------------------------------------------------------------------------
462
void String8::setPathName(const char* name)
464
setPathName(name, strlen(name));
467
void String8::setPathName(const char* name, size_t len)
469
char* buf = lockBuffer(len);
471
memcpy(buf, name, len);
473
// remove trailing path separator, if present
474
if (len > 0 && buf[len-1] == OS_PATH_SEPARATOR)
482
String8 String8::getPathLeaf(void) const
485
const char*const buf = mString;
487
cp = strrchr(buf, OS_PATH_SEPARATOR);
489
return String8(*this);
491
return String8(cp+1);
494
String8 String8::getPathDir(void) const
497
const char*const str = mString;
499
cp = strrchr(str, OS_PATH_SEPARATOR);
503
return String8(str, cp - str);
506
String8 String8::walkPath(String8* outRemains) const
509
const char*const str = mString;
510
const char* buf = str;
512
cp = strchr(buf, OS_PATH_SEPARATOR);
514
// don't include a leading '/'.
516
cp = strchr(buf, OS_PATH_SEPARATOR);
520
String8 res = buf != str ? String8(buf) : *this;
521
if (outRemains) *outRemains = String8("");
525
String8 res(buf, cp-buf);
526
if (outRemains) *outRemains = String8(cp+1);
531
* Helper function for finding the start of an extension in a pathname.
533
* Returns a pointer inside mString, or NULL if no extension was found.
535
char* String8::find_extension(void) const
537
const char* lastSlash;
540
const char* const str = mString;
542
// only look at the filename
543
lastSlash = strrchr(str, OS_PATH_SEPARATOR);
544
if (lastSlash == NULL)
550
lastDot = strrchr(lastSlash, '.');
554
// looks good, ship it
555
return const_cast<char*>(lastDot);
558
String8 String8::getPathExtension(void) const
562
ext = find_extension();
569
String8 String8::getBasePath(void) const
572
const char* const str = mString;
574
ext = find_extension();
576
return String8(*this);
578
return String8(str, ext - str);
581
String8& String8::appendPath(const char* name)
583
// TODO: The test below will fail for Win32 paths. Fix later or ignore.
584
if (name[0] != OS_PATH_SEPARATOR) {
590
size_t len = length();
592
// no existing filename, just use the new one
597
// make room for oldPath + '/' + newPath
598
int newlen = strlen(name);
600
char* buf = lockBuffer(len+1+newlen);
602
// insert a '/' if needed
603
if (buf[len-1] != OS_PATH_SEPARATOR)
604
buf[len++] = OS_PATH_SEPARATOR;
606
memcpy(buf+len, name, newlen+1);
618
String8& String8::convertToResPath()
620
#if OS_PATH_SEPARATOR != RES_PATH_SEPARATOR
621
size_t len = length();
623
char * buf = lockBuffer(len);
624
for (char * end = buf + len; buf < end; ++buf) {
625
if (*buf == OS_PATH_SEPARATOR)
626
*buf = RES_PATH_SEPARATOR;
634
}; // namespace android