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_