Mercurial > code
changeset 266:41bdde9027c0
Pack:
* TypeInfo<T>::convert does not check and is constexpr
* Pack::convert does the check though
* Make overloads for std::[oi]stream available for different streams
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 14 Oct 2014 12:59:10 +0200 |
parents | 4ddc300e8998 |
children | bc9b5e7421a7 |
files | C++/Pack.cpp C++/Pack.h |
diffstat | 2 files changed, 93 insertions(+), 88 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/Pack.cpp Tue Oct 14 11:40:50 2014 +0200 +++ b/C++/Pack.cpp Tue Oct 14 12:59:10 2014 +0200 @@ -28,6 +28,6 @@ return (ptr[0] == 1) ? Pack::Little : Pack::Big; } -} +} // !namespace const Pack::Endian Pack::mode = checkMode();
--- a/C++/Pack.h Tue Oct 14 11:40:50 2014 +0200 +++ b/C++/Pack.h Tue Oct 14 12:59:10 2014 +0200 @@ -46,37 +46,6 @@ Big //! Big endian }; -private: - static void writeFile(std::ofstream &, Endian) - { - // dummy, stop recursion - } - - template <typename T, typename... Args> - static void writeFile(std::ofstream &out, Endian endian, const T &value, Args&... args) - { - static_assert(TypeInfo<T>::supported, "unsupported type"); - - T ret = convert(value, endian); - out.write(reinterpret_cast<const char *>(&ret), TypeInfo<T>::size); - writeFile(out, endian, args...); - } - - static void readFile(std::ifstream &, Endian) - { - // dummy, stop recursion - } - - template <typename T, typename... Args> - static void readFile(std::ifstream &in, Endian endian, T &value, Args&&... args) - { - static_assert(TypeInfo<T>::supported, "unsupported type"); - - in.read(reinterpret_cast<char *>(&value), TypeInfo<T>::size); - value = convert(value, endian); - readFile(in, endian, args...); - } - public: /** * Host system endian mode. @@ -92,21 +61,51 @@ template <typename T> struct TypeInfo { static const bool supported = false; - static const size_t size = 0; }; /** - * Convert data. + * Convert data only if the requested endian is different. * * @param value the value to convert if needed * @param endian the endian mode * @return the converted value */ template <typename T> - static T convert(T value, Endian endian); + static inline T convert(T value, Endian endian) + { + static_assert(TypeInfo<T>::supported, "unsupported type"); + + if (endian != mode) + return TypeInfo<T>::convert(value, endian); + + return value; + } + + /** + * Write nothing, stop recursion. + */ + static void write(std::ostream &, Endian) + { + } /** - * Write binary data to the file + * Write binary data to the stream. + * + * @param out the output stream + * @param endian the endian mode + * @param args the arguments + * @throw std::runtime_exception on error + */ + template <typename T, typename... Args> + static void write(std::ostream &out, Endian endian, const T &value, const Args&... args) + { + T ret = convert(value, endian); + out.write(reinterpret_cast<const char *>(&ret), TypeInfo<T>::size); + write(out, endian, args...); + } + + /** + * Write binary data to the file. * * @param path the path to the file * @param endian the endian mode @@ -114,9 +113,7 @@ * @throw std::runtime_exception on error */ template <typename... Args> - static void write(const std::string &path, - Endian endian, - Args&&... args) + static void write(const std::string &path, Endian endian, const Args&... args) { std::ofstream out; @@ -124,11 +121,34 @@ if (!out.is_open()) throw std::runtime_error("Can't open file for writing"); - writeFile(out, endian, std::forward<Args>(args)...); + write(out, endian, args...); + } + + /** + * Read nothing, stop recursion. + */ + static void read(std::istream &, Endian) + { } /** - * Read binary data from the file + * Read binary data from the stream. + * + * @param in the input stream + * @param endian the endian mode + * @param args the arguments + * @throw std::runtime_exception on error + */ + template <typename T, typename... Args> + static void read(std::istream &in, Endian endian, T &value, Args&... args) + { + in.read(reinterpret_cast<char *>(&value), TypeInfo<T>::size); + value = convert(value, endian); + read(in, endian, args...); + } + + /** + * Read binary data from the file. * * @param path the path to the file * @param endian the endian mode @@ -136,9 +156,7 @@ * @throw std::runtime_exception on error */ template <typename... Args> - static void read(const std::string &path, - Endian endian, - Args&&... args) + static void read(const std::string &path, Endian endian, Args&&... args) { std::ifstream in; @@ -146,65 +164,53 @@ if (!in.is_open()) throw std::runtime_error("Can't open file for reading"); - readFile(in, endian, std::forward<Args>(args)...); + read(in, endian, args...); } }; template <> struct Pack::TypeInfo<uint8_t> { - static const bool supported = true; - static const size_t size = 1; + static constexpr const bool supported = true; + static constexpr const size_t size = sizeof (uint8_t); + + static constexpr uint8_t convert(uint8_t v, Endian endian) + { + return v; + } }; template <> struct Pack::TypeInfo<uint16_t> { - static const bool supported = true; - static const size_t size = 2; + static constexpr const bool supported = true; + static constexpr const size_t size = sizeof (uint16_t); + + static constexpr uint16_t convert(uint16_t v, Endian endian) + { + return (((v >> 8) & 0x00FFL) | ((v << 8) & 0xFF00L)); + } }; template <> struct Pack::TypeInfo<uint32_t> { - static const bool supported = true; - static const size_t size = 4; + static constexpr const bool supported = true; + static constexpr const size_t size = sizeof (uint32_t); + + static constexpr uint32_t convert(uint32_t v, Endian endian) + { + return ((((v) >> 24) & 0x000000FFL) + | (((v) >> 8) & 0x0000FF00L) + | (((v) << 8) & 0x00FF0000L) + | (((v) << 24) & 0xFF000000L)); + } }; template <> struct Pack::TypeInfo<uint64_t> { - static const bool supported = true; - static const size_t size = 8; -}; - -template <> -inline uint8_t Pack::convert(uint8_t v, Endian) -{ - return v; -} - -template <> -inline uint16_t Pack::convert(uint16_t v, Endian endian) -{ - if (mode != endian) - return (((v >> 8) & 0x00FFL) | ((v << 8) & 0xFF00L)); + static constexpr const bool supported = true; + static constexpr const size_t size = sizeof (uint64_t); - return v; -} - -template <> -inline uint32_t Pack::convert(uint32_t v, Endian endian) -{ - if (mode != endian) - return ((((v) >> 24) & 0x000000FFL) - | (((v) >> 8) & 0x0000FF00L) - | (((v) << 8) & 0x00FF0000L) - | (((v) << 24) & 0xFF000000L)); - - return v; -} - -template <> -inline uint64_t Pack::convert(uint64_t v, Endian endian) -{ - if (mode != endian) + static constexpr uint64_t convert(uint64_t v, Endian endian) + { return ((((v) & 0xff00000000000000ull) >> 56) | (((v) & 0x00ff000000000000ull) >> 40) | (((v) & 0x0000ff0000000000ull) >> 24) @@ -213,8 +219,7 @@ | (((v) & 0x0000000000ff0000ull) << 24) | (((v) & 0x000000000000ff00ull) << 40) | (((v) & 0x00000000000000ffull) << 56)); - - return v; -} + } +}; #endif // !_PACK_H_