• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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), size_(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 size_;
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             (void)strcpy_s(string_, strlen(string) + 1, string);
117         }
118     }
119 }
120 
String(const char * string,size_t length)121 String::String(const char* string, size_t length)
122 {
123     if (string !=  nullptr) {
124         string_ = SharedData::ToString(SharedData::Allocate(length));
125         if (string_ != nullptr) {
126             errno_t ret = memcpy_s(string_, length + 1, string, length);
127             if (ret == EOK) {
128                 string_[length] = '\0';
129             } else {
130                 free(string_);
131                 string_ = nullptr;
132             }
133         }
134     }
135 }
136 
String(const String & other)137 String::String(const String& other)
138 {
139     string_ = other.string_;
140     SharedData::AddRef(string_);
141 }
142 
String(String && other)143 String::String(String&& other)
144 {
145     string_ = other.string_;
146     other.string_ = nullptr;
147 }
148 
String(int size)149 String::String(int size)
150 {
151     string_ = SharedData::ToString(SharedData::Allocate(size));
152     if (string_ != nullptr) {
153         (void)memset_s(string_, size + 1, 0, size + 1);
154     }
155 }
156 
~String()157 String::~String()
158 {
159     SharedData::Release(string_);
160 }
161 
GetLength() const162 int String::GetLength() const
163 {
164     if (string_ == nullptr) {
165         return 0;
166     }
167 
168     return SharedData::GetHeader(string_)->size_;
169 }
170 
operator [](int index) const171 char String::operator[](int index) const
172 {
173     if (index < 0 || index >= GetLength()) {
174         return '\0';
175     }
176     return string_[index];
177 }
178 
Equals(const char * string) const179 bool String::Equals(const char* string) const
180 {
181     if (string_ == nullptr && string == nullptr) {
182         return true;
183     }
184 
185     if (string != nullptr && string_ != nullptr) {
186         if ((size_t)GetLength() != strlen(string)) {
187             return false;
188         }
189         return strcmp(string, string_) == 0;
190     }
191 
192     return false;
193 }
194 
Equals(const String & other) const195 bool String::Equals(const String& other) const
196 {
197     if (string_ == nullptr && other.string_ == nullptr) {
198         return true;
199     }
200 
201     if (string_ != nullptr && other.string_ != nullptr) {
202         if (GetLength() != other.GetLength()) {
203             return false;
204         }
205         return strcmp(string_, other.string_) == 0;
206     }
207     return false;
208 }
209 
GetHashCode() const210 int String::GetHashCode() const
211 {
212     // BKDR Hash Function
213     unsigned int seed = 31; // 31 131 1313 13131 131313 etc..
214     unsigned int hash = 0;
215 
216     const char* string = string_;
217     if (string != nullptr) {
218         for (; *string; ++string) {
219             hash = hash * seed + (*string);
220         }
221     }
222     return (hash & 0x7FFFFFFF);
223 }
224 
IndexOf(char c,int fromIndex) const225 int String::IndexOf(char c, int fromIndex) const
226 {
227     if (IsEmpty() || c == '\0') {
228         return -1;
229     }
230 
231     if (fromIndex < 0) {
232         fromIndex = 0;
233     } else if (fromIndex >= GetLength()) {
234         return -1;
235     }
236 
237     char* p = string_ + fromIndex;
238     char* end = string_ + GetLength();
239     while (p != end) {
240         if (*p == c) {
241             return p - string_;
242         }
243         p++;
244     }
245     return -1;
246 }
247 
IndexOf(const char * string,int fromIndex) const248 int String::IndexOf(const char* string, int fromIndex) const
249 {
250     if (IsEmpty() || string == nullptr || string[0] == '\0') {
251         return -1;
252     }
253 
254     if (fromIndex < 0) {
255         fromIndex = 0;
256     } else if (fromIndex >= GetLength()) {
257         return -1;
258     }
259 
260     char* c = strstr(string_ + fromIndex, string);
261     return c != nullptr ? c - string_ : -1;
262 }
263 
IndexOf(const String & other,int fromIndex) const264 int String::IndexOf(const String& other, int fromIndex) const
265 {
266     if (IsEmpty() || other.IsEmpty()) {
267         return -1;
268     }
269 
270     if (fromIndex < 0) {
271         fromIndex = 0;
272     } else if (fromIndex >= GetLength()) {
273         return -1;
274     }
275 
276     char* c = strstr(string_ + fromIndex, other.string_);
277     return c != nullptr ? c - string_ : -1;
278 }
279 
LastIndexOf(char c,int fromIndex) const280 int String::LastIndexOf(char c, int fromIndex) const
281 {
282     if (IsEmpty() || c == '\0') {
283         return -1;
284     }
285 
286     if (fromIndex < 0) {
287         return -1;
288     } else if (fromIndex == 0 || fromIndex >= GetLength()) {
289         fromIndex = GetLength() - 1;
290     }
291     char* p = string_ + fromIndex;
292     while (p != string_) {
293         if (*p == c) {
294             return p - string_;
295         }
296         p--;
297     }
298     return -1;
299 }
300 
LastIndexOf(const char * string,int fromIndex) const301 int String::LastIndexOf(const char* string, int fromIndex) const
302 {
303     if (IsEmpty() || string == nullptr || string[0] == '\0') {
304         return -1;
305     }
306 
307     if (fromIndex < 0) {
308         return -1;
309     } else if (fromIndex == 0 || fromIndex >= GetLength()) {
310         fromIndex = GetLength() - 1;
311     }
312 
313     return LastIndexOfInternal(string, fromIndex);
314 }
315 
LastIndexOf(const String & other,int fromIndex) const316 int String::LastIndexOf(const String& other, int fromIndex) const
317 {
318     if (IsEmpty() || other.IsEmpty()) {
319         return -1;
320     }
321 
322     if (fromIndex < 0) {
323         return -1;
324     } else if (fromIndex == 0 || fromIndex >= GetLength()) {
325         fromIndex = GetLength() - 1;
326     }
327 
328     return LastIndexOfInternal(other.string(), fromIndex);
329 }
330 
LastIndexOfInternal(const char * string,int fromIndex) const331 int String::LastIndexOfInternal(const char* string, int fromIndex) const
332 {
333     int sourceLen = GetLength();
334     int stringLen = strlen(string);
335     int rightIndex = sourceLen - stringLen;
336     if (fromIndex > rightIndex) {
337         fromIndex = rightIndex;
338     }
339 
340     int stringLastIndex = stringLen - 1;
341     char stringLastChar = string[stringLastIndex];
342     int min = stringLen - 1;
343     int i = min + fromIndex;
344 
345 startSearchLastChar:
346     while (true) {
347         while (i >= min && string_[i] != stringLastChar) {
348             i--;
349         }
350         if (i < min) {
351             return -1;
352         }
353         int j = i - 1;
354         int start = j - (stringLen - 1);
355         int k = stringLastIndex - 1;
356 
357         while (j > start) {
358             if (string_[j--] != string[k--]) {
359                 i--;
360                 goto startSearchLastChar;
361             }
362         }
363         return start + 1;
364     }
365 }
366 
StartsWith(const char * string) const367 bool String::StartsWith(const char* string) const
368 {
369     if (string == nullptr || string_ == nullptr) {
370         return false;
371     }
372 
373     if (string[0] == '\0' && string_[0] == '\0') {
374         return true;
375     }
376 
377     size_t count = strlen(string);
378     if (count > (size_t)GetLength()) {
379         return false;
380     }
381 
382     return memcmp(string_, string, count) == 0;
383 }
384 
StartsWith(const String & other) const385 bool String::StartsWith(const String& other) const
386 {
387     if (other.string_ == nullptr || string_ == nullptr) {
388         return false;
389     }
390 
391     if (other.string_[0] == '\0' && string_[0] == '\0') {
392         return true;
393     }
394 
395     size_t count = other.GetLength();
396     if (count > (size_t)GetLength()) {
397         return false;
398     }
399 
400     return memcmp(string_, other.string_, count) == 0;
401 }
402 
EndsWith(const char * string) const403 bool String::EndsWith(const char* string) const
404 {
405     if (string == nullptr || string_ == nullptr) {
406         return false;
407     }
408 
409     if (string[0] == '\0') {
410         return true;
411     }
412 
413     size_t count = strlen(string);
414     size_t len = GetLength();
415     if (count > len) {
416         return false;
417     }
418 
419     return memcmp(string_ + len - count, string, count) == 0;
420 }
421 
EndsWith(const String & other) const422 bool String::EndsWith(const String& other) const
423 {
424     if (other.string_ == nullptr || string_ == nullptr) {
425         return false;
426     }
427 
428     if (other.string_[0] == '\0') {
429         return true;
430     }
431 
432     size_t count = other.GetLength();
433     size_t len = GetLength();
434     if (count > len) {
435         return false;
436     }
437 
438     return memcmp(string_ + len - count, other.string_, count) == 0;
439 }
440 
ToLowerCase() const441 String String::ToLowerCase() const
442 {
443     if (IsEmpty()) {
444         return *this;
445     }
446 
447     size_t size = GetLength();
448     for (size_t i = 0; i < size; i++) {
449         if (isupper(string_[i])) {
450             String newStr(string_);
451             for (size_t j = i; j < size; j++) {
452                 newStr.string_[j] = tolower(newStr.string_[j]);
453             }
454             return newStr;
455         }
456     }
457     return *this;
458 }
459 
ToUpperCase() const460 String String::ToUpperCase() const
461 {
462     if (IsEmpty()) {
463         return *this;
464     }
465 
466     size_t size = GetLength();
467     for (size_t i = 0; i < size; i++) {
468         if (islower(string_[i])) {
469             String newStr(string_);
470             for (size_t j = i; j < size; j++) {
471                 newStr.string_[j] = toupper(newStr.string_[j]);
472             }
473             return newStr;
474         }
475     }
476     return *this;
477 }
478 
Substring(int begin) const479 String String::Substring(int begin) const
480 {
481     if (begin < 0 || begin >= GetLength()) {
482         return String();
483     }
484 
485     return String(string_ + begin);
486 }
487 
Substring(int begin,int end) const488 String String::Substring(int begin, int end) const
489 {
490     if (begin < 0 || end > GetLength() || begin > end) {
491         return String();
492     }
493 
494     return String(string_ + begin, end - begin);
495 }
496 
Replace(char oldChar,char newChar) const497 String String::Replace(char oldChar, char newChar) const
498 {
499     if (oldChar == newChar) {
500         return *this;
501     }
502 
503     size_t size = GetLength();
504     for (size_t i = 0; i < size; i++) {
505         if (string_[i] == oldChar) {
506             String newStr(string_);
507             for (size_t j = i; j < size; j++) {
508                 if (newStr.string_[j] == oldChar) {
509                     newStr.string_[j] = newChar;
510                 }
511             }
512             return newStr;
513         }
514     }
515     return *this;
516 }
517 
Replace(const char * target,const char * replacement) const518 String String::Replace(const char* target, const char* replacement) const
519 {
520     if (target == nullptr || target[0] == '\0' || replacement == nullptr) {
521         return *this;
522     }
523 
524     int index = IndexOf(target);
525     if (index == -1) {
526         return *this;
527     }
528 
529     StringBuilder sb;
530     int begin = 0;
531     int step = strlen(target);
532     while (index != -1) {
533         sb.Append(Substring(begin, index));
534         sb.Append(replacement);
535         begin = index + step;
536         index = IndexOf(target, begin);
537     }
538     sb.Append(Substring(begin));
539     return sb.ToString();
540 }
541 
Replace(const String & target,const String & replacement) const542 String String::Replace(const String& target, const String& replacement) const
543 {
544     if (target.IsEmpty() || replacement.IsNull()) {
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 = target.GetLength();
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 
operator =(const char * string)566 String& String::operator=(const char* string)
567 {
568     SharedData::Release(string_);
569 
570     if (string == nullptr) {
571         string_ = nullptr;
572         return *this;
573     }
574 
575     string_ = SharedData::ToString(SharedData::Allocate(strlen(string)));
576     if (string_ != nullptr) {
577         (void)strcpy_s(string_, strlen(string) + 1, string);
578     }
579     return *this;
580 }
581 
operator =(const String & other)582 String& String::operator=(const String& other)
583 {
584     if (string_ == other.string_) {
585         return *this;
586     }
587 
588     SharedData::Release(string_);
589     SharedData::AddRef(other.string_);
590     string_ = other.string_;
591     return *this;
592 }
593 
operator =(String && other)594 String& String::operator=(String&& other)
595 {
596     SharedData::Release(string_);
597     string_ = other.string_;
598     other.string_ = nullptr;
599     return *this;
600 }
601 
operator +=(const char * string) const602 String String::operator+=(const char* string) const
603 {
604     if (string == nullptr || string[0] == '\0') {
605         return *this;
606     }
607 
608     int thisSize = GetLength();
609     int newSize = thisSize + strlen(string);
610     String newString(newSize);
611     if (newString.string_ != nullptr) {
612         (void)memcpy_s(newString.string_, newSize + 1, string_, thisSize);
613         (void)strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize,  string);
614     }
615     return newString;
616 }
617 
operator +=(const String & other) const618 String String::operator+=(const String& other) const
619 {
620     if (other.IsEmpty()) {
621         return *this;
622     }
623 
624     int thisSize = GetLength();
625     int newSize = thisSize + other.GetLength();
626     String newString(newSize);
627     if (newString.string_ != nullptr) {
628         (void)memcpy_s(newString.string_, newSize + 1, string_, thisSize);
629         (void)strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other.string_);
630     }
631     return newString;
632 }
633 
Format(const char * format,...)634 String String::Format(const char* format, ...)
635 {
636     va_list args, argsCopy;
637 
638     va_start(args, format);
639     va_copy(argsCopy, args);
640 
641     char buf[LINE_MAX_SIZE] = {0};
642     int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args);
643     String string;
644     if (len <= 0) {
645         va_end(args);
646         va_end(argsCopy);
647         return string;
648     }
649 
650     string = String(len);
651     if (string.string_ == nullptr) {
652         va_end(args);
653         va_end(argsCopy);
654         return string;
655     }
656 
657     if (vsnprintf_s(string.string_, len + 1, len, format, argsCopy) < 0) {
658         va_end(args);
659         va_end(argsCopy);
660         return string;
661     }
662 
663     va_end(args);
664     va_end(argsCopy);
665     return string;
666 }
667 }
668 }
669