From 73adfd11dea0941805f1eb261f7997345ccfe2c0 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 28 Apr 2015 00:10:21 +0200 Subject: [PATCH 1/3] Added bitfield marshalling type --- win32/DSGame-server/DSGame-server.vcxproj | 1 + win32/DSGame-server/DSGame-server.vcxproj.filters | 3 +++ 2 files changed, 4 insertions(+) diff --git a/win32/DSGame-server/DSGame-server.vcxproj b/win32/DSGame-server/DSGame-server.vcxproj index 995b222402f..c832927129e 100644 --- a/win32/DSGame-server/DSGame-server.vcxproj +++ b/win32/DSGame-server/DSGame-server.vcxproj @@ -196,6 +196,7 @@ + diff --git a/win32/DSGame-server/DSGame-server.vcxproj.filters b/win32/DSGame-server/DSGame-server.vcxproj.filters index c37e7e49308..fb5c370de6f 100644 --- a/win32/DSGame-server/DSGame-server.vcxproj.filters +++ b/win32/DSGame-server/DSGame-server.vcxproj.filters @@ -830,6 +830,9 @@ Header Files\common\marshal + + Header Files\common\marshal + From a5a3d40cbb4d6f305159eaa1dede4b5d685e72d8 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 28 Apr 2015 00:11:38 +0200 Subject: [PATCH 2/3] This time with 100% more marshalling --- src/common/marshal/bitfield.h | 136 ++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100755 src/common/marshal/bitfield.h diff --git a/src/common/marshal/bitfield.h b/src/common/marshal/bitfield.h new file mode 100755 index 00000000000..513124e7f55 --- /dev/null +++ b/src/common/marshal/bitfield.h @@ -0,0 +1,136 @@ +#include +#include +#include + +namespace marshal +{ + template + struct bitsection + { + static std::size_t const size = Size; + typedef T type; + }; + + template + class bitfield + { + private: + + unsigned char buffer[Bytes] = {}; + + template + struct section_at + { + typedef typename section_at::section section; + }; + + template + struct section_at<0, Section, Rest...> + { + typedef Section section; + }; + + template + struct offset_at + { + static std::size_t const value = offset_at::value + section_at::section::size; + }; + + template + struct offset_at<0, Section, Rest...> + { + static std::size_t const value = 0; + }; + + public: + + static_assert(offset_at::value <= 8 * Bytes, "Provided bit sections exceed available space."); + + bitfield() + {} + + template + bitfield(C const& cont) + : bitfield(cont.begin(), cont.end()) + {} + + template + bitfield(char(&other)[N]) + : bitfield(other, other + N) + {} + + template + bitfield(unsigned char(&other)[N]) + : bitfield(other, other + N) + {} + + template + bitfield(It const& start, It const& end) + { + static_assert(sizeof(*start) == 1, "Invalid range constructor. Underlying iterator type needs to be char or unsigned char."); + + std::copy(start, end, buffer); + } + + template + void set(R value) + { + static_assert(Index < sizeof...(Sections), "Index out of bit field range."); + + auto const offset = offset_at::value; + auto const shift = offset % 8; + typedef typename section_at::section section; + + std::uint64_t copy = 0; + std::copy_n(buffer + offset / 8, ((section::size + 7) & ~7) / 8, reinterpret_cast(©)); + copy &= ~(((1 << section::size) - 1) << shift); + copy |= (value & ((1 << section::size) - 1)) << shift; + std::copy_n(reinterpret_cast(©), ((shift + section::size + 7) & ~7) / 8, buffer + offset / 8); + } + + template + typename section_at::section::type get() + { + static_assert(Index < sizeof...(Sections), "Index out of bit field range."); + + auto const offset = offset_at::value; + auto const shift = offset % 8; + typedef typename section_at::section section; + + std::uint64_t copy = 0; + std::copy_n(buffer + offset / 8, ((shift + section::size + 7) & ~7) / 8, reinterpret_cast(©)); + + return (typename section::type)((copy >> shift) & ((1 << section::size) - 1)); + } + + std::size_t size() const + { + return Bytes; + } + + unsigned char* data() + { + return buffer; + } + + unsigned char* begin() + { + return buffer; + } + + unsigned char* end() + { + return buffer + size(); + } + + unsigned char const* cbegin() const + { + return buffer; + } + + unsigned char const* cend() const + { + return buffer + size(); + } + }; +} From 4018c1afb10c482378b8c570088339be87e0db5a Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Wed, 29 Apr 2015 20:23:44 +0200 Subject: [PATCH 3/3] Removed redundancies, added safety checks, provided free getter/setter --- src/common/marshal/bitfield.h | 103 ++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 41 deletions(-) diff --git a/src/common/marshal/bitfield.h b/src/common/marshal/bitfield.h index 513124e7f55..9207978ab21 100755 --- a/src/common/marshal/bitfield.h +++ b/src/common/marshal/bitfield.h @@ -4,9 +4,16 @@ namespace marshal { + typedef std::uint64_t max_bit_type; + template struct bitsection { + static_assert(sizeof(T) <= sizeof(marshal::max_bit_type), "Type size exceeds highest allowed type size."); +#if !defined(__GNUC__) || __GNUC__ > 5 + static_assert(std::is_trivially_copyable::value, "The type of a bit section needs to be trivially copyable."); +#endif + static std::size_t const size = Size; typedef T type; }; @@ -42,6 +49,47 @@ namespace marshal static std::size_t const value = 0; }; + template + class mirror + { + private: + typedef typename section_at::section section; + static std::size_t const bit_offset = offset_at::value; + static std::size_t const bit_shift = bit_offset % 8; + static std::size_t const byte_offset = bit_offset / 8; + static std::size_t const byte_length = ((bit_shift + section::size + 7) & ~7) / 8; + + unsigned char* buffer; + union + { + marshal::max_bit_type value; + std::array array; + }; + + static_assert(Index < sizeof...(Sections), "Index out of bit field range."); + static_assert(byte_length <= sizeof(marshal::max_bit_type), "Invalid type with size larger than the maximum allowed."); + + public: + mirror(unsigned char* original) + : buffer{original + byte_offset}, value{0} + {} + + typename section::type operator =(typename section::type const& other) + { + std::copy_n(buffer, byte_length, array.data()); + value &= ~(((1 << section::size) - 1) << bit_shift); + value |= (other & ((1 << section::size) - 1)) << bit_shift; + std::copy_n(array.data(), byte_length, buffer); + return other; + } + + operator typename section::type() + { + std::copy_n(buffer, byte_length, array.data()); + return static_cast((value >> bit_shift) & ((1 << section::size) - 1)); + } + }; + public: static_assert(offset_at::value <= 8 * Bytes, "Provided bit sections exceed available space."); @@ -73,34 +121,15 @@ namespace marshal } template - void set(R value) + typename section_at::section::type set(R value) { - static_assert(Index < sizeof...(Sections), "Index out of bit field range."); - - auto const offset = offset_at::value; - auto const shift = offset % 8; - typedef typename section_at::section section; - - std::uint64_t copy = 0; - std::copy_n(buffer + offset / 8, ((section::size + 7) & ~7) / 8, reinterpret_cast(©)); - copy &= ~(((1 << section::size) - 1) << shift); - copy |= (value & ((1 << section::size) - 1)) << shift; - std::copy_n(reinterpret_cast(©), ((shift + section::size + 7) & ~7) / 8, buffer + offset / 8); + return mirror{buffer} = value; } template typename section_at::section::type get() { - static_assert(Index < sizeof...(Sections), "Index out of bit field range."); - - auto const offset = offset_at::value; - auto const shift = offset % 8; - typedef typename section_at::section section; - - std::uint64_t copy = 0; - std::copy_n(buffer + offset / 8, ((shift + section::size + 7) & ~7) / 8, reinterpret_cast(©)); - - return (typename section::type)((copy >> shift) & ((1 << section::size) - 1)); + return mirror(buffer); } std::size_t size() const @@ -112,25 +141,17 @@ namespace marshal { return buffer; } + }; - unsigned char* begin() - { - return buffer; - } - - unsigned char* end() - { - return buffer + size(); - } - - unsigned char const* cbegin() const - { - return buffer; - } + template + auto set(bitfield bf) -> decltype(bf.template set()) + { + return bf.template set(); + } - unsigned char const* cend() const - { - return buffer + size(); - } - }; + template + auto get(bitfield bf) -> decltype(bf.template get()) + { + return bf.template get(); + } }