00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #if !defined(INCLUDED_STREAM_TEXTSTREAM_H)
00023 #define INCLUDED_STREAM_TEXTSTREAM_H
00024
00027
00028 #include "itextstream.h"
00029
00030 #include <cctype>
00031 #include <cstddef>
00032 #include <cmath>
00033 #include <stdio.h>
00034 #include <string.h>
00035 #include <algorithm>
00036 #include <glib.h>
00037 #include <string>
00038
00039 #include "generic/arrayrange.h"
00040
00041 namespace TextOutputDetail {
00042 inline char* write_unsigned_nonzero_decimal_backward(char* ptr, unsigned int decimal) {
00043 for (; decimal != 0; decimal /= 10) {
00044 *--ptr = char('0' + int(decimal % 10));
00045 }
00046 return ptr;
00047 }
00048
00049 #if defined (_WIN64) || defined (__LP64__) || defined (__APPLE__)
00050 inline char* write_size_t_nonzero_decimal_backward(char* ptr, size_t decimal) {
00051 for (; decimal != 0; decimal /= 10) {
00052 *--ptr = char('0' + (size_t)(decimal % 10));
00053 }
00054 return ptr;
00055 }
00056 #endif
00057
00058 inline char* write_signed_nonzero_decimal_backward(char* ptr, int decimal, bool show_positive) {
00059 const bool negative = decimal < 0 ;
00060 ptr = write_unsigned_nonzero_decimal_backward(ptr, negative ? -decimal : decimal);
00061 if (negative) {
00062 *--ptr = '-';
00063 } else if (show_positive) {
00064 *--ptr = '+';
00065 }
00066 return ptr;
00067 }
00068
00069 inline char* write_unsigned_nonzero_decimal_backward(char* ptr, unsigned int decimal, bool show_positive) {
00070 ptr = write_unsigned_nonzero_decimal_backward(ptr, decimal);
00071 if (show_positive) {
00072 *--ptr = '+';
00073 }
00074 return ptr;
00075 }
00076
00077 #if defined (_WIN64) || defined (__LP64__) || defined (__APPLE__)
00078 inline char* write_size_t_nonzero_decimal_backward(char* ptr, size_t decimal, bool show_positive) {
00079 ptr = write_size_t_nonzero_decimal_backward(ptr, decimal);
00080 if (show_positive) {
00081 *--ptr = '+';
00082 }
00083 return ptr;
00084 }
00085 #endif
00086
00087 inline char* write_signed_decimal_backward(char* ptr, int decimal, bool show_positive) {
00088 if (decimal == 0) {
00089 *--ptr = '0';
00090 } else {
00091 ptr = write_signed_nonzero_decimal_backward(ptr, decimal, show_positive);
00092 }
00093 return ptr;
00094 }
00095
00096 inline char* write_unsigned_decimal_backward(char* ptr, unsigned int decimal, bool show_positive) {
00097 if (decimal == 0) {
00098 *--ptr = '0';
00099 } else {
00100 ptr = write_unsigned_nonzero_decimal_backward(ptr, decimal, show_positive);
00101 }
00102 return ptr;
00103 }
00104
00105 #if defined (_WIN64) || defined (__LP64__) || defined (__APPLE__)
00106 inline char* write_size_t_decimal_backward(char* ptr, size_t decimal, bool show_positive) {
00107 if (decimal == 0) {
00108 *--ptr = '0';
00109 } else {
00110 ptr = write_size_t_nonzero_decimal_backward(ptr, decimal, show_positive);
00111 }
00112 return ptr;
00113 }
00114 #endif
00115 }
00116
00117
00119 template<typename TextOutputStreamType>
00120 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, char c) {
00121 ostream.write(&c, 1);
00122 return ostream;
00123 }
00124
00128 template<typename TextOutputStreamType>
00129 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const double d) {
00130 const std::size_t bufferSize = 16;
00131 char buf[bufferSize];
00132 ostream.write(buf, g_snprintf(buf, bufferSize, "%g", d));
00133 return ostream;
00134 }
00135
00138 template<typename TextOutputStreamType>
00139 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const float f) {
00140 return ostream_write(ostream, static_cast<double>(f));
00141 }
00142
00145 template<typename TextOutputStreamType>
00146 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const int i) {
00147 const std::size_t bufferSize = 16;
00148 char buf[bufferSize];
00149 char* begin = TextOutputDetail::write_signed_decimal_backward(buf + bufferSize, i, false);
00150 ostream.write(begin, (buf + bufferSize) - begin);
00151 return ostream;
00152 }
00153
00154 typedef unsigned int Unsigned;
00155
00157 template<typename TextOutputStreamType>
00158 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const Unsigned i) {
00159 const std::size_t bufferSize = 16;
00160 char buf[bufferSize];
00161 char* begin = TextOutputDetail::write_unsigned_decimal_backward(buf + bufferSize, i, false);
00162 ostream.write(begin, (buf + bufferSize) - begin);
00163 return ostream;
00164 }
00165
00166 #if defined (_WIN64) || defined (__LP64__) || defined (__APPLE__)
00167
00169 template<typename TextOutputStreamType>
00170 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const size_t i) {
00171
00172 const std::size_t bufferSize = 32;
00173 char buf[bufferSize];
00174 char* begin = TextOutputDetail::write_size_t_decimal_backward(buf + bufferSize, i, false);
00175 ostream.write(begin, (buf + bufferSize) - begin);
00176 return ostream;
00177 }
00178
00179 #endif
00180
00182 template<typename TextOutputStreamType>
00183 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const char* string) {
00184 ostream.write(string, strlen(string));
00185 return ostream;
00186 }
00187
00189 template<typename TextOutputStreamType>
00190 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const std::string& string) {
00191 ostream.write(string.c_str(), string.length());
00192 return ostream;
00193 }
00194
00195 class HexChar {
00196 public:
00197 char m_value;
00198 HexChar(char value) : m_value(value) {
00199 }
00200 };
00201
00203 template<typename TextOutputStreamType>
00204 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const HexChar& c) {
00205 const std::size_t bufferSize = 16;
00206 char buf[bufferSize];
00207 ostream.write(buf, g_snprintf(buf, bufferSize, "%X", c.m_value & 0xFF));
00208 return ostream;
00209 }
00210
00211 class FloatFormat {
00212 public:
00213 double m_f;
00214 int m_width;
00215 int m_precision;
00216 FloatFormat(double f, int width, int precision)
00217 : m_f(f), m_width(width), m_precision(precision) {
00218 }
00219 };
00220
00222 template<typename TextOutputStreamType>
00223 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const FloatFormat& formatted) {
00224 const std::size_t bufferSize = 32;
00225 char buf[bufferSize];
00226 ostream.write(buf, g_snprintf(buf, bufferSize, "%*.*lf", formatted.m_width, formatted.m_precision, formatted.m_f));
00227 return ostream;
00228 }
00229
00233 class Decimal {
00234 public:
00235 double m_f;
00236 Decimal(double f) : m_f(f) {
00237 }
00238 };
00239
00241 template<typename TextOutputStreamType>
00242 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const Decimal& decimal) {
00243 const int bufferSize = 22;
00244 char buf[bufferSize];
00245 std::size_t length = g_snprintf(buf, bufferSize, "%.7g", decimal.m_f);
00246 ostream.write(buf, length);
00247 return ostream;
00248 }
00249
00250
00252 template<typename TextOutputStreamType>
00253 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const StringRange& range) {
00254 ostream.write(range.first, range.last - range.first);
00255 return ostream;
00256 }
00257
00258 template<typename Type>
00259 class Quoted {
00260 public:
00261 const Type& m_type;
00262 Quoted(const Type& type)
00263 : m_type(type) {
00264 }
00265 };
00266
00267 template<typename Type>
00268 inline Quoted<Type> makeQuoted(const Type& type) {
00269 return Quoted<Type>(type);
00270 }
00271
00273 template<typename TextOutputStreamType, typename Type>
00274 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const Quoted<Type>& quoted) {
00275 return ostream << '"' << quoted.m_type << '"';
00276 }
00277
00278
00279 class LowerCase {
00280 public:
00281 const char* m_string;
00282 LowerCase(const char* string) : m_string(string) {
00283 }
00284 };
00285
00287 template<typename TextOutputStreamType>
00288 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const LowerCase& lower) {
00289 for (const char* p = lower.m_string; *p != '\0'; ++p) {
00290 ostream << static_cast<char>(std::tolower(*p));
00291 }
00292 return ostream;
00293 }
00294
00295
00297 template < typename TextInputStreamType, int SIZE = 1024 >
00298 class SingleCharacterInputStream {
00299 TextInputStreamType& m_inputStream;
00300 char m_buffer[SIZE];
00301 char* m_cur;
00302 char* m_end;
00303
00304 bool fillBuffer() {
00305 m_end = m_buffer + m_inputStream.read(m_buffer, SIZE);
00306 m_cur = m_buffer;
00307 return m_cur != m_end;
00308 }
00309 public:
00310
00311 SingleCharacterInputStream(TextInputStreamType& inputStream) : m_inputStream(inputStream), m_cur(m_buffer), m_end(m_buffer) {
00312 }
00313 bool readChar(char& c) {
00314 if (m_cur == m_end && !fillBuffer()) {
00315 return false;
00316 }
00317
00318 c = *m_cur++;
00319 return true;
00320 }
00321 };
00322
00324 class SingleCharacterOutputStream : public TextOutputStream {
00325 enum unnamed0 { m_bufsize = 1024 };
00326 TextOutputStream& m_ostream;
00327 char m_buffer[m_bufsize];
00328 char* m_pos;
00329 const char* m_end;
00330
00331 const char* end() const {
00332 return m_end;
00333 }
00334 void reset() {
00335 m_pos = m_buffer;
00336 }
00337 void flush() {
00338 m_ostream.write(m_buffer, m_pos - m_buffer);
00339 reset();
00340 }
00341 public:
00342 SingleCharacterOutputStream(TextOutputStream& ostream) : m_ostream(ostream), m_pos(m_buffer), m_end(m_buffer + m_bufsize) {
00343 }
00344 ~SingleCharacterOutputStream() {
00345 flush();
00346 }
00347 void write(const char c) {
00348 if (m_pos == end()) {
00349 flush();
00350 }
00351 *m_pos++ = c;
00352 }
00353 std::size_t write(const char* buffer, std::size_t length) {
00354 const char*const end = buffer + length;
00355 for (const char* p = buffer; p != end; ++p) {
00356 write(*p);
00357 }
00358 return length;
00359 }
00360 };
00361
00363 template < typename TextOutputStreamType, int SIZE = 1024 >
00364 class BufferedTextOutputStream : public TextOutputStream {
00365 TextOutputStreamType outputStream;
00366 char m_buffer[SIZE];
00367 char* m_cur;
00368
00369 public:
00370 BufferedTextOutputStream(TextOutputStreamType& outputStream) : outputStream(outputStream), m_cur(m_buffer) {
00371 }
00372 ~BufferedTextOutputStream() {
00373 outputStream.write(m_buffer, m_cur - m_buffer);
00374 }
00375 std::size_t write(const char* buffer, std::size_t length) {
00376 std::size_t remaining = length;
00377 for (;;) {
00378 std::size_t n = std::min(remaining, std::size_t((m_buffer + SIZE) - m_cur));
00379 m_cur = std::copy(buffer, buffer + n, m_cur);
00380 remaining -= n;
00381 if (remaining == 0) {
00382 return 0;
00383 }
00384 outputStream.write(m_buffer, SIZE);
00385 m_cur = m_buffer;
00386 }
00387 }
00388 };
00389
00390 #endif