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 
30 namespace OHOS {
31 namespace Idl {
32 constexpr int LINE_MAX_SIZE = 1024;
33 
34 using 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 
Allocate(int size)59 SharedData* 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 
AddRef(const void * handle)80 void 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 
Release(const void * handle)93 void 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 
109 const char* String::TAG = "String";
110 
String(const char * string)111 String::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 
String(const char * string,size_t length)124 String::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 
String(const String & other)144 String::String(const String& other)
145 {
146     string_ = other.string_;
147     SharedData::AddRef(string_);
148 }
149 
String(String && other)150 String::String(String&& other)
151 {
152     string_ = other.string_;
153     other.string_ = nullptr;
154 }
155 
String(int size)156 String::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 
~String()164 String::~String()
165 {
166     SharedData::Release(string_);
167 }
168 
GetLength() const169 int String::GetLength() const
170 {
171     if (string_ == nullptr) {
172         return 0;
173     }
174 
175     return SharedData::GetHeader(string_)->shareDataSize;
176 }
177 
operator [](int index) const178 char String::operator[](int index) const
179 {
180     if (index < 0 || index >= GetLength()) {
181         return '\0';
182     }
183     return string_[index];
184 }
185 
186 bool String::Equals(const char* string) const
__anon5e4de09e0202(int index) 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 
202 bool String::Equals(const String& other) const
__anon5e4de09e0302(int index) 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 
217 int String::GetHashCode() const
__anon5e4de09e0402(int index) 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 
232 int String::IndexOf(char c, int fromIndex) const
__anon5e4de09e0502(int index) 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 
255 int String::IndexOf(const char* string, int fromIndex) const
__anon5e4de09e0602(int index) 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 
271 int String::IndexOf(const String& other, int fromIndex) const
__anon5e4de09e0702(int index) 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 
287 int String::LastIndexOf(char c, int fromIndex) const
__anon5e4de09e0802(int index) 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 
308 int String::LastIndexOf(const char* string, int fromIndex) const
__anon5e4de09e0902(int index) 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 
323 int String::LastIndexOf(const String& other, int fromIndex) const
__anon5e4de09e0a02(int index) 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 
338 int String::LastIndexOfInternal(const char* string, int fromIndex) const
__anon5e4de09e0b02(int index) 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 
352 startSearchLastChar:
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 
374 bool String::StartsWith(const char* string) const
__anon5e4de09e0c02(int index) 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 
392 bool String::StartsWith(const String& other) const
__anon5e4de09e0d02(int index) 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 
410 bool String::EndsWith(const char* string) const
__anon5e4de09e0e02(int index) 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 
429 bool String::EndsWith(const String& other) const
__anon5e4de09e0f02(int index) 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 
448 String String::ToLowerCase() const
__anon5e4de09e1002(int index) 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 
467 String String::ToUpperCase() const
__anon5e4de09e1102(int index) 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 
486 String String::Substring(int begin) const
__anon5e4de09e1202(int index) 487 {
488     if (begin < 0 || begin >= GetLength()) {
489         return String();
490     }
491 
492     return String(string_ + begin);
493 }
494 
495 String String::Substring(int begin, int end) const
__anon5e4de09e1302(int index) 496 {
497     if (begin < 0 || end > GetLength() || begin > end) {
498         return String();
499     }
500 
501     return String(string_ + begin, end - begin);
502 }
503 
504 String String::Replace(char oldChar, char newChar) const
__anon5e4de09e1402(int index) 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 
526 String String::Replace(const char* target, const char* replacement) const
__anon5e4de09e1502(int index) 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 
550 String String::Replace(const String& target, const String& replacement) const
__anon5e4de09e1602(int index) 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 
574 String& 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 
operator =(const String & other)593 String& 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 
operator =(String && other)605 String& String::operator=(String&& other)
606 {
607     SharedData::Release(string_);
608     string_ = other.string_;
609     other.string_ = nullptr;
610     return *this;
611 }
612 
operator +=(const char * string) const613 String 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 
operator +=(const String & other) const635 String 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 
Format(const char * format,...)654 String 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