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