-
Notifications
You must be signed in to change notification settings - Fork 0
/
Object.hpp
205 lines (170 loc) · 5.49 KB
/
Object.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#ifndef OBJECT_HPP_
# define OBJECT_HPP_
# include <iostream>
# include <iomanip>
# include <vector>
# include <string.h>
# include "Utils.hpp"
namespace ActNut
{
class Object
{
protected:
const Object* parent;
const char* type;
std::string name;
std::vector<Object*> members;
void addMember(Object* member);
public:
static bool _printFullNames;
static void printFullNames(bool value);
Object(const Object* parent, const char* type, const std::string& name);
virtual ~Object() {}
template<typename T>
static T* read(const Object* parent, IBuffer& buf, const std::string& name)
{
T* obj = new T(parent, name);
if (!obj->readValue(buf))
{
delete obj;
return nullptr;
}
return obj;
}
template<typename T>
static T* read(const std::string& filename)
{
FileBuffer buf(filename, std::ios_base::in);
IBuffer* oldBuffer = Error::setErrorBuffer(&buf);
T* ret = read<T>(nullptr, buf, filename);
Error::setErrorBuffer(oldBuffer);
return ret;
}
const Object* getParent() const;
const std::string& getName() const;
virtual uint32_t getNumType() const;
std::string getFullName() const;
int getIndentLevel() const;
std::string printIndent(int indentLevel = -1) const;
virtual bool readValue(IBuffer& buf) = 0;
virtual void print(std::ostream& os) const = 0;
virtual bool writeValue(IBuffer& buf) const = 0;
virtual bool writeToFile(const std::string& filename) const;
virtual Object* operator[](const char* key);
virtual const Object* operator[](const char* key) const;
virtual Object* getChild(const char* path);
virtual const Object* getChild(const char* path) const;
virtual const Object& operator=(const std::string& new_value);
void setName(const std::string& name);
};
std::ostream& operator<<(std::ostream& os, const Object& o);
template<typename T>
class Number : public Object
{
protected:
enum class Type
{
BOOLEAN,
INTEGER,
FLOAT
};
T storage;
T& n;
const uint32_t numType;
const Type nType;
public:
// By default, the Number class will contain a number in storage.
Number(const Object* parent, const char* type, const std::string& name, uint32_t numType = 0, Type nType = Type::INTEGER)
: Object(parent, type, name), storage(0), n(storage), numType(numType), nType(nType)
{ }
// We can also use the Number class to wrap a variable. In that case, storage is not used (because it is external to the class).
Number(const Object* parent, const char* type, const std::string& name, T& ref, uint32_t numType = 0, Type nType = Type::INTEGER)
: Object(parent, type, name), n(ref), numType(numType), nType(nType)
{ }
uint32_t getNumType() const
{ return numType; }
bool readValue(IBuffer& buf)
{ return buf.readBytes((uint8_t*)&this->n, sizeof(this->n)); }
bool writeValue(IBuffer& buf) const
{ return buf.writeBytes((uint8_t*)&this->n, sizeof(this->n)); }
void print(std::ostream& os) const
{
if (nType == Type::FLOAT)
os << std::setprecision(2) << std::fixed;
if (nType == Type::BOOLEAN)
os << std::boolalpha;
os << +this->n;
if (nType == Type::FLOAT)
os << std::defaultfloat;
if (nType == Type::BOOLEAN)
os << std::noboolalpha;
}
const Object& operator=(const T& new_value)
{
this->n = new_value;
return *this;
}
virtual const Object& operator=(const std::string& new_value)
{
switch (nType)
{
case Type::INTEGER:
this->n = (T)stol(new_value, nullptr, 0);
break ;
case Type::FLOAT:
this->n = (T)stod(new_value, nullptr);
break ;
case Type::BOOLEAN:
if (!strcmp(new_value.c_str(), "true") || !strcmp(new_value.c_str(), "True") || !strcmp(new_value.c_str(), "TRUE"))
this->n = true;
else if (!strcmp(new_value.c_str(), "false") || !strcmp(new_value.c_str(), "False") || !strcmp(new_value.c_str(), "FALSE"))
this->n = false;
else if (stol(new_value, nullptr, 0) != 0)
this->n = true;
else
this->n = false;
break ;
}
return *this;
}
operator T() const { return this->n; }
};
class String : public Object
{
protected:
std::string value;
public:
String(const Object* parent, const char* type, const std::string& name);
bool readValue(IBuffer& buf);
void print(std::ostream& os) const;
bool writeValue(IBuffer& buf) const;
const Object& operator=(const std::string& new_value);
bool operator==(const std::string& other) const;
};
class vector : public Object, public std::vector<Object*>
{
public:
vector(const Object* parent, const std::string& name)
: Object(parent, "std::vector", name) {}
~vector();
vector& operator=(const vector&) = delete;
using Object::operator=;
bool readValue(IBuffer& buf);
bool writeValue(IBuffer& buf) const;
template<typename T>
bool add(T* (*readerFunc)(const Object* parent, IBuffer& buf, const std::string& name), IBuffer& buf)
{
Object* obj = readerFunc(this, buf, std::to_string(this->size()));
if (!obj)
return false;
this->push_back(obj);
return true;
}
void print(std::ostream& os) const;
virtual Object* operator[](size_type n);
virtual const Object* operator[](size_type n) const;
virtual Object* operator[](const char* key);
virtual const Object* operator[](const char* key) const;
};
}
#endif /* !OBJECT_HPP_ */