29 #ifndef CEREAL_DETAILS_EXTENDABLE_BINARY_DETAILS_HPP_ 30 #define CEREAL_DETAILS_EXTENDABLE_BINARY_DETAILS_HPP_ 40 namespace extendable_binary_detail
46 static std::int32_t test = 1;
47 return *
reinterpret_cast<std::int8_t*
>( &test ) == 1;
54 template <std::
size_t DataSize>
57 for( std::size_t i = 0, end = DataSize / 2; i < end; ++i )
58 std::swap( data[i], data[DataSize - i - 1] );
70 positive_integer = 0x1,
74 negative_integer = 0x2,
108 EmptyClass = 0x1 << 0,
111 HasVersion = 0x1 << 1,
116 l =
static_cast<ClassMarkers>(
static_cast<std::uint8_t
>(l) | static_cast<std::uint8_t>(r));
122 return static_cast<std::uint8_t
>(l) & static_cast<std::uint8_t>(r);
135 IsSharedPtr = 0x1 << 1,
138 IsPolymorphicPointer = 0x1 << 2
143 l =
static_cast<PointerMarkers>(
static_cast<std::uint8_t
>(l) | static_cast<std::uint8_t>(r));
149 return static_cast<std::uint8_t
>(l) & static_cast<std::uint8_t>(r);
154 enum { maxVarintSize = 10 };
156 inline std::uint8_t writeType(
FieldType fieldType, std::uint8_t other) {
157 return (static_cast<std::uint8_t>(fieldType) << 4) | (0xf & other);
160 inline std::pair<FieldType, std::uint8_t> readType(std::uint8_t input) {
161 std::uint8_t fieldType = (input >> 4);
162 if(static_cast<std::uint8_t>(fieldType) >=
static_cast<std::uint8_t
>(FieldType::LAST_RESERVED_UNUSED)) {
163 throw Exception(
"FieldType has unknown value " + std::to_string(fieldType) +
" all:" + std::to_string(input));
165 return std::make_pair(static_cast<FieldType>(fieldType), (0xf & input));
172 template <
class T>
inline 191 template <
class T>
inline 197 union {
float f; std::uint32_t i; } f;
205 union {
double d; std::uint64_t i; } d;
206 d.i = 0x7FF8000000000000ull;
211 template <
class T>
inline 226 throw Exception(
"Unsupported floating point size");
232 template <
class T>
inline 235 static_assert(
sizeof(T) == 4 ||
sizeof(T) == 8,
"unsupported floating point type");
236 static_assert(std::is_floating_point<T>::value,
"expected floating point type");
273 }
else if(byteCount <= 16) {
275 }
else if(byteCount <= 32) {
285 std::streamoff start;
307 StreamAdapter(std::istream & stream, std::stringstream & sharedObjectStream, std::size_t maxBytesInSharedStream)
308 : nowReading(nullptr), bytesLeft(0), endOfWritingStream(0), startOfStream(sharedObjectStream.tellg()),
309 mainStream(stream), backStream(sharedObjectStream), maxBytesSharedStream(maxBytesInSharedStream)
317 if (nowReading ==
nullptr) {
319 endOfWritingStream = backStream.tellg();
322 backStreams.push(std::make_pair(backStream.tellg(), nowReading));
324 backStream.seekg(streamPos.start);
325 nowReading = &streamPos;
326 bytesLeft = streamPos.end - streamPos.start;
336 inline std::size_t
readBinary(
void *
const data, std::size_t size)
338 std::size_t readSize;
339 if (nowReading ==
nullptr) {
340 readSize =
static_cast<std::size_t
>( mainStream.rdbuf()->sgetn(reinterpret_cast<char *>( data ), size));
342 if (size > bytesLeft) {
343 throw Exception(
"went to far reading skipped shared object stream");
345 readSize =
static_cast<std::size_t
>( backStream.rdbuf()->sgetn(reinterpret_cast<char *>( data ), size));
346 bytesLeft -= readSize;
347 if (0 == bytesLeft) {
360 if (nowReading ==
nullptr) {
361 mainStream.ignore(size);
362 streamError = !mainStream;
364 if (size > bytesLeft) {
365 throw Exception(
"went to far reading skipped shared object stream");
367 backStream.ignore(size);
368 streamError = !backStream;
370 if (0 == bytesLeft) {
375 throw Exception(
"Failed to skip " + std::to_string(size) +
" bytes from input stream!");
384 std::size_t posNow =
static_cast<std::size_t
>(stream.tellp());
385 if (posNow - startOfStream + size > maxBytesSharedStream) {
386 throw Exception(
"Shared obiect shared data limit hit");
396 checkIfMaxSize(size, stream);
397 auto copyN = [](std::istream & from, std::size_t sizeToCopy, std::ostream & to) {
398 auto start = std::istreambuf_iterator<char>(from);
399 auto end = std::istreambuf_iterator<char>();
400 auto dest = std::ostreambuf_iterator<char>(to);
401 for (; sizeToCopy > 0 && start != end; ++start, ++dest, --sizeToCopy) {
405 throw Exception(
"Failed to skip data from input stream!");
408 if (nowReading ==
nullptr) {
409 copyN(mainStream, size, stream);
413 if (size > bytesLeft) {
414 throw Exception(
"went to far reading skipped shared object stream");
416 copyN(mainStream, size, stream);
418 if (0 == bytesLeft) {
429 if (backStreams.empty()) {
431 backStream.seekg(endOfWritingStream);
432 nowReading =
nullptr;
435 const auto & next = backStreams.back();
436 backStream.seekg(next.first);
438 bytesLeft = next.second->end - next.first;
439 nowReading = next.second;
446 std::size_t bytesLeft;
447 std::size_t endOfWritingStream;
448 const std::size_t startOfStream;
450 std::queue<std::pair<std::size_t, StreamPos *>> backStreams;
451 std::istream & mainStream;
452 std::istream & backStream;
453 const std::size_t maxBytesSharedStream;
void readToOtherStream(std::size_t size, std::ostream &stream)
Reads size bytes from the input stream and copies them to other stream.
Definition: extendable_binary_details.hpp:394
void checkIfMaxSize(std::size_t size, std::ostream &stream)
Check if by adding size bytes limit for max copied data is hit.
Definition: extendable_binary_details.hpp:382
std::size_t readBinary(void *const data, std::size_t size)
Reads binary data from stream which is on top.
Definition: extendable_binary_details.hpp:336
Used to delay a static_assert until template instantiation.
Definition: traits.hpp:57
std::uint8_t is_little_endian()
Returns true if the current machine is little endian.
Definition: extendable_binary_details.hpp:44
std::uint8_t getIntSizeFromTagSize(std::uint8_t tagSize)
Get number of bytes to load based on value of identifier for integer tag.
Definition: extendable_binary_details.hpp:246
FieldType
Describes type of saved field.
Definition: extendable_binary_details.hpp:63
std::uint8_t getHighestBit(T v)
Get number of bytes needed to save value.
Definition: extendable_binary_details.hpp:173
Class used as an adapter to queue of streams.
Definition: extendable_binary_details.hpp:299
void swap_bytes(std::uint8_t *data)
Swaps the order of bytes for some chunk of memory.
Definition: extendable_binary_details.hpp:55
Definition: access.hpp:40
void pushReadingPos(StreamPos &streamPos)
Pushes new reading position on the stream.
Definition: extendable_binary_details.hpp:315
std::uint8_t getTagSizeFromFloatType()
Get size identifier for floating point type.
Definition: extendable_binary_details.hpp:233
T getqNaN()
Get quiet not a number value for type.
Definition: extendable_binary_details.hpp:212
PointerMarkers
Markers for FieldType::pointer.
Definition: extendable_binary_details.hpp:127
Main cereal functionality.
StreamAdapter(std::istream &stream, std::stringstream &sharedObjectStream, std::size_t maxBytesInSharedStream)
Construct new object with main and secondary stream.
Definition: extendable_binary_details.hpp:307
ClassMarkers
Markers for FieldType::class_t.
Definition: extendable_binary_details.hpp:102
Struct to keep position of start and end in stream.
Definition: extendable_binary_details.hpp:283
std::uint8_t getIntSizeTagFromByteCount(unsigned int byteCount)
Get identifier for size for integer tag based on number of bytes being stored.
Definition: extendable_binary_details.hpp:270
void skipData(std::size_t size)
Discards size bytes from the input stream.
Definition: extendable_binary_details.hpp:357
std::uint8_t getFloatSizeFromTagSize(std::uint8_t tagSize)
Get size of floating point data for size identifier.
Definition: extendable_binary_details.hpp:218
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48