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