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 33 namespace android { 34 35 static SharedBuffer* gEmptyStringBuf = NULL; 36 static char16_t* gEmptyString = NULL; 37 38 static inline char16_t* getEmptyString() 39 { 40 gEmptyStringBuf->acquire(); 41 return gEmptyString; 42 } 43 44 void 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 53 void terminate_string16() 54 { 55 SharedBuffer::bufferFromData(gEmptyString)->release(); 56 gEmptyStringBuf = NULL; 57 gEmptyString = NULL; 58 } 59 60 // --------------------------------------------------------------------------- 61 62 static 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 94 String16::String16() 95 : mString(getEmptyString()) 96 { 97 } 98 99 String16::String16(const String16& o) 100 : mString(o.mString) 101 { 102 SharedBuffer::bufferFromData(mString)->acquire(); 103 } 104 105 String16::String16(const String16& o, size_t len, size_t begin) 106 : mString(getEmptyString()) 107 { 108 setTo(o, len, begin); 109 } 110 111 String16::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 126 String16::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 141 String16::String16(const String8& o) 142 : mString(allocFromUTF8(o.string(), o.size())) 143 { 144 } 145 146 String16::String16(const char* o) 147 : mString(allocFromUTF8(o, strlen(o))) 148 { 149 } 150 151 String16::String16(const char* o, size_t len) 152 : mString(allocFromUTF8(o, len)) 153 { 154 } 155 156 String16::~String16() 157 { 158 SharedBuffer::bufferFromData(mString)->release(); 159 } 160 161 void String16::setTo(const String16& other) 162 { 163 SharedBuffer::bufferFromData(other.mString)->acquire(); 164 SharedBuffer::bufferFromData(mString)->release(); 165 mString = other.mString; 166 } 167 168 status_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 189 status_t String16::setTo(const char16_t* other) 190 { 191 return setTo(other, strlen16(other)); 192 } 193 194 status_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 208 status_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 230 status_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 252 status_t String16::insert(size_t pos, const char16_t* chrs) 253 { 254 return insert(pos, chrs, strlen16(chrs)); 255 } 256 257 status_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 293 ssize_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 307 ssize_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 321 bool 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 328 bool 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 335 status_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 357 status_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 378 status_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 412 TextOutput& operator<<(TextOutput& to, const String16& val) 413 { 414 to << String8(val).string(); 415 return to; 416 } 417 418 }; // namespace android 419