1cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project/*
2cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * Copyright (C) 2005 The Android Open Source Project
3cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project *
4cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * you may not use this file except in compliance with the License.
6cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * You may obtain a copy of the License at
7cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project *
8cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project *
10cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * See the License for the specific language governing permissions and
14cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * limitations under the License.
15cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project */
16cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
17cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project#include <utils/String8.h>
18cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
19cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project#include <utils/Log.h>
20ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root#include <utils/Unicode.h>
21ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root#include <utils/SharedBuffer.h>
22cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project#include <utils/String16.h>
23cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project#include <utils/threads.h>
24cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
25cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project#include <ctype.h>
26cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
2744dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa/*
2844dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa * Functions outside android is below the namespace android, since they use
2944dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa * functions and constants in android namespace.
3044dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa */
31cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
32cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project// ---------------------------------------------------------------------------
33cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
3444dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawanamespace android {
3544dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
36cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project// Separator used by resource paths. This is not platform dependent contrary
37cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project// to OS_PATH_SEPARATOR.
38cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project#define RES_PATH_SEPARATOR '/'
39cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
40cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatic SharedBuffer* gEmptyStringBuf = NULL;
41cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatic char* gEmptyString = NULL;
42cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
43cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectextern int gDarwinCantLoadAllObjects;
44cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectint gDarwinIsReallyAnnoying;
45cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
469eb2a3b1c0cc1ff3082a9283e24c8babc112f56bMathias Agopianvoid initialize_string8();
479eb2a3b1c0cc1ff3082a9283e24c8babc112f56bMathias Agopian
48cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatic inline char* getEmptyString()
49cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
50cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    gEmptyStringBuf->acquire();
51cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return gEmptyString;
52cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
53cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
54cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid initialize_string8()
55cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
5688753ae9d8f5432590df5e5338e0906834124c1dDan Egnor    // HACK: This dummy dependency forces linking libutils Static.cpp,
5788753ae9d8f5432590df5e5338e0906834124c1dDan Egnor    // which is needed to initialize String8/String16 classes.
5888753ae9d8f5432590df5e5338e0906834124c1dDan Egnor    // These variables are named for Darwin, but are needed elsewhere too,
5988753ae9d8f5432590df5e5338e0906834124c1dDan Egnor    // including static linking on any platform.
6088753ae9d8f5432590df5e5338e0906834124c1dDan Egnor    gDarwinIsReallyAnnoying = gDarwinCantLoadAllObjects;
6144dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
62cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer* buf = SharedBuffer::alloc(1);
63cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    char* str = (char*)buf->data();
64cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    *str = 0;
65cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    gEmptyStringBuf = buf;
66cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    gEmptyString = str;
67cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
68cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
69cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid terminate_string8()
70cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
71cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer::bufferFromData(gEmptyString)->release();
72cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    gEmptyStringBuf = NULL;
73cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    gEmptyString = NULL;
74cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
75cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
76cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project// ---------------------------------------------------------------------------
77cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
78cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatic char* allocFromUTF8(const char* in, size_t len)
79cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
80cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (len > 0) {
81cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        SharedBuffer* buf = SharedBuffer::alloc(len+1);
82ae07445e9793724324b93bb593fe20be2a386707Steve Block        ALOG_ASSERT(buf, "Unable to allocate shared buffer");
83cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        if (buf) {
84cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            char* str = (char*)buf->data();
85cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            memcpy(str, in, len);
86cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            str[len] = 0;
87cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            return str;
88cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        }
89cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return NULL;
90cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
91cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
92cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return getEmptyString();
93cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
94cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
95ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Rootstatic char* allocFromUTF16(const char16_t* in, size_t len)
96cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
97cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (len == 0) return getEmptyString();
9844dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
99ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    const ssize_t bytes = utf16_to_utf8_length(in, len);
100ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    if (bytes < 0) {
101ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root        return getEmptyString();
102cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
10344dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
104cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer* buf = SharedBuffer::alloc(bytes+1);
105ae07445e9793724324b93bb593fe20be2a386707Steve Block    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
106ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    if (!buf) {
107ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root        return getEmptyString();
108cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
10944dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
110ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    char* str = (char*)buf->data();
111ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    utf16_to_utf8(in, len, str);
112ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    return str;
113cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
114cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
115ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Rootstatic char* allocFromUTF32(const char32_t* in, size_t len)
11644dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa{
117ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    if (len == 0) {
118ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root        return getEmptyString();
119ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    }
1209a2d83e698b16ec86ad2751b6e7cf103ad645cceKenny Root
121ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    const ssize_t bytes = utf32_to_utf8_length(in, len);
122ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    if (bytes < 0) {
123ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root        return getEmptyString();
124ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    }
1259a2d83e698b16ec86ad2751b6e7cf103ad645cceKenny Root
1269a2d83e698b16ec86ad2751b6e7cf103ad645cceKenny Root    SharedBuffer* buf = SharedBuffer::alloc(bytes+1);
127ae07445e9793724324b93bb593fe20be2a386707Steve Block    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
128ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    if (!buf) {
129ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root        return getEmptyString();
1309a2d83e698b16ec86ad2751b6e7cf103ad645cceKenny Root    }
1319a2d83e698b16ec86ad2751b6e7cf103ad645cceKenny Root
132ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    char* str = (char*) buf->data();
133ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    utf32_to_utf8(in, len, str);
13444dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
135ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    return str;
13644dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa}
13744dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
138cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project// ---------------------------------------------------------------------------
139cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
140cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8::String8()
141cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    : mString(getEmptyString())
142cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
143cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
144cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
1454485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias AgopianString8::String8(StaticLinkage)
1464485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian    : mString(0)
1474485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian{
1484485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian    // this constructor is used when we can't rely on the static-initializers
1494485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian    // having run. In this case we always allocate an empty string. It's less
1504485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian    // efficient than using getEmptyString(), but we assume it's uncommon.
1514485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian
1524485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian    char* data = static_cast<char*>(
1534485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian            SharedBuffer::alloc(sizeof(char))->data());
1544485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian    data[0] = 0;
1554485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian    mString = data;
1564485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian}
1574485d0d966d062d1b45b635e2447a2d2f96c3f38Mathias Agopian
158cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8::String8(const String8& o)
159cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    : mString(o.mString)
160cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
161cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer::bufferFromData(mString)->acquire();
162cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
163cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
164cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8::String8(const char* o)
165cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    : mString(allocFromUTF8(o, strlen(o)))
166cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
167cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (mString == NULL) {
168cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        mString = getEmptyString();
169cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
170cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
171cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
172cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8::String8(const char* o, size_t len)
173cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    : mString(allocFromUTF8(o, len))
174cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
175cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (mString == NULL) {
176cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        mString = getEmptyString();
177cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
178cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
179cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
180cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8::String8(const String16& o)
181cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    : mString(allocFromUTF16(o.string(), o.size()))
182cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
183cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
184cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
185cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8::String8(const char16_t* o)
186cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    : mString(allocFromUTF16(o, strlen16(o)))
187cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
188cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
189cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
190cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8::String8(const char16_t* o, size_t len)
191cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    : mString(allocFromUTF16(o, len))
192cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
193cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
194cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
19544dad3e006e0a966d93473dde3d74b2b43555519Daisuke MiyakawaString8::String8(const char32_t* o)
19644dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa    : mString(allocFromUTF32(o, strlen32(o)))
19744dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa{
19844dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa}
19944dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
20044dad3e006e0a966d93473dde3d74b2b43555519Daisuke MiyakawaString8::String8(const char32_t* o, size_t len)
20144dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa    : mString(allocFromUTF32(o, len))
20244dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa{
20344dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa}
20444dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
205cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8::~String8()
206cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
207cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer::bufferFromData(mString)->release();
208cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
209cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
2101d618d63c1bb99728b5b0afe320f5a6afa95436cJeff BrownString8 String8::format(const char* fmt, ...)
2111d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown{
2121d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown    va_list args;
2131d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown    va_start(args, fmt);
2141d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown
2151d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown    String8 result(formatV(fmt, args));
2161d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown
2171d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown    va_end(args);
2181d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown    return result;
2191d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown}
2201d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown
2211d618d63c1bb99728b5b0afe320f5a6afa95436cJeff BrownString8 String8::formatV(const char* fmt, va_list args)
2221d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown{
2231d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown    String8 result;
2241d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown    result.appendFormatV(fmt, args);
2251d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown    return result;
2261d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown}
2271d618d63c1bb99728b5b0afe320f5a6afa95436cJeff Brown
22848da31b735ebbc6a00c4e9fe9631f4af79e2c9dfJeff Brownvoid String8::clear() {
22948da31b735ebbc6a00c4e9fe9631f4af79e2c9dfJeff Brown    SharedBuffer::bufferFromData(mString)->release();
23048da31b735ebbc6a00c4e9fe9631f4af79e2c9dfJeff Brown    mString = getEmptyString();
23148da31b735ebbc6a00c4e9fe9631f4af79e2c9dfJeff Brown}
23248da31b735ebbc6a00c4e9fe9631f4af79e2c9dfJeff Brown
233cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid String8::setTo(const String8& other)
234cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
235cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer::bufferFromData(other.mString)->acquire();
236cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer::bufferFromData(mString)->release();
237cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    mString = other.mString;
238cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
239cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
240cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatus_t String8::setTo(const char* other)
241cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
24210e5da58e4c22f2262f7ec7f82745d9673bed14bAndreas Huber    const char *newString = allocFromUTF8(other, strlen(other));
243cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer::bufferFromData(mString)->release();
24410e5da58e4c22f2262f7ec7f82745d9673bed14bAndreas Huber    mString = newString;
245cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (mString) return NO_ERROR;
246cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
247cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    mString = getEmptyString();
248cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return NO_MEMORY;
249cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
250cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
251cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatus_t String8::setTo(const char* other, size_t len)
252cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
25310e5da58e4c22f2262f7ec7f82745d9673bed14bAndreas Huber    const char *newString = allocFromUTF8(other, len);
254cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer::bufferFromData(mString)->release();
25510e5da58e4c22f2262f7ec7f82745d9673bed14bAndreas Huber    mString = newString;
256cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (mString) return NO_ERROR;
257cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
258cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    mString = getEmptyString();
259cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return NO_MEMORY;
260cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
261cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
262cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatus_t String8::setTo(const char16_t* other, size_t len)
263cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
26410e5da58e4c22f2262f7ec7f82745d9673bed14bAndreas Huber    const char *newString = allocFromUTF16(other, len);
265cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer::bufferFromData(mString)->release();
26610e5da58e4c22f2262f7ec7f82745d9673bed14bAndreas Huber    mString = newString;
267cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (mString) return NO_ERROR;
268cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
269cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    mString = getEmptyString();
270cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return NO_MEMORY;
271cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
272cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
27344dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawastatus_t String8::setTo(const char32_t* other, size_t len)
27444dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa{
27510e5da58e4c22f2262f7ec7f82745d9673bed14bAndreas Huber    const char *newString = allocFromUTF32(other, len);
27644dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa    SharedBuffer::bufferFromData(mString)->release();
27710e5da58e4c22f2262f7ec7f82745d9673bed14bAndreas Huber    mString = newString;
27844dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa    if (mString) return NO_ERROR;
27944dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
28044dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa    mString = getEmptyString();
28144dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa    return NO_MEMORY;
28244dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa}
28344dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
284cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatus_t String8::append(const String8& other)
285cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
286cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const size_t otherLen = other.bytes();
287cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (bytes() == 0) {
288cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        setTo(other);
289cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return NO_ERROR;
290cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    } else if (otherLen == 0) {
291cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return NO_ERROR;
292cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
293cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
294cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return real_append(other.string(), otherLen);
295cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
296cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
297cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatus_t String8::append(const char* other)
298cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
299cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return append(other, strlen(other));
300cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
301cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
302cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatus_t String8::append(const char* other, size_t otherLen)
303cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
304cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (bytes() == 0) {
305cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return setTo(other, otherLen);
306cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    } else if (otherLen == 0) {
307cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return NO_ERROR;
308cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
309cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
310cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return real_append(other, otherLen);
311cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
312cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
31335a154e57f2f59722de580395ccd5172e44842cbJeff Brownstatus_t String8::appendFormat(const char* fmt, ...)
31435a154e57f2f59722de580395ccd5172e44842cbJeff Brown{
315647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown    va_list args;
316647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown    va_start(args, fmt);
31735a154e57f2f59722de580395ccd5172e44842cbJeff Brown
318647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown    status_t result = appendFormatV(fmt, args);
319647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown
320647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown    va_end(args);
321647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown    return result;
322647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown}
323647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown
324647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brownstatus_t String8::appendFormatV(const char* fmt, va_list args)
325647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown{
326fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin    int n, result = NO_ERROR;
327fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin    va_list tmp_args;
328fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin
329fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin    /* args is undefined after vsnprintf.
330fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin     * So we need a copy here to avoid the
331fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin     * second vsnprintf access undefined args.
332fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin     */
333fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin    va_copy(tmp_args, args);
334fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin    n = vsnprintf(NULL, 0, fmt, tmp_args);
335fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin    va_end(tmp_args);
336fff9d11be528ad8f581cc7223b879c55009d7396Fengwei Yin
33735a154e57f2f59722de580395ccd5172e44842cbJeff Brown    if (n != 0) {
33835a154e57f2f59722de580395ccd5172e44842cbJeff Brown        size_t oldLength = length();
33935a154e57f2f59722de580395ccd5172e44842cbJeff Brown        char* buf = lockBuffer(oldLength + n);
34035a154e57f2f59722de580395ccd5172e44842cbJeff Brown        if (buf) {
341647925ddf053989b641b4c5c8a51efd55c931f22Jeff Brown            vsnprintf(buf + oldLength, n + 1, fmt, args);
34235a154e57f2f59722de580395ccd5172e44842cbJeff Brown        } else {
34335a154e57f2f59722de580395ccd5172e44842cbJeff Brown            result = NO_MEMORY;
34435a154e57f2f59722de580395ccd5172e44842cbJeff Brown        }
34535a154e57f2f59722de580395ccd5172e44842cbJeff Brown    }
34635a154e57f2f59722de580395ccd5172e44842cbJeff Brown    return result;
34735a154e57f2f59722de580395ccd5172e44842cbJeff Brown}
34835a154e57f2f59722de580395ccd5172e44842cbJeff Brown
349cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatus_t String8::real_append(const char* other, size_t otherLen)
350cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
351cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const size_t myLen = bytes();
352cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
353cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
354cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        ->editResize(myLen+otherLen+1);
355cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (buf) {
356cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        char* str = (char*)buf->data();
357cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        mString = str;
358cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        str += myLen;
359cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        memcpy(str, other, otherLen);
360cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        str[otherLen] = '\0';
361cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return NO_ERROR;
362cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
363cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return NO_MEMORY;
364cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
365cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
366cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectchar* String8::lockBuffer(size_t size)
367cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
368cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
369cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        ->editResize(size+1);
370cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (buf) {
371cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        char* str = (char*)buf->data();
372cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        mString = str;
373cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return str;
374cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
375cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return NULL;
376cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
377cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
378cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid String8::unlockBuffer()
379cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
380cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    unlockBuffer(strlen(mString));
381cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
382cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
383cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectstatus_t String8::unlockBuffer(size_t size)
384cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
385cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (size != this->size()) {
386cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
387cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            ->editResize(size+1);
38835a154e57f2f59722de580395ccd5172e44842cbJeff Brown        if (! buf) {
38935a154e57f2f59722de580395ccd5172e44842cbJeff Brown            return NO_MEMORY;
390cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        }
39135a154e57f2f59722de580395ccd5172e44842cbJeff Brown
39235a154e57f2f59722de580395ccd5172e44842cbJeff Brown        char* str = (char*)buf->data();
39335a154e57f2f59722de580395ccd5172e44842cbJeff Brown        str[size] = 0;
39435a154e57f2f59722de580395ccd5172e44842cbJeff Brown        mString = str;
395cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
39635a154e57f2f59722de580395ccd5172e44842cbJeff Brown
39735a154e57f2f59722de580395ccd5172e44842cbJeff Brown    return NO_ERROR;
398cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
399cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
400cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectssize_t String8::find(const char* other, size_t start) const
401cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
402cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    size_t len = size();
403cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (start >= len) {
404cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return -1;
405cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
406cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* s = mString+start;
407cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* p = strstr(s, other);
408cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return p ? p-mString : -1;
409cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
410cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
4115ee915afe17b7190f992addc48cb53ed6371a68dJeff Brownbool String8::removeAll(const char* other) {
4125ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    ssize_t index = find(other);
4135ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    if (index < 0) return false;
4145ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown
4155ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    char* buf = lockBuffer(size());
4165ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    if (!buf) return false; // out of memory
4175ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown
4185ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    size_t skip = strlen(other);
4195ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    size_t len = size();
4205ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    size_t tail = index;
4215ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    while (size_t(index) < len) {
4225ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown        ssize_t next = find(other, index + skip);
4235ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown        if (next < 0) {
4245ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown            next = len;
4255ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown        }
4265ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown
4275ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown        memcpy(buf + tail, buf + index + skip, next - index - skip);
4285ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown        tail += next - index - skip;
4295ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown        index = next;
4305ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    }
4315ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    unlockBuffer(tail);
4325ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown    return true;
4335ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown}
4345ee915afe17b7190f992addc48cb53ed6371a68dJeff Brown
435cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid String8::toLower()
436cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
437cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    toLower(0, size());
438cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
439cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
440cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid String8::toLower(size_t start, size_t length)
441cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
442cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const size_t len = size();
443cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (start >= len) {
444cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return;
445cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
446cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (start+length > len) {
447cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        length = len-start;
448cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
449cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    char* buf = lockBuffer(len);
450cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    buf += start;
451cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    while (length > 0) {
452cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        *buf = tolower(*buf);
453cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        buf++;
454cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        length--;
455cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
456cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    unlockBuffer(len);
457cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
458cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
459cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid String8::toUpper()
460cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
461cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    toUpper(0, size());
462cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
463cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
464cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid String8::toUpper(size_t start, size_t length)
465cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
466cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const size_t len = size();
467cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (start >= len) {
468cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return;
469cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
470cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (start+length > len) {
471cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        length = len-start;
472cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
473cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    char* buf = lockBuffer(len);
474cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    buf += start;
475cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    while (length > 0) {
476cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        *buf = toupper(*buf);
477cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        buf++;
478cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        length--;
479cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
480cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    unlockBuffer(len);
481cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
482cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
48344dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawasize_t String8::getUtf32Length() const
48444dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa{
485ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    return utf8_to_utf32_length(mString, length());
48644dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa}
48744dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
48844dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawaint32_t String8::getUtf32At(size_t index, size_t *next_index) const
48944dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa{
490ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    return utf32_from_utf8_at(mString, length(), index, next_index);
49144dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa}
49244dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
493ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Rootvoid String8::getUtf32(char32_t* dst) const
49444dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa{
495ba0165bef09729a33ab8e0ca329342be05e0d859Kenny Root    utf8_to_utf32(mString, length(), dst);
49644dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa}
49744dad3e006e0a966d93473dde3d74b2b43555519Daisuke Miyakawa
498cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project// ---------------------------------------------------------------------------
499cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project// Path functions
500cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
501cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid String8::setPathName(const char* name)
502cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
503cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    setPathName(name, strlen(name));
504cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
505cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
506cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectvoid String8::setPathName(const char* name, size_t len)
507cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
508cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    char* buf = lockBuffer(len);
509cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
510cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    memcpy(buf, name, len);
511cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
512cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    // remove trailing path separator, if present
513cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (len > 0 && buf[len-1] == OS_PATH_SEPARATOR)
514cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        len--;
515cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
516cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    buf[len] = '\0';
517cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
518cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    unlockBuffer(len);
519cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
520cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
521cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8 String8::getPathLeaf(void) const
522cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
523cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* cp;
524cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char*const buf = mString;
525cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
526cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    cp = strrchr(buf, OS_PATH_SEPARATOR);
527cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (cp == NULL)
528cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return String8(*this);
529cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    else
530cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return String8(cp+1);
531cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
532cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
533cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8 String8::getPathDir(void) const
534cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
535cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* cp;
536cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char*const str = mString;
537cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
538cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    cp = strrchr(str, OS_PATH_SEPARATOR);
539cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (cp == NULL)
540cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return String8("");
541cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    else
542cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return String8(str, cp - str);
543cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
544cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
545cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8 String8::walkPath(String8* outRemains) const
546cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
547cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* cp;
548cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char*const str = mString;
549cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* buf = str;
550cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
551cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    cp = strchr(buf, OS_PATH_SEPARATOR);
552cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (cp == buf) {
553cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        // don't include a leading '/'.
554cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        buf = buf+1;
555cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        cp = strchr(buf, OS_PATH_SEPARATOR);
556cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
557cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
558cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (cp == NULL) {
559cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        String8 res = buf != str ? String8(buf) : *this;
560cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        if (outRemains) *outRemains = String8("");
561cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return res;
562cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
563cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
564cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    String8 res(buf, cp-buf);
565cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (outRemains) *outRemains = String8(cp+1);
566cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return res;
567cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
568cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
569cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project/*
570cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * Helper function for finding the start of an extension in a pathname.
571cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project *
572cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project * Returns a pointer inside mString, or NULL if no extension was found.
573cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project */
574cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Projectchar* String8::find_extension(void) const
575cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
576cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* lastSlash;
577cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* lastDot;
578cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* const str = mString;
579cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
580cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    // only look at the filename
581cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    lastSlash = strrchr(str, OS_PATH_SEPARATOR);
582cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (lastSlash == NULL)
583cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        lastSlash = str;
584cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    else
585cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        lastSlash++;
586cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
587cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    // find the last dot
588cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    lastDot = strrchr(lastSlash, '.');
589cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (lastDot == NULL)
590cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return NULL;
591cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
592cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    // looks good, ship it
593cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return const_cast<char*>(lastDot);
594cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
595cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
596cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8 String8::getPathExtension(void) const
597cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
598cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    char* ext;
599cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
600cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    ext = find_extension();
601cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (ext != NULL)
602cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return String8(ext);
603cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    else
604cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return String8("");
605cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
606cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
607cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8 String8::getBasePath(void) const
608cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
609cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    char* ext;
610cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    const char* const str = mString;
611cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
612cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    ext = find_extension();
613cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (ext == NULL)
614cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return String8(*this);
615cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    else
616cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return String8(str, ext - str);
617cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
618cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
619cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8& String8::appendPath(const char* name)
620cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
621cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    // TODO: The test below will fail for Win32 paths. Fix later or ignore.
622cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (name[0] != OS_PATH_SEPARATOR) {
623cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        if (*name == '\0') {
624cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            // nothing to do
625cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            return *this;
626cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        }
627cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
628cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        size_t len = length();
629cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        if (len == 0) {
630cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            // no existing filename, just use the new one
631cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            setPathName(name);
632cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            return *this;
633cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        }
634cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
635cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        // make room for oldPath + '/' + newPath
636cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        int newlen = strlen(name);
637cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
638cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        char* buf = lockBuffer(len+1+newlen);
639cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
640cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        // insert a '/' if needed
641cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        if (buf[len-1] != OS_PATH_SEPARATOR)
642cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            buf[len++] = OS_PATH_SEPARATOR;
643cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
644cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        memcpy(buf+len, name, newlen+1);
645cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        len += newlen;
646cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
647cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        unlockBuffer(len);
648cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
649cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return *this;
650cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    } else {
651cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        setPathName(name);
652cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        return *this;
653cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
654cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
655cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
656cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source ProjectString8& String8::convertToResPath()
657cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project{
658cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project#if OS_PATH_SEPARATOR != RES_PATH_SEPARATOR
659cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    size_t len = length();
660cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    if (len > 0) {
661cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        char * buf = lockBuffer(len);
662cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        for (char * end = buf + len; buf < end; ++buf) {
663cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project            if (*buf == OS_PATH_SEPARATOR)
664cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project                *buf = RES_PATH_SEPARATOR;
665cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        }
666cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project        unlockBuffer(len);
667cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    }
668cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project#endif
669cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project    return *this;
670cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}
671cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project
672cbb1011c95e0c25c29e40e203a6a31bccd029da3The Android Open Source Project}; // namespace android
673