Build system improvements
[ustl.git] / sostream.cc
blob9bfca041c86dfd0cd6d1529ee9e7a25e4dbfd48e
1 // This file is part of the ustl library, an STL implementation.
2 //
3 // Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
5 //
6 // sostream.h
7 //
9 #include "mistream.h" // for istream_iterator, referenced in utf8.h
10 #include "sostream.h"
11 #include "ustring.h"
12 #include "ulimits.h"
13 #include <stdio.h>
15 namespace ustl {
17 /// Creates an output string stream linked to the given memory area.
18 ostringstream::ostringstream (void* p, size_t n)
19 : ostream (),
20 m_Buffer (),
21 m_Flags (0),
22 m_Width (0),
23 m_Base (10),
24 m_Precision (2)
26 link (p, n);
29 /// Creates an output string stream, initializing the buffer with v.
30 ostringstream::ostringstream (const string& v)
31 : ostream (),
32 m_Buffer (v),
33 m_Flags (0),
34 m_Width (0),
35 m_Base (10),
36 m_Precision (2)
38 ostream::link (m_Buffer);
41 /// Copies \p s to the internal buffer.
42 void ostringstream::str (const string& s)
44 m_Buffer = s;
45 ostream::link (m_Buffer);
46 SetPos (m_Buffer.size());
49 /// Writes a single character into the stream.
50 void ostringstream::iwrite (uint8_t v)
52 if (remaining() >= 1 || overflow() >= 1)
53 ostream::iwrite (v);
56 /// Writes \p buf of size \p bufSize through the internal buffer.
57 void ostringstream::write_buffer (const char* buf, size_type bufSize)
59 size_type btw = 0, written = 0;
60 while ((written += btw) < bufSize && (remaining() || overflow(bufSize - written)))
61 write (buf + written, btw = min (remaining(), bufSize - written));
64 /// Simple decimal encoding of \p n into \p fmt.
65 inline char* ostringstream::encode_dec (char* fmt, uint32_t n) const
67 do {
68 *fmt++ = '0' + n % 10;
69 } while (n /= 10);
70 return (fmt);
73 /// Generates a sprintf format string for the given type.
74 void ostringstream::fmtstring (char* fmt, const char* typestr, bool bInteger) const
76 *fmt++ = '%';
77 if (m_Width)
78 fmt = encode_dec (fmt, m_Width);
79 if (m_Flags & left)
80 *fmt++ = '-';
81 if (!bInteger) {
82 *fmt++ = '.';
83 fmt = encode_dec (fmt, m_Precision);
85 while (*typestr)
86 *fmt++ = *typestr++;
87 if (bInteger) {
88 if (m_Base == 16)
89 fmt[-1] = 'X';
90 else if (m_Base == 8)
91 fmt[-1] = 'o';
92 } else {
93 if (m_Flags & scientific)
94 fmt[-1] = 'E';
96 *fmt = 0;
99 /// Writes \p v into the stream as utf8
100 void ostringstream::iwrite (wchar_t v)
102 char buffer [8];
103 *utf8out(buffer) = v;
104 write_buffer (buffer, Utf8Bytes(v));
107 /// Writes value \p v into the stream as text.
108 void ostringstream::iwrite (bool v)
110 static const char tf[2][8] = { "false", "true" };
111 write_buffer (tf[v], 5 - v);
114 /// Equivalent to a vsprintf on the string.
115 int ostringstream::vformat (const char* fmt, va_list args)
117 #if HAVE_VA_COPY
118 va_list args2;
119 #else
120 #define args2 args
121 #undef __va_copy
122 #define __va_copy(x,y)
123 #endif
124 size_t rv, space;
125 do {
126 space = remaining();
127 __va_copy (args2, args);
128 rv = vsnprintf (ipos(), space, fmt, args2);
129 if (ssize_t(rv) < 0)
130 rv = space;
131 } while (rv >= space && rv < overflow(rv + 1));
132 SetPos (pos() + min (rv, space));
133 return (rv);
136 /// Equivalent to a sprintf on the string.
137 int ostringstream::format (const char* fmt, ...)
139 va_list args;
140 va_start (args, fmt);
141 const int rv = vformat (fmt, args);
142 va_end (args);
143 return (rv);
146 /// Links to string \p l as resizable.
147 void ostringstream::link (void* p, size_t n)
149 assert ((p || !n) && "The output string buffer must not be read-only");
150 ostream::link (p, n);
151 m_Buffer.link (p, n);
154 /// Writes the contents of \p buffer of \p size into the stream.
155 void ostringstream::write (const void* buffer, size_type sz)
157 if (remaining() < sz && overflow(sz) < sz)
158 return;
159 ostream::write (buffer, sz);
162 /// Writes the contents of \p buf into the stream.
163 void ostringstream::write (const cmemlink& buf)
165 if (remaining() < buf.size() && overflow(buf.size()) < buf.size())
166 return;
167 ostream::write (buf);
170 /// Flushes the internal buffer by truncating it at the current position.
171 void ostringstream::flush (void)
173 m_Buffer.resize (pos());
176 /// Attempts to create more output space. Returns remaining().
177 ostringstream::size_type ostringstream::overflow (size_type n)
179 if (n > remaining()) {
180 const uoff_t oldPos (pos());
181 m_Buffer.reserve (oldPos + n, false);
182 m_Buffer.resize (oldPos + n);
183 ostream::link (m_Buffer);
184 SetPos (oldPos);
186 verify_remaining ("write", "text", n);
187 return (remaining());
190 } // namespace ustl