Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
Loading...
Searching...
No Matches
string_builder.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Roc Streaming authors
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 */
8
9//! @file roc_core/string_builder.h
10//! @brief String builder.
11
12#ifndef ROC_CORE_STRING_BUILDER_H_
13#define ROC_CORE_STRING_BUILDER_H_
14
17#include "roc_core/optional.h"
18#include "roc_core/stddefs.h"
20
21namespace roc {
22namespace core {
23
24//! String builder.
25//!
26//! Allows to incrementally build a string. Doesn't own the string itself, but
27//! insetead holds a reference to external fixed-size or dynamic buffer.
28//
29//! Supports "dry run" mode when no actual writing happens. This can be used
30//! to calculate the required buffer size before writing.
31//!
32//! When used with fixed-sized buffer, all methods are signal-safe and hence
33//! can be used from a signal handler.
34class StringBuilder : public NonCopyable<> {
35public:
36 //! Construct string builder on top of fixed-size buffer.
37 //!
38 //! The builder will write output string into the given buffer.
39 //! If the output buffer is too small, the output string is truncated
40 //! and error flag is set. If the output buffer has at least one byte,
41 //! it will be always zero-terminated, even if truncation occurred.
42 //!
43 //! @p buf may be NULL. In this case, nothing will be written, but
44 //! needed_size() will be still calculated.
45 //!
46 //! If @p buf is non-NULL, @p bufsz should be non-zero so that buffer
47 //! could hold at least zero terminator. Otherwise, error flag is raised
48 //! immediately in constructor.
49 //!
50 //! If @p buf is NULL, @p bufsz may be both zero and non-zero. Use
51 //! non-zero to get an error when buffer size is exceeded (like if it was
52 //! a real buffer); use zero to disable buffer size checking (there is
53 //! no buffer anyway).
54 StringBuilder(char* buf, size_t bufsz) {
55 writer_.reset(new (writer_) StaticBufferWriter(buf, bufsz));
56 initialize_();
57 }
58
59 //! Construct string builder on top of dynamic buffer.
60 //!
61 //! The builder will write output string into the given buffer. The buffer
62 //! will be resized accordingly to the output string size plus terminating
63 //! zero byte. The buffer will be always zero-terminated.
64 template <size_t N> StringBuilder(StringBuffer<N>& buf) {
65 writer_.reset(new (writer_) DynamicBufferWriter<StringBuffer<N> >(buf));
66 initialize_();
67 }
68
69 //! Get number of bytes required to store the output string.
70 //! Includes terminating zero byte.
71 //!
72 //! @remarks
73 //! If there is non-NULL output buffer, and no error occurred, this size
74 //! is equal to actual_size(). Otherwise it may be larger.
75 size_t needed_size() const;
76
77 //! Get number of bytes actually written to the output string.
78 //! Includes terminating zero byte.
79 size_t actual_size() const;
80
81 //! Check for errors.
82 //!
83 //! @remark
84 //! Error flag is raised if any of the methods fail, and is resetted
85 //! if an assign* method succeedes.
86 bool ok() const;
87
88 //! Overwrite result with given string.
89 //! If there is not enough space, truncates the string and returns false.
90 bool assign_str(const char* str);
91
92 //! Overwrite result with given range.
93 //! If there is not enough space, truncates the string and returns false.
94 bool assign_str(const char* str_begin, const char* str_end);
95
96 //! Append to result given string.
97 //! If there is not enough space, truncates the string and returns false.
98 bool append_str(const char* str);
99
100 //! Append to result given range.
101 //! If there is not enough space, truncates the string and returns false.
102 bool append_str(const char* str_begin, const char* str_end);
103
104 //! Append to result given character.
105 //! If there is not enough space, truncates the string and returns false.
106 bool append_char(char ch);
107
108 //! Format and append to result given number.
109 //! If there is not enough space, truncates the string and returns false.
110 bool append_uint(uint64_t number, unsigned int base);
111
112private:
113 class IBufferWriter {
114 public:
115 virtual ~IBufferWriter();
116
117 virtual bool is_noop() = 0;
118 virtual bool reset() = 0;
119 virtual bool grow_by(size_t n_chars) = 0;
120 virtual ssize_t extend_by(size_t n_chars) = 0;
121 virtual char* write_ptr() = 0;
122 };
123
124 class StaticBufferWriter : public IBufferWriter {
125 public:
126 StaticBufferWriter(char* buf, size_t buf_size);
127
128 virtual bool is_noop();
129 virtual bool reset();
130 virtual bool grow_by(size_t n_chars);
131 virtual ssize_t extend_by(size_t n_chars);
132 virtual char* write_ptr();
133
134 private:
135 char* const buf_;
136 const size_t buf_max_size_;
137 size_t buf_cur_size_;
138 char* buf_wr_ptr_;
139 };
140
141 template <class Buffer = StringBuffer<> >
142 class DynamicBufferWriter : public IBufferWriter {
143 public:
144 DynamicBufferWriter(Buffer& buf)
145 : buf_(buf)
146 , buf_wr_ptr_(NULL) {
147 }
148
149 virtual bool is_noop() {
150 return false;
151 }
152
153 virtual bool reset() {
154 buf_.clear();
155 buf_wr_ptr_ = NULL;
156 return true;
157 }
158
159 virtual bool grow_by(size_t n_chars) {
160 return buf_.grow_exp(buf_.len() + n_chars);
161 }
162
163 virtual ssize_t extend_by(size_t n_chars) {
164 buf_wr_ptr_ = buf_.extend(n_chars);
165 return buf_wr_ptr_ ? (ssize_t)n_chars : -1;
166 }
167
168 virtual char* write_ptr() {
169 return buf_wr_ptr_;
170 }
171
172 private:
173 Buffer& buf_;
174 char* buf_wr_ptr_;
175 };
176
177 void initialize_();
178 void reset_();
179 bool append_(const char* str, size_t str_size, bool grow);
180
181 Optional<IBufferWriter,
182 ROC_MAX(sizeof(StaticBufferWriter), sizeof(DynamicBufferWriter<>))>
183 writer_;
184
185 size_t n_processed_;
186 size_t n_written_;
187
188 bool truncation_error_;
189 bool write_error_;
190};
191
192} // namespace core
193} // namespace roc
194
195#endif // ROC_CORE_STRING_BUILDER_H_
Base class for non-copyable objects.
Definition: noncopyable.h:23
void reset(T *ptr=NULL)
Set pointer to the newly created object, destroy old pointed object if set.
Definition: optional.h:40
size_t needed_size() const
Get number of bytes required to store the output string. Includes terminating zero byte.
bool assign_str(const char *str)
Overwrite result with given string. If there is not enough space, truncates the string and returns fa...
bool append_str(const char *str)
Append to result given string. If there is not enough space, truncates the string and returns false.
bool ok() const
Check for errors.
bool append_uint(uint64_t number, unsigned int base)
Format and append to result given number. If there is not enough space, truncates the string and retu...
bool assign_str(const char *str_begin, const char *str_end)
Overwrite result with given range. If there is not enough space, truncates the string and returns fal...
StringBuilder(StringBuffer< N > &buf)
Construct string builder on top of dynamic buffer.
StringBuilder(char *buf, size_t bufsz)
Construct string builder on top of fixed-size buffer.
size_t actual_size() const
Get number of bytes actually written to the output string. Includes terminating zero byte.
bool append_str(const char *str_begin, const char *str_end)
Append to result given range. If there is not enough space, truncates the string and returns false.
bool append_char(char ch)
Append to result given character. If there is not enough space, truncates the string and returns fals...
Helper macros.
#define ROC_MAX(a, b)
Select minum value.
Definition: macro_helpers.h:21
Root namespace.
Non-copyable object.
Optionally constructed object.
Commonly used types and functions.
String buffer.