Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_string / string_builder.cc
1 // Copyright 2019 The Pigweed Authors
2 //
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
5 // the License at
6 //
7 //     https://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, 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
13 // the License.
14
15 #include "pw_string/string_builder.h"
16
17 #include <cstdio>
18
19 #include "pw_string/format.h"
20 #include "pw_string/util.h"
21
22 namespace pw {
23
24 void StringBuilder::clear() {
25   size_ = 0;
26   NullTerminate();
27   status_ = OkStatus();
28   last_status_ = OkStatus();
29 }
30
31 StringBuilder& StringBuilder::append(size_t count, char ch) {
32   char* const append_destination = &buffer_[size_];
33   std::memset(append_destination, ch, ResizeAndTerminate(count));
34   return *this;
35 }
36
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));
40   return *this;
41 }
42
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()));
48 }
49
50 StringBuilder& StringBuilder::append(const std::string_view& str) {
51   return append(str.data(), str.size());
52 }
53
54 StringBuilder& StringBuilder::append(const std::string_view& str,
55                                      size_t pos,
56                                      size_t count) {
57   if (pos > str.size()) {
58     SetErrorStatus(Status::OutOfRange());
59     return *this;
60   }
61
62   return append(str.data() + pos, std::min(str.size() - pos, count));
63 }
64
65 size_t StringBuilder::ResizeAndTerminate(size_t chars_to_append) {
66   const size_t copied = std::min(chars_to_append, max_size() - size());
67   size_ += copied;
68   NullTerminate();
69
70   if (buffer_.empty() || chars_to_append != copied) {
71     SetErrorStatus(Status::ResourceExhausted());
72   } else {
73     last_status_ = OkStatus();
74   }
75   return copied;
76 }
77
78 void StringBuilder::resize(size_t new_size) {
79   if (new_size <= size_) {
80     size_ = new_size;
81     NullTerminate();
82     last_status_ = OkStatus();
83   } else {
84     SetErrorStatus(Status::OutOfRange());
85   }
86 }
87
88 StringBuilder& StringBuilder::Format(const char* format, ...) {
89   va_list args;
90   va_start(args, format);
91   FormatVaList(format, args);
92   va_end(args);
93
94   return *this;
95 }
96
97 StringBuilder& StringBuilder::FormatVaList(const char* format, va_list args) {
98   HandleStatusWithSize(
99       string::FormatVaList(buffer_.subspan(size_), format, args));
100   return *this;
101 }
102
103 void StringBuilder::CopySizeAndStatus(const StringBuilder& other) {
104   size_ = other.size_;
105   status_ = other.status_;
106   last_status_ = other.last_status_;
107 }
108
109 void StringBuilder::HandleStatusWithSize(StatusWithSize written) {
110   const Status status = written.status();
111   last_status_ = status;
112   if (!status.ok()) {
113     status_ = status;
114   }
115
116   size_ += written.size();
117 }
118
119 void StringBuilder::SetErrorStatus(Status status) {
120   last_status_ = status;
121   status_ = status;
122 }
123
124 }  // namespace pw