1 // Copyright 2019 The Pigweed Authors
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
7 // https://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
15 #include "pw_string/string_builder.h"
19 #include "pw_string/format.h"
20 #include "pw_string/util.h"
24 void StringBuilder::clear() {
28 last_status_ = OkStatus();
31 StringBuilder& StringBuilder::append(size_t count, char ch) {
32 char* const append_destination = &buffer_[size_];
33 std::memset(append_destination, ch, ResizeAndTerminate(count));
37 StringBuilder& StringBuilder::append(const char* str, size_t count) {
38 char* const append_destination = &buffer_[size_];
39 std::memcpy(append_destination, str, ResizeAndTerminate(count));
43 StringBuilder& StringBuilder::append(const char* str) {
44 // Use buffer_.size() - size() as the maximum length so that strings too long
45 // to fit in the buffer will request one character too many, which sets the
46 // status to RESOURCE_EXHAUSTED.
47 return append(str, string::Length(str, buffer_.size() - size()));
50 StringBuilder& StringBuilder::append(const std::string_view& str) {
51 return append(str.data(), str.size());
54 StringBuilder& StringBuilder::append(const std::string_view& str,
57 if (pos > str.size()) {
58 SetErrorStatus(Status::OutOfRange());
62 return append(str.data() + pos, std::min(str.size() - pos, count));
65 size_t StringBuilder::ResizeAndTerminate(size_t chars_to_append) {
66 const size_t copied = std::min(chars_to_append, max_size() - size());
70 if (buffer_.empty() || chars_to_append != copied) {
71 SetErrorStatus(Status::ResourceExhausted());
73 last_status_ = OkStatus();
78 void StringBuilder::resize(size_t new_size) {
79 if (new_size <= size_) {
82 last_status_ = OkStatus();
84 SetErrorStatus(Status::OutOfRange());
88 StringBuilder& StringBuilder::Format(const char* format, ...) {
90 va_start(args, format);
91 FormatVaList(format, args);
97 StringBuilder& StringBuilder::FormatVaList(const char* format, va_list args) {
99 string::FormatVaList(buffer_.subspan(size_), format, args));
103 void StringBuilder::CopySizeAndStatus(const StringBuilder& other) {
105 status_ = other.status_;
106 last_status_ = other.last_status_;
109 void StringBuilder::HandleStatusWithSize(StatusWithSize written) {
110 const Status status = written.status();
111 last_status_ = status;
116 size_ += written.size();
119 void StringBuilder::SetErrorStatus(Status status) {
120 last_status_ = status;