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