0031313: Foundation Classes - Dump improvement for classes
[occt.git] / src / Standard / Standard_Dump.hxx
index ba5d4ae..d9b56c8 100644 (file)
 #ifndef _Standard_Dump_HeaderFile
 #define _Standard_Dump_HeaderFile
 
+#include <NCollection_IndexedDataMap.hxx>
+#include <NCollection_List.hxx>
 #include <Standard_SStream.hxx>
 #include <TCollection_AsciiString.hxx>
 
-class Standard_DumpSentry;
-
 //! The file contains interface to prepare dump output for OCCT objects. Format of the dump is JSON.
 //! To prepare this output, implement method DumpJson in the object and use macro functions from this file.
 //! Macros have one parameter for both, key and the value. It is a field of the current class. Macro has internal analyzer that
@@ -50,14 +50,27 @@ class Standard_DumpSentry;
 //! Creates an instance of Sentry to cover the current Dump implementation with keys of start and end.
 //! This row should be inserted before other macros. The end key will be added by the sentry remove,
 //! (exit of the method).
-#define OCCT_DUMP_CLASS_BEGIN(theOStream, theName) \
-  Standard_DumpSentry aSentry (theOStream, OCCT_CLASS_NAME(theName));
+#define OCCT_DUMP_CLASS_BEGIN(theOStream, theField) \
+{ \
+  const char* className = OCCT_CLASS_NAME(theField); \
+  OCCT_DUMP_FIELD_VALUE_STRING (theOStream, className) \
+}
+
+//! @def OCCT_DUMP_TRANSIENT_CLASS_BEGIN
+//! Creates an instance of Sentry to cover the current Dump implementation with keys of start and end.
+//! This row should be inserted before other macros. The end key will be added by the sentry remove,
+//! (exit of the method).
+#define OCCT_DUMP_TRANSIENT_CLASS_BEGIN(theOStream) \
+{ \
+  const char* className = get_type_name(); \
+  OCCT_DUMP_FIELD_VALUE_STRING (theOStream, className) \
+}
 
 //! @def OCCT_DUMP_FIELD_VALUE_NUMERICAL
 //! Append into output value: "Name": Field
 #define OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, theField) \
 { \
-  const char* aName = Standard_Dump::DumpFieldToName (#theField); \
+  TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField); \
   Standard_Dump::AddValuesSeparator (theOStream); \
   theOStream << "\"" << aName << "\": " << theField; \
 }
@@ -66,7 +79,7 @@ class Standard_DumpSentry;
 //! Append into output value: "Name": "Field"
 #define OCCT_DUMP_FIELD_VALUE_STRING(theOStream, theField) \
 { \
-  const char* aName = Standard_Dump::DumpFieldToName (#theField); \
+  TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField); \
   Standard_Dump::AddValuesSeparator (theOStream); \
   theOStream << "\"" << aName << "\": \"" << theField << "\""; \
 }
@@ -75,11 +88,22 @@ class Standard_DumpSentry;
 //! Append into output value: "Name": "address of the pointer"
 #define OCCT_DUMP_FIELD_VALUE_POINTER(theOStream, theField) \
 { \
-  const char* aName = Standard_Dump::DumpFieldToName (#theField); \
+  TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField); \
   Standard_Dump::AddValuesSeparator (theOStream); \
   theOStream << "\"" << aName << "\": \"" << Standard_Dump::GetPointerInfo (theField) << "\""; \
 }
 
+//! @def OCCT_DUMP_FIELD_VALUE_STRING
+//! Append into output value: "Name": "Field"
+#define OCCT_DUMP_FIELD_VALUE_GUID(theOStream, theField) \
+{ \
+  TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField); \
+  Standard_Dump::AddValuesSeparator (theOStream); \
+  char aStr[Standard_GUID_SIZE_ALLOC]; \
+  theField.ToCString (aStr); \
+  theOStream << "\"" << aName << "\": \"" << aStr << "\""; \
+}
+
 //! @def OCCT_DUMP_FIELD_VALUES_DUMPED
 //! Append into output value: "Name": { field dumped values }
 //! It computes Dump of the fields. The expected field is a pointer.
