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