palimpsest v3.0.0
Loading...
Searching...
No Matches
Value.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2022 Stéphane Caron
3// Copyright 2024 Inria
4/*
5 * This file incorporates work covered by the following copyright and
6 * permission notice:
7 *
8 * Configuration and DataStore classes of mc_rtc
9 * Copyright 2015-2020 CNRS-UM LIRMM, CNRS-AIST JRL
10 * SPDX-License-Identifier: BSD-2-Clause
11 */
12
13#pragma once
14
15#include <functional>
16#include <memory>
17#include <stdexcept>
18#include <string>
19#include <typeinfo>
20
22#include "palimpsest/internal/Allocator.h"
23#include "palimpsest/internal/is_valid_hash.h"
24#include "palimpsest/internal/type_name.h"
25#include "palimpsest/json/write.h"
26#include "palimpsest/mpack/Writer.h"
27#include "palimpsest/mpack/read.h"
28#include "palimpsest/mpack/write.h"
29
30namespace palimpsest {
31
32using exceptions::TypeError;
33
38class Value {
39 public:
41 Value() = default;
42
44 Value(const Value &other) {
45 if (other.buffer) {
46 other.copy_(*this, other);
47 }
48 }
49
51 Value &operator=(const Value &other) {
52 if (this != &other) {
53 // Clean up existing buffer if any
54 if (this->buffer) {
55 destroy_(*this);
56 this->buffer = nullptr;
57 }
58
59 // Copy from other if it has data
60 if (other.buffer) {
61 other.copy_(*this, other);
62 }
63 }
64 return *this;
65 }
66
68 Value(Value &&) = default;
69
71 Value &operator=(Value &&) = default;
72
75 if (this->buffer) {
76 destroy_(*this);
77 }
78 }
79
81 template <typename T>
82 void allocate() {
83 this->buffer.reset(
84 reinterpret_cast<uint8_t *>(internal::Allocator<T>().allocate(1)));
85 }
86
92 void deserialize(mpack_node_t node) { deserialize_(*this, node); }
93
98 void print(std::ostream &stream) const { print_(*this, stream); }
99
104 void serialize(mpack::Writer &writer) const {
105 serialize_(*this, writer.mpack_writer());
106 }
107
112 template <typename T, typename... ArgsT>
113 T &setup() {
114 this->type_name = &internal::type_name<T>;
115 this->same = &internal::is_valid_hash<T, ArgsT...>;
116 copy_ = [](Value &dest, const Value &src) {
117 dest.allocate<T>();
118 dest.type_name = src.type_name;
119 dest.same = src.same;
120 dest.deserialize_ = src.deserialize_;
121 dest.destroy_ = src.destroy_;
122 dest.print_ = src.print_;
123 dest.serialize_ = src.serialize_;
124 dest.copy_ = src.copy_;
125 const T *src_obj = reinterpret_cast<const T *>(src.buffer.get());
126 new (dest.buffer.get()) T(*src_obj);
127 };
128 deserialize_ = [](Value &self, mpack_node_t node) {
129 T *cast_buffer = reinterpret_cast<T *>(self.buffer.get());
130 mpack::read<T>(node, *cast_buffer);
131 };
132 destroy_ = [](Value &self) {
133 T *p = reinterpret_cast<T *>(self.buffer.release());
134 p->~T();
135 internal::Allocator<T>().deallocate(p, 1);
136 };
137 print_ = [](const Value &self, std::ostream &stream) {
138 const T *cast_buffer = reinterpret_cast<const T *>(self.buffer.get());
139 json::write<T>(stream, *cast_buffer);
140 };
141 serialize_ = [](const Value &self, mpack_writer_t *writer) {
142 const T *cast_buffer = reinterpret_cast<const T *>(self.buffer.get());
143 mpack::write<T>(writer, *cast_buffer);
144 };
145 return *(reinterpret_cast<T *>(this->buffer.get()));
146 }
147
154 template <typename T>
155 T &get_reference() const {
156 if (!this->same(typeid(T).hash_code())) {
157 std::string cast_type = this->type_name();
158 throw TypeError(__FILE__, __LINE__,
159 "Object has type \"" + cast_type +
160 "\" but is being cast to type \"" + typeid(T).name() +
161 "\".");
162 }
163 return *(reinterpret_cast<T *>(this->buffer.get()));
164 }
165
166 public:
168 std::unique_ptr<uint8_t[]> buffer = nullptr;
169
171 const char *(*type_name)();
172
174 bool (*same)(std::size_t);
175
176 private:
178 void (*copy_)(Value &, const Value &);
179
181 void (*deserialize_)(Value &, mpack_node_t);
182
184 void (*destroy_)(Value &);
185
187 void (*print_)(const Value &, std::ostream &);
188
190 void (*serialize_)(const Value &, mpack_writer_t *);
191};
192
193} // namespace palimpsest
Internal wrapper around an object and its type information.
Definition: Value.h:38
T & setup()
Allocate object and register internal functions.
Definition: Value.h:113
Value & operator=(Value &&)=default
Default move assignment operator.
~Value()
Destruct the object and free the internal buffer.
Definition: Value.h:74
bool(* same)(std::size_t)
Function that checks if a given type matches the object's type.
Definition: Value.h:174
void deserialize(mpack_node_t node)
Update value from an MPack node.
Definition: Value.h:92
void print(std::ostream &stream) const
Print value to an output stream;.
Definition: Value.h:98
Value()=default
Default constructor.
void allocate()
Allocate the internal buffer.
Definition: Value.h:82
void serialize(mpack::Writer &writer) const
Serialize value to a MessagePack writer.
Definition: Value.h:104
T & get_reference() const
Cast value to its object's type after checking that it matches T.
Definition: Value.h:155
Value(Value &&)=default
Default move constructor.
Value & operator=(const Value &other)
Copy assignment operator.
Definition: Value.h:51
std::unique_ptr< uint8_t[]> buffer
Internal buffer that holds the actual object.
Definition: Value.h:168
Value(const Value &other)
Copy constructor.
Definition: Value.h:44
const char *(* type_name)()
Function returning the name of the object's type.
Definition: Value.h:171
Requested type doesn't match the one already in the dictionary.
Definition: TypeError.h:13
Main library namespace.
Definition: Dictionary.h:34