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