00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef _OASYS_STRING_BUFFER_H_
00019 #define _OASYS_STRING_BUFFER_H_
00020
00021 #include <algorithm>
00022
00023 #include "../debug/Log.h"
00024 #include "ScratchBuffer.h"
00025
00026 namespace oasys {
00027
00028 class ExpandableBuffer;
00029
00038 class StringBuffer {
00039 public:
00044 StringBuffer(size_t initsz = 256, const char* initstr = 0);
00045
00047 StringBuffer(const char* fmt, ...) PRINTFLIKE(2, 3);
00048
00050 StringBuffer(ExpandableBuffer* buffer, bool own_buf);
00052
00053 ~StringBuffer();
00054
00058 ExpandableBuffer* expandable_buf() { return buf_; }
00059
00063 const char* data() const { return buf_->raw_buf(); }
00064
00068 char* data() { return buf_->raw_buf(); }
00069
00074 size_t length() const { return buf_->len(); }
00075
00079 const char* c_str() const;
00080
00088 size_t append(const char* str, size_t len = 0);
00089
00096 size_t append(const std::string& str)
00097 {
00098 return append(str.data(), str.length());
00099 }
00100
00107 size_t append(char c);
00108
00115 size_t appendf(const char* fmt, ...) PRINTFLIKE(2, 3);
00116
00135 size_t vappendf(const char* fmt, size_t* lenp, va_list ap);
00136
00142 size_t append_int(u_int32_t val, int base);
00143
00149 size_t append_int(u_int64_t val, int base);
00150
00154 void trim(size_t cnt)
00155 {
00156 ASSERT(buf_->len() >= cnt);
00157 buf_->set_len(buf_->len() - cnt);
00158 }
00159
00163 void set_length(size_t len)
00164 {
00165 ASSERT(buf_->buf_len() >= len);
00166 buf_->set_len(len);
00167 }
00168
00169 private:
00170 mutable ExpandableBuffer* buf_;
00171 bool own_buf_;
00172 };
00173
00179 #define STRINGBUFFER_VAPPENDF(_stringbuf, _fmt) \
00180 do { \
00181 size_t ret; \
00182 size_t len = 0; \
00183 \
00184 \
00185 { \
00186 va_list ap; \
00187 va_start(ap, _fmt); \
00188 ret = (_stringbuf).vappendf(_fmt, &len, ap); \
00189 va_end(ap); \
00190 } \
00191 \
00192 \
00193 if (ret >= len) \
00194 { \
00195 (_stringbuf).trim(len); \
00196 len = ret; \
00197 va_list ap; \
00198 va_start(ap, _fmt); \
00199 ret = (_stringbuf).vappendf(_fmt, &len, ap); \
00200 va_end(ap); \
00201 } \
00202 \
00203 ASSERT(ret == len); \
00204 } while (0)
00205
00214 template<size_t _sz>
00215 class StaticStringBuffer : public StringBuffer {
00216 public:
00220 StaticStringBuffer()
00221 : StringBuffer(new ScratchBuffer<char*, _sz>(), true) {}
00222
00228 StaticStringBuffer(const char* fmt, ...) PRINTFLIKE(2, 3);
00229 };
00230
00231 template <size_t _sz>
00232 StaticStringBuffer<_sz>::StaticStringBuffer(const char* fmt, ...)
00233 : StringBuffer(new ScratchBuffer<char*, _sz>(), true)
00234 {
00235 if (fmt != 0)
00236 {
00237 STRINGBUFFER_VAPPENDF(*this, fmt);
00238 }
00239 }
00240
00241
00242 }
00243
00244 #endif