From e5ac5b800b1636652836cfab649fb53004188420 Mon Sep 17 00:00:00 2001 From: David Crocker Date: Tue, 10 Mar 2020 09:11:13 +0000 Subject: Object model changes Temperature sensors now report their types in the same format as M308 accepts them Added 'directories' root element to the OM Refactored type codes in expressions --- src/ObjectModel/ObjectModel.cpp | 141 ++++++++++++++++++++++++---------------- src/ObjectModel/ObjectModel.h | 111 ++++++++++++++++--------------- 2 files changed, 145 insertions(+), 107 deletions(-) (limited to 'src/ObjectModel') diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp index e7bba1a4..ac885501 100644 --- a/src/ObjectModel/ObjectModel.cpp +++ b/src/ObjectModel/ObjectModel.cpp @@ -9,57 +9,55 @@ #if SUPPORT_OBJECT_MODEL +#include +#include #include #include #include #include -ExpressionValue::ExpressionValue(const MacAddress& mac) noexcept : type(TYPE_OF(MacAddress)), param(mac.HighWord()), uVal(mac.LowWord()) +ExpressionValue::ExpressionValue(const MacAddress& mac) noexcept : type((uint32_t)TypeCode::MacAddress), param(mac.HighWord()), uVal(mac.LowWord()) { } // Append a string representation of this value to a string void ExpressionValue::AppendAsString(const StringRef& str) const noexcept { - switch (type) + switch (GetType()) { - case TYPE_OF(char): + case TypeCode::Char: str.cat(cVal); break; - case TYPE_OF(const char*): + case TypeCode::CString: str.cat(sVal); break; - case TYPE_OF(float): + case TypeCode::Float: str.catf(GetFloatFormatString(), (double)fVal); break; - case TYPE_OF(uint32_t): + case TypeCode::Uint32: str.catf("%" PRIu32, uVal); // convert unsigned integer to string break; - case TYPE_OF(int32_t): + case TypeCode::Int32: str.catf("%" PRIi32, uVal); // convert signed integer to string break; - case TYPE_OF(bool): + case TypeCode::Bool: str.cat((bVal) ? "true" : "false"); // convert bool to string break; - case TYPE_OF(IPAddress): + case TypeCode::IPAddress: str.cat(IP4String(uVal).c_str()); break; - case TYPE_OF(const ObjectModel*): - str.cat("{object}"); - break; - - case NoType: + case TypeCode::None: str.cat("null"); break; - case TYPE_OF(DateTime): + case TypeCode::DateTime: { const time_t time = Get56BitValue(); tm timeInfo; @@ -69,7 +67,7 @@ void ExpressionValue::AppendAsString(const StringRef& str) const noexcept } break; - case TYPE_OF(DriverId): + case TypeCode::DriverId: #if SUPPORT_CAN_EXPANSION str.catf("%u.%u", (unsigned int)(uVal >> 8), (unsigned int)(uVal & 0xFF)); #else @@ -77,20 +75,44 @@ void ExpressionValue::AppendAsString(const StringRef& str) const noexcept #endif break; - case TYPE_OF(MacAddress): + case TypeCode::MacAddress: str.catf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)(uVal & 0xFF), (unsigned int)((uVal >> 8) & 0xFF), (unsigned int)((uVal >> 16) & 0xFF), (unsigned int)((uVal >> 24) & 0xFF), (unsigned int)(param & 0xFF), (unsigned int)((param >> 8) & 0xFF)); break; #if SUPPORT_CAN_EXPANSION - case TYPE_OF(CanExpansionBoardDetails): + case TypeCode::CanExpansionBoardDetails: ExtractRequestedPart(str); break; #endif - default: - str.cat(""); + case TypeCode::Special: + switch ((SpecialType)param) + { + case SpecialType::sysDir: + reprap.GetPlatform().AppendSysDir(str); + break; + } + break; + + // We don't fully handle the remaining types + case TypeCode::ObjectModel: + str.cat("{object}"); + break; + + case TypeCode::Array: + str.cat("[array]"); + break; + + case TypeCode::Bitmap16: + case TypeCode::Bitmap32: + case TypeCode::Bitmap64: + str.cat("(Bitmap)"); + break; + + case TypeCode::Enum32: + str.cat("(enumeration)"); break; } } @@ -310,18 +332,18 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& if (context.WantArrayLength() && *filter == 0) { // We have been asked for the length of an array and we have reached the end of the filter, so the value should be an array - switch (val.type) + switch (val.GetType()) { - case TYPE_OF(const ObjectModelArrayDescriptor*): + case TypeCode::Array: buf->catf("%u", val.omadVal->GetNumElements(this, context)); break; - case TYPE_OF(Bitmap): - case TYPE_OF(Bitmap): + case TypeCode::Bitmap16: + case TypeCode::Bitmap32: buf->catf("%u", Bitmap::MakeFromRaw(val.uVal).CountSetBits()); break; - case TYPE_OF(Bitmap): + case TypeCode::Bitmap64: buf->catf("%u", Bitmap::MakeFromRaw(val.Get56BitValue()).CountSetBits()); break; @@ -332,9 +354,9 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& } else { - switch (val.type) + switch (val.GetType()) { - case TYPE_OF(const ObjectModelArrayDescriptor*): + case TypeCode::Array: if (*filter == '[') { ++filter; @@ -377,7 +399,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& } break; - case TYPE_OF(const ObjectModel*): + case TypeCode::ObjectModel: if (*filter == '.') { ++filter; @@ -390,7 +412,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& val.omVal->ReportAsJson(buf, context, val.param, filter); break; - case TYPE_OF(float): + case TypeCode::Float: if (val.fVal == 0.0) { buf->cat('0'); // replace 0.000... in JSON by 0. This is mostly to save space when writing workplace coordinates. @@ -401,26 +423,26 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& } break; - case TYPE_OF(uint32_t): + case TypeCode::Uint32: buf->catf("%" PRIu32, val.uVal); break; - case TYPE_OF(int32_t): + case TypeCode::Int32: buf->catf("%" PRIi32, val.iVal); break; - case TYPE_OF(const char*): + case TypeCode::CString: buf->EncodeString(val.sVal, true); break; #ifdef DUET3 - case TYPE_OF(CanExpansionBoardDetails): + case TypeCode::CanExpansionBoardDetails: ReportExpansionBoardDetail(buf, val); break; #endif - case TYPE_OF(Bitmap): - case TYPE_OF(Bitmap): + case TypeCode::Bitmap16: + case TypeCode::Bitmap32: if (*filter == '[') { ++filter; @@ -466,7 +488,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& } break; - case TYPE_OF(Bitmap): + case TypeCode::Bitmap64: if (*filter == '[') { ++filter; @@ -512,7 +534,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& } break; - case TYPE_OF(Enum32): + case TypeCode::Enum32: if (context.ShortFormReport()) { buf->catf("%" PRIu32, val.uVal); @@ -524,17 +546,17 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& } break; - case TYPE_OF(bool): + case TypeCode::Bool: buf->cat((val.bVal) ? "true" : "false"); break; - case TYPE_OF(char): + case TypeCode::Char: buf->cat('"'); buf->EncodeChar(val.cVal); buf->cat('"'); break; - case TYPE_OF(IPAddress): + case TypeCode::IPAddress: { const IPAddress ipVal(val.uVal); char sep = '"'; @@ -547,11 +569,11 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& } break; - case TYPE_OF(DateTime): + case TypeCode::DateTime: ReportDateTime(buf, val); break; - case TYPE_OF(DriverId): + case TypeCode::DriverId: #if SUPPORT_CAN_EXPANSION buf->catf("\"%u.%u\"", (unsigned int)(val.uVal >> 8), (unsigned int)(val.uVal & 0xFF)); #else @@ -559,13 +581,22 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& #endif break; - case TYPE_OF(MacAddress): + case TypeCode::MacAddress: buf->catf("\"%02x:%02x:%02x:%02x:%02x:%02x\"", (unsigned int)(val.uVal & 0xFF), (unsigned int)((val.uVal >> 8) & 0xFF), (unsigned int)((val.uVal >> 16) & 0xFF), (unsigned int)((val.uVal >> 24) & 0xFF), (unsigned int)(val.param & 0xFF), (unsigned int)((val.param >> 8) & 0xFF)); break; - case NoType: + case TypeCode::Special: + switch ((ExpressionValue::SpecialType)val.param) + { + case ExpressionValue::SpecialType::sysDir: + reprap.GetPlatform().EncodeSysDir(buf); + break; + } + break; + + case TypeCode::None: buf->cat("null"); break; } @@ -649,7 +680,7 @@ bool ObjectModelTableEntry::ReportAsJson(OutputBuffer* buf, ObjectExplorationCon { const char * nextElement = ObjectModel::GetNextElement(filter); const ExpressionValue val = func(self, context); - if (val.type != NoType || context.ShouldIncludeNulls()) + if (val.GetType() != TypeCode::None || context.ShouldIncludeNulls()) { if (*filter == 0) { @@ -698,9 +729,9 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, c ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, ExpressionValue val, const char *idString) const { - switch (val.type) + switch (val.GetType()) { - case TYPE_OF(const ObjectModelArrayDescriptor*): + case TypeCode::Array: { if (*idString == 0 && context.WantArrayLength()) { @@ -724,7 +755,7 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, E return GetObjectValue(context, arrayElement, idString + 1); } - case TYPE_OF(const ObjectModel*): + case TypeCode::ObjectModel: switch (*idString) { case 0: @@ -738,15 +769,15 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, E } break; - case NoType: + case TypeCode::None: if (*idString == 0) { return val; // a null value can be compared to null } throw context.ConstructParseException("reached null object before end of selector string"); - case TYPE_OF(Bitmap): - case TYPE_OF(Bitmap): + case TypeCode::Bitmap16: + case TypeCode::Bitmap32: if (context.WantArrayLength()) { if (*idString != 0) @@ -776,7 +807,7 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, E } return ExpressionValue((int32_t)val.uVal); - case TYPE_OF(Bitmap): + case TypeCode::Bitmap64: if (context.WantArrayLength()) { if (*idString != 0) @@ -806,7 +837,7 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, E } return ExpressionValue((int32_t)val.uVal); - case TYPE_OF(MacAddress): + case TypeCode::MacAddress: if (*idString == 0) { return (context.WantArrayLength()) ? ExpressionValue((int32_t)17) : val; @@ -814,7 +845,7 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, E break; #ifdef DUET3 - case TYPE_OF(CanExpansionBoardDetails): + case TypeCode::CanExpansionBoardDetails: if (*idString == 0) { if (context.WantArrayLength()) @@ -826,7 +857,7 @@ ExpressionValue ObjectModel::GetObjectValue(ObjectExplorationContext& context, E break; #endif - case TYPE_OF(const char*): + case TypeCode::CString: if (*idString == 0 && context.WantArrayLength()) { return ExpressionValue((int32_t)strlen(val.sVal)); diff --git a/src/ObjectModel/ObjectModel.h b/src/ObjectModel/ObjectModel.h index 46ee6b8d..db34689d 100644 --- a/src/ObjectModel/ObjectModel.h +++ b/src/ObjectModel/ObjectModel.h @@ -18,13 +18,38 @@ #include #include -typedef uint8_t TypeCode; -constexpr TypeCode NoType = 0; // code for an invalid or unknown type +// Type codes to indicate what type of expression we have and how it is represented. +// The "Special" type is for items that we have to evaluate when we are ready to write them out, in particular strings whose storage might disappear. +enum class TypeCode : uint8_t +{ + None = 0, + Bool, + Char, + Uint32, + Int32, + Float, + Bitmap16, + Bitmap32, + Bitmap64, // only 56 bits actually available + Enum32, + ObjectModel, + CString, + IPAddress, + Array, + DateTime, + DriverId, + MacAddress, + Special, +#if SUPPORT_CAN_EXPANSION + CanExpansionBoardDetails +#endif +}; // Dummy types, used to define type codes class Bitmap32; class Bitmap64; class Enum32; +class SpecialString; #if SUPPORT_CAN_EXPANSION @@ -48,33 +73,6 @@ struct DateTime time_t tim; }; -// Function template used to get constexpr type codes -// Each type must return a unique type code in the range 1 to 127 (0 is NoType) -template constexpr TypeCode TypeOf() noexcept; - -template<> constexpr TypeCode TypeOf () noexcept { return 1; } -template<> constexpr TypeCode TypeOf () noexcept { return 2; } -template<> constexpr TypeCode TypeOf () noexcept { return 3; } -template<> constexpr TypeCode TypeOf () noexcept { return 4; } -template<> constexpr TypeCode TypeOf () noexcept { return 5; } -template<> constexpr TypeCode TypeOf> () noexcept { return 6; } -template<> constexpr TypeCode TypeOf> () noexcept { return 7; } -template<> constexpr TypeCode TypeOf> () noexcept { return 8; } -template<> constexpr TypeCode TypeOf () noexcept { return 9; } -template<> constexpr TypeCode TypeOf () noexcept { return 10; } -template<> constexpr TypeCode TypeOf () noexcept { return 11; } -template<> constexpr TypeCode TypeOf () noexcept { return 12; } -template<> constexpr TypeCode TypeOf () noexcept { return 13; } -template<> constexpr TypeCode TypeOf () noexcept { return 14; } -template<> constexpr TypeCode TypeOf () noexcept { return 15; } -template<> constexpr TypeCode TypeOf () noexcept { return 16; } - -#if SUPPORT_CAN_EXPANSION -template<> constexpr TypeCode TypeOf () noexcept { return 17; } -#endif - -#define TYPE_OF(_t) (TypeOf<_t>()) - // Forward declarations class ObjectModelTableEntry; class ObjectModel; @@ -97,33 +95,42 @@ struct ExpressionValue const ObjectModelArrayDescriptor *omadVal; }; - ExpressionValue() noexcept : type(NoType) { } - explicit constexpr ExpressionValue(bool b) noexcept : type(TYPE_OF(bool)), param(0), bVal(b) { } - explicit constexpr ExpressionValue(char c) noexcept : type(TYPE_OF(char)), param(0), cVal(c) { } - explicit constexpr ExpressionValue(float f) noexcept : type(TYPE_OF(float)), param(MaxFloatDigitsDisplayedAfterPoint), fVal(f) { } - constexpr ExpressionValue(float f, uint8_t numDecimalPlaces) noexcept : type(TYPE_OF(float)), param(numDecimalPlaces), fVal(f) { } - explicit constexpr ExpressionValue(int32_t i) noexcept : type(TYPE_OF(int32_t)), param(0), iVal(i) { } - explicit constexpr ExpressionValue(const ObjectModel *om) noexcept : type((om == nullptr) ? NoType : TYPE_OF(const ObjectModel*)), param(0), omVal(om) { } - constexpr ExpressionValue(const ObjectModel *om, uint8_t tableNumber) noexcept : type((om == nullptr) ? NoType : TYPE_OF(const ObjectModel*)), param(tableNumber), omVal(om) { } - explicit constexpr ExpressionValue(const char *s) noexcept : type(TYPE_OF(const char*)), param(0), sVal(s) { } - explicit constexpr ExpressionValue(const ObjectModelArrayDescriptor *omad) noexcept : type(TYPE_OF(const ObjectModelArrayDescriptor*)), param(0), omadVal(omad) { } - explicit constexpr ExpressionValue(IPAddress ip) noexcept : type(TYPE_OF(IPAddress)), param(0), uVal(ip.GetV4LittleEndian()) { } - explicit constexpr ExpressionValue(nullptr_t dummy) noexcept : type(NoType), param(0), uVal(0) { } - explicit ExpressionValue(DateTime t) noexcept : type((t.tim == 0) ? NoType : TYPE_OF(DateTime)), param(t.tim >> 32), uVal((uint32_t)t.tim) { } - explicit ExpressionValue(DriverId id) noexcept : type(TYPE_OF(DriverId)), param(0), uVal(id.AsU32()) { } - explicit ExpressionValue(Bitmap bm) noexcept : type(TYPE_OF(Bitmap)), param(0), uVal(bm.GetRaw()) { } - explicit ExpressionValue(Bitmap bm) noexcept : type(TYPE_OF(Bitmap)), param(0), uVal(bm.GetRaw()) { } - explicit ExpressionValue(Bitmap bm) noexcept : type(TYPE_OF(Bitmap)), param(bm.GetRaw() >> 32), uVal((uint32_t)bm.GetRaw()) { } + enum class SpecialType : uint32_t + { + sysDir = 0 + }; + + ExpressionValue() noexcept : type((uint32_t)TypeCode::None) { } + explicit constexpr ExpressionValue(bool b) noexcept : type((uint32_t)TypeCode::Bool), param(0), bVal(b) { } + explicit constexpr ExpressionValue(char c) noexcept : type((uint32_t)TypeCode::Char), param(0), cVal(c) { } + explicit constexpr ExpressionValue(float f) noexcept : type((uint32_t)TypeCode::Float), param(MaxFloatDigitsDisplayedAfterPoint), fVal(f) { } + constexpr ExpressionValue(float f, uint8_t numDecimalPlaces) noexcept : type((uint32_t)TypeCode::Float), param(numDecimalPlaces), fVal(f) { } + explicit constexpr ExpressionValue(int32_t i) noexcept : type((uint32_t)TypeCode::Int32), param(0), iVal(i) { } + explicit constexpr ExpressionValue(const ObjectModel *om) noexcept : type((om == nullptr) ? (uint32_t)TypeCode::None : (uint32_t)TypeCode::ObjectModel), param(0), omVal(om) { } + constexpr ExpressionValue(const ObjectModel *om, uint8_t tableNumber) noexcept : type((om == nullptr) ? (uint32_t)TypeCode::None : (uint32_t)TypeCode::ObjectModel), param(tableNumber), omVal(om) { } + explicit constexpr ExpressionValue(const char *s) noexcept : type((uint32_t)TypeCode::CString), param(0), sVal(s) { } + explicit constexpr ExpressionValue(const ObjectModelArrayDescriptor *omad) noexcept : type((uint32_t)TypeCode::Array), param(0), omadVal(omad) { } + explicit constexpr ExpressionValue(IPAddress ip) noexcept : type((uint32_t)TypeCode::IPAddress), param(0), uVal(ip.GetV4LittleEndian()) { } + explicit constexpr ExpressionValue(nullptr_t dummy) noexcept : type((uint32_t)TypeCode::None), param(0), uVal(0) { } + explicit ExpressionValue(DateTime t) noexcept : type((t.tim == 0) ? (uint32_t)TypeCode::None : (uint32_t)TypeCode::DateTime), param(t.tim >> 32), uVal((uint32_t)t.tim) { } + explicit ExpressionValue(DriverId id) noexcept : type((uint32_t)TypeCode::DriverId), param(0), uVal(id.AsU32()) { } + explicit ExpressionValue(Bitmap bm) noexcept : type((uint32_t)TypeCode::Bitmap16), param(0), uVal(bm.GetRaw()) { } + explicit ExpressionValue(Bitmap bm) noexcept : type((uint32_t)TypeCode::Bitmap32), param(0), uVal(bm.GetRaw()) { } + explicit ExpressionValue(Bitmap bm) noexcept : type((uint32_t)TypeCode::Bitmap64), param(bm.GetRaw() >> 32), uVal((uint32_t)bm.GetRaw()) { } explicit ExpressionValue(const MacAddress& mac) noexcept; + explicit ExpressionValue(SpecialType s) noexcept : type((uint32_t)TypeCode::Special), param((uint32_t)s), uVal(0) { } #if SUPPORT_CAN_EXPANSION - ExpressionValue(const char*s, ExpansionDetail p) noexcept : type(TYPE_OF(CanExpansionBoardDetails)), param((uint32_t)p), sVal(s) { } + ExpressionValue(const char*s, ExpansionDetail p) noexcept : type((uint32_t)TypeCode::CanExpansionBoardDetails), param((uint32_t)p), sVal(s) { } #endif - void Set(bool b) noexcept { type = TYPE_OF(bool); bVal = b; } - void Set(char c) noexcept { type = TYPE_OF(char); cVal = c; } - void Set(int32_t i) noexcept { type = TYPE_OF(int32_t); iVal = i; } - void Set(float f) noexcept { type = TYPE_OF(float); fVal = f; param = 1; } - void Set(const char *s) noexcept { type = TYPE_OF(const char*); sVal = s; } + TypeCode GetType() const noexcept { return (TypeCode)type; } + void SetType(TypeCode t) noexcept { type = (uint32_t)t; } + + void Set(bool b) noexcept { type = (uint32_t)TypeCode::Bool; bVal = b; } + void Set(char c) noexcept { type = (uint32_t)TypeCode::Char; cVal = c; } + void Set(int32_t i) noexcept { type = (uint32_t)TypeCode::Int32; iVal = i; } + void Set(float f) noexcept { type = (uint32_t)TypeCode::Float; fVal = f; param = 1; } + void Set(const char *s) noexcept { type = (uint32_t)TypeCode::CString; sVal = s; } // Extract a 56-bit value that we have stored. Used to retrieve date/times and large bitmaps. uint64_t Get56BitValue() const noexcept { return ((uint64_t)param << 32) | uVal; } -- cgit v1.2.3