diff --git a/coding/endianness.hpp b/coding/endianness.hpp index 748772caa2..e68e328886 100644 --- a/coding/endianness.hpp +++ b/coding/endianness.hpp @@ -2,6 +2,9 @@ #include "../base/base.hpp" +#include "../std/type_traits.hpp" + + // #define ENDIAN_IS_BIG inline bool IsBigEndian() @@ -15,7 +18,8 @@ inline bool IsBigEndian() template T ReverseByteOrder(T t) { - // TODO: Static check that T is primitive type + STATIC_ASSERT(is_integral::value); + T res; char const * a = reinterpret_cast(&t); char * b = reinterpret_cast(&res); diff --git a/coding/streams_sink.hpp b/coding/streams_sink.hpp index 23ecad90f3..b80669560d 100644 --- a/coding/streams_sink.hpp +++ b/coding/streams_sink.hpp @@ -4,6 +4,8 @@ #include "reader.hpp" #include "write_to_sink.hpp" +#include "../std/type_traits.hpp" + namespace stream { @@ -14,39 +16,11 @@ namespace stream public: SinkReaderStream(TReader & reader) : m_reader(reader) {} - SinkReaderStream & operator >> (char & t) + template + typename enable_if, SinkReaderStream &>::type + operator >> (T & t) { - t = ReadPrimitiveFromSource(m_reader); - return (*this); - } - SinkReaderStream & operator >> (uint64_t & t) - { - t = ReadPrimitiveFromSource(m_reader); - return (*this); - } - SinkReaderStream & operator >> (uint32_t & t) - { - t = ReadPrimitiveFromSource(m_reader); - return (*this); - } - SinkReaderStream & operator >> (uint16_t & t) - { - t = ReadPrimitiveFromSource(m_reader); - return (*this); - } - SinkReaderStream & operator >> (int64_t & t) - { - t = ReadPrimitiveFromSource(m_reader); - return (*this); - } - SinkReaderStream & operator >> (int32_t & t) - { - t = ReadPrimitiveFromSource(m_reader); - return (*this); - } - SinkReaderStream & operator >> (int16_t & t) - { - t = ReadPrimitiveFromSource(m_reader); + t = ReadPrimitiveFromSource(m_reader); return (*this); } @@ -65,10 +39,10 @@ namespace stream SinkReaderStream & operator >> (double & t) { STATIC_ASSERT(sizeof(double) == sizeof(int64_t)); - operator>>(reinterpret_cast(t)); + int64_t * tInt = reinterpret_cast(&t); + operator >> (*tInt); return *this; } - }; template class SinkWriterStream @@ -78,37 +52,9 @@ namespace stream public: SinkWriterStream(TWriter & writer) : m_writer(writer) {} - SinkWriterStream & operator << (char t) - { - WriteToSink(m_writer, t); - return (*this); - } - SinkWriterStream & operator << (uint64_t t) - { - WriteToSink(m_writer, t); - return (*this); - } - SinkWriterStream & operator << (uint32_t t) - { - WriteToSink(m_writer, t); - return (*this); - } - SinkWriterStream & operator << (uint16_t t) - { - WriteToSink(m_writer, t); - return (*this); - } - SinkWriterStream & operator << (int64_t t) - { - WriteToSink(m_writer, t); - return (*this); - } - SinkWriterStream & operator << (int32_t t) - { - WriteToSink(m_writer, t); - return (*this); - } - SinkWriterStream & operator << (int16_t t) + template + typename enable_if, SinkWriterStream &>::type + operator << (T const & t) { WriteToSink(m_writer, t); return (*this); @@ -129,10 +75,9 @@ namespace stream SinkWriterStream & operator << (double t) { STATIC_ASSERT(sizeof(double) == sizeof(int64_t)); - int64_t tInt = *reinterpret_cast(&t); - operator<<(tInt); + int64_t const tInt = *reinterpret_cast(&t); + operator << (tInt); return (*this); } - }; } diff --git a/coding/write_to_sink.hpp b/coding/write_to_sink.hpp index 48043b0b88..163a54cad8 100644 --- a/coding/write_to_sink.hpp +++ b/coding/write_to_sink.hpp @@ -2,55 +2,14 @@ #include "endianness.hpp" -template void WriteToSink(TSink & sink, unsigned char c) -{ - sink.Write(&c, 1); -} +#include "../std/type_traits.hpp" -template void WriteToSink(TSink & sink, signed char c) -{ - sink.Write(&c, 1); -} -template void WriteToSink(TSink & sink, char c) +template +typename enable_if, void>::type WriteToSink(TSink & sink, T const & v) { - sink.Write(&c, 1); -} - -template void WriteToSink(TSink & sink, uint16_t v) -{ - uint16_t t = SwapIfBigEndian(v); - sink.Write(&t, 2); -} - -template void WriteToSink(TSink & sink, int16_t v) -{ - int16_t t = SwapIfBigEndian(v); - sink.Write(&t, 2); -} - -template void WriteToSink(TSink & sink, int32_t v) -{ - int32_t t = SwapIfBigEndian(v); - sink.Write(&t, 4); -} - -template void WriteToSink(TSink & sink, uint32_t v) -{ - uint32_t t = SwapIfBigEndian(v); - sink.Write(&t, 4); -} - -template void WriteToSink(TSink & sink, int64_t v) -{ - int64_t t = SwapIfBigEndian(v); - sink.Write(&t, 8); -} - -template void WriteToSink(TSink & sink, uint64_t v) -{ - uint64_t t = SwapIfBigEndian(v); - sink.Write(&t, 8); + T const t = SwapIfBigEndian(v); + sink.Write(&t, sizeof(T)); } template void WriteZeroesToSink(TSink & sink, uint64_t size) @@ -61,14 +20,13 @@ template void WriteZeroesToSink(TSink & sink, uint64_t size) sink.Write(zeroes, size & 255); } -template -struct WriterFunctor +template class WriterFunctor { SinkT & m_Sink; - explicit WriterFunctor(SinkT & sink) : m_Sink(sink) {} - template - inline void operator() (T const & t) const +public: + explicit WriterFunctor(SinkT & sink) : m_Sink(sink) {} + template void operator() (T const & t) const { m_Sink.Write(&t, sizeof(T)); } diff --git a/std/type_traits.hpp b/std/type_traits.hpp index 15016924fc..769bbf22a6 100644 --- a/std/type_traits.hpp +++ b/std/type_traits.hpp @@ -1,17 +1,31 @@ #pragma once #include "common_defines.hpp" +#include "target_os.hpp" #ifdef new #undef new #endif +#ifdef OMIM_OS_MAC +// http://stackoverflow.com/questions/8173620/c-boost-1-48-type-traits-and-cocoa-inclusion-weirdness +// Cocoa defines "check" macros as is. It breaks compilation of boost/type_traits. +#ifdef check +#undef check +#endif +#endif + #include +#include + +using boost::enable_if; + using boost::is_same; using boost::make_signed; using boost::make_unsigned; using boost::is_signed; using boost::is_unsigned; using boost::is_floating_point; +using boost::is_integral; #ifdef DEBUG_NEW #define new DEBUG_NEW