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