textstream.h

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2001-2006, William Joseph.
00003 All Rights Reserved.
00004 
00005 This file is part of GtkRadiant.
00006 
00007 GtkRadiant is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 GtkRadiant is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GtkRadiant; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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     // max is 18446744073709551615, buffer of 32 chars should always be enough
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

Generated by  doxygen 1.6.2