CCF
Loading...
Searching...
No Matches
serialized.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
5#include <cstdint>
6#include <cstring>
7#include <stdexcept>
8#include <string>
9#include <utility>
10#include <vector>
11
12#define FMT_HEADER_ONLY
13#include <fmt/format.h>
14
15namespace serialized
16{
17 class InsufficientSpaceException : public std::exception
18 {
19 private:
20 std::string msg;
21
22 public:
23 InsufficientSpaceException(std::string msg_) : msg(std::move(msg_)) {}
24
25 [[nodiscard]] const char* what() const noexcept override
26 {
27 return msg.c_str();
28 }
29 };
30
31 template <class T>
32 T peek(const uint8_t*& data, size_t& size)
33 {
34 // This should only be used for numeric types and small structs
35 static constexpr auto max_size = 32u;
36 static_assert(sizeof(T) <= max_size);
37
38 if (size < sizeof(T))
39 {
41 fmt::format("Insufficient space (peek<T>: {} < {})", size, sizeof(T)));
42 }
43
44 static constexpr auto alignment = alignof(T);
45 if (reinterpret_cast<std::uintptr_t>(data) % alignment != 0)
46 {
47 // Data is not aligned - copy to scratch memory
48 alignas(T) uint8_t scratch[max_size];
49 std::memcpy(scratch, data, sizeof(T));
50 return *(T*)scratch;
51 }
52
53 // Cast directly from source memory
54 return *(T*)data;
55 }
56
57 template <class T>
58 T read(const uint8_t*& data, size_t& size)
59 {
60 if (size < sizeof(T))
61 {
63 fmt::format("Insufficient space (read<T>: {} < {})", size, sizeof(T)));
64 }
65
66 T v;
67 std::memcpy(reinterpret_cast<uint8_t*>(&v), data, sizeof(T));
68 data += sizeof(T);
69 size -= sizeof(T);
70 return v;
71 }
72
73 template <>
74 inline std::string read(const uint8_t*& data, size_t& size)
75 {
76 auto len = read<size_t>(data, size);
77 if (size < len)
78 {
80 fmt::format("Insufficient space (read string: {} < {})", size, len));
81 }
82
83 std::string v(data, data + len);
84 data += len;
85 size -= len;
86 return v;
87 }
88
89 inline std::vector<uint8_t> read(
90 const uint8_t*& data, size_t& size, size_t block_size)
91 {
92 if (size < block_size)
93 {
94 throw InsufficientSpaceException(fmt::format(
95 "Insufficient space (read block: {} < {})", size, block_size));
96 }
97
98 std::vector<uint8_t> v(data, data + block_size);
99 data += block_size;
100 size -= block_size;
101 return v;
102 }
103
104 template <class T>
105 void write(uint8_t*& data, size_t& size, const T& v)
106 {
107 if (size < sizeof(T))
108 {
110 fmt::format("Insufficient space (write<T>: {} < {})", size, sizeof(T)));
111 }
112
113 const auto* const src = reinterpret_cast<const uint8_t*>(&v);
114 std::memcpy(data, src, sizeof(T));
115 data += sizeof(T);
116 size -= sizeof(T);
117 }
118
119 inline void write(
120 uint8_t*& data, size_t& size, const uint8_t* block, size_t block_size)
121 {
122 if (size < block_size)
123 {
124 throw InsufficientSpaceException(fmt::format(
125 "Insufficient space (write block: {} < {})", size, block_size));
126 }
127
128 if (block_size > 0)
129 {
130 std::memcpy(data, block, block_size);
131 }
132
133 data += block_size;
134 size -= block_size;
135 }
136
137 inline void write(uint8_t*& data, size_t& size, const std::string& v)
138 {
139 const auto string_size = sizeof(size_t) + v.size();
140 if (size < string_size)
141 {
142 throw InsufficientSpaceException(fmt::format(
143 "Insufficient space (write string: {} < {})", size, string_size));
144 }
145
146 write(data, size, v.size());
147 write(data, size, reinterpret_cast<const uint8_t*>(v.data()), v.size());
148 }
149
150 template <class T>
151 T& overlay(const uint8_t*& data, size_t& size)
152 {
153 if (size < sizeof(T))
154 {
155 throw InsufficientSpaceException(fmt::format(
156 "Insufficient space (overlay<T>: {} < {})", size, sizeof(T)));
157 }
158
159 T* v = (T*)data;
160 data += sizeof(T);
161 size -= sizeof(T);
162 return *v;
163 }
164
165 inline void skip(const uint8_t*& data, size_t& size, size_t skip)
166 {
167 if (size < skip)
168 {
170 fmt::format("Insufficient space (skip: {} < {})", size, skip));
171 }
172
173 data += skip;
174 size -= skip;
175 }
176}
Definition serialized.h:18
InsufficientSpaceException(std::string msg_)
Definition serialized.h:23
const char * what() const noexcept override
Definition serialized.h:25
Definition serialized.h:16
void write(uint8_t *&data, size_t &size, const T &v)
Definition serialized.h:105
void skip(const uint8_t *&data, size_t &size, size_t skip)
Definition serialized.h:165
T read(const uint8_t *&data, size_t &size)
Definition serialized.h:58
T & overlay(const uint8_t *&data, size_t &size)
Definition serialized.h:151
T peek(const uint8_t *&data, size_t &size)
Definition serialized.h:32
STL namespace.