1 /* 2 * Copyright 2018 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef RTC_BASE_STRINGS_STRING_BUILDER_H_ 12 #define RTC_BASE_STRINGS_STRING_BUILDER_H_ 13 14 #include <cstdio> 15 #include <string> 16 #include <utility> 17 18 #include "absl/strings/string_view.h" 19 #include "api/array_view.h" 20 #include "rtc_base/string_encode.h" 21 22 namespace rtc { 23 24 // This is a minimalistic string builder class meant to cover the most cases of 25 // when you might otherwise be tempted to use a stringstream (discouraged for 26 // anything except logging). It uses a fixed-size buffer provided by the caller 27 // and concatenates strings and numbers into it, allowing the results to be 28 // read via `str()`. 29 class SimpleStringBuilder { 30 public: 31 explicit SimpleStringBuilder(rtc::ArrayView<char> buffer); 32 SimpleStringBuilder(const SimpleStringBuilder&) = delete; 33 SimpleStringBuilder& operator=(const SimpleStringBuilder&) = delete; 34 35 SimpleStringBuilder& operator<<(char ch); 36 SimpleStringBuilder& operator<<(absl::string_view str); 37 SimpleStringBuilder& operator<<(int i); 38 SimpleStringBuilder& operator<<(unsigned i); 39 SimpleStringBuilder& operator<<(long i); // NOLINT 40 SimpleStringBuilder& operator<<(long long i); // NOLINT 41 SimpleStringBuilder& operator<<(unsigned long i); // NOLINT 42 SimpleStringBuilder& operator<<(unsigned long long i); // NOLINT 43 SimpleStringBuilder& operator<<(float f); 44 SimpleStringBuilder& operator<<(double f); 45 SimpleStringBuilder& operator<<(long double f); 46 47 // Returns a pointer to the built string. The name `str()` is borrowed for 48 // compatibility reasons as we replace usage of stringstream throughout the 49 // code base. str()50 const char* str() const { return buffer_.data(); } 51 52 // Returns the length of the string. The name `size()` is picked for STL 53 // compatibility reasons. size()54 size_t size() const { return size_; } 55 56 // Allows appending a printf style formatted string. 57 #if defined(__GNUC__) 58 __attribute__((__format__(__printf__, 2, 3))) 59 #endif 60 SimpleStringBuilder& 61 AppendFormat(const char* fmt, ...); 62 63 private: IsConsistent()64 bool IsConsistent() const { 65 return size_ <= buffer_.size() - 1 && buffer_[size_] == '\0'; 66 } 67 68 // An always-zero-terminated fixed-size buffer that we write to. The fixed 69 // size allows the buffer to be stack allocated, which helps performance. 70 // Having a fixed size is furthermore useful to avoid unnecessary resizing 71 // while building it. 72 const rtc::ArrayView<char> buffer_; 73 74 // Represents the number of characters written to the buffer. 75 // This does not include the terminating '\0'. 76 size_t size_ = 0; 77 }; 78 79 // A string builder that supports dynamic resizing while building a string. 80 // The class is based around an instance of std::string and allows moving 81 // ownership out of the class once the string has been built. 82 // Note that this class uses the heap for allocations, so SimpleStringBuilder 83 // might be more efficient for some use cases. 84 class StringBuilder { 85 public: StringBuilder()86 StringBuilder() {} StringBuilder(absl::string_view s)87 explicit StringBuilder(absl::string_view s) : str_(s) {} 88 89 // TODO(tommi): Support construction from StringBuilder? 90 StringBuilder(const StringBuilder&) = delete; 91 StringBuilder& operator=(const StringBuilder&) = delete; 92 93 StringBuilder& operator<<(const absl::string_view str) { 94 str_.append(str.data(), str.length()); 95 return *this; 96 } 97 98 StringBuilder& operator<<(char c) = delete; 99 100 StringBuilder& operator<<(int i) { 101 str_ += rtc::ToString(i); 102 return *this; 103 } 104 105 StringBuilder& operator<<(unsigned i) { 106 str_ += rtc::ToString(i); 107 return *this; 108 } 109 110 StringBuilder& operator<<(long i) { // NOLINT 111 str_ += rtc::ToString(i); 112 return *this; 113 } 114 115 StringBuilder& operator<<(long long i) { // NOLINT 116 str_ += rtc::ToString(i); 117 return *this; 118 } 119 120 StringBuilder& operator<<(unsigned long i) { // NOLINT 121 str_ += rtc::ToString(i); 122 return *this; 123 } 124 125 StringBuilder& operator<<(unsigned long long i) { // NOLINT 126 str_ += rtc::ToString(i); 127 return *this; 128 } 129 130 StringBuilder& operator<<(float f) { 131 str_ += rtc::ToString(f); 132 return *this; 133 } 134 135 StringBuilder& operator<<(double f) { 136 str_ += rtc::ToString(f); 137 return *this; 138 } 139 140 StringBuilder& operator<<(long double f) { 141 str_ += rtc::ToString(f); 142 return *this; 143 } 144 str()145 const std::string& str() const { return str_; } 146 Clear()147 void Clear() { str_.clear(); } 148 size()149 size_t size() const { return str_.size(); } 150 Release()151 std::string Release() { 152 std::string ret = std::move(str_); 153 str_.clear(); 154 return ret; 155 } 156 157 // Allows appending a printf style formatted string. 158 StringBuilder& AppendFormat(const char* fmt, ...) 159 #if defined(__GNUC__) 160 __attribute__((__format__(__printf__, 2, 3))) 161 #endif 162 ; 163 164 private: 165 std::string str_; 166 }; 167 168 } // namespace rtc 169 170 #endif // RTC_BASE_STRINGS_STRING_BUILDER_H_ 171