lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
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