@@ -88,12 +112,11 @@ class Standard_DumpSentry;
 //! Depth = -1 is the default value, dump here is unlimited.
 #define OCCT_DUMP_FIELD_VALUES_DUMPED(theOStream, theDepth, theField) \
 { \
-  if (theDepth != 0) \
+  if (theDepth != 0 && (void*)(theField) != NULL) \
   { \
     Standard_SStream aFieldStream; \
-    if ((theField) != NULL) \
-      (theField)->DumpJson (aFieldStream, theDepth - 1); \
-    const char* aName = Standard_Dump::DumpFieldToName (#theField); \
+    (theField)->DumpJson (aFieldStream, theDepth - 1); \
+    TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField); \
     Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (aFieldStream)); \
   } \
 }
@@ -130,10 +153,8 @@ class Standard_DumpSentry;
 { \
   if (theDepth != 0) \
   { \
-    Standard_SStream aFieldStream; \
-    theField::DumpJson (aFieldStream, theDepth - 1); \
-    const char* aName = Standard_Dump::DumpFieldToName (#theField); \
-    Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (aFieldStream)); \
+    Standard_Dump::AddValuesSeparator (theOStream); \
+    theField::DumpJson (theOStream, theDepth - 1); \
   } \
 }
 
@@ -143,26 +164,34 @@ class Standard_DumpSentry;
 //! It's possible to use it without necessity of OCCT_DUMP_CLASS_BEGIN call, but pay attention that it should be only one row in the object dump.
 #define OCCT_DUMP_VECTOR_CLASS(theOStream, theName, theCount, ...) \
 { \
-  theOStream << "\"" << OCCT_CLASS_NAME(theName) << "\": ["; \
+  Standard_Dump::AddValuesSeparator (theOStream); \
+  theOStream << "\"" << theName << "\": ["; \
   Standard_Dump::DumpRealValues (theOStream, theCount, __VA_ARGS__);\
   theOStream << "]"; \
 }
 
-//! @brief Simple sentry class providing convenient interface to dump.
-//! Appends start and last rows in dump with class name key.
-//! An example of the using: for ClassName, the result is: "ClassName" { ... }
-//! Create instance of that class in the first row of Dump.
-class Standard_DumpSentry
+//! Kind of key in Json string
+enum Standard_JsonKey
 {
-public:
-  //! Constructor - add parameters of start class name definition in the stream
-  Standard_EXPORT Standard_DumpSentry (Standard_OStream& theOStream, const char* theClassName);
+  Standard_JsonKey_None, //!< no key
+  Standard_JsonKey_OpenChild, //!< "{"
+  Standard_JsonKey_CloseChild, //!< "}"
+  Standard_JsonKey_OpenContainer, //!< "["
+  Standard_JsonKey_CloseContainer, //!< "]"
+  Standard_JsonKey_Quote, //!< "\""
+  Standard_JsonKey_SeparatorKeyToValue, //!< ": "
+  Standard_JsonKey_SeparatorValueToValue //!< ", "
+};
 
-  //! Destructor - add parameters of stop class name definition in the stream
-  Standard_EXPORT ~Standard_DumpSentry();
+//! Type for storing a dump value with the stream position
+struct Standard_DumpValue
+{
+  Standard_DumpValue() : myStartPosition (0) {}
+  Standard_DumpValue (const TCollection_AsciiString& theValue, const Standard_Integer theStartPos)
+    : myValue (theValue), myStartPosition (theStartPos) {}
 
-private:
-  Standard_OStream* myOStream; //!< modified stream
+  TCollection_AsciiString myValue; //!< current string value
+  Standard_Integer myStartPosition; //!< position of the value first char in the whole stream
 };
 
 //! This interface has some tool methods for stream (in JSON format) processing.
@@ -183,12 +212,39 @@ public:
   //! @return text presentation
   Standard_EXPORT static TCollection_AsciiString FormatJson (const Standard_SStream& theStream, const Standard_Integer theIndent = 3);
 
