mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
0031313: Foundation Classes - Dump improvement for classes
- Provide DumpJson for geometrical, ocaf and visualization classes; - Change depth parameter of DumpJson (constant is not obligate here) - Introduce a new macro for transient objects to be called as the first row in DumpJson: OCCT_DUMP_TRANSIENT_CLASS_BEGIN. We need not put the class name in the macro, using get_type_name of Standard_Transient for it. - change implementation of OCCT_DUMP_CLASS_BEGIN and OCCT_DUMP_TRANSIENT_CLASS_BEGIN. It is not an sentry more and it does not create a new hierarchy level. It appends a new row into the output stream: "className": <className> - OCCT_DUMP_* does not require semicolon - class header is included first in source files of TDataStd, TDocStd, TCAFDoc
This commit is contained in:
@@ -15,25 +15,6 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
// =======================================================================
|
||||
// function : Constructor
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_DumpSentry::Standard_DumpSentry (Standard_OStream& theOStream, const char* theClassName)
|
||||
: myOStream (&theOStream)
|
||||
{
|
||||
(*myOStream) << "\"" << theClassName << "\": {";
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Destructor
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_DumpSentry::~Standard_DumpSentry()
|
||||
{
|
||||
(*myOStream) << "}";
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : AddValuesSeparator
|
||||
// purpose :
|
||||
@@ -43,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.EndsWith ("{"))
|
||||
if (!aStreamStr.IsEmpty() && !aStreamStr.EndsWith ("{"))
|
||||
theOStream << ", ";
|
||||
}
|
||||
|
||||
@@ -52,7 +33,7 @@ void Standard_Dump::AddValuesSeparator (Standard_OStream& theOStream)
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void Standard_Dump::DumpKeyToClass (Standard_OStream& theOStream,
|
||||
const char* theKey,
|
||||
const TCollection_AsciiString& theKey,
|
||||
const TCollection_AsciiString& theField)
|
||||
{
|
||||
AddValuesSeparator (theOStream);
|
||||
@@ -112,6 +93,9 @@ TCollection_AsciiString Standard_Dump::GetPointerInfo (const Handle(Standard_Tra
|
||||
// =======================================================================
|
||||
TCollection_AsciiString Standard_Dump::GetPointerInfo (const void* thePointer, const bool isShortInfo)
|
||||
{
|
||||
if (!thePointer)
|
||||
return TCollection_AsciiString();
|
||||
|
||||
std::ostringstream aPtrStr;
|
||||
aPtrStr << thePointer;
|
||||
if (!isShortInfo)
|
||||
@@ -133,17 +117,35 @@ TCollection_AsciiString Standard_Dump::GetPointerInfo (const void* thePointer, c
|
||||
// =======================================================================
|
||||
// DumpFieldToName
|
||||
// =======================================================================
|
||||
const char* Standard_Dump::DumpFieldToName (const char* theField)
|
||||
TCollection_AsciiString Standard_Dump::DumpFieldToName (const TCollection_AsciiString& theField)
|
||||
{
|
||||
const char* aName = theField;
|
||||
|
||||
if (aName[0] == '&')
|
||||
TCollection_AsciiString aName = theField;
|
||||
if (theField.StartsWith ('&'))
|
||||
{
|
||||
aName = aName + 1;
|
||||
aName.Remove (1, 1);
|
||||
}
|
||||
if (::LowerCase (aName[0]) == 'm' && aName[1] == 'y')
|
||||
|
||||
if (aName.Length() > 1 && aName.Value (1) == 'a')
|
||||
{
|
||||
aName = aName + 2;
|
||||
if (aName.Length() > 2 && aName.Value (2) == 'n')
|
||||
{
|
||||
aName.Remove (1, 2);
|
||||
}
|
||||
else
|
||||
aName.Remove (1, 1);
|
||||
}
|
||||
else if (aName.Length() > 2 && ::LowerCase (aName.Value (1)) == 'm' && aName.Value (2) == 'y')
|
||||
{
|
||||
aName.Remove (1, 2);
|
||||
}
|
||||
|
||||
if (aName.EndsWith (".get()"))
|
||||
{
|
||||
aName = aName.SubString (1, aName.Length() - TCollection_AsciiString (".get()").Length());
|
||||
}
|
||||
else if (aName.EndsWith ("()"))
|
||||
{
|
||||
aName = aName.SubString (1, aName.Length() - TCollection_AsciiString ("()").Length());
|
||||
}
|
||||
return aName;
|
||||
}
|
||||
@@ -222,3 +224,270 @@ TCollection_AsciiString Standard_Dump::FormatJson (const Standard_SStream& theSt
|
||||
}
|
||||
return aText;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// SplitJson
|
||||
// =======================================================================
|
||||
Standard_Boolean Standard_Dump::SplitJson (const TCollection_AsciiString& theStreamStr,
|
||||
NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>& theKeyToValues)
|
||||
{
|
||||
Standard_Integer aNextIndex = 1;
|
||||
while (aNextIndex < theStreamStr.Length())
|
||||
{
|
||||
Standard_JsonKey aKey = Standard_JsonKey_None;
|
||||
if (!jsonKey (theStreamStr, aNextIndex, aNextIndex, aKey))
|
||||
return Standard_False;
|
||||
|
||||
Standard_Boolean aProcessed = Standard_False;
|
||||
switch (aKey)
|
||||
{
|
||||
case Standard_JsonKey_Quote:
|
||||
{
|
||||
aProcessed = splitKeyToValue (theStreamStr, aNextIndex, aNextIndex, theKeyToValues);
|
||||
break;
|
||||
}
|
||||
case Standard_JsonKey_OpenChild:
|
||||
{
|
||||
Standard_Integer aStartIndex = aNextIndex;
|
||||
Standard_Integer aClosePos = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_OpenChild, Standard_JsonKey_CloseChild);
|
||||
if (aClosePos == 0)
|
||||
return Standard_False;
|
||||
|
||||
TCollection_AsciiString aSubStreamStr = theStreamStr.SubString (aStartIndex + JsonKeyLength (aKey), aNextIndex - 2);
|
||||
if (!SplitJson (aSubStreamStr, theKeyToValues))
|
||||
return Standard_False;
|
||||
|
||||
aNextIndex = aClosePos + Standard_Integer (JsonKeyLength (Standard_JsonKey_CloseChild));
|
||||
break;
|
||||
}
|
||||
case Standard_JsonKey_SeparatorValueToValue:
|
||||
{
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!aProcessed)
|
||||
return Standard_False;
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// HierarchicalValueIndices
|
||||
// =======================================================================
|
||||
NCollection_List<Standard_Integer> Standard_Dump::HierarchicalValueIndices (
|
||||
const NCollection_IndexedDataMap<TCollection_AsciiString, TCollection_AsciiString>& theValues)
|
||||
{
|
||||
NCollection_List<Standard_Integer> anIndices;
|
||||
|
||||
for (Standard_Integer anIndex = 1; anIndex <= theValues.Extent(); anIndex++)
|
||||
{
|
||||
if (HasChildKey (theValues.FindFromIndex (anIndex)))
|
||||
anIndices.Append (anIndex);
|
||||
}
|
||||
return anIndices;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// splitKeyToValue
|
||||
// =======================================================================
|
||||
Standard_Boolean Standard_Dump::splitKeyToValue (const TCollection_AsciiString& theStreamStr,
|
||||
Standard_Integer theStartIndex,
|
||||
Standard_Integer& theNextIndex,
|
||||
NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>& theValues)
|
||||
{
|
||||
// find key value: "key"
|
||||
Standard_Integer aStartIndex = theStartIndex;
|
||||
Standard_Integer aCloseIndex = nextClosePosition (theStreamStr, aStartIndex + 1, Standard_JsonKey_None, Standard_JsonKey_Quote);
|
||||
if (aCloseIndex == 0)
|
||||
return Standard_False;
|
||||
|
||||
TCollection_AsciiString aSplitKey = theStreamStr.SubString (aStartIndex, aCloseIndex - 1);
|
||||
|
||||
// key to value
|
||||
aStartIndex = aCloseIndex + 1;
|
||||
Standard_JsonKey aKey = Standard_JsonKey_None;
|
||||
if (!jsonKey (theStreamStr, aStartIndex, aCloseIndex, aKey))
|
||||
return Standard_False;
|
||||
|
||||
// find value
|
||||
aStartIndex = aCloseIndex;
|
||||
aKey = Standard_JsonKey_None;
|
||||
jsonKey (theStreamStr, aStartIndex, aCloseIndex, aKey);
|
||||
aStartIndex = aCloseIndex;
|
||||
|
||||
TCollection_AsciiString aSplitValue;
|
||||
theNextIndex = -1;
|
||||
switch (aKey)
|
||||
{
|
||||
case Standard_JsonKey_OpenChild:
|
||||
{
|
||||
aCloseIndex = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_OpenChild, Standard_JsonKey_CloseChild);
|
||||
if (aCloseIndex > aStartIndex)
|
||||
aSplitValue = theStreamStr.SubString (aStartIndex, aCloseIndex);
|
||||
theNextIndex = aCloseIndex + 1;
|
||||
break;
|
||||
}
|
||||
case Standard_JsonKey_OpenContainer:
|
||||
{
|
||||
aCloseIndex = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_OpenContainer, Standard_JsonKey_CloseContainer);
|
||||
if (aCloseIndex > aStartIndex)
|
||||
aSplitValue = theStreamStr.SubString (aStartIndex, aCloseIndex - 1);
|
||||
theNextIndex = aCloseIndex + 1;
|
||||
break;
|
||||
}
|
||||
case Standard_JsonKey_Quote:
|
||||
{
|
||||
Standard_JsonKey aKeyTmp = Standard_JsonKey_None;
|
||||
if (jsonKey (theStreamStr, aStartIndex, aCloseIndex, aKeyTmp) && aKeyTmp == Standard_JsonKey_Quote) // emptyValue
|
||||
{
|
||||
aSplitValue = "";
|
||||
theNextIndex = aCloseIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
aCloseIndex = nextClosePosition (theStreamStr, aStartIndex + 1, Standard_JsonKey_None, Standard_JsonKey_Quote);
|
||||
aSplitValue = theStreamStr.SubString (aStartIndex, aCloseIndex - 1);
|
||||
theNextIndex = aCloseIndex + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Standard_JsonKey_None:
|
||||
{
|
||||
if (aStartIndex == theStreamStr.Length())
|
||||
{
|
||||
aSplitValue = aStartIndex <= aCloseIndex ? theStreamStr.SubString (aStartIndex, aCloseIndex) : "";
|
||||
aSplitValue = theStreamStr.SubString (aStartIndex, aCloseIndex);
|
||||
aCloseIndex = aStartIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
Standard_Integer aCloseIndex1 = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_None, Standard_JsonKey_CloseChild) - 1;
|
||||
Standard_Integer aCloseIndex2 = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_None, Standard_JsonKey_SeparatorValueToValue) - 1;
|
||||
aCloseIndex = aCloseIndex1 < aCloseIndex2 ? aCloseIndex1 : aCloseIndex2;
|
||||
aSplitValue = aStartIndex <= aCloseIndex ? theStreamStr.SubString (aStartIndex, aCloseIndex) : "";
|
||||
}
|
||||
theNextIndex = aCloseIndex + 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
Standard_DumpValue aValue;
|
||||
if (theValues.FindFromKey (aSplitKey, aValue))
|
||||
{
|
||||
Standard_Integer anIndex = 1;
|
||||
// increment key until the new key does not exist in the container
|
||||
TCollection_AsciiString anIndexedSuffix = TCollection_AsciiString ("_") + TCollection_AsciiString (anIndex);
|
||||
while (theValues.FindFromKey (TCollection_AsciiString (aSplitKey + anIndexedSuffix), aValue))
|
||||
{
|
||||
anIndex++;
|
||||
anIndexedSuffix = TCollection_AsciiString ("_") + TCollection_AsciiString (anIndex);
|
||||
}
|
||||
aSplitKey = aSplitKey + anIndexedSuffix;
|
||||
}
|
||||
|
||||
theValues.Add (aSplitKey, Standard_DumpValue (aSplitValue, aStartIndex));
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// jsonKey
|
||||
// =======================================================================
|
||||
Standard_Boolean Standard_Dump::jsonKey (const TCollection_AsciiString& theStreamStr,
|
||||
Standard_Integer theStartIndex,
|
||||
Standard_Integer& theNextIndex,
|
||||
Standard_JsonKey& theKey)
|
||||
{
|
||||
TCollection_AsciiString aSubStreamStr = theStreamStr.SubString (theStartIndex, theStreamStr.Length());
|
||||
for (Standard_Integer aKeyId = (Standard_Integer)Standard_JsonKey_OpenChild; aKeyId <= Standard_JsonKey_SeparatorValueToValue; aKeyId++)
|
||||
{
|
||||
Standard_JsonKey aKey = (Standard_JsonKey)aKeyId;
|
||||
Standard_CString aKeyToStr = JsonKeyToString (aKey);
|
||||
if (!aSubStreamStr.StartsWith (aKeyToStr))
|
||||
continue;
|
||||
|
||||
theNextIndex = theStartIndex + Standard_Integer (JsonKeyLength (aKey));
|
||||
theKey = aKey;
|
||||
return Standard_True;
|
||||
}
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// HasChildKey
|
||||
// =======================================================================
|
||||
Standard_Boolean Standard_Dump::HasChildKey (const TCollection_AsciiString& theSourceValue)
|
||||
{
|
||||
return theSourceValue.Search (JsonKeyToString (Standard_JsonKey_SeparatorKeyToValue)) >= 0;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// JsonKeyToString
|
||||
// =======================================================================
|
||||
Standard_CString Standard_Dump::JsonKeyToString (const Standard_JsonKey theKey)
|
||||
{
|
||||
switch (theKey)
|
||||
{
|
||||
case Standard_JsonKey_None: return "";
|
||||
case Standard_JsonKey_OpenChild: return "{";
|
||||
case Standard_JsonKey_CloseChild: return "}";
|
||||
case Standard_JsonKey_OpenContainer: return "[";
|
||||
case Standard_JsonKey_CloseContainer: return "]";
|
||||
case Standard_JsonKey_Quote: return "\"";
|
||||
case Standard_JsonKey_SeparatorKeyToValue: return ": ";
|
||||
case Standard_JsonKey_SeparatorValueToValue: return ", ";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// JsonKeyLength
|
||||
// =======================================================================
|
||||
Standard_Integer Standard_Dump::JsonKeyLength (const Standard_JsonKey theKey)
|
||||
{
|
||||
return (Standard_Integer)strlen (JsonKeyToString (theKey));
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// nextClosePosition
|
||||
// =======================================================================
|
||||
Standard_Integer Standard_Dump::nextClosePosition (const TCollection_AsciiString& theSourceValue,
|
||||
const Standard_Integer theStartPosition,
|
||||
const Standard_JsonKey theOpenKey,
|
||||
const Standard_JsonKey theCloseKey)
|
||||
{
|
||||
Standard_CString anOpenKey = JsonKeyToString (theOpenKey);
|
||||
Standard_CString aCloseKeyStr = JsonKeyToString (theCloseKey);
|
||||
|
||||
Standard_Integer aStartPos = theStartPosition;
|
||||
Standard_Integer aDepthKey = 0;
|
||||
|
||||
while (aStartPos < theSourceValue.Length())
|
||||
{
|
||||
Standard_Integer anOpenKeyPos = theSourceValue.Location (anOpenKey, aStartPos, theSourceValue.Length());
|
||||
Standard_Integer aCloseKeyPos = theSourceValue.Location (aCloseKeyStr, aStartPos, theSourceValue.Length());
|
||||
if (aCloseKeyPos == 0)
|
||||
break;
|
||||
|
||||
if (anOpenKeyPos != 0 && anOpenKeyPos <= aCloseKeyPos)
|
||||
{
|
||||
aDepthKey++;
|
||||
aStartPos = anOpenKeyPos + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aDepthKey == 0)
|
||||
return aCloseKeyPos;
|
||||
else
|
||||
{
|
||||
aDepthKey--;
|
||||
aStartPos = aCloseKeyPos + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return theSourceValue.Length();
|
||||
}
|
||||
|
@@ -14,11 +14,11 @@
|
||||
#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
|
||||
|
Reference in New Issue
Block a user