Added static_assert from Loki
[ustl.git] / sistream.cc
blobfed4333b0139a87c1c718aa1eef64282702ae3b0
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 // sistream.cc
7 //
9 #include "sistream.h"
10 #include "sostream.h"
11 #include "ustring.h"
13 namespace ustl {
15 const char ios_base::c_DefaultDelimiters [istringstream::c_MaxDelimiters] = " \t\n\r;:,.?";
17 /// Default constructor.
18 istringstream::istringstream (void)
19 : istream (),
20 m_Base (0)
22 set_delimiters (c_DefaultDelimiters);
25 istringstream::istringstream (const void* p, size_type n)
26 : istream (),
27 m_Base (0)
29 link (p, n);
30 set_delimiters (c_DefaultDelimiters);
33 istringstream::istringstream (const cmemlink& source)
34 : istream (),
35 m_Base (0)
37 link (source);
38 set_delimiters (c_DefaultDelimiters);
41 /// Sets delimiters to the contents of \p delimiters.
42 void istringstream::set_delimiters (const char* delimiters)
44 fill (VectorRange (m_Delimiters), '\0');
45 strncpy (m_Delimiters, delimiters, VectorSize(m_Delimiters)-1);
48 inline bool istringstream::is_delimiter (char c) const
50 return (memchr (m_Delimiters, c, VectorSize(m_Delimiters)-1));
53 char istringstream::skip_delimiters (void)
55 char c = m_Delimiters[0];
56 while (is_delimiter(c) && (remaining() || underflow()))
57 istream::iread (c);
58 return (c);
61 void istringstream::iread (int8_t& v)
63 v = skip_delimiters();
66 typedef istringstream::iterator issiter_t;
67 template <typename T>
68 inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, T& v)
69 { v = strtol (i, const_cast<char**>(iend), base); }
70 template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t, double& v)
71 { v = strtod (i, const_cast<char**>(iend)); }
72 #ifdef HAVE_LONG_LONG
73 template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, long long& v)
74 { v = strtoll (i, const_cast<char**>(iend), base); }
75 #endif
77 template <typename T>
78 inline void istringstream::read_number (T& v)
80 v = 0;
81 if (skip_delimiters() == m_Delimiters[0])
82 return;
83 ungetc();
84 iterator ilast;
85 do {
86 str_to_num<T> (ipos(), &ilast, m_Base, v);
87 } while (ilast == end() && underflow());
88 skip (distance (ipos(), ilast));
91 void istringstream::iread (int32_t& v) { read_number (v); }
92 void istringstream::iread (double& v) { read_number (v); }
93 #if HAVE_INT64_T
94 void istringstream::iread (int64_t& v) { read_number (v); }
95 #endif
96 #if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
97 void istringstream::iread (long long& v) { read_number (v); }
98 #endif
100 void istringstream::iread (wchar_t& v)
102 if ((v = skip_delimiters()) == wchar_t(m_Delimiters[0]))
103 return;
104 size_t cs = Utf8SequenceBytes (v) - 1;
105 if (remaining() >= cs || underflow(cs) >= cs) {
106 ungetc();
107 v = *utf8in (ipos());
108 skip (cs + 1);
112 void istringstream::iread (bool& v)
114 static const char tf[2][8] = { "false", "true" };
115 char c = skip_delimiters();
116 v = (c == 't' || c == '1');
117 if (c != tf[v][0])
118 return;
119 for (const char* tv = tf[v]; c == *tv && (remaining() || underflow()); ++tv)
120 istream::iread (c);
121 ungetc();
124 void istringstream::iread (string& v)
126 v.clear();
127 char prevc, quoteChar = 0, c = skip_delimiters();
128 if (c == '\"' || c == '\'')
129 quoteChar = c;
130 else
131 v += c;
132 while (remaining() || underflow()) {
133 prevc = c;
134 istream::iread (c);
135 if (!quoteChar && is_delimiter(c))
136 break;
137 if (prevc == '\\') {
138 switch (c) {
139 case 't': c = '\t'; break;
140 case 'n': c = '\n'; break;
141 case 'r': c = '\r'; break;
142 case 'b': c = '\b'; break;
143 case 'E': c = 27; break; // ESC sequence
144 case '\"': c = '\"'; break;
145 case '\'': c = '\''; break;
146 case '\\': c = '\\'; break;
148 v.end()[-1] = c;
149 } else {
150 if (c == quoteChar)
151 break;
152 v += c;
157 void istringstream::read (void* buffer, size_type sz)
159 if (remaining() < sz && underflow(sz) < sz)
160 #ifdef WANT_STREAM_BOUNDS_CHECKING
161 verify_remaining ("read", "", sz);
162 #else
163 assert (remaining() >= size());
164 #endif
165 istream::read (buffer, sz);
168 void istringstream::read (memlink& buf)
170 if (remaining() < buf.size() && underflow(buf.size()) < buf.size())
171 #ifdef WANT_STREAM_BOUNDS_CHECKING
172 verify_remaining ("read", "", buf.size());
173 #else
174 assert (remaining() >= buf.size());
175 #endif
176 istream::read (buf);
179 /// Reads one character from the stream.
180 int istringstream::get (void)
182 int8_t v = 0;
183 if (remaining() || underflow())
184 istream::iread (v);
185 return (v);
188 /// Reads characters into \p s until \p delim is found (but not stored or extracted)
189 void istringstream::get (string& s, char delim)
191 getline (s, delim);
192 if (!s.empty() && pos() > 0 && ipos()[-1] == delim)
193 ungetc();
196 /// Reads characters into \p p,n until \p delim is found (but not stored or extracted)
197 void istringstream::get (char* p, size_type n, char delim)
199 assert (p && !n && "A non-empty buffer is required by this implementation");
200 string s;
201 get (s, delim);
202 const size_t ntc (min (n - 1, s.size()));
203 memcpy (p, s.data(), ntc);
204 p[ntc] = 0;
207 /// Reads characters into \p s until \p delim is extracted (but not stored)
208 void istringstream::getline (string& s, char delim)
210 char oldDelim [VectorSize(m_Delimiters)];
211 copy (VectorRange (m_Delimiters), oldDelim);
212 fill (VectorRange (m_Delimiters), '\0');
213 m_Delimiters[0] = delim;
214 iread (s);
215 copy (VectorRange (oldDelim), m_Delimiters);
218 /// Reads characters into \p p,n until \p delim is extracted (but not stored)
219 void istringstream::getline (char* p, size_type n, char delim)
221 assert (p && !n && "A non-empty buffer is required by this implementation");
222 string s;
223 getline (s, delim);
224 const size_t ntc (min (n - 1, s.size()));
225 memcpy (p, s.data(), ntc);
226 p[ntc] = 0;
229 /// Extract until \p delim or \p n chars have been read.
230 void istringstream::ignore (size_type n, char delim)
232 while (n-- && (remaining() || underflow()) && get() != delim);
235 } // namespace ustl