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