Files
bitsery/include/bitsery/details/brief_syntax_common.h
2019-07-05 14:18:27 +03:00

150 lines
6.0 KiB
C++

//MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
#ifndef BITSERY_DETAILS_BRIEF_SYNTAX_COMMON_H
#define BITSERY_DETAILS_BRIEF_SYNTAX_COMMON_H
#include "../traits/core/traits.h"
#include <limits>
namespace bitsery {
namespace brief_syntax {
//these function overloads is required to apply maxSize, and optimize for fundamental types
//for contigous arrays of fundamenal types, memcpy will be applied
template<typename S, typename T, typename std::enable_if<
details::IsFundamentalType<typename traits::ContainerTraits<T>::TValue>::value
&& traits::ContainerTraits<T>::isResizable
>::type * = nullptr>
void processContainer(S &s, T &c, size_t maxSize = std::numeric_limits<size_t>::max()) {
using TValue = typename traits::ContainerTraits<T>::TValue;
s.template container<sizeof(TValue)>(c, maxSize);
}
template<typename S, typename T, typename std::enable_if<
!details::IsFundamentalType<typename traits::ContainerTraits<T>::TValue>::value
&& traits::ContainerTraits<T>::isResizable
>::type * = nullptr>
void processContainer(S &s, T &c, size_t maxSize = std::numeric_limits<size_t>::max()) {
s.container(c, maxSize);
}
template<typename S, typename T, typename std::enable_if<
details::IsFundamentalType<typename traits::ContainerTraits<T>::TValue>::value
&& !traits::ContainerTraits<T>::isResizable
>::type * = nullptr>
void processContainer(S &s, T &c) {
using TValue = typename traits::ContainerTraits<T>::TValue;
s.template container<sizeof(TValue)>(c);
}
template<typename S, typename T, typename std::enable_if<
!details::IsFundamentalType<typename traits::ContainerTraits<T>::TValue>::value
&& !traits::ContainerTraits<T>::isResizable
>::type * = nullptr>
void processContainer(S &s, T &c) {
s.container(c);
}
//overloads for text processing to apply maxSize
template<typename S, typename T, typename std::enable_if<
traits::ContainerTraits<T>::isResizable>::type * = nullptr>
void processText(S &s, T &c, size_t maxSize = std::numeric_limits<size_t>::max()) {
using TValue = typename traits::ContainerTraits<T>::TValue;
s.template text<sizeof(TValue)>(c, maxSize);
}
template<typename S, typename T, typename std::enable_if<
!traits::ContainerTraits<T>::isResizable>::type * = nullptr>
void processText(S &s, T &c) {
using TValue = typename traits::ContainerTraits<T>::TValue;
s.template text<sizeof(TValue)>(c);
}
//all wrapper functions, that modify behaviour, should inherit from this
struct ModFnc {
};
//this type is used to differentiate between container and text behaviour
template<typename T, size_t N, bool isText>
struct CArray : public ModFnc {
CArray(T (&data_)[N]) : data{data_} {};
T (&data)[N];
};
template<typename S, typename T, size_t N>
void serialize(S &s, CArray<T, N, true> &str) {
processText(s, str.data);
}
template<typename S, typename T, size_t N>
void serialize(S &s, CArray<T, N, false> &obj) {
processContainer(s, obj.data);
}
//used to set max container size
template<typename T>
struct MaxSize : public ModFnc {
MaxSize(T &data_, size_t maxSize_) : data{data_}, maxSize{maxSize_} {};
T &data;
size_t maxSize;
};
//if container, then call procesContainer, this memcpy for fundamental types contiguous container
template<typename S, typename T>
void processMaxSize(S &s, T& data, size_t maxSize, std::true_type) {
processContainer(s, data, maxSize);
}
//overload for const T&
template<typename S, typename T>
void processMaxSize(S &s, const T& data, size_t maxSize, std::true_type) {
processContainer(s, const_cast<T&>(data), maxSize);
}
//try to call serialize overload with maxsize, extensions use this technique
template<typename S, typename T>
void processMaxSize(S &s, T& data, size_t maxSize, std::false_type) {
serialize(s, data, maxSize);
}
//overload for const T&
template<typename S, typename T>
void processMaxSize(S &s, const T& data, size_t maxSize, std::false_type) {
serialize(s, const_cast<T&>(data), maxSize);
}
template<typename S, typename T>
void serialize(S &s, const MaxSize<T> &ms) {
processMaxSize(s, ms.data, ms.maxSize, details::IsContainerTraitsDefined<typename std::decay<T>::type>{});
}
}
}
#endif //BITSERY_DETAILS_BRIEF_SYNTAX_COMMON_H