-  //! Add Json values separator if the stream last symbol is not an open brace.
+  //! Converts stream into map of values. Values are not empty if the stream contains at least two values.
+  //!
+  //! The one level stream example: <class_name>key_1\value_1\key_2\value_2</class_name>
+  //! In output: theStreamKey equals class_name, theValues contains key_1, value_1, key_2, and value_2.
+  //!
+  //! Two level stream example: <class_name>key_1\value_1\key_2\value_2\key_3<subclass_name>subclass_key_1\subclass_value1</subclass_name></class_name>
+  //! In output: theStreamKey equals class_name, theValues contains key_1, value_1, key_2, and value_2, key_3 and
+  //! <subclass_name>subclass_key_1\subclass_value1</subclass_name>.
+  //! The last value might be processed later using the same method.
+  //!
+  //! @param theStream stream value
+  //! @param theKeyToValues [out] container of split values
+  Standard_EXPORT static Standard_Boolean SplitJson (const TCollection_AsciiString& theStreamStr,
+                                                     NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>& theKeyToValues);
+
+  //! Returns container of indices in values, that has hierarchical value
+  Standard_EXPORT static NCollection_List<Standard_Integer> HierarchicalValueIndices (
+    const NCollection_IndexedDataMap<TCollection_AsciiString, TCollection_AsciiString>& theValues);
+
+  //! Returns true if the value has bracket key
+  Standard_EXPORT static Standard_Boolean HasChildKey (const TCollection_AsciiString& theSourceValue);
+
+  //! Returns key value for enum type
+  Standard_EXPORT static Standard_CString JsonKeyToString (const Standard_JsonKey theKey);
+
+  //! Returns length value for enum type
+  Standard_EXPORT static Standard_Integer JsonKeyLength (const Standard_JsonKey theKey);
+
   //! @param theStream source value
   static Standard_EXPORT void AddValuesSeparator (Standard_OStream& theOStream);
 
   //! Returns default prefix added for each pointer info string if short presentation of pointer used
-  Standard_EXPORT static TCollection_AsciiString GetPointerPrefix() { return "0x"; }
+  static TCollection_AsciiString GetPointerPrefix() { return "0x"; }
 
   //! Convert handle pointer to address of the pointer. If the handle is NULL, the result is an empty string.
   //! @param thePointer a pointer
@@ -209,7 +265,7 @@ public:
   //! @param theKey a source value
   //! @param theField stream value
   Standard_EXPORT static void DumpKeyToClass (Standard_OStream& theOStream,
-                                              const char* theKey,
+                                              const TCollection_AsciiString& theKey,
                                               const TCollection_AsciiString& theField);
 
   //! Unite values in one value using template: "value_1", "value_2", ..., "value_n"
@@ -226,7 +282,35 @@ public:
   //! An example, for field myValue, theName is Value, for &myCLass, the name is Class
   //! @param theField a source value 
   //! @param theName [out] an updated name 
-  Standard_EXPORT static const char* DumpFieldToName (const char* theField);
+  Standard_EXPORT static TCollection_AsciiString DumpFieldToName (const TCollection_AsciiString& theField);
+
+private:
+  //! Extracts from the string value a pair (key, value), add it into output container, update index value
+  //! Example:
+  //! stream string starting the index position contains: ..."key": <value>...
+  //! a pair key, value will be added into theValues
+  //! at beginning theIndex is the position of the quota before <key>, after the index is the next position after the value
+  //! splitDumped(aString) gives theSplitValue = "abc", theTailValue = "defg", theKey = "key"
+  Standard_EXPORT static Standard_Boolean splitKeyToValue (const TCollection_AsciiString& theStreamStr,
+                                                           Standard_Integer theStartIndex,
+                                                           Standard_Integer& theNextIndex,
+                                                           NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>& theValues);
+
+
+  //! Returns key of json in the index position. Incement the index position to the next symbol in the row
+  Standard_EXPORT static Standard_Boolean jsonKey (const TCollection_AsciiString& theStreamStr,
+                                                   Standard_Integer theStartIndex,
+                                                   Standard_Integer& theNextIndex,
+                                                   Standard_JsonKey& theKey);
+
+  //! Find position in the source string of the symbol close after the start position.
+  //! Ignore combination <symbol open> ... <symbol close> between the close symbol.
+  //! Example, for case ... { ... { ... } ...} ... } it returns the position of the forth brace
+  Standard_EXPORT static Standard_Integer nextClosePosition (const TCollection_AsciiString& theSourceValue,
+                                                             const Standard_Integer theStartPosition,
+                                                             const Standard_JsonKey theCloseKey,
+                                                             const Standard_JsonKey theOpenKey);
+
 };
 
 #endif // _Standard_Dump_HeaderFile