1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "util/string.h"
10 #include <atomic>
11 #include <cctype>
12 #include <cstddef>
13 #include <cstdlib>
14 #include <cstring>
15 #include <new>
16 #include "securec.h"
17 #include "util/logger.h"
18 #include "util/string_builder.h"
19
20 namespace OHOS {
21 namespace HDI {
22 constexpr int LINE_MAX_SIZE = 1024;
23
24 using SharedData = struct SharedData {
25 SharedData(int refCount, int size) : refCount_(refCount), size_(size) {}
26
27 static SharedData* Allocate(int size);
28
29 static void AddRef(const void* handle);
30
31 static void Release(const void* handle);
32
33 inline static char* ToString(SharedData* header)
34 {
35 return reinterpret_cast<char*>(header + 1);
36 }
37
38 inline static SharedData* GetHeader(const void* handle)
39 {
40 return reinterpret_cast<SharedData*>(const_cast<void*>(handle)) - 1;
41 }
42
43 std::atomic<int> refCount_;
44 int size_;
45 };
46
Allocate(int size)47 SharedData* SharedData::Allocate(int size)
48 {
49 if (size < 0) {
50 Logger::E(String::TAG, "Size %d is illegal.", size);
51 return nullptr;
52 }
53 if (size > String::MAX_SIZE) {
54 Logger::E(String::TAG, "The string is too large to alloc.");
55 return nullptr;
56 }
57
58 auto handle = reinterpret_cast<SharedData*>(malloc(sizeof(SharedData) + size + 1));
59 if (handle == nullptr) {
60 Logger::E(String::TAG, "Fail to malloc %lu bytes memory", size);
61 return handle;
62 }
63
64 new (handle)SharedData(1, size);
65 return handle;
66 }
67
AddRef(const void * handle)68 void SharedData::AddRef(const void* handle)
69 {
70 if (handle == nullptr) {
71 return;
72 }
73
74 SharedData* data = GetHeader(handle);
75 int before = data->refCount_.fetch_add(1);
76 if (before + 1 <= 1) {
77 Logger::E(String::TAG, "The refCount %d of %p is error in AddRef.", before, data);
78 };
79 }
80
Release(const void * handle)81 void SharedData::Release(const void* handle)
82 {
83 if (handle == nullptr) {
84 return;
85 }
86
87 SharedData* data = GetHeader(handle);
88 int before = data->refCount_.fetch_sub(1);
89 if (before - 1 == 0) {
90 free(data);
91 } else if (before - 1 < 0) {
92 Logger::E(String::TAG, "The refCount %d of %p is error in Release.", before - 1, data);
93 };
94 }
95
96 const char* String::TAG = "String";
97
String(const char * string)98 String::String(const char* string)
99 {
100 if (string != nullptr) {
101 string_ = SharedData::ToString(SharedData::Allocate(strlen(string)));
102 if (string_ == nullptr) {
103 return;
104 }
105
106 if (strcpy_s(string_, strlen(string) + 1, string) != EOK) {
107 Logger::E(String::TAG, "The Construct of \"%s\" is failed.", string);
108 SharedData::Release(string_);
109 string_ = nullptr;
110 }
111 }
112 }
113
String(const char * string,size_t length)114 String::String(const char* string, size_t length)
115 {
116 if (string != nullptr) {
117 string_ = SharedData::ToString(SharedData::Allocate(length));
118 if (string_ != nullptr) {
119 (void)memcpy_s(string_, length + 1, string, length);
120 string_[length] = '\0';
121 }
122 }
123 }
124
String(const String & other)125 String::String(const String& other)
126 {
127 string_ = other.string_;
128 SharedData::AddRef(string_);
129 }
130
String(String && other)131 String::String(String && other)
132 {
133 string_ = other.string_;
134 other.string_ = nullptr;
135 }
136
String(int size)137 String::String(int size)
138 {
139 string_ = SharedData::ToString(SharedData::Allocate(size));
140 if (string_ != nullptr) {
141 (void)memset_s(string_, size + 1, 0, size + 1);
142 }
143 }
144
~String()145 String::~String()
146 {
147 SharedData::Release(string_);
148 }
149
GetLength() const150 int String::GetLength() const
151 {
152 if (string_ == nullptr) {
153 return 0;
154 }
155
156 return SharedData::GetHeader(string_)->size_;
157 }
158
operator [](int index) const159 char String::operator[](int index) const
160 {
161 if (index < 0 || index >= GetLength()) {
162 return '\0';
163 }
164 return string_[index];
165 }
166
Equals(const char * string) const167 bool String::Equals(const char* string) const
168 {
169 if (string_ == nullptr && string == nullptr) {
170 return true;
171 }
172
173 if (string != nullptr && string_ != nullptr) {
174 if ((size_t)GetLength() != strlen(string)) {
175 return false;
176 }
177 return strcmp(string, string_) == 0;
178 }
179
180 return false;
181 }
182
Equals(const String & other) const183 bool String::Equals(const String& other) const
184 {
185 if (string_ == nullptr && other.string_ == nullptr) {
186 return true;
187 }
188
189 if (string_ != nullptr && other.string_ != nullptr) {
190 if (GetLength() != other.GetLength()) {
191 return false;
192 }
193 return strcmp(string_, other.string_) == 0;
194 }
195 return false;
196 }
197
Compare(const String & other) const198 int String::Compare(const String& other) const
199 {
200 if (string_ == nullptr) {
201 if (other.string_ == nullptr) {
202 return 0;
203 } else {
204 return -1;
205 }
206 }
207
208 if (other.string_ == nullptr) {
209 return 1;
210 }
211
212 return strcmp(string_, other.string_);
213 }
214
GetHashCode() const215 int String::GetHashCode() const
216 {
217 // BKDR Hash Function
218 unsigned int seed = 31; // 31 131 1313 13131 131313 etc..
219 unsigned int hash = 0;
220
221 const char* string = string_;
222 if (string != nullptr) {
223 for (; *string; ++string) {
224 hash = hash * seed + (*string);
225 }
226 }
227 return (hash & 0x7FFFFFFF);
228 }
229
IndexOf(char c,int fromIndex) const230 int String::IndexOf(char c, int fromIndex) const
231 {
232 if (IsEmpty() || c == '\0') {
233 return -1;
234 }
235
236 if (fromIndex < 0) {
237 fromIndex = 0;
238 } else if (fromIndex >= GetLength()) {
239 return -1;
240 }
241
242 char* p = string_ + fromIndex;
243 char* end = string_ + GetLength();
244 while (p != end) {
245 if (*p == c) {
246 return p - string_;
247 }
248 p++;
249 }
250 return -1;
251 }
252
IndexOf(const char * string,int fromIndex) const253 int String::IndexOf(const char* string, int fromIndex) const
254 {
255 if (IsEmpty() || string == nullptr || string[0] == '\0') {
256 return -1;
257 }
258
259 if (fromIndex < 0) {
260 fromIndex = 0;
261 } else if (fromIndex >= GetLength()) {
262 return -1;
263 }
264
265 char* c = strstr(string_ + fromIndex, string);
266 return (c != nullptr) ? (c - string_) : -1;
267 }
268
IndexOf(const String & other,int fromIndex) const269 int String::IndexOf(const String& other, int fromIndex) const
270 {
271 if (IsEmpty() || other.IsEmpty()) {
272 return -1;
273 }
274
275 if (fromIndex < 0) {
276 fromIndex = 0;
277 } else if (fromIndex >= GetLength()) {
278 return -1;
279 }
280
281 char* c = strstr(string_ + fromIndex, other.string_);
282 return (c != nullptr) ? (c - string_) : -1;
283 }
284
LastIndexOf(char c,int fromIndex) const285 int String::LastIndexOf(char c, int fromIndex) const
286 {
287 if (IsEmpty() || c == '\0') {
288 return -1;
289 }
290
291 if (fromIndex < 0) {
292 return -1;
293 } else if (fromIndex == 0 || fromIndex >= GetLength()) {
294 fromIndex = GetLength() - 1;
295 }
296 char* p = string_ + fromIndex;
297 while (p != string_) {
298 if (*p == c) {
299 return p - string_;
300 }
301 p--;
302 }
303 return -1;
304 }
305
LastIndexOf(const char * string,int fromIndex) const306 int String::LastIndexOf(const char* string, int fromIndex) const
307 {
308 if (IsEmpty() || string == nullptr || string[0] == '\0') {
309 return -1;
310 }
311
312 if (fromIndex < 0) {
313 return -1;
314 } else if (fromIndex == 0 || fromIndex >= GetLength()) {
315 fromIndex = GetLength() - 1;
316 }
317
318 return LastIndexOfInternal(string, fromIndex);
319 }
320
LastIndexOf(const String & other,int fromIndex) const321 int String::LastIndexOf(const String& other, int fromIndex) const
322 {
323 if (IsEmpty() || other.IsEmpty()) {
324 return -1;
325 }
326
327 if (fromIndex < 0) {
328 return -1;
329 } else if (fromIndex == 0 || fromIndex >= GetLength()) {
330 fromIndex = GetLength() - 1;
331 }
332
333 return LastIndexOfInternal(other.string(), fromIndex);
334 }
335
LastIndexOfInternal(const char * string,int fromIndex) const336 int String::LastIndexOfInternal(const char* string, int fromIndex) const
337 {
338 int sourceLen = GetLength();
339 int stringLen = strlen(string);
340 int rightIndex = sourceLen - stringLen;
341 if (fromIndex > rightIndex) {
342 fromIndex = rightIndex;
343 }
344
345 int stringLastIndex = stringLen - 1;
346 char stringLastChar = string[stringLastIndex];
347 int leftIndex = stringLen - 1;
348 int index = leftIndex + fromIndex;
349
350 while (true) {
351 while (index >= leftIndex && string_[index] != stringLastChar) {
352 index--;
353 }
354 if (index < leftIndex) {
355 return -1;
356 }
357
358 int compareIndex = index - 1;
359 int start = compareIndex - (stringLen - 1);
360 int strIndex = stringLastIndex - 1;
361
362 while (compareIndex > start) {
363 if (string_[compareIndex--] != string[strIndex--]) {
364 index--;
365 break;
366 }
367 }
368
369 if (compareIndex == start) {
370 return start + 1;
371 }
372 }
373 }
374
StartsWith(const char * string) const375 bool String::StartsWith(const char* string) const
376 {
377 if (string == nullptr || string_ == nullptr) {
378 return false;
379 }
380
381 if (string[0] == '\0' && string_[0] == '\0') {
382 return true;
383 }
384
385 size_t count = strlen(string);
386 if (count > (size_t)GetLength()) {
387 return false;
388 }
389
390 return memcmp(string_, string, count) == 0;
391 }
392
StartsWith(const String & other) const393 bool String::StartsWith(const String& other) const
394 {
395 if (other.string_ == nullptr || string_ == nullptr) {
396 return false;
397 }
398
399 if (other.string_[0] == '\0' && string_[0] == '\0') {
400 return true;
401 }
402
403 size_t count = other.GetLength();
404 if (count > (size_t)GetLength()) {
405 return false;
406 }
407
408 return memcmp(string_, other.string_, count) == 0;
409 }
410
EndsWith(char c) const411 bool String::EndsWith(char c) const
412 {
413 if (string_ == nullptr) {
414 return false;
415 }
416
417 size_t len = GetLength();
418 if (len < 1) {
419 return false;
420 }
421
422 return string_[len - 1] == c;
423 }
424
EndsWith(const char * string) const425 bool String::EndsWith(const char* string) const
426 {
427 if (string == nullptr || string_ == nullptr) {
428 return false;
429 }
430
431 if (string[0] == '\0') {
432 return true;
433 }
434
435 size_t count = strlen(string);
436 size_t len = GetLength();
437 if (count > len) {
438 return false;
439 }
440
441 return memcmp(string_ + len - count, string, count) == 0;
442 }
443
EndsWith(const String & other) const444 bool String::EndsWith(const String& other) const
445 {
446 if (other.string_ == nullptr || string_ == nullptr) {
447 return false;
448 }
449
450 if (other.string_[0] == '\0') {
451 return true;
452 }
453
454 size_t count = other.GetLength();
455 size_t len = GetLength();
456 if (count > len) {
457 return false;
458 }
459
460 return memcmp(string_ + len - count, other.string_, count) == 0;
461 }
462
ToLowerCase() const463 String String::ToLowerCase() const
464 {
465 if (IsEmpty()) {
466 return *this;
467 }
468
469 size_t size = GetLength();
470 for (size_t i = 0; i < size; i++) {
471 if (isupper(string_[i])) {
472 String newStr(string_);
473 for (size_t j = i; j < size; j++) {
474 newStr.string_[j] = tolower(newStr.string_[j]);
475 }
476 return newStr;
477 }
478 }
479 return *this;
480 }
481
ToUpperCase() const482 String String::ToUpperCase() const
483 {
484 if (IsEmpty()) {
485 return *this;
486 }
487
488 size_t size = GetLength();
489 for (size_t i = 0; i < size; i++) {
490 if (islower(string_[i])) {
491 String newStr(string_);
492 for (size_t j = i; j < size; j++) {
493 newStr.string_[j] = toupper(newStr.string_[j]);
494 }
495 return newStr;
496 }
497 }
498 return *this;
499 }
500
Substring(int begin) const501 String String::Substring(int begin) const
502 {
503 if (begin < 0 || begin >= GetLength()) {
504 return String();
505 }
506
507 return String(string_ + begin);
508 }
509
Substring(int begin,int end) const510 String String::Substring(int begin, int end) const
511 {
512 if (begin < 0 || end > GetLength() || begin > end) {
513 return String();
514 }
515
516 return String(string_ + begin, end - begin);
517 }
518
Replace(char oldChar,char newChar) const519 String String::Replace(char oldChar, char newChar) const
520 {
521 if (oldChar == newChar) {
522 return *this;
523 }
524
525 size_t size = GetLength();
526 for (size_t i = 0; i < size; i++) {
527 if (string_[i] != oldChar) {
528 continue;
529 }
530
531 String newStr(string_);
532 for (size_t j = i; j < size; j++) {
533 if (newStr.string_[j] == oldChar) {
534 newStr.string_[j] = newChar;
535 }
536 }
537 return newStr;
538 }
539 return *this;
540 }
541
Replace(const char * target,const char * replacement) const542 String String::Replace(const char* target, const char* replacement) const
543 {
544 if (target == nullptr || target[0] == '\0' || replacement == nullptr) {
545 return *this;
546 }
547
548 int index = IndexOf(target);
549 if (index == -1) {
550 return *this;
551 }
552
553 StringBuilder sb;
554 int begin = 0;
555 int step = strlen(target);
556 while (index != -1) {
557 sb.Append(Substring(begin, index));
558 sb.Append(replacement);
559 begin = index + step;
560 index = IndexOf(target, begin);
561 }
562 sb.Append(Substring(begin));
563 return sb.ToString();
564 }
565
Replace(const String & target,const String & replacement) const566 String String::Replace(const String& target, const String& replacement) const
567 {
568 if (target.IsEmpty() || replacement.IsNull()) {
569 return *this;
570 }
571
572 int index = IndexOf(target);
573 if (index == -1) {
574 return *this;
575 }
576
577 StringBuilder sb;
578 int begin = 0;
579 int step = target.GetLength();
580 while (index != -1) {
581 sb.Append(Substring(begin, index));
582 sb.Append(replacement);
583 begin = index + step;
584 index = IndexOf(target, begin);
585 }
586 sb.Append(Substring(begin));
587 return sb.ToString();
588 }
589
Replace(int position,int len,const String & other)590 String& String::Replace(int position, int len, const String& other)
591 {
592 if (position < 0 || position > GetLength()) {
593 return *this;
594 }
595
596 if (len < 0) {
597 return *this;
598 }
599
600 if (other.IsEmpty()) {
601 return *this;
602 }
603
604 String lStr = Substring(0, position);
605 String rStr = Substring(position + len);
606 String newStr;
607 newStr += lStr + other + rStr;
608
609 SharedData::Release(string_);
610 SharedData::AddRef(newStr.string_);
611 string_ = newStr.string_;
612 return *this;
613 }
614
Split(const String & separator) const615 std::vector<String> String::Split(const String& separator) const
616 {
617 std::vector<String> result;
618 if (IsEmpty()) {
619 return result;
620 }
621
622 int startIndex = 0;
623 int endIndex = IndexOf(separator, startIndex);
624 while (endIndex != -1) {
625 result.push_back(Substring(startIndex, endIndex));
626 startIndex = endIndex + 1;
627 endIndex = IndexOf(separator, startIndex);
628 }
629
630 if (startIndex < GetLength()) {
631 result.push_back(Substring(startIndex));
632 }
633
634 return result;
635 }
636
insert(int index,const String & other)637 String& String::insert(int index, const String& other)
638 {
639 if (index < 0 || index > GetLength()) {
640 return *this;
641 }
642
643 if (other.IsEmpty()) {
644 return *this;
645 }
646
647 String newStr;
648
649 String lStr = Substring(0, index);
650 String rStr = Substring(index);
651
652 newStr += lStr + other + rStr;
653
654 SharedData::Release(string_);
655 SharedData::AddRef(newStr.string_);
656 string_ = newStr.string_;
657 return *this;
658 }
659
operator =(const char * string)660 String& String::operator=(const char* string)
661 {
662 SharedData::Release(string_);
663
664 if (string == nullptr) {
665 string_ = nullptr;
666 return *this;
667 }
668
669 string_ = SharedData::ToString(SharedData::Allocate(strlen(string)));
670 if (string_ == nullptr) {
671 return *this;
672 }
673
674 if (strcpy_s(string_, strlen(string) + 1, string) != EOK) {
675 Logger::E(String::TAG, "The operator= of \"%s\" is failed.", string);
676 SharedData::Release(string_);
677 string_ = nullptr;
678 }
679
680 return *this;
681 }
682
operator =(const String & other)683 String& String::operator=(const String& other)
684 {
685 if (string_ == other.string_) {
686 return *this;
687 }
688
689 SharedData::Release(string_);
690 SharedData::AddRef(other.string_);
691 string_ = other.string_;
692 return *this;
693 }
694
operator =(String && other)695 String& String::operator=(String && other)
696 {
697 SharedData::Release(string_);
698 string_ = other.string_;
699 other.string_ = nullptr;
700 return *this;
701 }
702
operator +=(const char * other)703 String& String::operator+=(const char* other)
704 {
705 if (other == nullptr || other[0] == '\0') {
706 return *this;
707 }
708
709 int thisSize = GetLength();
710 int newSize = thisSize + strlen(other);
711 String newString(newSize);
712 if (newString.string_ == nullptr) {
713 Logger::E(String::TAG, "The operator+= of \"%s\" is failed.", string_);
714 goto FINISHED;
715 }
716
717 if (string_ != nullptr && thisSize > 0) {
718 if (memcpy_s(newString.string_, newSize + 1, string_, thisSize) != EOK) {
719 Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 2", string_);
720 goto FINISHED;
721 }
722 }
723
724 if (strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other) != EOK) {
725 Logger::E(String::TAG, "The operator+= of \"%s\" is failed.", string_);
726 goto FINISHED;
727 }
728
729 FINISHED:
730 SharedData::Release(string_);
731 SharedData::AddRef(newString.string_);
732 string_ = newString.string_;
733 return *this;
734 }
735
operator +=(const String & other)736 String& String::operator+=(const String& other)
737 {
738 if (other.IsEmpty()) {
739 return *this;
740 }
741
742 int thisSize = GetLength();
743 int newSize = thisSize + other.GetLength();
744 String newString(newSize);
745 if (newString.string_ == nullptr) {
746 Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 1", string_);
747 goto FINISHED;
748 }
749
750 if (string_ != nullptr && thisSize > 0) {
751 if (memcpy_s(newString.string_, newSize + 1, string_, thisSize) != EOK) {
752 Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 2", string_);
753 goto FINISHED;
754 }
755 }
756
757 if (strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other.string_) != EOK) {
758 Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 3", string_);
759 goto FINISHED;
760 }
761
762 FINISHED:
763 SharedData::Release(string_);
764 SharedData::AddRef(newString.string_);
765 string_ = newString.string_;
766 return *this;
767 }
768
Format(const char * format,...)769 String String::Format(const char* format, ...)
770 {
771 va_list args, argsCopy;
772
773 va_start(args, format);
774 va_copy(argsCopy, args);
775
776 char buf[LINE_MAX_SIZE] = {0};
777 int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args);
778 String string;
779 if (len <= 0) {
780 va_end(args);
781 va_end(argsCopy);
782 return string;
783 }
784
785 string = String(len);
786 if (string.string_ == nullptr) {
787 va_end(args);
788 va_end(argsCopy);
789 return string;
790 }
791
792 if (vsnprintf_s(string.string_, len + 1, len, format, argsCopy) < 0) {
793 va_end(args);
794 va_end(argsCopy);
795 return string;
796 }
797
798 va_end(args);
799 va_end(argsCopy);
800 return string;
801 }
802 } // namespace HDI
803 } // namespace OHOS