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_builder.h"
10 #include "securec.h"
11 #include "util/logger.h"
12
13 namespace OHOS {
14 namespace HDI {
15 const char* StringBuilder::TAG = "StringBuilder";
16 constexpr int LINE_MAX_SIZE = 1024;
17
~StringBuilder()18 StringBuilder::~StringBuilder()
19 {
20 if (buffer_ != nullptr) {
21 free(buffer_);
22 }
23 }
24
Append(char c)25 StringBuilder& StringBuilder::Append(char c)
26 {
27 if (position_ + 1 >= capacity_) {
28 if (!Grow(1)) {
29 return *this;
30 }
31 }
32
33 buffer_[position_] = c;
34 position_ += 1;
35 return *this;
36 }
37
Append(const char * string)38 StringBuilder& StringBuilder::Append(const char* string)
39 {
40 if (string == nullptr || string[0] == '\0') {
41 return *this;
42 }
43
44 size_t len = strlen(string);
45 if (position_ + len >= capacity_) {
46 if (!Grow(len)) {
47 return *this;
48 }
49 }
50
51 (void)memcpy_s(buffer_ + position_, capacity_ - position_, string, len);
52 position_ += len;
53 return *this;
54 }
55
Append(const String & string)56 StringBuilder& StringBuilder::Append(const String& string)
57 {
58 if (string.IsEmpty()) {
59 return *this;
60 }
61
62 size_t len = string.GetLength();
63 if (position_ + len >= capacity_) {
64 if (!Grow(len)) {
65 return *this;
66 }
67 }
68
69 (void)memcpy_s(buffer_ + position_, capacity_ - position_, string.string(), len);
70 position_ += len;
71 return *this;
72 }
73
AppendFormat(const char * format,...)74 StringBuilder& StringBuilder::AppendFormat(const char* format, ...)
75 {
76 va_list args, argsCopy;
77
78 va_start(args, format);
79 va_copy(argsCopy, args);
80
81 char buf[LINE_MAX_SIZE] = {0};
82 int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args);
83 if (len <= 0) {
84 va_end(args);
85 va_end(argsCopy);
86 return *this;
87 }
88
89 if (position_ + len >= capacity_) {
90 if (!Grow(len)) {
91 va_end(args);
92 va_end(argsCopy);
93 return *this;
94 }
95 }
96
97 if (vsnprintf_s(buffer_ + position_, len + 1, len, format, argsCopy) < 0) {
98 va_end(args);
99 va_end(argsCopy);
100 return *this;
101 }
102 position_ += len;
103
104 va_end(args);
105 va_end(argsCopy);
106
107 return *this;
108 }
109
Grow(size_t size)110 bool StringBuilder::Grow(size_t size)
111 {
112 if (capacity_ > String::MAX_SIZE) {
113 Logger::E(TAG, "The StringBuilder is full.");
114 return false;
115 }
116 // 256->the default capacity.
117 size_t newSize = (capacity_ == 0) ? 256 : (capacity_ * 2);
118 if (newSize < capacity_ + size) {
119 newSize = capacity_ + size;
120 }
121 if (newSize > String::MAX_SIZE) {
122 newSize = String::MAX_SIZE;
123 }
124 if (newSize <= capacity_) {
125 return false;
126 }
127
128 char* newBuffer = reinterpret_cast<char*>(calloc(newSize, 1));
129 if (newBuffer == nullptr) {
130 Logger::E(TAG, "Fail to malloc %lu bytes memory.", newSize);
131 return false;
132 }
133
134 if (buffer_ != nullptr) {
135 (void)memcpy_s(newBuffer, newSize, buffer_, capacity_);
136 free(buffer_);
137 }
138 buffer_ = newBuffer;
139 capacity_ = newSize;
140 return true;
141 }
142
ToString() const143 String StringBuilder::ToString() const
144 {
145 return String(buffer_, position_);
146 }
147 } // namespace HDI
148 } // namespace OHOS