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