• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2022 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// This file contains the definitions of most pw::InlineBasicString functions.
16// The file is included inline in the fixed-capacity pw::InlineBasicString<T,
17// kCapacity> and generic-capacity pw::InlineBasicString<T> specialization
18// classes.
19//
20// These functions cannot simply be defined in the pw::InlineBasicString<T> base
21// class because:
22//
23//   1. Many functions return a *this reference. The functions should to return
24//      a reference to the exact type they are called on rather than the
25//      generic-capacity base class.
26//   2. Operations on the generic base class cannot be constexpr unless the
27//      class is an InlineBasicString<T, 0>. The functions must be defined in
28//      the fixed-capacity dervied classes to support constexpr operations.
29//
30// These functions have no logic and simply defer to shared, length-agnostic
31// implementations so they do not increase code size.
32
33PW_MODIFY_DIAGNOSTICS_PUSH();
34PW_MODIFY_DIAGNOSTIC_GCC(ignored, "-Wtype-limits");
35
36// Assignment functions
37
38constexpr InlineBasicString& assign(size_type count, T ch) {
39  return static_cast<InlineBasicString&>(Fill(data(), ch, count));
40}
41
42// Checks capacity rather than current size.
43template <size_type kOtherCapacity>
44constexpr InlineBasicString& assign(
45    const InlineBasicString<T, kOtherCapacity>& other) {
46  static_assert(
47      kOtherCapacity == string_impl::kGeneric || kOtherCapacity <= kCapacity,
48      _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING);
49  return static_cast<InlineBasicString&>(
50      Copy(data(), other.data(), other.size()));
51}
52
53constexpr InlineBasicString& assign(const InlineBasicString& other,
54                                    size_type index,
55                                    size_type count = npos) {
56  return static_cast<InlineBasicString&>(
57      CopySubstr(data(), other.data(), other.size(), index, count));
58}
59
60constexpr InlineBasicString& assign(const T* string, size_type count) {
61  return static_cast<InlineBasicString&>(Copy(data(), string, count));
62}
63
64template <typename U, typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
65constexpr InlineBasicString& assign(U c_string) {
66  return assign(c_string,
67                string_impl::BoundedStringLength(c_string, max_size()));
68}
69
70// Assignment from character array or string literal. For known-size strings,
71// the capacity is checked against the string/array size at compile time.
72template <size_t kCharArraySize>
73constexpr InlineBasicString& assign(const T (&array)[kCharArraySize]) {
74  static_assert(
75      string_impl::NullTerminatedArrayFitsInString(kCharArraySize, kCapacity),
76      _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY);
77  return static_cast<InlineBasicString&>(
78      Copy(data(), array, string_impl::ArrayStringLength(array, max_size())));
79}
80
81template <typename InputIterator,
82          typename = string_impl::EnableIfInputIterator<InputIterator>>
83constexpr InlineBasicString& assign(InputIterator start, InputIterator finish) {
84  return static_cast<InlineBasicString&>(
85      IteratorCopy(start, finish, data(), data() + max_size()));
86}
87
88constexpr InlineBasicString& assign(std::initializer_list<T> list) {
89  return assign(list.begin(), list.size());
90}
91
92#if PW_CXX_STANDARD_IS_SUPPORTED(17)  // std::string_view is a C++17 feature
93
94template <typename StringView,
95          typename = string_impl::EnableIfStringViewLike<T, StringView>>
96constexpr InlineBasicString& assign(const StringView& string) {
97  const std::basic_string_view<T> view = string;
98  PW_ASSERT(view.size() < npos);
99  return assign(view.data(), view.size());
100}
101
102template <typename StringView,
103          typename = string_impl::EnableIfStringViewLike<T, StringView>>
104constexpr InlineBasicString& assign(const StringView& string,
105                                    size_type index,
106                                    size_type count = npos) {
107  const std::basic_string_view<T> view = string;
108  PW_ASSERT(view.size() < npos);
109  return static_cast<InlineBasicString&>(CopySubstr(
110      data(), view.data(), static_cast<size_type>(view.size()), index, count));
111}
112
113#endif  // PW_CXX_STANDARD_IS_SUPPORTED(17)
114
115constexpr InlineBasicString& assign(std::nullptr_t) = delete;
116
117// Element access
118
119constexpr reference at(size_type index) {
120  PW_ASSERT(index < length());
121  return data()[index];
122}
123constexpr const_reference at(size_type index) const {
124  PW_ASSERT(index < length());
125  return data()[index];
126}
127
128constexpr reference operator[](size_type index) { return data()[index]; }
129constexpr const_reference operator[](size_type index) const {
130  return data()[index];
131}
132
133constexpr reference front() { return data()[0]; }
134constexpr const_reference front() const { return data()[0]; }
135
136constexpr reference back() { return data()[size() - 1]; }
137constexpr const_reference back() const { return data()[size() - 1]; }
138
139constexpr const_pointer c_str() const noexcept { return data(); }
140
141constexpr operator std::basic_string_view<T>() const noexcept {
142  return std::basic_string_view<T>(data(), size());
143}
144
145// Iterators
146
147constexpr iterator begin() noexcept { return &data()[0]; }
148constexpr const_iterator begin() const noexcept { return &data()[0]; }
149constexpr const_iterator cbegin() const noexcept { return &data()[0]; }
150
151constexpr iterator end() noexcept { return &data()[size()]; }
152constexpr const_iterator end() const noexcept { return &data()[size()]; }
153constexpr const_iterator cend() const noexcept { return &data()[size()]; }
154
155constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
156constexpr const_reverse_iterator rbegin() const noexcept {
157  return const_reverse_iterator(end());
158}
159constexpr const_reverse_iterator crbegin() const noexcept {
160  return const_reverse_iterator(cend());
161}
162
163constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
164constexpr const_reverse_iterator rend() const noexcept {
165  return const_reverse_iterator(begin());
166}
167constexpr const_reverse_iterator crend() const noexcept {
168  return const_reverse_iterator(cbegin());
169}
170
171// Capacity
172
173[[nodiscard]] constexpr bool empty() const noexcept { return size() == 0u; }
174
175// The number of characters in the string.
176constexpr size_type length() const noexcept { return size(); }
177
178constexpr size_type capacity() const noexcept { return max_size(); }
179
180// Operations
181
182constexpr void clear() { SetSizeAndTerminate(data(), 0); }
183
184// TODO(b/239996007): Implement insert and erase.
185
186constexpr void push_back(value_type ch) {
187  static_assert(kCapacity != 0,
188                "Cannot add a character to pw::InlineString<0>");
189  PushBack(data(), ch);
190}
191
192constexpr void pop_back() {
193  static_assert(kCapacity != 0,
194                "Cannot remove a character from pw::InlineString<0>");
195  PopBack(data());
196}
197
198constexpr InlineBasicString& append(size_type count, T ch) {
199  return static_cast<InlineBasicString&>(FillExtend(data(), ch, count));
200}
201
202template <size_type kOtherCapacity>
203constexpr InlineBasicString& append(
204    const InlineBasicString<T, kOtherCapacity>& string) {
205  static_assert(
206      kOtherCapacity == string_impl::kGeneric || kOtherCapacity <= kCapacity,
207      _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING);
208  return append(string.data(), string.size());
209}
210
211template <size_type kOtherCapacity>
212constexpr InlineBasicString& append(
213    const InlineBasicString<T, kOtherCapacity>& other,
214    size_type index,
215    size_type count = npos) {
216  return static_cast<InlineBasicString&>(
217      CopyExtendSubstr(data(), other.data(), other.size(), index, count));
218}
219
220constexpr InlineBasicString& append(const T* string, size_type count) {
221  return static_cast<InlineBasicString&>(CopyExtend(data(), string, count));
222}
223
224template <size_t kCharArraySize>
225constexpr InlineBasicString& append(const T (&array)[kCharArraySize]) {
226  static_assert(
227      string_impl::NullTerminatedArrayFitsInString(kCharArraySize, kCapacity),
228      _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY);
229  return append(array, string_impl::ArrayStringLength(array, max_size()));
230}
231
232template <typename U, typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
233constexpr InlineBasicString& append(U c_string) {
234  return append(c_string,
235                string_impl::BoundedStringLength(c_string, max_size()));
236}
237
238template <typename InputIterator,
239          typename = string_impl::EnableIfInputIterator<InputIterator>>
240constexpr InlineBasicString& append(InputIterator first, InputIterator last) {
241  return static_cast<InlineBasicString&>(
242      IteratorExtend(first, last, data() + size(), data() + max_size()));
243}
244
245constexpr InlineBasicString& append(std::initializer_list<T> list) {
246  return append(list.begin(), list.size());
247}
248
249#if PW_CXX_STANDARD_IS_SUPPORTED(17)  // std::string_view is a C++17 feature
250
251template <typename StringView,
252          typename = string_impl::EnableIfStringViewLike<T, StringView>>
253constexpr InlineBasicString& append(const StringView& string) {
254  const std::basic_string_view<T> view = string;
255  PW_ASSERT(view.size() < npos);
256  return append(view.data(), view.size());
257}
258
259template <typename StringView,
260          typename = string_impl::EnableIfStringViewLike<T, StringView>>
261constexpr InlineBasicString& append(const StringView& string,
262                                    size_type index,
263                                    size_type count = npos) {
264  const std::basic_string_view<T> view = string;
265  PW_ASSERT(view.size() < npos);
266  return static_cast<InlineBasicString&>(CopyExtendSubstr(
267      data(), view.data(), static_cast<size_type>(view.size()), index, count));
268}
269
270#endif  // PW_CXX_STANDARD_IS_SUPPORTED(17)
271
272template <size_type kOtherCapacity>
273constexpr int compare(
274    const InlineBasicString<T, kOtherCapacity>& other) const noexcept {
275  return string_impl::Compare(data(), size(), other.data(), other.size());
276}
277
278constexpr int compare(const T* other) const {
279  return string_impl::Compare(
280      data(),
281      size(),
282      other,
283      string_impl::BoundedStringLength(other, max_size()));
284}
285
286// TODO(b/239996007): Implement other compare overloads.
287
288// TODO(b/239996007): Implement other std::string functions:
289//
290//   - starts_with
291//   - ends_with
292//   - replace
293//   - substr
294//   - copy
295
296constexpr void resize(size_type new_size) { resize(new_size, T()); }
297
298constexpr void resize(size_type new_size, T ch) {
299  return Resize(data(), new_size, ch);
300}
301
302// resize_and_overwrite() only takes the callable object since the underlying
303// buffer has a fixed size.
304template <typename Operation>
305constexpr void resize_and_overwrite(Operation operation) {
306  const auto new_size = std::move(operation)(data(), max_size());
307  PW_ASSERT(static_cast<size_t>(new_size) <= max_size());
308  SetSizeAndTerminate(data(), new_size);
309}
310
311// TODO(b/239996007): Implement swap
312
313// Search
314
315// TODO(b/239996007): Implement std::string search functions:
316//
317// - find
318// - rfind
319// - find_first_of
320// - find_first_not_of
321// - find_last_of
322// - find_last_not_of
323
324PW_MODIFY_DIAGNOSTICS_POP();
325