Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ObjectModel.h « ObjectModel « src - github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d76f9ce59f008eeed8ab33eb737ef0fd74f4447b (plain)
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
 * ObjectModel.h
 *
 *  Created on: 27 Aug 2018
 *      Author: David
 */

#ifndef SRC_OBJECTMODEL_OBJECTMODEL_H_
#define SRC_OBJECTMODEL_OBJECTMODEL_H_

#include "RepRapFirmware.h"
#include <General/IPAddress.h>

#if SUPPORT_OBJECT_MODEL

typedef uint32_t ObjectModelFilterFlags;
typedef uint8_t TypeCode;
constexpr TypeCode IsArray = 128;						// this is or'ed in to a type code to indicate an array
constexpr TypeCode NoType = 0;							// code for an invalid or unknown type

// Forward declarations
class ObjectModelTableEntry;
class ObjectModel;

union ExpressionValue
{
	float fVal;
	int32_t iVal;
	uint32_t uVal;
	const char *sVal;
	const ObjectModel *omVal;
};

// Dummy types, used to define type codes
class Bitmap32 { };
class Enum32 { };

class ObjectModel
{
public:
	enum ReportFlags : uint16_t
	{
		flagsNone,
		flagShortForm = 1
	};

	ObjectModel();

	// Construct a JSON representation of those parts of the object model requested by the user
	bool ReportAsJson(OutputBuffer *buf, const char *filter, ReportFlags rflags);

	// Return the type of an object
	TypeCode GetObjectType(const char *idString);

	// Get the value of an object when we don't know what its type is
	TypeCode GetObjectValue(ExpressionValue& val, const char *idString);

	// Get values of various types from the object model, returning true if successful
	template<class T> bool GetObjectValue(T& val, const char *idString);

	bool GetStringObjectValue(const StringRef& str, const char* idString) const;
	bool GetLongEnumObjectValue(const StringRef& str, const char *idString) const;
	bool GetShortEnumObjectValue(uint32_t &val, const char *idString) const;
	bool GetBitmapObjectValue(uint32_t &val, const char *idString) const;

	// Try to set values of various types from the object model, returning true if successful
	bool SetFloatObjectValue(float val, const char *idString);
	bool SetUnsignedObjectValue(uint32_t val, const char *idString);
	bool SetSignedObjectValue(int32_t val, const char *idString);
	bool SetStringObjectValue(const StringRef& str, const char *idString);
	bool SetLongEnumObjectValue(const StringRef& str, const char *idString);
	bool SetShortEnumObjectValue(uint32_t val, const char *idString);
	bool SetBitmapObjectValue(uint32_t val, const char *idString);
	bool SetBoolObjectValue(bool val, const char *idString);

	// Try to adjust values of various types from the object model, returning true if successful
	bool AdjustFloatObjectValue(float val, const char *idString);
	bool AdjustUnsignedObjectValue(int32_t val, const char *idString);
	bool AdjustSignedObjectValue(int32_t val, const char *idString);
	bool ToggleBoolObjectValue(const char *idString);

	// Get the object model table entry for the current level object in the query
	const ObjectModelTableEntry *FindObjectModelTableEntry(const char *idString);

	// Get the object model table entry for the leaf object in the query
	const ObjectModelTableEntry *FindObjectModelLeafEntry(const char *idString);
	// Skip the current element in the ID or filter string
	static const char* GetNextElement(const char *id);

protected:
	virtual const ObjectModelTableEntry *GetObjectModelTable(size_t& numEntries) const = 0;

private:
	// Get pointers to various types from the object model, returning null if failed
	template<class T> T* GetObjectPointer(const char* idString);

	const char **GetStringObjectPointer(const char *idString);
	uint32_t *GetShortEnumObjectPointer(const char *idString);
	uint32_t *GetBitmapObjectPointer(const char *idString);
};

// Function template used to get constexpr type IDs
// Each type must return a unique type code in the range 1 to 127
template<class T> constexpr TypeCode TypeOf();

template<> constexpr TypeCode TypeOf<bool> () { return 1; }
template<> constexpr TypeCode TypeOf<uint32_t> () { return 2; }
template<> constexpr TypeCode TypeOf<int32_t>() { return 3; }
template<> constexpr TypeCode TypeOf<float>() { return 4; }
template<> constexpr TypeCode TypeOf<Bitmap32>() { return 5; }
template<> constexpr TypeCode TypeOf<Enum32>() { return 6; }
template<> constexpr TypeCode TypeOf<ObjectModel>() { return 7; }
template<> constexpr TypeCode TypeOf<const char *>() { return 8; }
template<> constexpr TypeCode TypeOf<IPAddress>() { return 9; }

