forked from andrewprock/ustl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sostream.h
213 lines (197 loc) · 8.66 KB
/
sostream.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// This file is part of the uSTL library, an STL implementation.
//
// Copyright (c) 2005 by Mike Sharov <[email protected]>
// This file is free software, distributed under the MIT License.
#pragma once
#include "ustring.h"
#include "mostream.h"
namespace ustl {
class string;
/// \class ostringstream sostream.h ustl.h
/// \ingroup TextStreams
///
/// \brief This stream writes textual data into a memory block.
///
class ostringstream : public ostream {
public:
ostringstream (const string& v = "");
ostringstream (void* p, size_t n) noexcept;
inline fmtflags flags (void) const { return _flags; }
inline fmtflags flags (fmtflags f) { fmtflags of (_flags); _flags = f; return of; }
inline fmtflags setf (fmtflags f) { fmtflags of (_flags); _flags |= f; return of; }
inline fmtflags unsetf (fmtflags f) { fmtflags of (_flags); _flags &= ~f; return of; }
inline fmtflags setf (fmtflags f, fmtflags m) { unsetf(m); return setf(f); }
void iwrite (unsigned char v);
void iwrite (wchar_t v);
inline void iwrite (char v) { iwrite ((unsigned char) v); }
inline void iwrite (short v) { iformat (v); }
inline void iwrite (unsigned short v) { iformat (v); }
inline void iwrite (int v) { iformat (v); }
inline void iwrite (unsigned int v) { iformat (v); }
inline void iwrite (long int v) { iformat (v); }
inline void iwrite (unsigned long int v) { iformat (v); }
inline void iwrite (float v) { iformat (v); }
inline void iwrite (double v) { iformat (v); }
inline void iwrite (long double v) { iformat (v); }
void iwrite (bool v);
inline void iwrite (const char* s) { write (s, strlen(s)); }
inline void iwrite (const unsigned char* s) { iwrite ((const char*) s); }
inline void iwrite (const string& v) { write (v.begin(), v.size()); }
inline void iwrite (fmtflags_bits f);
#if HAVE_THREE_CHAR_TYPES
inline void iwrite (signed char v) { iwrite ((char) v); }
#endif
#if HAVE_LONG_LONG
inline void iwrite (long long v) { iformat (v); }
inline void iwrite (unsigned long long v) { iformat (v); }
#endif
inline size_type max_size (void) const { return _buffer.max_size(); }
inline ostringstream& put (char c) { iwrite (uint8_t(c)); return *this; }
int vformat (const char* fmt, va_list args);
int format (const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
inline uint16_t width (void) const { return _width; }
inline void width (uint16_t w) { _width = w; }
inline void set_width (uint16_t w) { _width = w; }
inline char fill (void) const { return _fill; }
inline void fill (char c) { _fill = c; }
inline uint8_t precision (void) const { return _precision; }
inline void precision (uint8_t v) { _precision = v; }
inline void set_precision (uint8_t v) { _precision = v; }
void link (void* p, size_type n) noexcept;
inline void link (memlink& l) { link (l.data(), l.writable_size()); }
inline const string& str (void) { flush(); return _buffer; }
void str (const string& s);
ostringstream& write (const void* buffer, size_type size);
inline ostringstream& write (const cmemlink& buf) { return write (buf.begin(), buf.size()); }
inline ostringstream& seekp (off_t p, seekdir d =beg) { ostream::seekp(p,d); return *this; }
virtual ostream& flush (void) override { ostream::flush(); _buffer.resize (pos()); return *this; }
virtual size_type overflow (size_type n = 1) override;
protected:
inline void reserve (size_type n) { _buffer.reserve (n, false); }
inline size_type capacity (void) const { return _buffer.capacity(); }
private:
inline void write_strz (const char*) { assert (!"Writing nul characters into a text stream is not allowed"); }
inline char* encode_dec (char* fmt, uint32_t n) const noexcept;
void fmtstring (char* fmt, const char* typestr, bool bInteger) const;
template <typename T>
void iformat (T v);
private:
string _buffer; ///< The output buffer.
fmtflags _flags; ///< See ios_base::fmtflags.
uint16_t _width; ///< Field width.
uint8_t _precision; ///< Number of digits after the decimal separator.
char _fill; ///< Character for padding variable width fields (space or 0 only)
};
//----------------------------------------------------------------------
template <typename T>
inline const char* printf_typestring (const T&) { return ""; }
#define PRINTF_TYPESTRING_SPEC(type,str) \
template <> inline const char* printf_typestring (const type&) { return str; }
PRINTF_TYPESTRING_SPEC (short, "hd")
PRINTF_TYPESTRING_SPEC (unsigned short, "hu")
PRINTF_TYPESTRING_SPEC (int, "d")
PRINTF_TYPESTRING_SPEC (unsigned int, "u")
PRINTF_TYPESTRING_SPEC (long, "ld")
PRINTF_TYPESTRING_SPEC (unsigned long, "lu")
PRINTF_TYPESTRING_SPEC (float, "f")
PRINTF_TYPESTRING_SPEC (double, "lf")
PRINTF_TYPESTRING_SPEC (long double, "Lf")
#if HAVE_LONG_LONG
PRINTF_TYPESTRING_SPEC (long long, "lld")
PRINTF_TYPESTRING_SPEC (unsigned long long, "llu")
#endif
#undef PRINTF_TYPESTRING_SPEC
template <typename T>
void ostringstream::iformat (T v)
{
char fmt [16];
fmtstring (fmt, printf_typestring(v), numeric_limits<T>::is_integer);
format (fmt, v);
}
void ostringstream::iwrite (fmtflags_bits f)
{
if (f & basefield) setf (f, basefield);
else if (f & floatfield) setf (f, floatfield);
else if (f & adjustfield) setf (f, adjustfield);
setf (f);
}
//----------------------------------------------------------------------
template <typename T> struct object_text_writer {
inline void operator()(ostringstream& os, const T& v) const { v.text_write (os); }
};
template <typename T> struct integral_text_object_writer {
inline void operator()(ostringstream& os, const T& v) const { os.iwrite (v); }
};
template <typename T>
inline ostringstream& operator<< (ostringstream& os, const T& v) {
typedef typename tm::Select <tm::TypeTraits<T>::isFundamental
|| tm::TypeTraits<T>::isPointer
|| tm::Conversion<T,long>::exists,
integral_text_object_writer<T>, object_text_writer<T> >::Result object_writer_t;
object_writer_t()(os, v);
return os;
}
// Needed because if called with a char[], numeric_limits will not work. Should be removed if I find out how to partial specialize for arrays...
inline ostringstream& operator<< (ostringstream& os, const char* v)
{ os.iwrite (v); return os; }
inline ostringstream& operator<< (ostringstream& os, char* v)
{ os.iwrite (v); return os; }
//----------------------------------------------------------------------
// Object writer operators
template <> struct object_text_writer<string> {
inline void operator()(ostringstream& os, const string& v) const { os.iwrite (v); }
};
template <typename T> struct integral_text_object_writer<T*> {
inline void operator() (ostringstream& os, const T* const& v) const
{ os.iwrite ((uintptr_t)(v)); }
};
//----------------------------------------------------------------------
// Manipulators
namespace {
static constexpr const struct Sendl {
inline constexpr Sendl (void) {}
inline void text_write (ostringstream& os) const { os << '\n'; os.flush(); }
inline void write (ostream& os) const { os.iwrite ('\n'); }
} endl;
static constexpr const struct Sflush {
inline constexpr Sflush (void) {}
inline void text_write (ostringstream& os) const { os.flush(); }
inline void write (ostringstream& os) const { os.flush(); }
inline void write (ostream&) const { }
} flush;
constexpr const char ends = '\0'; ///< End of string character.
} // namespace
struct setiosflags {
inline constexpr setiosflags (ios_base::fmtflags f) : _f(f) {}
inline void text_write (ostringstream& os) const { os.setf(_f); }
private:
const ios_base::fmtflags _f;
};
struct resetiosflags {
inline constexpr resetiosflags (ios_base::fmtflags f) : _f(f) {}
inline void text_write (ostringstream& os) const { os.unsetf(_f); }
private:
const ios_base::fmtflags _f;
};
class setw {
uint16_t _w;
public:
inline constexpr setw (uint16_t w) : _w(w) {}
inline void text_write (ostringstream& os) const { os.width(_w); }
inline void write (ostringstream& os) const { os.width(_w); }
};
class setfill {
char _c;
public:
inline constexpr setfill (char c) : _c(c) {}
inline void text_write (ostringstream& os) const { os.fill(_c); }
inline void write (ostringstream& os) const { os.fill(_c); }
};
class setprecision {
uint8_t _p;
public:
inline constexpr setprecision (uint8_t p) : _p(p) {}
inline void text_write (ostringstream& os) const { os.precision(_p); }
inline void write (ostringstream& os) const { os.precision(_p); }
};
} // namespace ustl