• 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     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