Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #pragma once
19 :
20 : #include <nlassert.h>
21 :
22 : #include "BufferWriter.h"
23 :
24 : namespace chip {
25 :
26 : /// Build a c-style string out of distinct parts
27 : class StringBuilderBase
28 : {
29 : public:
30 497 : StringBuilderBase(char * buffer, size_t size) : mWriter(reinterpret_cast<uint8_t *>(buffer), size - 1)
31 : {
32 : nlASSERT(size > 0);
33 497 : buffer[0] = 0; // make c-str work by default
34 497 : }
35 :
36 : /// Append a null terminated string
37 1636 : StringBuilderBase & Add(const char * s)
38 : {
39 1636 : mWriter.Put(s);
40 1636 : NullTerminate();
41 1636 : return *this;
42 : }
43 :
44 : /// Append an integer value
45 : StringBuilderBase & Add(int value)
46 : {
47 : char buff[32];
48 : snprintf(buff, sizeof(buff), "%d", value);
49 : buff[sizeof(buff) - 1] = 0;
50 : return Add(buff);
51 : }
52 :
53 : /// did all the values fit?
54 : bool Fit() const { return mWriter.Fit(); }
55 :
56 : /// Was nothing written yet?
57 : bool Empty() const { return mWriter.Needed() == 0; }
58 :
59 : /// Write a formatted string to the stringbuilder
60 : StringBuilderBase & AddFormat(const char * format, ...) ENFORCE_FORMAT(2, 3);
61 :
62 : /// For strings we often want to know when they were truncated. If the underlying writer did
63 : /// not fit, this replaces the last 3 characters with "."
64 : StringBuilderBase & AddMarkerIfOverflow();
65 :
66 341 : StringBuilderBase & Reset()
67 : {
68 341 : mWriter.Reset();
69 341 : NullTerminate();
70 341 : return *this;
71 : }
72 :
73 : /// access the underlying value
74 704 : const char * c_str() const { return reinterpret_cast<const char *>(mWriter.Buffer()); }
75 :
76 : private:
77 : Encoding::BufferWriter mWriter;
78 :
79 3735 : void NullTerminate()
80 : {
81 3735 : if (mWriter.Fit())
82 : {
83 3727 : mWriter.Buffer()[mWriter.Needed()] = 0;
84 : }
85 : else
86 : {
87 8 : mWriter.Buffer()[mWriter.Size()] = 0;
88 : }
89 3735 : }
90 : };
91 :
92 : /// a preallocated sized string builder
93 : template <size_t kSize>
94 : class StringBuilder : public StringBuilderBase
95 : {
96 : public:
97 497 : StringBuilder() : StringBuilderBase(mBuffer, kSize) {}
98 :
99 : private:
100 : char mBuffer[kSize];
101 : };
102 :
103 : } // namespace chip
|