diff --git a/src/Message/Message.cxx b/src/Message/Message.cxx index 0a4de98751..cdc7dc6520 100644 --- a/src/Message/Message.cxx +++ b/src/Message/Message.cxx @@ -25,9 +25,10 @@ namespace { - static Standard_CString Message_Table_PrintMetricTypeEnum[11] = + static Standard_CString Message_Table_PrintMetricTypeEnum[13] = { - "NONE", "UserTimeCPU", "SystemTimeInfo", "WallClock", "MemPrivate", "MemVirtual", + "NONE", "ThreadCPUUserTime", "ThreadCPUSystemTime", "ProcessCPUUserTime", "ProcessCPUSystemTime", + "WallClock", "MemPrivate", "MemVirtual", "MemWorkingSet", "MemWorkingSetPeak", "MemSwapUsage", "MemSwapUsagePeak", "MemHeapUsage" }; } diff --git a/src/Message/Message_AttributeMeter.cxx b/src/Message/Message_AttributeMeter.cxx index 0fe5042dc2..531c0f0e9c 100644 --- a/src/Message/Message_AttributeMeter.cxx +++ b/src/Message/Message_AttributeMeter.cxx @@ -255,13 +255,7 @@ void Message_AttributeMeter::DumpJson (Standard_OStream& theOStream, for (NCollection_IndexedDataMap::Iterator anIterator (myMetrics); anIterator.More(); anIterator.Next()) { - Message_MetricType aMetricType = anIterator.Key(); - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aMetricType) - - Standard_Real aStartValue = anIterator.Value().first; - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aStartValue) - - Standard_Real aStopValue = anIterator.Value().second; - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aStopValue) + OCCT_DUMP_VECTOR_CLASS (theOStream, Message::MetricToString (anIterator.Key()), + 2, anIterator.Value().first, anIterator.Value().second) } } diff --git a/src/Message/Message_AttributeStream.cxx b/src/Message/Message_AttributeStream.cxx index ba0ff7e8a0..3574395584 100644 --- a/src/Message/Message_AttributeStream.cxx +++ b/src/Message/Message_AttributeStream.cxx @@ -47,6 +47,5 @@ void Message_AttributeStream::DumpJson (Standard_OStream& theOStream, OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Message_Attribute) - TCollection_AsciiString aStream = Standard_Dump::Text (myStream); - OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aStream) + OCCT_DUMP_STREAM_VALUE_DUMPED (theOStream, myStream) } diff --git a/src/Message/Message_CompositeAlerts.cxx b/src/Message/Message_CompositeAlerts.cxx index 312b059634..5c1a267ea3 100644 --- a/src/Message/Message_CompositeAlerts.cxx +++ b/src/Message/Message_CompositeAlerts.cxx @@ -169,15 +169,16 @@ void Message_CompositeAlerts::DumpJson (Standard_OStream& theOStream, { OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) + Standard_Integer anInc = 1; for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i) { - Message_Gravity aGravity = (Message_Gravity)i; - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aGravity) + if (myAlerts[i].IsEmpty()) + continue; - for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); anIt.Next()) + for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); anIt.Next(), anInc++) { const Handle(Message_Alert)& anAlert = anIt.Value(); - OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, anAlert.get()) + OCCT_DUMP_FIELD_VALUES_DUMPED_INC (theOStream, theDepth, anAlert.get(), anInc) } } } diff --git a/src/Message/Message_Report.cxx b/src/Message/Message_Report.cxx index d8ed266198..2b038c1726 100644 --- a/src/Message/Message_Report.cxx +++ b/src/Message/Message_Report.cxx @@ -489,10 +489,11 @@ void Message_Report::DumpJson (Standard_OStream& theOStream, Standard_Integer th Standard_Integer anAlertLevels = myAlertLevels.Size(); OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, anAlertLevels) + Standard_Integer anInc = 1; for (NCollection_IndexedMap::Iterator anIterator (myActiveMetrics); anIterator.More(); anIterator.Next()) { Message_MetricType anActiveMetric = anIterator.Value(); - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, anActiveMetric) + OCCT_DUMP_FIELD_VALUE_NUMERICAL_INC (theOStream, anActiveMetric, anInc++) } OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLimit) diff --git a/src/Standard/Standard_Dump.cxx b/src/Standard/Standard_Dump.cxx index 49e0d16c3b..355db4647a 100644 --- a/src/Standard/Standard_Dump.cxx +++ b/src/Standard/Standard_Dump.cxx @@ -24,7 +24,7 @@ void Standard_Dump::AddValuesSeparator (Standard_OStream& theOStream) Standard_SStream aStream; aStream << theOStream.rdbuf(); TCollection_AsciiString aStreamStr = Standard_Dump::Text (aStream); - if (!aStreamStr.IsEmpty() && !aStreamStr.EndsWith ("{")) + if (!aStreamStr.IsEmpty() && !aStreamStr.EndsWith ("{") && !aStreamStr.EndsWith (", ")) theOStream << ", "; } @@ -302,9 +302,15 @@ TCollection_AsciiString Standard_Dump::FormatJson (const Standard_SStream& theSt Standard_Integer anIndentCount = 0; Standard_Boolean isMassiveValues = Standard_False; - for (Standard_Integer anIndex = 1; anIndex < aStreamStr.Length(); anIndex++) + for (Standard_Integer anIndex = 1; anIndex <= aStreamStr.Length(); anIndex++) { Standard_Character aSymbol = aStreamStr.Value (anIndex); + if (anIndex == 1 && aText.IsEmpty() && aSymbol != '{') + { + // append opening brace for json start + aSymbol = '{'; + anIndex--; + } if (aSymbol == '{') { anIndentCount++; @@ -313,7 +319,9 @@ TCollection_AsciiString Standard_Dump::FormatJson (const Standard_SStream& theSt aText += '\n'; for (int anIndent = 0; anIndent < anIndentCount; anIndent++) + { aText += anIndentStr; + } } else if (aSymbol == '}') { @@ -348,8 +356,24 @@ TCollection_AsciiString Standard_Dump::FormatJson (const Standard_SStream& theSt else aText += aSymbol; } + else if (aSymbol == '\n') + { + aText += ""; // json does not support multi-lined values, skip this symbol + } else aText += aSymbol; + + if (anIndex == aStreamStr.Length() && aSymbol != '}') + { + // append closing brace for json end + aSymbol = '}'; + + anIndentCount--; + aText += '\n'; + for (int anIndent = 0; anIndent < anIndentCount; anIndent++) + aText += anIndentStr; + aText += aSymbol; + } } return aText; } diff --git a/src/Standard/Standard_Dump.hxx b/src/Standard/Standard_Dump.hxx index d2b294c7d1..a6935be7fe 100644 --- a/src/Standard/Standard_Dump.hxx +++ b/src/Standard/Standard_Dump.hxx @@ -27,10 +27,15 @@ //! uses the variable name to generate key. If the parameter has prefix symbols "&", "*" and "my", it is cut. //! //! - OCCT_DUMP_FIELD_VALUE_NUMERICAL. Use it for fields of numerical C++ types, like int, float, double. It creates a pair "key", "value", +//! - OCCT_DUMP_FIELD_VALUE_NUMERICAL_INC. Use it for fields of numerical C++ types, like int, float, double. +//! It creates a pair "key_inc", "value", //! - OCCT_DUMP_FIELD_VALUE_STRING. Use it for char* type. It creates a pair "key", "value", //! - OCCT_DUMP_FIELD_VALUE_POINTER. Use it for pointer fields. It creates a pair "key", "value", where the value is the pointer address, //! - OCCT_DUMP_FIELD_VALUES_DUMPED. Use it for fields that has own Dump implementation. It expects the pointer to the class instance. //! It creates "key": { result of dump of the field } +//! - OCCT_DUMP_FIELD_VALUES_DUMPED_INC. Use it for fields that has own Dump implementation. It expects the pointer to the class instance. +//! It creates "key_inc": { result of dump of the field } +//! - OCCT_DUMP_STREAM_VALUE_DUMPED. Use it for Standard_SStream. It creates "key": { text of stream } //! - OCCT_DUMP_FIELD_VALUES_NUMERICAL. Use it for unlimited list of fields of C++ double type. //! It creates massive of values [value_1, value_2, ...] //! - OCCT_DUMP_FIELD_VALUES_STRING. Use it for unlimited list of fields of TCollection_AsciiString types. @@ -77,6 +82,16 @@ theOStream << "\"" << aName << "\": " << theField; \ } +//! @def OCCT_DUMP_FIELD_VALUE_NUMERICAL +//! Append into output value: "Name": Field +//! Inc name value added to the key to provide unique keys +#define OCCT_DUMP_FIELD_VALUE_NUMERICAL_INC(theOStream, theField, theIncName) \ +{ \ + TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField) + theIncName; \ + Standard_Dump::AddValuesSeparator (theOStream); \ + theOStream << "\"" << aName << "\": " << theField; \ +} + //! @def OCCT_INIT_FIELD_VALUE_REAL //! Append vector values into output value: "Name": [value_1, value_2, ...] //! This macro is intended to have only one row for dumped object in Json. @@ -155,6 +170,24 @@ } \ } +//! @def OCCT_DUMP_FIELD_VALUES_DUMPED_INC +//! Append into output value: "Name": { field dumped values } +//! It computes Dump of the fields. The expected field is a pointer. +//! Use this macro for fields of the dumped class which has own Dump implementation. +//! The macros is recursive. Recursion is stopped when the depth value becomes equal to zero. +//! Depth = -1 is the default value, dump here is unlimited. +//! Inc name value added to the key to provide unique keys +#define OCCT_DUMP_FIELD_VALUES_DUMPED_INC(theOStream, theDepth, theField, theIncName) \ +{ \ + if (theDepth != 0 && (void*)(theField) != NULL) \ + { \ + Standard_SStream aFieldStream; \ + (theField)->DumpJson (aFieldStream, theDepth - 1); \ + TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField) + theIncName; \ + Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (aFieldStream)); \ + } \ +} + //! @def OCCT_INIT_FIELD_VALUES_DUMPED //! Append into output value: "Name": { field dumped values } //! It computes Dump of the fields. The expected field is a pointer. @@ -167,6 +200,16 @@ return Standard_False; \ } +//! @def OCCT_DUMP_STREAM_VALUE_DUMPED +//! Append into output value: "Name": { stream text } +//! It computes Dump of the fields. The expected field is a pointer. +//! Use this macro for Standard_SStream field. +#define OCCT_DUMP_STREAM_VALUE_DUMPED(theOStream, theField) \ +{ \ + TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField); \ + Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (theField)); \ +} + //! @def OCCT_DUMP_FIELD_VALUES_NUMERICAL //! Append real values into output values in an order: [value_1, value_2, ...] //! It computes Dump of the parent. The expected field is a parent class name to call ClassName::Dump. @@ -267,6 +310,7 @@ public: //! - for '{' append after '\n' and indent to the next value, increment current indent value //! - for '}' append '\n' and current indent before it, decrement indent value //! - for ',' append after '\n' and indent to the next value. If the current symbol is in massive container [], do nothing + //! Covers result with opened and closed brackets on the top level, if it has no symbols there. //! @param theStream source value //! @param theIndent count of ' ' symbols to apply hierarchical indent of the text values //! @return text presentation