0904aa63 |
1 | // Copyright (c) 2019 OPEN CASCADE SAS |
2 | // |
3 | // This file is part of Open CASCADE Technology software library. |
4 | // |
5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
9 | // distribution for complete text of the license and disclaimer of any warranty. |
10 | // |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
13 | |
14 | #ifndef _Standard_Dump_HeaderFile |
15 | #define _Standard_Dump_HeaderFile |
16 | |
17 | #include <Standard_SStream.hxx> |
18 | #include <TCollection_AsciiString.hxx> |
19 | |
20 | class Standard_DumpSentry; |
21 | |
22 | //! The file contains interface to prepare dump output for OCCT objects. Format of the dump is JSON. |
3de0f784 |
23 | //! To prepare this output, implement method DumpJson in the object and use macro functions from this file. |
0904aa63 |
24 | //! Macros have one parameter for both, key and the value. It is a field of the current class. Macro has internal analyzer that |
25 | //! uses the variable name to generate key. If the parameter has prefix symbols "&", "*" and "my", it is cut. |
26 | //! |
3de0f784 |
27 | //! - OCCT_DUMP_FIELD_VALUE_NUMERICAL. Use it for fields of numerical C++ types, like int, float, double. It creates a pair "key", "value", |
28 | //! - OCCT_DUMP_FIELD_VALUE_STRING. Use it for char* type. It creates a pair "key", "value", |
29 | //! - OCCT_DUMP_FIELD_VALUE_POINTER. Use it for pointer fields. It creates a pair "key", "value", where the value is the pointer address, |
30 | //! - OCCT_DUMP_FIELD_VALUES_DUMPED. Use it for fields that has own Dump implementation. It expects the pointer to the class instance. |
0904aa63 |
31 | //! It creates "key": { result of dump of the field } |
3de0f784 |
32 | //! - OCCT_DUMP_FIELD_VALUES_NUMERICAL. Use it for unlimited list of fields of C++ double type. |
0904aa63 |
33 | //! It creates massive of values [value_1, value_2, ...] |
3de0f784 |
34 | //! - OCCT_DUMP_FIELD_VALUES_STRING. Use it for unlimited list of fields of TCollection_AsciiString types. |
0904aa63 |
35 | //! It creates massive of values ["value_1", "value_2", ...] |
3de0f784 |
36 | //! - OCCT_DUMP_BASE_CLASS. Use if Dump implementation of the class is virtual, to perform ClassName::Dump() of the parent class, |
0904aa63 |
37 | //! expected parameter is the parent class name. |
38 | //! It creates "key": { result of dump of the field } |
3de0f784 |
39 | //! - OCCT_DUMP_VECTOR_CLASS. Use it as a single row in some object dump to have one row in output. |
40 | //! It's possible to use it without necessity of OCCT_DUMP_CLASS_BEGIN call. |
0904aa63 |
41 | //! It creates massive of values [value_1, value_2, ...] |
42 | //! |
43 | //! The Dump result prepared by these macros is an output stream, it is not arranged with spaces and line feed. |
44 | //! To have output in a more readable way, use ConvertToAlignedString method for obtained stream. |
45 | |
46 | //! Converts the class type into a string value |
3de0f784 |
47 | #define OCCT_CLASS_NAME(theClass) #theClass |
0904aa63 |
48 | |
3de0f784 |
49 | //! @def OCCT_DUMP_CLASS_BEGIN |
0904aa63 |
50 | //! Creates an instance of Sentry to cover the current Dump implementation with keys of start and end. |
51 | //! This row should be inserted before other macros. The end key will be added by the sentry remove, |
52 | //! (exit of the method). |
3de0f784 |
53 | #define OCCT_DUMP_CLASS_BEGIN(theOStream, theName) \ |
54 | Standard_DumpSentry aSentry (theOStream, OCCT_CLASS_NAME(theName)); |
0904aa63 |
55 | |
3de0f784 |
56 | //! @def OCCT_DUMP_FIELD_VALUE_NUMERICAL |
0904aa63 |
57 | //! Append into output value: "Name": Field |
3de0f784 |
58 | #define OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, theField) \ |
0904aa63 |
59 | { \ |
3de0f784 |
60 | const char* aName = Standard_Dump::DumpFieldToName (#theField); \ |
61 | Standard_Dump::AddValuesSeparator (theOStream); \ |
0904aa63 |
62 | theOStream << "\"" << aName << "\": " << theField; \ |
63 | } |
64 | |
3de0f784 |
65 | //! @def OCCT_DUMP_FIELD_VALUE_STRING |
0904aa63 |
66 | //! Append into output value: "Name": "Field" |
3de0f784 |
67 | #define OCCT_DUMP_FIELD_VALUE_STRING(theOStream, theField) \ |
0904aa63 |
68 | { \ |
3de0f784 |
69 | const char* aName = Standard_Dump::DumpFieldToName (#theField); \ |
70 | Standard_Dump::AddValuesSeparator (theOStream); \ |
0904aa63 |
71 | theOStream << "\"" << aName << "\": \"" << theField << "\""; \ |
72 | } |
73 | |
3de0f784 |
74 | //! @def OCCT_DUMP_FIELD_VALUE_POINTER |
0904aa63 |
75 | //! Append into output value: "Name": "address of the pointer" |
3de0f784 |
76 | #define OCCT_DUMP_FIELD_VALUE_POINTER(theOStream, theField) \ |
0904aa63 |
77 | { \ |
3de0f784 |
78 | const char* aName = Standard_Dump::DumpFieldToName (#theField); \ |
79 | Standard_Dump::AddValuesSeparator (theOStream); \ |
0904aa63 |
80 | theOStream << "\"" << aName << "\": \"" << Standard_Dump::GetPointerInfo (theField) << "\""; \ |
81 | } |
82 | |
3de0f784 |
83 | //! @def OCCT_DUMP_FIELD_VALUES_DUMPED |
0904aa63 |
84 | //! Append into output value: "Name": { field dumped values } |
85 | //! It computes Dump of the fields. The expected field is a pointer. |
86 | //! Use this macro for fields of the dumped class which has own Dump implementation. |
87 | //! The macros is recursive. Recursion is stopped when the depth value becomes equal to zero. |
88 | //! Depth = -1 is the default value, dump here is unlimited. |
3de0f784 |
89 | #define OCCT_DUMP_FIELD_VALUES_DUMPED(theOStream, theDepth, theField) \ |
0904aa63 |
90 | { \ |
91 | if (theDepth != 0) \ |
92 | { \ |
93 | Standard_SStream aFieldStream; \ |
94 | if ((theField) != NULL) \ |
95 | (theField)->DumpJson (aFieldStream, theDepth - 1); \ |
3de0f784 |
96 | const char* aName = Standard_Dump::DumpFieldToName (#theField); \ |
0904aa63 |
97 | Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (aFieldStream)); \ |
98 | } \ |
99 | } |
100 | |
3de0f784 |
101 | //! @def OCCT_DUMP_FIELD_VALUES_NUMERICAL |
0904aa63 |
102 | //! Append real values into output values in an order: [value_1, value_2, ...] |
103 | //! It computes Dump of the parent. The expected field is a parent class name to call ClassName::Dump. |
3de0f784 |
104 | #define OCCT_DUMP_FIELD_VALUES_NUMERICAL(theOStream, theName, theCount, ...) \ |
0904aa63 |
105 | { \ |
3de0f784 |
106 | Standard_Dump::AddValuesSeparator (theOStream); \ |
0904aa63 |
107 | theOStream << "\"" << theName << "\": ["; \ |
108 | Standard_Dump::DumpRealValues (theOStream, theCount, __VA_ARGS__);\ |
109 | theOStream << "]"; \ |
110 | } |
111 | |
3de0f784 |
112 | //! @def OCCT_DUMP_FIELD_VALUES_STRING |
0904aa63 |
113 | //! Append real values into output values in an order: ["value_1", "value_2", ...] |
114 | //! It computes Dump of the parent. The expected field is a parent class name to call ClassName::Dump. |
3de0f784 |
115 | #define OCCT_DUMP_FIELD_VALUES_STRING(theOStream, theName, theCount, ...) \ |
0904aa63 |
116 | { \ |
3de0f784 |
117 | Standard_Dump::AddValuesSeparator (theOStream); \ |
0904aa63 |
118 | theOStream << "\"" << theName << "\": ["; \ |
119 | Standard_Dump::DumpCharacterValues (theOStream, theCount, __VA_ARGS__);\ |
120 | theOStream << "]"; \ |
121 | } |
122 | |
3de0f784 |
123 | //! @def OCCT_DUMP_BASE_CLASS |
0904aa63 |
124 | //! Append into output value: "Name": { field dumped values } |
125 | //! It computes Dump of the parent. The expected field is a parent class name to call ClassName::Dump. |
126 | //! Use this macro for parent of the current class. |
127 | //! The macros is recursive. Recursive is stoped when the depth value becomes equal to zero. |
128 | //! Depth = -1 is the default value, dump here is unlimited. |
3de0f784 |
129 | #define OCCT_DUMP_BASE_CLASS(theOStream, theDepth, theField) \ |
0904aa63 |
130 | { \ |
131 | if (theDepth != 0) \ |
132 | { \ |
133 | Standard_SStream aFieldStream; \ |
134 | theField::DumpJson (aFieldStream, theDepth - 1); \ |
3de0f784 |
135 | const char* aName = Standard_Dump::DumpFieldToName (#theField); \ |
0904aa63 |
136 | Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (aFieldStream)); \ |
137 | } \ |
138 | } |
139 | |
3de0f784 |
140 | //! @def OCCT_DUMP_VECTOR_CLASS |
0904aa63 |
141 | //! Append vector values into output value: "Name": [value_1, value_2, ...] |
142 | //! This macro is intended to have only one row for dumped object in Json. |
3de0f784 |
143 | //! 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. |
144 | #define OCCT_DUMP_VECTOR_CLASS(theOStream, theName, theCount, ...) \ |
0904aa63 |
145 | { \ |
3de0f784 |
146 | theOStream << "\"" << OCCT_CLASS_NAME(theName) << "\": ["; \ |
0904aa63 |
147 | Standard_Dump::DumpRealValues (theOStream, theCount, __VA_ARGS__);\ |
148 | theOStream << "]"; \ |
149 | } |
150 | |
151 | //! @brief Simple sentry class providing convenient interface to dump. |
152 | //! Appends start and last rows in dump with class name key. |
153 | //! An example of the using: for ClassName, the result is: "ClassName" { ... } |
154 | //! Create instance of that class in the first row of Dump. |
155 | class Standard_DumpSentry |
156 | { |
157 | public: |
158 | //! Constructor - add parameters of start class name definition in the stream |
159 | Standard_EXPORT Standard_DumpSentry (Standard_OStream& theOStream, const char* theClassName); |
160 | |
161 | //! Destructor - add parameters of stop class name definition in the stream |
162 | Standard_EXPORT ~Standard_DumpSentry(); |
163 | |
164 | private: |
165 | Standard_OStream* myOStream; //!< modified stream |
166 | }; |
167 | |
168 | //! This interface has some tool methods for stream (in JSON format) processing. |
169 | class Standard_Dump |
170 | { |
171 | public: |
172 | //! Converts stream value to string value. The result is original stream value. |
173 | //! @param theStream source value |
174 | //! @return text presentation |
175 | Standard_EXPORT static TCollection_AsciiString Text (const Standard_SStream& theStream); |
176 | |
177 | //! Converts stream value to string value. Improves the text presentation with the following cases: |
178 | //! - for '{' append after '\n' and indent to the next value, increment current indent value |
179 | //! - for '}' append '\n' and current indent before it, decrement indent value |
180 | //! - for ',' append after '\n' and indent to the next value. If the current symbol is in massive container [], do nothing |
181 | //! @param theStream source value |
182 | //! @param theIndent count of ' ' symbols to apply hierarchical indent of the text values |
183 | //! @return text presentation |
184 | Standard_EXPORT static TCollection_AsciiString FormatJson (const Standard_SStream& theStream, const Standard_Integer theIndent = 3); |
185 | |
3de0f784 |
186 | //! Add Json values separator if the stream last symbol is not an open brace. |
0904aa63 |
187 | //! @param theStream source value |
3de0f784 |
188 | static Standard_EXPORT void AddValuesSeparator (Standard_OStream& theOStream); |
0904aa63 |
189 | |
190 | //! Returns default prefix added for each pointer info string if short presentation of pointer used |
191 | Standard_EXPORT static TCollection_AsciiString GetPointerPrefix() { return "0x"; } |
192 | |
193 | //! Convert handle pointer to address of the pointer. If the handle is NULL, the result is an empty string. |
194 | //! @param thePointer a pointer |
195 | //! @param isShortInfo if true, all '0' symbols in the beginning of the pointer are skipped |
196 | //! @return the string value |
197 | Standard_EXPORT static TCollection_AsciiString GetPointerInfo (const Handle(Standard_Transient)& thePointer, |
198 | const bool isShortInfo = true); |
199 | |
200 | //! Convert pointer to address of the pointer. If the handle is NULL, the result is an empty string. |
201 | //! @param thePointer a pointer |
202 | //! @param isShortInfo if true, all '0' symbols in the beginning of the pointer are skipped |
203 | //! @return the string value |
204 | Standard_EXPORT static TCollection_AsciiString GetPointerInfo (const void* thePointer, |
205 | const bool isShortInfo = true); |
206 | |
207 | //! Append into output value: "Name": { Field } |
208 | //! @param theOStream [out] stream to be fill with values |
209 | //! @param theKey a source value |
210 | //! @param theField stream value |
211 | Standard_EXPORT static void DumpKeyToClass (Standard_OStream& theOStream, |
212 | const char* theKey, |
213 | const TCollection_AsciiString& theField); |
214 | |
215 | //! Unite values in one value using template: "value_1", "value_2", ..., "value_n" |
216 | //! @param theOStream [out] stream to be fill with values |
217 | //! @param theCount numer of values |
218 | Standard_EXPORT static void DumpCharacterValues (Standard_OStream& theOStream, int theCount, ...); |
219 | |
220 | //! Unite values in one value using template: value_1, value_2, ..., value_n |
221 | //! @param theOStream [out] stream to be fill with values |
222 | //! @param theCount numer of values |
223 | Standard_EXPORT static void DumpRealValues (Standard_OStream& theOStream, int theCount, ...); |
224 | |
225 | //! Convert field name into dump text value, removes "&" and "my" prefixes |
226 | //! An example, for field myValue, theName is Value, for &myCLass, the name is Class |
227 | //! @param theField a source value |
228 | //! @param theName [out] an updated name |
3de0f784 |
229 | Standard_EXPORT static const char* DumpFieldToName (const char* theField); |
0904aa63 |
230 | }; |
231 | |
232 | #endif // _Standard_Dump_HeaderFile |