1 /* 2 * Copyright (C) 2005 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 #include <utils/String16.h> 18 19 #include <utils/Debug.h> 20 #include <utils/Log.h> 21 #include <utils/Unicode.h> 22 #include <utils/String8.h> 23 #include <utils/threads.h> 24 25 #include <memory.h> 26 #include <stdio.h> 27 #include <ctype.h> 28 29 30 namespace android { 31 32 static SharedBuffer* gEmptyStringBuf = NULL; 33 static char16_t* gEmptyString = NULL; 34 35 static inline char16_t* getEmptyString() 36 { 37 gEmptyStringBuf->acquire(); 38 return gEmptyString; 39 } 40 41 void initialize_string16() 42 { 43 SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)); 44 char16_t* str = (char16_t*)buf->data(); 45 *str = 0; 46 gEmptyStringBuf = buf; 47 gEmptyString = str; 48 } 49 50 void terminate_string16() 51 { 52 SharedBuffer::bufferFromData(gEmptyString)->release(); 53 gEmptyStringBuf = NULL; 54 gEmptyString = NULL; 55 } 56 57 // --------------------------------------------------------------------------- 58 59 static char16_t* allocFromUTF8(const char* u8str, size_t u8len) 60 { 61 if (u8len == 0) return getEmptyString(); 62 63 const uint8_t* u8cur = (const uint8_t*) u8str; 64 65 const ssize_t u16len = utf8_to_utf16_length(u8cur, u8len); 66 if (u16len < 0) { 67 return getEmptyString(); 68 } 69 70 const uint8_t* const u8end = u8cur + u8len; 71 72 SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)*(u16len+1)); 73 if (buf) { 74 u8cur = (const uint8_t*) u8str; 75 char16_t* u16str = (char16_t*)buf->data(); 76 77 utf8_to_utf16(u8cur, u8len, u16str); 78 79 //printf("Created UTF-16 string from UTF-8 \"%s\":", in); 80 //printHexData(1, str, buf->size(), 16, 1); 81 //printf("\n"); 82 83 return u16str; 84 } 85 86 return getEmptyString(); 87 } 88 89 // --------------------------------------------------------------------------- 90 91 String16::String16() 92 : mString(getEmptyString()) 93 { 94 } 95 96 String16::String16(StaticLinkage) 97 : mString(0) 98 { 99 // this constructor is used when we can't rely on the static-initializers 100 // having run. In this case we always allocate an empty string. It's less 101 // efficient than using getEmptyString(), but we assume it's uncommon. 102 103 char16_t* data = static_cast<char16_t*>( 104 SharedBuffer::alloc(sizeof(char16_t))->data()); 105 data[0] = 0; 106 mString = data; 107 } 108 109 String16::String16(const String16& o) 110 : mString(o.mString) 111 { 112 SharedBuffer::bufferFromData(mString)->acquire(); 113 } 114 115 String16::String16(const String16& o, size_t len, size_t begin) 116 : mString(getEmptyString()) 117 { 118 setTo(o, len, begin); 119 } 120 121 String16::String16(const char16_t* o) 122 { 123 size_t len = strlen16(o); 124 SharedBuffer* buf = SharedBuffer::alloc((len+1)*sizeof(char16_t)); 125 ALOG_ASSERT(buf, "Unable to allocate shared buffer"); 126 if (buf) { 127 char16_t* str = (char16_t*)buf->data(); 128 strcpy16(str, o); 129 mString = str; 130 return; 131 } 132 133 mString = getEmptyString(); 134 } 135 136 String16::String16(const char16_t* o, size_t len) 137 { 138 SharedBuffer* buf = SharedBuffer::alloc((len+1)*sizeof(char16_t)); 139 ALOG_ASSERT(buf, "Unable to allocate shared buffer"); 140 if (buf) { 141 char16_t* str = (char16_t*)buf->data(); 142 memcpy(str, o, len*sizeof(char16_t)); 143 str[len] = 0; 144 mString = str; 145 return; 146 } 147 148 mString = getEmptyString(); 149 } 150 151 String16::String16(const String8& o) 152 : mString(allocFromUTF8(o.string(), o.size())) 153 { 154 } 155 156 String16::String16(const char* o) 157 : mString(allocFromUTF8(o, strlen(o))) 158 { 159 } 160 161 String16::String16(const char* o, size_t len) 162 : mString(allocFromUTF8(o, len)) 163 { 164 } 165 166 String16::~String16() 167 { 168 SharedBuffer::bufferFromData(mString)->release(); 169 } 170 171 void String16::setTo(const String16& other) 172 { 173 SharedBuffer::bufferFromData(other.mString)->acquire(); 174 SharedBuffer::bufferFromData(mString)->release(); 175 mString = other.mString; 176 } 177 178 status_t String16::setTo(const String16& other, size_t len, size_t begin) 179 { 180 const size_t N = other.size(); 181 if (begin >= N) { 182 SharedBuffer::bufferFromData(mString)->release(); 183 mString = getEmptyString(); 184 return NO_ERROR; 185 } 186 if ((begin+len) > N) len = N-begin; 187 if (begin == 0 && len == N) { 188 setTo(other); 189 return NO_ERROR; 190 } 191 192 if (&other == this) { 193 LOG_ALWAYS_FATAL("Not implemented"); 194 } 195 196 return setTo(other.string()+begin, len); 197 } 198 199 status_t String16::setTo(const char16_t* other) 200 { 201 return setTo(other, strlen16(other)); 202 } 203 204 status_t String16::setTo(const char16_t* other, size_t len) 205 { 206 SharedBuffer* buf = SharedBuffer::bufferFromData(mString) 207 ->editResize((len+1)*sizeof(char16_t)); 208 if (buf) { 209 char16_t* str = (char16_t*)buf->data(); 210 memmove(str, other, len*sizeof(char16_t)); 211 str[len] = 0; 212 mString = str; 213 return NO_ERROR; 214 } 215 return NO_MEMORY; 216 } 217 218 status_t String16::append(const String16& other) 219 { 220 const size_t myLen = size(); 221 const size_t otherLen = other.size(); 222 if (myLen == 0) { 223 setTo(other); 224 return NO_ERROR; 225 } else if (otherLen == 0) { 226 return NO_ERROR; 227 } 228 229 SharedBuffer* buf = SharedBuffer::bufferFromData(mString) 230 ->editResize((myLen+otherLen+1)*sizeof(char16_t)); 231 if (buf) { 232 char16_t* str = (char16_t*)buf->data(); 233 memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t)); 234 mString = str; 235 return NO_ERROR; 236 } 237 return NO_MEMORY; 238 } 239 240 status_t String16::append(const char16_t* chrs, size_t otherLen) 241 { 242 const size_t myLen = size(); 243 if (myLen == 0) { 244 setTo(chrs, otherLen); 245 return NO_ERROR; 246 } else if (otherLen == 0) { 247 return NO_ERROR; 248 } 249 250 SharedBuffer* buf = SharedBuffer::bufferFromData(mString) 251 ->editResize((myLen+otherLen+1)*sizeof(char16_t)); 252 if (buf) { 253 char16_t* str = (char16_t*)buf->data(); 254 memcpy(str+myLen, chrs, otherLen*sizeof(char16_t)); 255 str[myLen+otherLen] = 0; 256 mString = str; 257 return NO_ERROR; 258 } 259 return NO_MEMORY; 260 } 261 262 status_t String16::insert(size_t pos, const char16_t* chrs) 263 { 264 return insert(pos, chrs, strlen16(chrs)); 265 } 266 267 status_t String16::insert(size_t pos, const char16_t* chrs, size_t len) 268 { 269 const size_t myLen = size(); 270 if (myLen == 0) { 271 return setTo(chrs, len); 272 return NO_ERROR; 273 } else if (len == 0) { 274 return NO_ERROR; 275 } 276 277 if (pos > myLen) pos = myLen; 278 279 #if 0 280 printf("Insert in to %s: pos=%d, len=%d, myLen=%d, chrs=%s\n", 281 String8(*this).string(), pos, 282 len, myLen, String8(chrs, len).string()); 283 #endif 284 285 SharedBuffer* buf = SharedBuffer::bufferFromData(mString) 286 ->editResize((myLen+len+1)*sizeof(char16_t)); 287 if (buf) { 288 char16_t* str = (char16_t*)buf->data(); 289 if (pos < myLen) { 290 memmove(str+pos+len, str+pos, (myLen-pos)*sizeof(char16_t)); 291 } 292 memcpy(str+pos, chrs, len*sizeof(char16_t)); 293 str[myLen+len] = 0; 294 mString = str; 295 #if 0 296 printf("Result (%d chrs): %s\n", size(), String8(*this).string()); 297 #endif 298 return NO_ERROR; 299 } 300 return NO_MEMORY; 301 } 302 303 ssize_t String16::findFirst(char16_t c) const 304 { 305 const char16_t* str = string(); 306 const char16_t* p = str; 307 const char16_t* e = p + size(); 308 while (p < e) { 309 if (*p == c) { 310 return p-str; 311 } 312 p++; 313 } 314 return -1; 315 } 316 317 ssize_t String16::findLast(char16_t c) const 318 { 319 const char16_t* str = string(); 320 const char16_t* p = str; 321 const char16_t* e = p + size(); 322 while (p < e) { 323 e--; 324 if (*e == c) { 325 return e-str; 326 } 327 } 328 return -1; 329 } 330 331 bool String16::startsWith(const String16& prefix) const 332 { 333 const size_t ps = prefix.size(); 334 if (ps > size()) return false; 335 return strzcmp16(mString, ps, prefix.string(), ps) == 0; 336 } 337 338 bool String16::startsWith(const char16_t* prefix) const 339 { 340 const size_t ps = strlen16(prefix); 341 if (ps > size()) return false; 342 return strncmp16(mString, prefix, ps) == 0; 343 } 344 345 status_t String16::makeLower() 346 { 347 const size_t N = size(); 348 const char16_t* str = string(); 349 char16_t* edit = NULL; 350 for (size_t i=0; i<N; i++) { 351 const char16_t v = str[i]; 352 if (v >= 'A' && v <= 'Z') { 353 if (!edit) { 354 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit(); 355 if (!buf) { 356 return NO_MEMORY; 357 } 358 edit = (char16_t*)buf->data(); 359 mString = str = edit; 360 } 361 edit[i] = tolower((char)v); 362 } 363 } 364 return NO_ERROR; 365 } 366 367 status_t String16::replaceAll(char16_t replaceThis, char16_t withThis) 368 { 369 const size_t N = size(); 370 const char16_t* str = string(); 371 char16_t* edit = NULL; 372 for (size_t i=0; i<N; i++) { 373 if (str[i] == replaceThis) { 374 if (!edit) { 375 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit(); 376 if (!buf) { 377 return NO_MEMORY; 378 } 379 edit = (char16_t*)buf->data(); 380 mString = str = edit; 381 } 382 edit[i] = withThis; 383 } 384 } 385 return NO_ERROR; 386 } 387 388 status_t String16::remove(size_t len, size_t begin) 389 { 390 const size_t N = size(); 391 if (begin >= N) { 392 SharedBuffer::bufferFromData(mString)->release(); 393 mString = getEmptyString(); 394 return NO_ERROR; 395 } 396 if ((begin+len) > N) len = N-begin; 397 if (begin == 0 && len == N) { 398 return NO_ERROR; 399 } 400 401 if (begin > 0) { 402 SharedBuffer* buf = SharedBuffer::bufferFromData(mString) 403 ->editResize((N+1)*sizeof(char16_t)); 404 if (!buf) { 405 return NO_MEMORY; 406 } 407 char16_t* str = (char16_t*)buf->data(); 408 memmove(str, str+begin, (N-begin+1)*sizeof(char16_t)); 409 mString = str; 410 } 411 SharedBuffer* buf = SharedBuffer::bufferFromData(mString) 412 ->editResize((len+1)*sizeof(char16_t)); 413 if (buf) { 414 char16_t* str = (char16_t*)buf->data(); 415 str[len] = 0; 416 mString = str; 417 return NO_ERROR; 418 } 419 return NO_MEMORY; 420 } 421 422 }; // namespace android 423