Coverage Report

Created: 2024-07-09 06:09

/proc/self/cwd/pw_string/string_builder.cc
Line
Count
Source (jump to first uncovered line)
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
0
void StringBuilder::clear() {
25
0
  *size_ = 0;
26
0
  NullTerminate();
27
0
  status_ = StatusCode(OkStatus());
28
0
  last_status_ = StatusCode(OkStatus());
29
0
}
30
31
0
StringBuilder& StringBuilder::append(size_t count, char ch) {
32
0
  char* const append_destination = buffer_.data() + size();
33
0
  std::fill_n(append_destination, ResizeAndTerminate(count), ch);
34
0
  return *this;
35
0
}
36
37
0
StringBuilder& StringBuilder::append(const char* str, size_t count) {
38
0
  char* const append_destination = buffer_.data() + size();
39
0
  std::copy_n(str, ResizeAndTerminate(count), append_destination);
40
0
  return *this;
41
0
}
42
43
0
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
0
  return append(string::ClampedCString(str, buffer_.size() - size()));
48
0
}
49
50
0
StringBuilder& StringBuilder::append(std::string_view str) {
51
0
  return append(str.data(), str.size());
52
0
}
53
54
StringBuilder& StringBuilder::append(std::string_view str,
55
                                     size_t pos,
56
0
                                     size_t count) {
57
0
  if (pos > str.size()) {
58
0
    SetErrorStatus(Status::OutOfRange());
59
0
    return *this;
60
0
  }
61
62
0
  return append(str.data() + pos, std::min(str.size() - pos, count));
63
0
}
64
65
0
size_t StringBuilder::ResizeAndTerminate(size_t chars_to_append) {
66
0
  const size_t copied = std::min(chars_to_append, max_size() - size());
67
  // NOTE: `+=` is not used in order to avoid implicit integer conversion which
68
  // results in an error on some compilers.
69
0
  *size_ = static_cast<InlineString<>::size_type>(copied + *size_);
70
0
  NullTerminate();
71
72
0
  if (buffer_.empty() || chars_to_append != copied) {
73
0
    SetErrorStatus(Status::ResourceExhausted());
74
0
  } else {
75
0
    last_status_ = StatusCode(OkStatus());
76
0
  }
77
0
  return copied;
78
0
}
79
80
0
void StringBuilder::resize(size_t new_size) {
81
0
  if (new_size <= size()) {
82
0
    *size_ = static_cast<InlineString<>::size_type>(new_size);
83
0
    NullTerminate();
84
0
    last_status_ = StatusCode(OkStatus());
85
0
  } else {
86
0
    SetErrorStatus(Status::OutOfRange());
87
0
  }
88
0
}
89
90
0
StringBuilder& StringBuilder::Format(const char* format, ...) {
91
0
  va_list args;
92
0
  va_start(args, format);
93
0
  FormatVaList(format, args);
94
0
  va_end(args);
95
96
0
  return *this;
97
0
}
98
99
0
StringBuilder& StringBuilder::FormatVaList(const char* format, va_list args) {
100
0
  HandleStatusWithSize(
101
0
      string::FormatVaList(buffer_.subspan(size()), format, args));
102
0
  return *this;
103
0
}
104
105
0
void StringBuilder::WriteBytes(span<const std::byte> data) {
106
0
  if (size() + data.size() * 2 > max_size()) {
107
0
    SetErrorStatus(Status::ResourceExhausted());
108
0
  } else {
109
0
    for (std::byte val : data) {
110
0
      *this << val;
111
0
    }
112
0
  }
113
0
}
114
115
0
void StringBuilder::CopySizeAndStatus(const StringBuilder& other) {
116
0
  *size_ = static_cast<InlineString<>::size_type>(other.size());
117
0
  status_ = other.status_;
118
0
  last_status_ = other.last_status_;
119
0
}
120
121
0
void StringBuilder::HandleStatusWithSize(StatusWithSize written) {
122
0
  const Status status = written.status();
123
0
  last_status_ = StatusCode(status);
124
0
  if (!status.ok()) {
125
0
    status_ = StatusCode(status);
126
0
  }
127
128
  // NOTE: `+=` is not used in order to avoid implicit integer conversion which
129
  // results in an error on some compilers.
130
0
  *size_ = static_cast<InlineString<>::size_type>(written.size() + *size_);
131
0
}
132
133
0
void StringBuilder::SetErrorStatus(Status status) {
134
0
  last_status_ = StatusCode(status);
135
0
  status_ = StatusCode(status);
136
0
}
137
138
}  // namespace pw