OpenAstra
 
Loading...
Searching...
No Matches
dataitem.hpp
1#ifndef DATAITEM_H
2#define DATAITEM_H
3
4#include <vector>
5#include <variant>
6
7#include <stdint.h>
8
9#include "debugprint.hpp"
10#include "gameid.hpp"
11#include "starcoord.hpp"
12#include "quantity.hpp"
13#include "json.hpp"
14
15/*
16 */
18{
19public:
20 using Type = uint32_t;
21 static constexpr Type type_invalid = 0;
22 static constexpr Type type_integer = 1;
23 static constexpr Type type_double = 2;
24 static constexpr Type type_string = 3;
25 static constexpr Type type_bool = 4;
26 static constexpr Type type_id = 5;
27 static constexpr Type type_starcoord = 6;
28 static constexpr Type type_quantity = 7;
29 static constexpr Type type_vector_integer = 8;
30 static constexpr Type type_vector_double = 9;
31 static constexpr Type type_vector_string = 10;
32 static constexpr Type type_vector_bool = 11;
33 static constexpr Type type_vector_id = 12;
34 static constexpr Type type_vector_starcoord = 13;
35 static constexpr Type type_vector_quantity = 14;
36 // For shorter code
37 using vector_integer = std::vector<int64_t>;
38 using vector_double = std::vector<double>;
39 using vector_bool = std::vector<bool>;
40 using vector_id = std::vector<ObjectId>;
41 using vector_string = std::vector<std::string>;
42 using vector_starcoord = std::vector<StarCoord>;
43 using vector_quantity = std::vector<Quantity>;
44 // Type: type. bool: client writable (can be written by commands or not)
45 using DataItemMetadata = std::pair<Type, bool>;
46 using DataItemVariant = std::variant<std::monostate,
47 int64_t,
48 double,
49 std::string,
50 bool,
54 vector_integer,
55 vector_double,
56 vector_string,
57 vector_bool,
58 vector_id,
59 vector_starcoord,
60 vector_quantity>;
61
67 static void registerDataItem(const std::string &dataItem, Type dataType, bool clientWritable) {
68 if ( _dataitems_library.find( dataItem ) != _dataitems_library.end() )
69 DebugPrint() << "overwriting dataItem '" << dataItem << "' because it's already registered! (only LAST one will be registered...)";
70 _dataitems_library[ dataItem ] = DataItemMetadata(dataType, clientWritable);
71 }
72
78 static DataItemMetadata getDataItemMetadata(const std::string &dataItem) {
79 auto library_find = _dataitems_library.find(dataItem);
80 if (library_find != _dataitems_library.end())
81 return library_find->second;
82 return DataItemMetadata(type_invalid,false);
83 }
84
85public:
90 : _name()
91 , _item() {}
92
97 DataItem( const DataItem& other )
98 : _name( other._name )
99 , _item( other._item ) {}
100
105 DataItem( const std::string& name )
106 : _name( name )
107 , _item() {
108 auto metadata = getDataItemMetadata(name);
109 if (metadata.first != type_invalid) {
110 switch ( metadata.first ) {
111 case type_integer: _item.emplace<int64_t>(); break;
112 case type_double: _item.emplace<double>(); break;
113 case type_string: _item.emplace<std::string>(); break;
114 case type_bool: _item.emplace<bool>(); break;
115 case type_id: _item.emplace<ObjectId>(); break;
116 case type_starcoord: _item.emplace<StarCoord>(); break;
117 case type_quantity: _item.emplace<Quantity>(); break;
118 case type_vector_integer: _item.emplace<vector_integer>(); break;
119 case type_vector_double: _item.emplace<vector_double>(); break;
120 case type_vector_string: _item.emplace<vector_string>(); break;
121 case type_vector_bool: _item.emplace<vector_bool>(); break;
122 case type_vector_id: _item.emplace<vector_id>(); break;
123 case type_vector_starcoord: _item.emplace<vector_starcoord>(); break;
124 case type_vector_quantity: _item.emplace<vector_quantity>(); break;
125 default:
126 DebugPrint() << "unable to create DataItem (" << name << "): type is invalid??";
127 }
128 }
129 else
130 DebugPrint() << "unregistered DataItem: '" << name << "', dataItem not created.";
131 }
132
137 bool isValid() const {
138 return !std::holds_alternative<std::monostate>(_item);
139 }
140
145 const std::string& name() const {
146 return _name;
147 }
148
149 Type type() const {
150 return _item.index();
151 }
152
153public:
154 DataItem& operator=(const DataItem& other) = default;
155
161 template <typename T,
162 typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, DataItem> &&
163 !std::is_same_v<std::decay_t<T>, nlohmann::json>
164 >>
165 DataItem& operator=( T&& value ) {
166 std::get<std::decay_t<T>>(_item) = std::forward<T>(value);
167 return *this;
168 }
169
174 template <typename T>
175 operator T&() {
176 return std::get<std::decay_t<T>>(_item);
177 }
178
183 template <typename T>
184 operator const T&() const {
185 return std::get<std::decay_t<T>>(_item);
186 }
187
192 template <typename T>
193 T& as() {
194 return std::get<std::decay_t<T>>(_item);
195 }
196
201 template <typename T>
202 const T& as() const {
203 return std::get<std::decay_t<T>>(_item);
204 }
205
211 template <typename T,
212 typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, DataItem> &&
213 !std::is_same_v<std::decay_t<T>, nlohmann::json>
214 >>
215 bool operator==(const T& value) const {
216 if (auto* ptr = std::get_if<std::decay_t<T>>(&_item))
217 return *ptr == value;
218 return false;
219 }
220
226 template <typename T,
227 typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, DataItem> &&
228 !std::is_same_v<std::decay_t<T>, nlohmann::json>
229 >>
230 bool operator!=(const T& value) const {
231 if (auto* ptr = std::get_if<std::decay_t<T>>(&_item))
232 return *ptr != value;
233 return true;
234 }
235
236 bool operator!=(const DataItem& other) const {
237 return _item != other._item;
238 }
239
240 bool operator==(const DataItem& other) const {
241 return _item == other._item;
242 }
243
249 template <typename T>
251 T* ret = std::get_if<std::decay_t<T>>(&_item);
252 if ( ret == nullptr )
253 DebugPrint() << "DataItem->access: '" << _name << "' type mismatch!";
254 return ret;
255 }
256
257 DataItem& operator+=( const DataItem& other ) {
258 size_t i = _item.index();
259 if ( i == other._item.index() ) {
260 switch ( i ){
261 case type_integer: std::get<type_integer>(_item) += std::get<type_integer>(other._item); break;
262 case type_double: std::get<type_double>(_item) += std::get<type_double>(other._item); break;
263 case type_quantity: std::get<type_quantity>(_item) += std::get<type_quantity>(other._item); break;
264 default: DebugPrint() << "DataItem '" << _name << "' += '" << other._name << "' types are not compatible!";
265 }
266 }
267 else
268 DebugPrint() << "DataItem '" << _name << "' += '" << other._name << "' type mismatch!";
269 return *this;
270 }
271
272 template <typename T,
273 typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, DataItem> &&
274 !std::is_same_v<std::decay_t<T>, nlohmann::json>
275 >>
276 DataItem& operator+=( const T& value ) {
277 std::get<std::decay_t<T>>(_item) += value;
278 return *this;
279 }
280
286 DataItem& operator=(const nlohmann::json& JSON) {
287 // Yes this is verbose, but we want full control on type conversion
288 switch ( _item.index() )
289 {
290 case type_integer:
291 _item = JSON.get<int64_t>();
292 break;
293 case type_double:
294 _item = JSON.get<double>();
295 break;
296 case type_string:
297 _item = JSON.get<std::string>();
298 break;
299 case type_bool: // manage both 0/!=0 and real booleans
300 _item = JSON.is_boolean() ? JSON.get<bool>() : JSON != 0;
301 break;
302 case type_id:
303 _item = JSON.get<ObjectId>();
304 break;
305 case type_starcoord:
306 _item = JSON.get<StarCoord>();
307 break;
308 case type_quantity:
309 _item = JSON.get<Quantity>();
310 break;
311 case type_vector_integer:
312 _item = JSON.get<vector_integer>();
313 break;
314 case type_vector_double:
315 _item = JSON.get<vector_double>();
316 break;
317 case type_vector_string:
318 _item = JSON.get<vector_string>();
319 break;
320 case type_vector_bool:
321 _item = JSON.get<vector_bool>();
322 break;
323 case type_vector_id:
324 _item = JSON.get<vector_id>();
325 break;
326 case type_vector_starcoord:
327 _item = JSON.get<vector_starcoord>();
328 break;
329 case type_vector_quantity:
330 _item = JSON.get<vector_quantity>();
331 break;
332 default:
333 DebugPrint() << "error creating DataItem from JSON (" << _name << "). Type is invalid??";
334 }
335 return *this;
336 }
337
342 DataItemVariant& raw() {
343 return _item;
344 }
345
346private:
347 // These are ALL the valid dataitems, with type
348 inline static std::unordered_map<std::string, DataItemMetadata> _dataitems_library;
349
350 std::string _name;
351 DataItemVariant _item;
352};
353
354#endif // DATAITEM_H
Definition dataitem.hpp:18
bool operator==(const T &value) const
for usage like if ( DataItem == 5 )
Definition dataitem.hpp:215
static DataItemMetadata getDataItemMetadata(const std::string &dataItem)
Return data item type (if exist)
Definition dataitem.hpp:78
T & as()
for usage like double DataItem.as<std::vector<int64_t>>().push_back( ... )
Definition dataitem.hpp:193
DataItem(const DataItem &other)
Copy constructor.
Definition dataitem.hpp:97
DataItemVariant & raw()
get the raw std::variant inside
Definition dataitem.hpp:342
const std::string & name() const
return name of dataitem
Definition dataitem.hpp:145
DataItem()
Create an invalid DataItem.
Definition dataitem.hpp:89
DataItem(const std::string &name)
Initialize a DataItem, it requires the name of the DataItem to match the metadata.
Definition dataitem.hpp:105
const T & as() const
for usage like double DataItem.as<std::vector<int64_t>>().push_back( ... )
Definition dataitem.hpp:202
bool isValid() const
return true if the data item contains a valid type&value
Definition dataitem.hpp:137
bool operator!=(const T &value) const
for usage like if ( DataItem != 5 )
Definition dataitem.hpp:230
static void registerDataItem(const std::string &dataItem, Type dataType, bool clientWritable)
Globally add valid dataItems (With type) to the dataItems library.
Definition dataitem.hpp:67
DataItem & operator=(T &&value)
for usage like DataItem x = 5
Definition dataitem.hpp:165
T * accessPtr()
get a pointer to the data
Definition dataitem.hpp:250
DataItem & operator=(const nlohmann::json &JSON)
set data item value from JSON
Definition dataitem.hpp:286
Definition debugprint.hpp:10
Definition gameid.hpp:9
Definition quantity.hpp:9
Definition starcoord.hpp:16