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 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 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 89 String16::String16() 90 : mString(getEmptyString()) 91 { 92 } 93 94 String16::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 107 String16::String16(const String16& o) 108 : mString(o.mString) 109 { 110 SharedBuffer::bufferFromData(mString)->acquire(); 111 } 112 113 String16::String16(const String16& o, size_t len, size_t begin) 114 : mString(getEmptyString()) 115 { 116 setTo(o, len, begin); 117 } 118 119 String16::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 134 String16::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 149 String16::String16(const String8& o) 150 : mString(allocFromUTF8(o.string(), o.size())) 151 { 152 } 153 154 String16::String16(const char* o) 155 : mString(allocFromUTF8(o, strlen(o))) 156 { 157 } 158 159 String16::String16(const char* o, size_t len) 160 : mString(allocFromUTF8(o, len)) 161 { 162 } 163 164 String16::~String16() 165 { 166 SharedBuffer::bufferFromData(mString)->release(); 167 } 168 169 size_t String16::size() const 170 { 171 return SharedBuffer::sizeFromData(mString)/sizeof(char16_t)-1; 172 } 173 174 void String16::setTo(const String16& other) 175 { 176 SharedBuffer::bufferFromData(other.mString)->acquire(); 177 SharedBuffer::bufferFromData(mString)->release(); 178 mString = other.mString; 179 } 180 181 status_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 202 status_t String16::setTo(const char16_t* other) 203 { 204 return setTo(other, strlen16(other)); 205 } 206 207 status_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 221 status_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 243 status_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 265 status_t String16::insert(size_t pos, const char16_t* chrs) 266 { 267 return insert(pos, chrs, strlen16(chrs)); 268 } 269 270 status_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 306 ssize_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 320 ssize_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 334 bool 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 341 bool 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 348 bool String16::contains(const char16_t* chrs) const 349 { 350 return strstr16(mString, chrs) != nullptr; 351 } 352 353 status_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 375 status_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 396 status_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