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 315 : StringBuilderBase(char * buffer, size_t size) : mWriter(reinterpret_cast<uint8_t *>(buffer), size - 1) 31 : { 32 : nlASSERT(size > 0); 33 315 : buffer[0] = 0; // make c-str work by default 34 315 : } 35 : 36 : /// Append a null terminated string 37 1697 : StringBuilderBase & Add(const char * s) 38 : { 39 1697 : mWriter.Put(s); 40 1697 : NullTerminate(); 41 1697 : 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 296 : StringBuilderBase & Reset() 67 : { 68 296 : mWriter.Reset(); 69 296 : NullTerminate(); 70 296 : return *this; 71 : } 72 : 73 : /// access the underlying value 74 668 : const char * c_str() const { return reinterpret_cast<const char *>(mWriter.Buffer()); } 75 : 76 : private: 77 : Encoding::BufferWriter mWriter; 78 : 79 3690 : void NullTerminate() 80 : { 81 3690 : if (mWriter.Fit()) 82 : { 83 3682 : mWriter.Buffer()[mWriter.Needed()] = 0; 84 : } 85 : else 86 : { 87 8 : mWriter.Buffer()[mWriter.Size()] = 0; 88 : } 89 3690 : } 90 : }; 91 : 92 : /// a preallocated sized string builder 93 : template <size_t kSize> 94 : class StringBuilder : public StringBuilderBase 95 : { 96 : public: 97 315 : StringBuilder() : StringBuilderBase(mBuffer, kSize) {} 98 : 99 : private: 100 : char mBuffer[kSize]; 101 : }; 102 : 103 : } // namespace chip