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

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2020-05-12 18:46:41 +0300
committerDavid Crocker <dcrocker@eschertech.com>2020-05-12 18:46:41 +0300
commit05c4116dae852c2c08cf5256276488c084ade4d1 (patch)
tree601d4900456bce435a4ec843f3feae6c92cf405f /src/ObjectModel
parentafce5eb1226da3335ce0462e259e673c261a486f (diff)
Pick up inherited object model properties automatically
Diffstat (limited to 'src/ObjectModel')
-rw-r--r--src/ObjectModel/ObjectModel.cpp118
-rw-r--r--src/ObjectModel/ObjectModel.h14
2 files changed, 71 insertions, 61 deletions
diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp
index 6c4dd0e5..47e7bb98 100644
--- a/src/ObjectModel/ObjectModel.cpp
+++ b/src/ObjectModel/ObjectModel.cpp
@@ -283,37 +283,33 @@ GCodeException ObjectExplorationContext::ConstructParseException(const char *msg
}
// Report this object
-void ObjectModel::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, uint8_t tableNumber, const char* filter) const
+void ObjectModel::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, const ObjectModelClassDescriptor * null classDescriptor, uint8_t tableNumber, const char* filter) const
{
if (context.IncreaseDepth())
{
bool added = false;
- const ObjectModelClassDescriptor * classDescriptor = GetObjectModelClassDescriptor();
-
- if ((tableNumber & 0x80) != 0) // if we want the parent class table
+ if (classDescriptor == nullptr)
{
- classDescriptor = classDescriptor->parent;
- tableNumber &= 0x7F;
+ classDescriptor = GetObjectModelClassDescriptor();
}
- if (classDescriptor != nullptr)
+ while (classDescriptor != nullptr)
{
const uint8_t * const descriptor = classDescriptor->omd;
if (tableNumber < descriptor[0])
{
const ObjectModelTableEntry *tbl = classDescriptor->omt;
- size_t numEntries = descriptor[tableNumber + 1];
- while (tableNumber != 0)
+ for (size_t i = 0; i < tableNumber; ++i)
{
- --tableNumber;
- tbl += descriptor[tableNumber + 1];
+ tbl += descriptor[i + 1];
}
+ size_t numEntries = descriptor[tableNumber + 1];
while (numEntries != 0)
{
if (tbl->Matches(filter, context))
{
- if (tbl->ReportAsJson(buf, context, this, filter, !added))
+ if (tbl->ReportAsJson(buf, context, classDescriptor, this, filter, !added))
{
added = true;
}
@@ -321,13 +317,22 @@ void ObjectModel::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& cont
--numEntries;
++tbl;
}
- if (added && *filter == 0)
- {
- buf->cat('}');
- }
}
+ if (tableNumber != 0)
+ {
+ break;
+ }
+ classDescriptor = classDescriptor->parent; // do parent table too
}
- if (!added)
+
+ if (added)
+ {
+ if (*filter == 0)
+ {
+ buf->cat('}');
+ }
+ }
+ else
{
buf->cat((*filter == 0) ? "{}" : "null");
}
@@ -344,12 +349,12 @@ void ObjectModel::ReportAsJson(OutputBuffer *buf, const char *filter, const char
{
const unsigned int defaultMaxDepth = (wantArrayLength) ? 99 : (filter[0] == 0) ? 1 : 99;
ObjectExplorationContext context(reportFlags, wantArrayLength, defaultMaxDepth);
- ReportAsJson(buf, context, 0, filter);
+ ReportAsJson(buf, context, nullptr, 0, filter);
}
// Function to report a value or object as JSON
// This function is recursive, so keep its stack usage low
-void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& context, ExpressionValue val, const char *filter) const
+void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelClassDescriptor *classDescriptor, ExpressionValue val, const char *filter) const
{
if (context.WantArrayLength() && *filter == 0)
{
@@ -384,7 +389,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext&
++filter;
if (*filter == ']') // if reporting on [parts of] all elements in the array
{
- ReportArrayAsJson(buf, context, val.omadVal, filter + 1);
+ ReportArrayAsJson(buf, context, classDescriptor, val.omadVal, filter + 1);
}
else
{
@@ -402,7 +407,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext&
context.AddIndex(index);
{
ReadLocker lock(val.omadVal->lockPointer);
- ReportItemAsJson(buf, context, val.omadVal->GetElement(this, context), endptr + 1);
+ ReportItemAsJson(buf, context, classDescriptor, val.omadVal->GetElement(this, context), endptr + 1);
}
context.RemoveIndex();
if (*filter == 0)
@@ -413,7 +418,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext&
}
else if (*filter == 0) // else reporting on all subparts of all elements in the array, or just the length
{
- ReportArrayAsJson(buf, context, val.omadVal, filter);
+ ReportArrayAsJson(buf, context, classDescriptor, val.omadVal, filter);
}
else
{
@@ -431,7 +436,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext&
buf->cat("null"); // error, should have reached the end of the filter or a '.'
break;
}
- val.omVal->ReportAsJson(buf, context, val.param, filter);
+ val.omVal->ReportAsJson(buf, context, (val.omVal == this) ? classDescriptor : nullptr, val.param, filter);
break;
case TypeCode::Float:
@@ -636,7 +641,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext&
}
// Report an entire array as JSON
-void ObjectModel::ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelArrayDescriptor *omad, const char *filter) const
+void ObjectModel::ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelClassDescriptor *classDescriptor, const ObjectModelArrayDescriptor *omad, const char *filter) const
{
ReadLocker lock(omad->lockPointer);
@@ -649,26 +654,15 @@ void ObjectModel::ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext&
buf->cat(',');
}
context.AddIndex(i);
- ReportItemAsJson(buf, context, omad->GetElement(this, context), filter);
+ ReportItemAsJson(buf, context, classDescriptor, omad->GetElement(this, context), filter);
context.RemoveIndex();
}
buf->cat(']');
}
// Find the requested entry
-const ObjectModelTableEntry* ObjectModel::FindObjectModelTableEntry(uint8_t tableNumber, const char* idString) const noexcept
+const ObjectModelTableEntry* ObjectModel::FindObjectModelTableEntry(const ObjectModelClassDescriptor *classDescriptor, uint8_t tableNumber, const char* idString) const noexcept
{
- const ObjectModelClassDescriptor * classDescriptor = GetObjectModelClassDescriptor();
- if ((tableNumber & 0x80) != 0) // if we want the parent class table
- {
- classDescriptor = classDescriptor->parent;
- if (classDescriptor == nullptr)
- {
- return nullptr; // no parent
- }
- tableNumber &= 0x7F;
- }
-
const uint8_t * const descriptor = classDescriptor->omd;
if (tableNumber >= descriptor[0])
{
@@ -676,13 +670,12 @@ const ObjectModelTableEntry* ObjectModel::FindObjectModelTableEntry(uint8_t tabl
}
const ObjectModelTableEntry *tbl = classDescriptor->omt;
- const size_t numEntries = descriptor[tableNumber + 1];
- while (tableNumber != 0)
+ for (size_t i = 0; i < tableNumber; ++i)
{
- --tableNumber;
- tbl += descriptor[tableNumber + 1];
+ tbl += descriptor[i + 1];
}
+ const size_t numEntries = descriptor[tableNumber + 1];
size_t low = 0, high = numEntries;
while (high > low)
{
@@ -701,7 +694,11 @@ const ObjectModelTableEntry* ObjectModel::FindObjectModelTableEntry(uint8_t tabl
high = mid;
}
}
- return (low < numEntries && tbl[low].IdCompare(idString) == 0) ? &tbl[low] : nullptr;
+ if (low < numEntries && tbl[low].IdCompare(idString) == 0)
+ {
+ return &tbl[low];
+ }
+ return nullptr;
}
/*static*/ const char* ObjectModel::GetNextElement(const char *id) noexcept
@@ -719,7 +716,7 @@ bool ObjectModelTableEntry::Matches(const char* filterString, const ObjectExplor
}
// Add the value of this element to the buffer, returning true if it matched and we did
-bool ObjectModelTableEntry::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, const ObjectModel *self, const char* filter, bool first) const noexcept
+bool ObjectModelTableEntry::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, const ObjectModelClassDescriptor *classDescriptor, const ObjectModel *self, const char* filter, bool first) const noexcept
{
const char * nextElement = ObjectModel::GetNextElement(filter);
const ExpressionValue val = func(self, context);
@@ -731,7 +728,7 @@ bool ObjectModelTableEntry::ReportAsJson(OutputBuffer* buf, ObjectExplorationCon
buf->cat(name);
buf->cat("\":");
}
- self->ReportItemAsJson(buf, context, val, nextElement);
+ self->ReportItemAsJson(buf, context, classDescriptor, val, nextElement);
return true;
}
return false;
@@ -757,20 +754,33 @@ int ObjectModelTableEntry::IdCompare(const char *id) const noexcept
}
// Get the value of an object
-ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, const char *idString, uint8_t tableNumber) const
+ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, const ObjectModelClassDescriptor * null classDescriptor, const char *idString, uint8_t tableNumber) const
{
- const ObjectModelTableEntry *const e = FindObjectModelTableEntry(tableNumber, idString);
- if (e == nullptr)
+ if (classDescriptor == nullptr)
{
- throw context.ConstructParseException("unknown value '%s'", idString);
+ classDescriptor = GetObjectModelClassDescriptor();
+ }
+
+ while (classDescriptor != nullptr)
+ {
+ const ObjectModelTableEntry * const e = FindObjectModelTableEntry(classDescriptor, tableNumber, idString);
+ if (e != nullptr)
+ {
+ idString = GetNextElement(idString);
+ const ExpressionValue val = e->func(this, context);
+ return GetObjectValue(context, classDescriptor, val, idString);
+ }
+ if (tableNumber != 0)
+ {
+ break;
+ }
+ classDescriptor = classDescriptor->parent; // search parent class object model too
}
- idString = GetNextElement(idString);
- ExpressionValue val = e->func(this, context);
- return GetObjectValue(context, val, idString);
+ throw context.ConstructParseException("unknown value '%s'", idString);
}
-ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, ExpressionValue val, const char *idString) const
+ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, const ObjectModelClassDescriptor *classDescriptor, ExpressionValue val, const char *idString) const
{
switch (val.GetType())
{
@@ -799,7 +809,7 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, E
}
const ExpressionValue arrayElement = val.omadVal->GetElement(this, context);
- return GetObjectValue(context, arrayElement, idString + 1);
+ return GetObjectValue(context, classDescriptor, arrayElement, idString + 1);
}
case TypeCode::ObjectModel:
@@ -808,7 +818,7 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, E
case 0:
return val;
case '.':
- return val.omVal->GetObjectValue(context, idString + 1, val.param);
+ return val.omVal->GetObjectValue(context, (val.omVal == this) ? classDescriptor : nullptr, idString + 1, val.param);
case '^':
throw context.ConstructParseException("object is not an array");
default:
diff --git a/src/ObjectModel/ObjectModel.h b/src/ObjectModel/ObjectModel.h
index b67617f7..1f0a784e 100644
--- a/src/ObjectModel/ObjectModel.h
+++ b/src/ObjectModel/ObjectModel.h
@@ -224,26 +224,26 @@ public:
void ReportAsJson(OutputBuffer *buf, const char *filter, const char *reportFlags, bool wantArrayLength) const THROWS(GCodeException);
// Get the value of an object via the table
- ExpressionValue GetObjectValue(ObjectExplorationContext& context, const char *idString, uint8_t tableNumber = 0) const THROWS(GCodeException);
+ ExpressionValue GetObjectValue(ObjectExplorationContext& context, const ObjectModelClassDescriptor * null classDescriptor, const char *idString, uint8_t tableNumber = 0) const THROWS(GCodeException);
// Function to report a value or object as JSON
- void ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& context, ExpressionValue val, const char *filter) const THROWS(GCodeException);
+ void ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelClassDescriptor *classDescriptor, ExpressionValue val, const char *filter) const THROWS(GCodeException);
// Skip the current element in the ID or filter string
static const char* GetNextElement(const char *id) noexcept;
protected:
// Construct a JSON representation of those parts of the object model requested by the user
- void ReportAsJson(OutputBuffer *buf, ObjectExplorationContext& context, uint8_t tableNumber, const char *filter) const THROWS(GCodeException);
+ void ReportAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelClassDescriptor * null classDescriptor, uint8_t tableNumber, const char *filter) const THROWS(GCodeException);
// Report an entire array as JSON
- void ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelArrayDescriptor *omad, const char *filter) const THROWS(GCodeException);
+ void ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelClassDescriptor *classDescriptor, const ObjectModelArrayDescriptor *omad, const char *filter) const THROWS(GCodeException);
// Get the value of an object that we hold
- ExpressionValue GetObjectValue(ObjectExplorationContext& context, ExpressionValue val, const char *idString) const THROWS(GCodeException);
+ ExpressionValue GetObjectValue(ObjectExplorationContext& context, const ObjectModelClassDescriptor *classDescriptor, ExpressionValue val, const char *idString) const THROWS(GCodeException);
// Get the object model table entry for the current level object in the query
- const ObjectModelTableEntry *FindObjectModelTableEntry(uint8_t tableNumber, const char *idString) const noexcept;
+ const ObjectModelTableEntry *FindObjectModelTableEntry(const ObjectModelClassDescriptor *classDescriptor, uint8_t tableNumber, const char *idString) const noexcept;
virtual const ObjectModelClassDescriptor *GetObjectModelClassDescriptor() const noexcept = 0;
@@ -284,7 +284,7 @@ public:
bool Matches(const char *filter, const ObjectExplorationContext& context) const noexcept;
// 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, ObjectExplorationContext& context, const ObjectModel *self, const char* filter, bool first) const noexcept;
+ bool ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, const ObjectModelClassDescriptor *classDescriptor, const ObjectModel *self, const char* filter, bool first) const noexcept;
// Return the name of this field
const char* GetName() const noexcept { return name; }