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