#define TYPE_OF(_t) (TypeOf<_t>())

// Entry to describe an array
class ObjectModelArrayDescriptor
{
public:
	size_t (*GetNumElements)(ObjectModel*);
	void * (*GetElement)(ObjectModel*, size_t);
};

// Object model table entry
// It must be possible to construct these in the form of initialised data in flash memory, to avoid using large amounts of RAM.
// Therefore we can't use a class hierarchy to represent different types of entry. Instead we use a type code and a void* parameter.
class ObjectModelTableEntry
{
public:
	// Type declarations
	// Flags field of a table entry
	enum ObjectModelEntryFlags : uint16_t
	{
		none = 0,				// nothing special
		live = 1,				// fast changing data, included in common status response
		canAlter = 2,			// we can alter this value
	};

	// Type of the function pointer in the table entry, that returns a pointer to the data
	typedef void *(*ParamFuncPtr_t)(ObjectModel*);

	// Member data. This must be public so that we can brace-initialise table entries.
	const char * name;				// name of this field
	ParamFuncPtr_t param;			// function that yields a pointer to this value
	TypeCode type;					// code for the type of this value
	ObjectModelEntryFlags flags;	// information about this value

	// Member functions. These must all be 'const'.

	// Return true if this object table entry matches a filter or query
	bool Matches(const char *filter, ObjectModelFilterFlags flags) const;

	// See whether we should add the value of this element to the buffer, returning true if it matched the filter and we did add it
	bool ReportAsJson(OutputBuffer* buf, ObjectModel *self, const char* filter, ObjectModel::ReportFlags flags) const;

	// Return the name of this field
	const char* GetName() const { return name; }

	// Compare the name of this field with the filter string that we are trying to match
	int IdCompare(const char *id) const;

	// Return true if this field is an object, not a primitive type
	bool IsObject() const { return type == TYPE_OF(ObjectModel); }

	// Follow the path specified by the ifString until we reach the end of it
	const ObjectModelTableEntry *FindLeafEntry(ObjectModel *self, const char *idString) const;

	// Check the type is correct, call the function and return the pointer
	void* GetValuePointer(ObjectModel *self, TypeCode t) const;

	// Private function to report a value of primitive type
	static void ReportItemAsJson(OutputBuffer *buf, const char *filter, ObjectModel::ReportFlags flags, void *nParam, TypeCode type);
};

// Function to retrieve a value by searching the object model
// Returns true if success
template<class T> bool ObjectModel::GetObjectValue(T& val, const char *idString)
{
	const ObjectModelTableEntry * const e = FindObjectModelLeafEntry(idString);
	if (e == nullptr)
	{
		return false;
	}
	const T *p = (float*)(e->GetValuePointer(this, TYPE_OF(T)));
	if (p == nullptr)
	{
		return false;
	}
	val = *p;
	return true;
}

// Specialisation of above for float, allowing conversion from integer to float
template<> bool ObjectModel::GetObjectValue(float& val, const char *idString);

// Specialisation of above for int, allowing conversion from unsigned to signed
template<> bool ObjectModel::GetObjectValue(int32_t& val, const char *idString);

template<class T> T* ObjectModel::GetObjectPointer(const char* idString)
{
	const ObjectModelTableEntry *e = FindObjectModelLeafEntry(idString);
	return (e == nullptr) ? nullptr : (T*)(e->GetValuePointer(this, TYPE_OF(T)));
}

// Use this macro to inherit form ObjectModel
#define INHERIT_OBJECT_MODEL	: public ObjectModel

// Use this macro in the 'protected' section of every class declaration that derived from ObjectModel
#define DECLARE_OBJECT_MODEL \
	const ObjectModelTableEntry *GetObjectModelTable(size_t& numEntries) const override; \
	static const ObjectModelTableEntry objectModelTable[];

#define DEFINE_GET_OBJECT_MODEL_TABLE(_class) \
	const ObjectModelTableEntry *_class::GetObjectModelTable(size_t& numEntries) const \
	{ \
		numEntries = ARRAY_SIZE(objectModelTable); \
		return objectModelTable; \
	}

#define OBJECT_MODEL_FUNC_BODY(_class,_ret) [] (ObjectModel* arg) { _class * const self = static_cast<_class*>(arg); return (void *)(_ret); }
#define OBJECT_MODEL_FUNC_NOSELF(_ret) [] (ObjectModel* arg) { return (void *)(_ret); }

#else

#define INHERIT_OBJECT_MODEL			// nothing
#define DECLARE_OBJECT_MODEL			// nothing
#define DEFINE_GET_OBJECT_MODEL_TABLE	// nothing

#endif

#endif /* SRC_OBJECTMODEL_OBJECTMODEL_H_ */