• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     if (buffer_ == nullptr) {
37         Logger::E(TAG, "buffer_ is nullptr!");
38         return *this;
39     }
40     buffer_[position_] = c;
41     position_ += 1;
42     return *this;
43 }
44 
Append(const char * string)45 StringBuilder &StringBuilder::Append(const char *string)
46 {
47     if (string == nullptr || string[0] == '\0') {
48         return *this;
49     }
50 
51     size_t len = strlen(string);
52     if (position_ + len >= capacity_) {
53         if (!Grow(len)) {
54             return *this;
55         }
56     }
57 
58     int ret = memcpy_s(buffer_ + position_, capacity_ - position_, string, len);
59     if (ret != 0) {
60         Logger::E(TAG, "memcpy_s error ret = %d!", ret);
61         return *this;
62     }
63     position_ += len;
64     return *this;
65 }
66 
Append(const std::string & string)67 StringBuilder &StringBuilder::Append(const std::string &string)
68 {
69     if (string.empty()) {
70         return *this;
71     }
72 
73     size_t len = string.size();
74     if (position_ + len >= capacity_) {
75         if (!Grow(len)) {
76             return *this;
77         }
78     }
79 
80     int ret = memcpy_s(buffer_ + position_, capacity_ - position_, string.c_str(), len);
81     if (ret != 0) {
82         Logger::E(TAG, "memcpy_s error ret = %d!", ret);
83         return *this;
84     }
85     position_ += len;
86     return *this;
87 }
88 
AppendFormat(const char * format,...)89 StringBuilder &StringBuilder::AppendFormat(const char *format, ...)
90 {
91     va_list args;
92     va_list argsCopy;
93 
94     va_start(args, format);
95     va_copy(argsCopy, args);
96 
97     char buf[StringHelper::lineMaxSize] = {0};
98     int len = vsnprintf_s(buf, StringHelper::lineMaxSize, StringHelper::lineMaxSize - 1, format, args);
99     if (len <= 0) {
100         va_end(args);
101         va_end(argsCopy);
102         return *this;
103     }
104 
105     size_t writeSize = static_cast<size_t>(len);
106     if (position_ + writeSize >= capacity_) {
107         if (!Grow(writeSize)) {
108             va_end(args);
109             va_end(argsCopy);
110             return *this;
111         }
112     }
113 
114     if (vsnprintf_s(buffer_ + position_, writeSize + 1, writeSize, format, argsCopy) < 0) {
115         va_end(args);
116         va_end(argsCopy);
117         return *this;
118     }
119     position_ += writeSize;
120 
121     va_end(args);
122     va_end(argsCopy);
123 
124     return *this;
125 }
126 
Grow(size_t size)127 bool StringBuilder::Grow(size_t size)
128 {
129     if (capacity_ > StringHelper::maxSize) {
130         Logger::E(TAG, "The StringBuilder is full.");
131         return false;
132     }
133     // 256->the default capacity.
134     size_t newSize = (capacity_ == 0) ? 256 : (capacity_ * 2);
135     if (newSize < capacity_ + size) {
136         newSize = capacity_ + size;
137     }
138     if (newSize > StringHelper::maxSize) {
139         newSize = StringHelper::maxSize;
140     }
141     if (newSize <= capacity_) {
142         return false;
143     }
144 
145     char *newBuffer = reinterpret_cast<char *>(calloc(newSize, 1));
146     if (newBuffer == nullptr) {
147         Logger::E(TAG, "Fail to malloc %lu bytes memory.", newSize);
148         return false;
149     }
150 
151     if (buffer_ != nullptr) {
152         int ret = memcpy_s(newBuffer, newSize, buffer_, capacity_);
153         if (ret != 0) {
154             Logger::E(TAG, "memcpy_s error ret = %d!", ret);
155             free(newBuffer);
156             return false;
157         }
158         free(buffer_);
159     }
160     buffer_ = newBuffer;
161     capacity_ = newSize;
162     return true;
163 }
164 
ToString() const165 std::string StringBuilder::ToString() const
166 {
167     if (buffer_ == nullptr) {
168         Logger::E(TAG, "buffer_ is nullptr");
169         return "";
170     }
171     return std::string(buffer_, position_);
172 }
173 } // namespace HDI
174 } // namespace OHOS