lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
generic.h
00001 /*****************************************************/
00002 /* lean IO                      (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_IO_GENERIC
00006 #define LEAN_IO_GENERIC
00007 
00008 #include "../lean.h"
00009 #include "../strings/types.h"
00010 #include "serializer.h"
00011 #include <typeinfo>
00012 #include <iostream>
00013 #include "../strings/charstream.h"
00014 #include "../io/numeric.h"
00015 
00016 namespace lean
00017 {
00018 namespace io
00019 {
00020 
00022 template <class Type, utf8_t Delimiter = ';'>
00023 class generic_serialization
00024 {
00025 public:
00027     typedef Type value_type;
00029     static const utf8_t delimiter = Delimiter;
00030 
00032     static size_t max_length(size_t count) { return 0; }
00033 
00034     // Writes the given number of values to the given stream.
00035     static bool write(std::basic_ostream<utf8_t> &stream, const std::type_info &type, const void *values, size_t count)
00036     {
00037         if (type != typeid(value_type))
00038             return false;
00039 
00040         const value_type *typedValues = static_cast<const value_type*>(values);
00041         
00042         for (size_t i = 0; i < count; ++i)
00043         {
00044             if (i != 0)
00045                 stream << delimiter;
00046 
00047             stream << typedValues[i];
00048         }
00049 
00050         return !stream.fail();
00051     }
00052 
00053     // Writes the given number of values to the given character buffer, returning the first character not written to.
00054     static utf8_t* write(utf8_t *begin, const std::type_info &type, const void *values, size_t count)
00055     {
00056         basic_charstream<utf8_t> stream(begin);
00057         write(stream, type, values, count);
00058         return stream.write_end();
00059     }
00060 
00061     // Reads the given number of values from the given stream.
00062     static bool read(std::basic_istream<utf8_t> &stream, const std::type_info &type, void *values, size_t count)
00063     {
00064         if (type != typeid(value_type))
00065             return false;
00066 
00067         value_type *typedValues = static_cast<value_type*>(values);
00068         
00069         for (size_t i = 0; i < count; ++i)
00070         {
00071             if (i != 0)
00072                 stream.ignore(std::numeric_limits<int>::max(), delimiter); // required to be int
00073 
00074             stream >> typedValues[i];
00075         }
00076 
00077         return !stream.fail();
00078     }
00079 
00080     // Reads the given number of values from the given range of characters, returning the first character not read.
00081     static const utf8_t* read(const utf8_t *begin, const utf8_t *end, const std::type_info &type, void *values, size_t count)
00082     {
00083         basic_charstream<utf8_t> stream(const_cast<utf8_t*>(begin), const_cast<utf8_t*>(end));
00084         read(stream, type, values, count);
00085         return stream.read_end();
00086     }
00087 };
00088 
00090 template <class Type, utf8_t Delimiter = ';'>
00091 struct int_serialization : public generic_serialization<Type, Delimiter>
00092 {
00094     typedef Type value_type;
00096     static const utf8_t delimiter = Delimiter;
00097 
00099     static size_t max_length(size_t count)
00100     {
00101         // N numbers & delimiters
00102         return (max_int_string_length<Type>::value + 1) * count;
00103     }
00104 
00105     // Writes the given number of values to the given character buffer, returning the first character not written to.
00106     static utf8_t* write(utf8_t *begin, const std::type_info &type, const void *values, size_t count)
00107     {
00108         if (type != typeid(value_type))
00109             return begin;
00110 
00111         const value_type *typedValues = static_cast<const value_type*>(values);
00112         
00113         for (size_t i = 0; i < count; ++i)
00114         {
00115             if (i != 0)
00116                 *begin++ = delimiter;
00117 
00118             begin = int_to_char(begin, typedValues[i]);
00119         }
00120 
00121         return begin;
00122     }
00123     using generic_serialization<Type, Delimiter>::write;
00124 
00125     // Reads the given number of values from the given range of characters, returning the first character not read.
00126     static const utf8_t* read(const utf8_t *begin, const utf8_t *end, const std::type_info &type, void *values, size_t count)
00127     {
00128         if (type != typeid(value_type))
00129             return begin;
00130 
00131         value_type *typedValues = static_cast<value_type*>(values);
00132 
00133         for (size_t i = 0; i < count; ++i)
00134         {
00135             if (i != 0)
00136                 // Skip UNTIL next delimiter found
00137                 while (begin != end && *begin++ != delimiter);
00138 
00139             begin = char_to_int(begin, end, typedValues[i]);
00140         }
00141 
00142         return begin;
00143     }
00144     using generic_serialization<Type, Delimiter>::read;
00145 };
00146 
00148 template <class Type, utf8_t Delimiter = ';'>
00149 struct float_serialization : public generic_serialization<Type, Delimiter>
00150 {
00152     typedef Type value_type;
00154     static const utf8_t delimiter = Delimiter;
00155 
00157     static size_t max_length(size_t count)
00158     {
00159         // N numbers & delimiters
00160         return (max_float_string_length<Type>::value + 1) * count;
00161     }
00162 
00163     // Writes the given number of values to the given character buffer, returning the first character not written to.
00164     static utf8_t* write(utf8_t *begin, const std::type_info &type, const void *values, size_t count)
00165     {
00166         if (type != typeid(value_type))
00167             return begin;
00168 
00169         const value_type *typedValues = static_cast<const value_type*>(values);
00170         
00171         for (size_t i = 0; i < count; ++i)
00172         {
00173             if (i != 0)
00174                 *begin++ = delimiter;
00175 
00176             begin = float_to_char(begin, typedValues[i]);
00177         }
00178 
00179         return begin;
00180     }
00181     using generic_serialization<Type, Delimiter>::write;
00182 
00183     // Reads the given number of values from the given range of characters, returning the first character not read.
00184     static const utf8_t* read(const utf8_t *begin, const utf8_t *end, const std::type_info &type, void *values, size_t count)
00185     {
00186         if (type != typeid(value_type))
00187             return begin;
00188 
00189         value_type *typedValues = static_cast<value_type*>(values);
00190 
00191         for (size_t i = 0; i < count; ++i)
00192         {
00193             if (i != 0)
00194                 // Skip UNTIL next delimiter found
00195                 while (begin != end && *begin++ != delimiter);
00196 
00197             begin = char_to_float(begin, end, typedValues[i]);
00198         }
00199 
00200         return begin;
00201     }
00202     using generic_serialization<Type, Delimiter>::read;
00203 };
00204 
00206 template <class Serialization>
00207 class generic_serializer : public serializer, public Serialization
00208 {
00209 public:
00211     typedef Serialization serialization_type;
00212 
00214     size_t max_length(size_t count) const { return serialization_type::max_length(); }
00215 
00216     // Writes the given number of values to the given stream.
00217     bool write(std::basic_ostream<utf8_t> &stream, const std::type_info &type, const void *values, size_t count) const { return serialization_type::write(stream, type, values, count); }
00218     // Writes the given number of values to the given character buffer, returning the first character not written to.
00219     utf8_t* write(utf8_t *begin, const std::type_info &type, const void *values, size_t count) const { return serialization_type::write(begin, type, values, count); }
00220 
00221     // Reads the given number of values from the given stream.
00222     bool read(std::basic_istream<utf8_t> &stream, const std::type_info &type, void *values, size_t count) const { return serialization_type::read(stream, type, values, count); }
00223     // Reads the given number of values from the given range of characters, returning the first character not read.
00224     const utf8_t* read(const utf8_t *begin, const utf8_t *end, const std::type_info &type, void *values, size_t count) const { return serialization_type::read(begin, end, type, values, count); }
00225 
00227     const std::type_info& type_info() const { return typeid(Type); }
00228 };
00229 
00231 template <class Type>
00232 LEAN_NOINLINE const serializer& get_generic_serializer()
00233 {
00234     static generic_serializer< generic_serialization<Type> > serializer;
00235     return serializer;
00236 }
00237 
00239 template <class Type>
00240 LEAN_NOINLINE const serializer& get_int_serializer()
00241 {
00242     static generic_serializer< int_serialization<Type> > serializer;
00243     return serializer;
00244 }
00245 
00247 template <class Type>
00248 LEAN_NOINLINE const serializer& get_float_serializer()
00249 {
00250     static generic_serializer< float_serialization<Type> > serializer;
00251     return serializer;
00252 }
00253 
00254 } // namespace
00255 
00256 using io::generic_serialization;
00257 using io::int_serialization;
00258 using io::float_serialization;
00259 
00260 using io::get_generic_serializer;
00261 using io::get_int_serializer;
00262 using io::get_float_serializer;
00263 
00264 } // namespace
00265 
00266 #endif