diff options
author | David Crocker <dcrocker@eschertech.com> | 2020-01-12 19:24:51 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2020-01-12 19:24:51 +0300 |
commit | d62a033787144bb4c90898309c9ffb12dc52bf37 (patch) | |
tree | 008557dd59da5cae7a1cff64040fcea012610dd6 /src/ObjectModel | |
parent | f08c1c3b0356578adeaa8a12fc70cd921b65ec72 (diff) |
More work on object model
Changed M408 P1 response to return the key and value separately, and to
return null as the value for queries that fail
Replaced Electronics.MainBoard object by Boards[0]
Added firmware and IAP name members to Boards[0] object
Diffstat (limited to 'src/ObjectModel')
-rw-r--r-- | src/ObjectModel/ObjectModel.cpp | 86 | ||||
-rw-r--r-- | src/ObjectModel/ObjectModel.h | 20 |
2 files changed, 62 insertions, 44 deletions
diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp index 7c497a2d..dbe1ffb4 100644 --- a/src/ObjectModel/ObjectModel.cpp +++ b/src/ObjectModel/ObjectModel.cpp @@ -48,9 +48,8 @@ unsigned int ObjectExplorationContext::GetIndex(size_t n) const } // Report this object -bool ObjectModel::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, uint8_t tableNumber, const char* filter) const +void ObjectModel::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, uint8_t tableNumber, const char* filter) const { - buf->cat('{'); bool added = false; const uint8_t *descriptor; const ObjectModelTableEntry *tbl = GetObjectModelTable(descriptor); @@ -67,35 +66,43 @@ bool ObjectModel::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& cont { if (tbl->Matches(filter, context)) { - if (added) + if (!added) { - buf->cat(','); + if (*filter == 0 || context.ReportFullPath()) + { + buf->cat('{'); + } + added = true; } - const char * nextElement = GetNextElement(filter); - if (*nextElement == '.') + else { - ++nextElement; + buf->cat(','); } - tbl->ReportAsJson(buf, context, this, nextElement); - added = true; + tbl->ReportAsJson(buf, context, this, filter); } --numEntries; ++tbl; } + if (added && (*filter == 0 || context.ReportFullPath())) + { + buf->cat('}'); + } + } + if (!added) + { + buf->cat("null"); } - buf->cat('}'); - return added; } // Construct a JSON representation of those parts of the object model requested by the user. This version is called on the root of the tree. -bool ObjectModel::ReportAsJson(OutputBuffer *buf, const char *filter, ObjectModelReportFlags rf, ObjectModelEntryFlags ff) const +void ObjectModel::ReportAsJson(OutputBuffer *buf, const char *filter, ObjectModelReportFlags rf, ObjectModelEntryFlags ff) const { ObjectExplorationContext context(rf, ff); - return ReportAsJson(buf, context, 0, filter); + ReportAsJson(buf, context, 0, filter); } // Function to report a value or object as JSON -bool ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& context, ExpressionValue val, const char *filter) const +void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& context, ExpressionValue val, const char *filter) const { switch (val.type) { @@ -112,25 +119,29 @@ bool ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& const long index = SafeStrtol(filter, &endptr); if (endptr == filter || *endptr != ']' || index < 0 || (size_t)index >= val.omadVal->GetNumElements(this, context)) { - buf->cat("[]"); // avoid returning badly-formed JSON - return false; // invalid syntax, or index out of range + buf->cat("null"); // avoid returning badly-formed JSON + break; // invalid syntax, or index out of range + } + if (*filter == 0 || context.ReportFullPath()) + { + buf->cat('['); } - buf->cat('['); context.AddIndex(index); - bool ret; { ReadLocker lock(val.omadVal->lockPointer); - ret = ReportItemAsJson(buf, context, val.omadVal->GetElement(this, context), endptr + 1); + ReportItemAsJson(buf, context, val.omadVal->GetElement(this, context), endptr + 1); } context.RemoveIndex(); - buf->cat(']'); - return ret; + if (*filter == 0 || context.ReportFullPath()) + { + buf->cat(']'); + } } - if (*filter == 0) // else reporting on all subparts of all elements in the array + else if (*filter == 0) // else reporting on all subparts of all elements in the array { - return ReportArrayAsJson(buf, context, val.omadVal, filter); + ReportArrayAsJson(buf, context, val.omadVal, filter); } - return false; + break;; case TYPE_OF(const ObjectModel*): if (val.omVal != nullptr) @@ -236,29 +247,26 @@ bool ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& buf->cat("null"); break; } - return true; } // Report an entire array as JSON -bool ObjectModel::ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelArrayDescriptor *omad, const char *filter) const +void ObjectModel::ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelArrayDescriptor *omad, const char *filter) const { ReadLocker lock(omad->lockPointer); buf->cat('['); - bool ret = true; const size_t count = omad->GetNumElements(this, context); - for (size_t i = 0; i < count && ret; ++i) + for (size_t i = 0; i < count; ++i) { if (i != 0) { buf->cat(','); } context.AddIndex(i); - ret = ReportItemAsJson(buf, context, omad->GetElement(this, context), filter); + ReportItemAsJson(buf, context, omad->GetElement(this, context), filter); context.RemoveIndex(); } buf->cat(']'); - return ret; } // Find the requested entry @@ -314,12 +322,20 @@ 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) const noexcept +void ObjectModelTableEntry::ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, const ObjectModel *self, const char* filter) const noexcept { - buf->cat('"'); - buf->cat(name); - buf->cat("\":"); - return self->ReportItemAsJson(buf, context, func(self, context), filter); + if (*filter == 0 || context.ReportFullPath()) + { + buf->cat('"'); + buf->cat(name); + buf->cat("\":"); + } + const char * nextElement = ObjectModel::GetNextElement(filter); + if (*nextElement == '.') + { + ++nextElement; + } + self->ReportItemAsJson(buf, context, func(self, context), nextElement); } // Compare an ID with the name of this object diff --git a/src/ObjectModel/ObjectModel.h b/src/ObjectModel/ObjectModel.h index 6d860a40..467d7fdd 100644 --- a/src/ObjectModel/ObjectModel.h +++ b/src/ObjectModel/ObjectModel.h @@ -109,7 +109,8 @@ struct ExpressionValue enum class ObjectModelReportFlags : uint16_t { none = 0, - shortForm = 1 + shortForm = 1, + fullPath = 2 }; // Flags field of a table entry @@ -133,6 +134,7 @@ public: ObjectModelReportFlags GetReportFlags() const noexcept { return reportFlags; } ObjectModelEntryFlags GetFilterFlags() const noexcept { return filterFlags; } bool ShortFormReport() const noexcept { return ((uint16_t)reportFlags & (uint16_t)ObjectModelReportFlags::shortForm) != 0; } + bool ReportFullPath() const noexcept { return ((uint16_t)reportFlags & (uint16_t)ObjectModelReportFlags::fullPath) != 0; } private: static constexpr size_t MaxIndices = 4; // max depth of array nesting @@ -159,20 +161,23 @@ public: ObjectModel() noexcept; // Construct a JSON representation of those parts of the object model requested by the user. This version is called on the root of the tree. - bool ReportAsJson(OutputBuffer *buf, const char *filter, ObjectModelReportFlags rf, ObjectModelEntryFlags ff) const THROWS_GCODE_EXCEPTION; + void ReportAsJson(OutputBuffer *buf, const char *filter, ObjectModelReportFlags rf, ObjectModelEntryFlags ff) const THROWS_GCODE_EXCEPTION; // Get the value of an object. This version is called on the root of the tree. ExpressionValue GetObjectValue(const StringParser& sp, const char *idString) const THROWS_GCODE_EXCEPTION; // Function to report a value or object as JSON - bool ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& context, ExpressionValue val, const char *filter) const THROWS_GCODE_EXCEPTION; + void ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& context, ExpressionValue val, const char *filter) const THROWS_GCODE_EXCEPTION; + + // 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 - bool ReportAsJson(OutputBuffer *buf, ObjectExplorationContext& context, uint8_t tableNumber, const char *filter) const THROWS_GCODE_EXCEPTION; + void ReportAsJson(OutputBuffer *buf, ObjectExplorationContext& context, uint8_t tableNumber, const char *filter) const THROWS_GCODE_EXCEPTION; // Report an entire array as JSON - bool ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelArrayDescriptor *omad, const char *filter) const THROWS_GCODE_EXCEPTION; + void ReportArrayAsJson(OutputBuffer *buf, ObjectExplorationContext& context, const ObjectModelArrayDescriptor *omad, const char *filter) const THROWS_GCODE_EXCEPTION; // Get the value of an object via the table ExpressionValue GetObjectValue(const StringParser& sp, ObjectExplorationContext& context, uint8_t tableNumber, const char *idString) const THROWS_GCODE_EXCEPTION; @@ -183,9 +188,6 @@ protected: // 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; - // Skip the current element in the ID or filter string - static const char* GetNextElement(const char *id) noexcept; - virtual const ObjectModelTableEntry *GetObjectModelTable(const uint8_t*& descriptor) const noexcept = 0; }; @@ -210,7 +212,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) const noexcept; + void ReportAsJson(OutputBuffer* buf, ObjectExplorationContext& context, const ObjectModel *self, const char* filter) const noexcept; // Return the name of this field const char* GetName() const noexcept { return name; } |