1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "util/string.h" 17 18#include <atomic> 19#include <cctype> 20#include <cstddef> 21#include <cstdio> 22#include <cstdlib> 23#include <cstring> 24#include <new> 25 26#include "securec.h" 27#include "util/logger.h" 28#include "util/string_builder.h" 29 30namespace OHOS { 31namespace Idl { 32constexpr int LINE_MAX_SIZE = 1024; 33 34using SharedData = struct SharedData { 35 SharedData(int refCount, int size) 36 : refCount_(refCount), shareDataSize(size) 37 {} 38 39 static SharedData* Allocate(int size); 40 41 static void AddRef(const void* handle); 42 43 static void Release(const void* handle); 44 45 static char* ToString(SharedData* header) 46 { 47 return reinterpret_cast<char*>(header + 1); 48 } 49 50 static SharedData* GetHeader(const void* handle) 51 { 52 return reinterpret_cast<SharedData*>(const_cast<void*>(handle)) - 1; 53 } 54 55 std::atomic<int> refCount_; 56 int shareDataSize; 57}; 58 59SharedData* SharedData::Allocate(int size) 60{ 61 if (size < 0) { 62 Logger::E(String::TAG, "Size %d is illegal.", size); 63 return nullptr; 64 } 65 if (size > String::MAX_SIZE) { 66 Logger::E(String::TAG, "The string is too large to alloc."); 67 return nullptr; 68 } 69 70 SharedData* handle = reinterpret_cast<SharedData*>(malloc(sizeof(SharedData) + size + 1)); 71 if (handle == nullptr) { 72 Logger::E(String::TAG, "Fail to malloc %lu bytes memory", size); 73 return handle; 74 } 75 76 new (handle)SharedData(1, size); 77 return handle; 78} 79 80void SharedData::AddRef(const void* handle) 81{ 82 if (handle == nullptr) { 83 return; 84 } 85 86 SharedData* data = GetHeader(handle); 87 int before = data->refCount_.fetch_add(1); 88 if (before + 1 <= 1) { 89 Logger::E(String::TAG, "The refCount is error in AddRef."); 90 }; 91} 92 93void SharedData::Release(const void* handle) 94{ 95 if (handle == nullptr) { 96 return; 97 } 98 99 SharedData* data = GetHeader(handle); 100 int before = data->refCount_.fetch_sub(1); 101 if (before - 1 == 0) { 102 free(data); 103 } else if (before - 1 < 0) { 104 Logger::E(String::TAG, "The refCount is error in Release."); 105 }; 106} 107 108 109const char* String::TAG = "String"; 110 111String::String(const char* string) 112{ 113 if (string != nullptr) { 114 string_ = SharedData::ToString(SharedData::Allocate(strlen(string))); 115 if (string_ != nullptr) { 116 errno_t ret = strcpy_s(string_, strlen(string) + 1, string); 117 if (ret != EOK) { 118 Logger::E(String::TAG, "The String::String is error in strcpy_s."); 119 } 120 } 121 } 122} 123 124String::String(const char* string, size_t length) 125{ 126 if (string != nullptr) { 127 SharedData* sharedData = SharedData::Allocate(length); 128 if (sharedData == nullptr) { 129 return; 130 } 131 string_ = SharedData::ToString(sharedData); 132 if (string_ != nullptr) { 133 errno_t ret = memcpy_s(string_, length + 1, string, length); 134 if (ret == EOK) { 135 string_[length] = '\0'; 136 } else { 137 free(sharedData); 138 string_ = nullptr; 139 } 140 } 141 } 142} 143 144String::String(const String& other) 145{ 146 string_ = other.string_; 147 SharedData::AddRef(string_); 148} 149 150String::String(String&& other) 151{ 152 string_ = other.string_; 153 other.string_ = nullptr; 154} 155 156String::String(int size) 157{ 158 string_ = SharedData::ToString(SharedData::Allocate(size)); 159 if (string_ != nullptr) { 160 (void)memset_s(string_, size + 1, 0, size + 1); 161 } 162} 163 164String::~String() 165{ 166 SharedData::Release(string_); 167} 168 169int String::GetLength() const 170{ 171 if (string_ == nullptr) { 172 return 0; 173 } 174 175 return SharedData::GetHeader(string_)->shareDataSize; 176} 177 178char String::operator[](int index) const 179{ 180 if (index < 0 || index >= GetLength()) { 181 return '\0'; 182 } 183 return string_[index]; 184} 185 186bool String::Equals(const char* string) const 187{ 188 if (string_ == nullptr && string == nullptr) { 189 return true; 190 } 191 192 if (string != nullptr && string_ != nullptr) { 193 if ((size_t)GetLength() != strlen(string)) { 194 return false; 195 } 196 return strcmp(string, string_) == 0; 197 } 198 199 return false; 200} 201 202bool String::Equals(const String& other) const 203{ 204 if (string_ == nullptr && other.string_ == nullptr) { 205 return true; 206 } 207 208 if (string_ != nullptr && other.string_ != nullptr) { 209 if (GetLength() != other.GetLength()) { 210 return false; 211 } 212 return strcmp(string_, other.string_) == 0; 213 } 214 return false; 215} 216 217int String::GetHashCode() const 218{ 219 // BKDR Hash Function 220 unsigned int seed = 31; // 31 131 1313 13131 131313 etc.. 221 unsigned int hash = 0; 222 223 const char* string = string_; 224 if (string != nullptr) { 225 for (; *string; ++string) { 226 hash = hash * seed + (*string); 227 } 228 } 229 return (hash & 0x7FFFFFFF); 230} 231 232int String::IndexOf(char c, int fromIndex) const 233{ 234 if (IsEmpty() || c == '\0') { 235 return -1; 236 } 237 238 if (fromIndex < 0) { 239 fromIndex = 0; 240 } else if (fromIndex >= GetLength()) { 241 return -1; 242 } 243 244 char* p = string_ + fromIndex; 245 char* end = string_ + GetLength(); 246 while (p != end) { 247 if (*p == c) { 248 return p - string_; 249 } 250 p++; 251 } 252 return -1; 253} 254 255int String::IndexOf(const char* string, int fromIndex) const 256{ 257 if (IsEmpty() || string == nullptr || string[0] == '\0') { 258 return -1; 259 } 260 261 if (fromIndex < 0) { 262 fromIndex = 0; 263 } else if (fromIndex >= GetLength()) { 264 return -1; 265 } 266 267 char* c = strstr(string_ + fromIndex, string); 268 return c != nullptr ? c - string_ : -1; 269} 270 271int String::IndexOf(const String& other, int fromIndex) const 272{ 273 if (IsEmpty() || other.IsEmpty()) { 274 return -1; 275 } 276 277 if (fromIndex < 0) { 278 fromIndex = 0; 279 } else if (fromIndex >= GetLength()) { 280 return -1; 281 } 282 283 char* c = strstr(string_ + fromIndex, other.string_); 284 return c != nullptr ? c - string_ : -1; 285} 286 287int String::LastIndexOf(char c, int fromIndex) const 288{ 289 if (IsEmpty() || c == '\0') { 290 return -1; 291 } 292 293 if (fromIndex < 0) { 294 return -1; 295 } else if (fromIndex == 0 || fromIndex >= GetLength()) { 296 fromIndex = GetLength() - 1; 297 } 298 char* p = string_ + fromIndex; 299 while (p != string_) { 300 if (*p == c) { 301 return p - string_; 302 } 303 p--; 304 } 305 return -1; 306} 307 308int String::LastIndexOf(const char* string, int fromIndex) const 309{ 310 if (IsEmpty() || string == nullptr || string[0] == '\0') { 311 return -1; 312 } 313 314 if (fromIndex < 0) { 315 return -1; 316 } else if (fromIndex == 0 || fromIndex >= GetLength()) { 317 fromIndex = GetLength() - 1; 318 } 319 320 return LastIndexOfInternal(string, fromIndex); 321} 322 323int String::LastIndexOf(const String& other, int fromIndex) const 324{ 325 if (IsEmpty() || other.IsEmpty()) { 326 return -1; 327 } 328 329 if (fromIndex < 0) { 330 return -1; 331 } else if (fromIndex == 0 || fromIndex >= GetLength()) { 332 fromIndex = GetLength() - 1; 333 } 334 335 return LastIndexOfInternal(other.string(), fromIndex); 336} 337 338int String::LastIndexOfInternal(const char* string, int fromIndex) const 339{ 340 int sourceLen = GetLength(); 341 int stringLen = strlen(string); 342 int rightIndex = sourceLen - stringLen; 343 if (fromIndex > rightIndex) { 344 fromIndex = rightIndex; 345 } 346 347 int stringLastIndex = stringLen - 1; 348 char stringLastChar = string[stringLastIndex]; 349 int min = stringLen - 1; 350 int i = min + fromIndex; 351 352startSearchLastChar: 353 while (true) { 354 while (i >= min && string_[i] != stringLastChar) { 355 i--; 356 } 357 if (i < min) { 358 return -1; 359 } 360 int j = i - 1; 361 int start = j - (stringLen - 1); 362 int k = stringLastIndex - 1; 363 364 while (j > start) { 365 if (string_[j--] != string[k--]) { 366 i--; 367 goto startSearchLastChar; 368 } 369 } 370 return start + 1; 371 } 372} 373 374bool String::StartsWith(const char* string) const 375{ 376 if (string == nullptr || string_ == nullptr) { 377 return false; 378 } 379 380 if (string[0] == '\0' && string_[0] == '\0') { 381 return true; 382 } 383 384 size_t count = strlen(string); 385 if (count > (size_t)GetLength()) { 386 return false; 387 } 388 389 return memcmp(string_, string, count) == 0; 390} 391 392bool String::StartsWith(const String& other) const 393{ 394 if (other.string_ == nullptr || string_ == nullptr) { 395 return false; 396 } 397 398 if (other.string_[0] == '\0' && string_[0] == '\0') { 399 return true; 400 } 401 402 int count = other.GetLength(); 403 if (count > GetLength()) { 404 return false; 405 } 406 407 return memcmp(string_, other.string_, count) == 0; 408} 409 410bool String::EndsWith(const char* string) const 411{ 412 if (string == nullptr || string_ == nullptr) { 413 return false; 414 } 415 416 if (string[0] == '\0') { 417 return true; 418 } 419 420 size_t count = strlen(string); 421 size_t len = static_cast<size_t>(GetLength()); 422 if (count > len) { 423 return false; 424 } 425 426 return memcmp(string_ + len - count, string, count) == 0; 427} 428 429bool String::EndsWith(const String& other) const 430{ 431 if (other.string_ == nullptr || string_ == nullptr) { 432 return false; 433 } 434 435 if (other.string_[0] == '\0') { 436 return true; 437 } 438 439 int count = other.GetLength(); 440 int len = GetLength(); 441 if (count > len) { 442 return false; 443 } 444 445 return memcmp(string_ + len - count, other.string_, count) == 0; 446} 447 448String String::ToLowerCase() const 449{ 450 if (IsEmpty()) { 451 return *this; 452 } 453 454 int size = GetLength(); 455 for (int i = 0; i < size; i++) { 456 if (isupper(string_[i])) { 457 String newStr(string_); 458 for (int j = i; j < size; j++) { 459 newStr.string_[j] = tolower(newStr.string_[j]); 460 } 461 return newStr; 462 } 463 } 464 return *this; 465} 466 467String String::ToUpperCase() const 468{ 469 if (IsEmpty()) { 470 return *this; 471 } 472 473 int size = GetLength(); 474 for (int i = 0; i < size; i++) { 475 if (islower(string_[i])) { 476 String newStr(string_); 477 for (int j = i; j < size; j++) { 478 newStr.string_[j] = toupper(newStr.string_[j]); 479 } 480 return newStr; 481 } 482 } 483 return *this; 484} 485 486String String::Substring(int begin) const 487{ 488 if (begin < 0 || begin >= GetLength()) { 489 return String(); 490 } 491 492 return String(string_ + begin); 493} 494 495String String::Substring(int begin, int end) const 496{ 497 if (begin < 0 || end > GetLength() || begin > end) { 498 return String(); 499 } 500 501 return String(string_ + begin, end - begin); 502} 503 504String String::Replace(char oldChar, char newChar) const 505{ 506 if (oldChar == newChar) { 507 return *this; 508 } 509 510 int size = GetLength(); 511 for (int i = 0; i < size; i++) { 512 if (string_[i] != oldChar) { 513 continue; 514 } 515 String newStr(string_); 516 for (int j = i; j < size; j++) { 517 if (newStr.string_[j] == oldChar) { 518 newStr.string_[j] = newChar; 519 } 520 } 521 return newStr; 522 } 523 return *this; 524} 525 526String String::Replace(const char* target, const char* replacement) const 527{ 528 if (target == nullptr || target[0] == '\0' || replacement == nullptr) { 529 return *this; 530 } 531 532 int index = IndexOf(target); 533 if (index == -1) { 534 return *this; 535 } 536 537 StringBuilder sb; 538 int begin = 0; 539 int step = strlen(target); 540 while (index != -1) { 541 sb.Append(Substring(begin, index)); 542 sb.Append(replacement); 543 begin = index + step; 544 index = IndexOf(target, begin); 545 } 546 sb.Append(Substring(begin)); 547 return sb.ToString(); 548} 549 550String String::Replace(const String& target, const String& replacement) const 551{ 552 if (target.IsEmpty() || replacement.IsNull()) { 553 return *this; 554 } 555 556 int index = IndexOf(target); 557 if (index== -1) { 558 return *this; 559 } 560 561 StringBuilder sb; 562 int begin = 0; 563 int step = target.GetLength(); 564 while (index != -1) { 565 sb.Append(Substring(begin, index)); 566 sb.Append(replacement); 567 begin = index + step; 568 index = IndexOf(target, begin); 569 } 570 sb.Append(Substring(begin)); 571 return sb.ToString(); 572} 573 574String& String::operator=(const char* string) 575{ 576 SharedData::Release(string_); 577 578 if (string == nullptr) { 579 string_ = nullptr; 580 return *this; 581 } 582 583 string_ = SharedData::ToString(SharedData::Allocate(strlen(string))); 584 if (string_ != nullptr) { 585 errno_t ret = strcpy_s(string_, strlen(string) + 1, string); 586 if (ret != EOK) { 587 Logger::E(String::TAG, "The operator= is error in strcpy_s."); 588 } 589 } 590 return *this; 591} 592 593String& String::operator=(const String& other) 594{ 595 if (string_ == other.string_) { 596 return *this; 597 } 598 599 SharedData::Release(string_); 600 SharedData::AddRef(other.string_); 601 string_ = other.string_; 602 return *this; 603} 604 605String& String::operator=(String&& other) 606{ 607 SharedData::Release(string_); 608 string_ = other.string_; 609 other.string_ = nullptr; 610 return *this; 611} 612 613String String::operator+=(const char* string) const 614{ 615 if (string == nullptr || string[0] == '\0') { 616 return *this; 617 } 618 619 int thisSize = GetLength(); 620 int newSize = thisSize + strlen(string); 621 String newString(newSize); 622 if (newString.string_ != nullptr) { 623 errno_t retMem = memcpy_s(newString.string_, newSize + 1, string_, thisSize); 624 if (retMem != EOK) { 625 Logger::E(String::TAG, "The operator+= char* is error in memcpy_s."); 626 } 627 errno_t ret = strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, string); 628 if (ret != EOK) { 629 Logger::E(String::TAG, "The operator+= char* is error in strcpy_s."); 630 } 631 } 632 return newString; 633} 634 635String String::operator+=(const String& other) const 636{ 637 if (other.IsEmpty()) { 638 return *this; 639 } 640 641 int thisSize = GetLength(); 642 int newSize = thisSize + other.GetLength(); 643 String newString(newSize); 644 if (newString.string_ != nullptr) { 645 (void)memcpy_s(newString.string_, newSize + 1, string_, thisSize); 646 errno_t ret = strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other.string_); 647 if (ret != EOK) { 648 Logger::E(String::TAG, "The operator+= is error in strcpy_s."); 649 } 650 } 651 return newString; 652} 653 654String String::Format(const char* format, ...) 655{ 656 va_list args, argsCopy; 657 658 va_start(args, format); 659 va_copy(argsCopy, args); 660 661 char buf[LINE_MAX_SIZE] = {0}; 662 int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args); 663 String string; 664 if (len <= 0) { 665 va_end(args); 666 va_end(argsCopy); 667 return string; 668 } 669 670 string = String(len); 671 if (string.string_ == nullptr) { 672 va_end(args); 673 va_end(argsCopy); 674 return string; 675 } 676 677 if (vsnprintf_s(string.string_, len + 1, len, format, argsCopy) < 0) { 678 va_end(args); 679 va_end(argsCopy); 680 return string; 681 } 682 683 va_end(args); 684 va_end(argsCopy); 685 return string; 686} 687} 688} 689