1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "util/string_builder.h" 17 18#include "securec.h" 19 20#include "util/logger.h" 21 22namespace OHOS { 23namespace Idl { 24const char* StringBuilder::TAG = "StringBuilder"; 25constexpr int LINE_MAX_SIZE = 1024; 26 27StringBuilder::~StringBuilder() 28{ 29 if (buffer_ != nullptr) { 30 free(buffer_); 31 } 32} 33 34StringBuilder& StringBuilder::Append(char c) 35{ 36 if (position_ + 1 >= capacity_) { 37 if (!Grow(1)) { 38 return *this; 39 } 40 } 41 42 buffer_[position_] = c; 43 position_ += 1; 44 return *this; 45} 46 47StringBuilder& StringBuilder::Append(const char* string) 48{ 49 if (string == nullptr || string[0] == '\0') { 50 return *this; 51 } 52 53 size_t len = strlen(string); 54 if (position_ + len >= capacity_) { 55 if (!Grow(len)) { 56 return *this; 57 } 58 } 59 60 if (memcpy_s(buffer_ + position_, capacity_ - position_, string, len) != EOK) { 61 return *this; 62 } 63 position_ += len; 64 return *this; 65} 66 67StringBuilder& StringBuilder::Append(const String& string) 68{ 69 if (string.IsEmpty()) { 70 return *this; 71 } 72 73 size_t len = static_cast<size_t>(string.GetLength()); 74 if (position_ + len >= capacity_) { 75 if (!Grow(len)) { 76 return *this; 77 } 78 } 79 80 if (memcpy_s(buffer_ + position_, capacity_ - position_, string.string(), len) != EOK) { 81 return *this; 82 } 83 position_ += len; 84 return *this; 85} 86 87StringBuilder& StringBuilder::AppendFormat(const char* format, ...) 88{ 89 va_list args, argsCopy; 90 91 va_start(args, format); 92 va_copy(argsCopy, args); 93 94 char buf[LINE_MAX_SIZE] = {0}; 95 int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args); 96 if (len <= 0) { 97 va_end(args); 98 va_end(argsCopy); 99 return *this; 100 } 101 102 size_t positionTmp = position_ + static_cast<size_t>(len); 103 if (positionTmp >= capacity_) { 104 if (!Grow(len)) { 105 va_end(args); 106 va_end(argsCopy); 107 return *this; 108 } 109 } 110 111 if (vsnprintf_s(buffer_ + position_, len + 1, len, format, argsCopy) < 0) { 112 va_end(args); 113 va_end(argsCopy); 114 return *this; 115 } 116 position_ += len; 117 va_end(args); 118 va_end(argsCopy); 119 120 return *this; 121} 122 123bool StringBuilder::Grow(size_t size) 124{ 125 if (capacity_ > String::MAX_SIZE) { 126 Logger::E(TAG, "The StringBuilder is full."); 127 return false; 128 } 129 // 256->the default capacity. 130 size_t newSize = (capacity_ == 0 ? 256 : capacity_ * 2); 131 if (newSize < capacity_ + size) { 132 newSize = capacity_ + size; 133 } 134 if (newSize > String::MAX_SIZE) { 135 newSize = String::MAX_SIZE; 136 } 137 if (newSize <= capacity_) { 138 return false; 139 } 140 141 char* newBuffer = reinterpret_cast<char*>(calloc(newSize, 1)); 142 if (newBuffer == nullptr) { 143 Logger::E(TAG, "Fail to malloc %lu bytes memory.", newSize); 144 return false; 145 } 146 147 if (buffer_ != nullptr) { 148 errno_t ret = memcpy_s(newBuffer, newSize, buffer_, capacity_); 149 if (ret != EOK) { 150 free(newBuffer); 151 newBuffer = nullptr; 152 return false; 153 } 154 free(buffer_); 155 } 156 buffer_ = newBuffer; 157 capacity_ = newSize; 158 return true; 159} 160 161String StringBuilder::ToString() const 162{ 163 return String(buffer_, position_); 164} 165} 166} 167