• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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