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. |
23 | //! To prepare this output, implement method Dump in the object and use macro functions from this file. |
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 | //! |
27 | //! - DUMP_FIELD_VALUE_NUMERICAL. Use it for fields of numerical C++ types, like int, float, double. It creates a pair "key", "value", |
28 | //! - DUMP_FIELD_VALUE_STRING. Use it for char* type. It creates a pair "key", "value", |
29 | //! - DUMP_FIELD_VALUE_POINTER. Use it for pointer fields. It creates a pair "key", "value", where the value is the pointer address, |
30 | //! - DUMP_FIELD_VALUES_DUMPED. Use it for fields that has own Dump implementation. It expects the pointer to the class instance. |
31 | //! It creates "key": { result of dump of the field } |
32 | //! - DUMP_FIELD_VALUES_NUMERICAL. Use it for unlimited list of fields of C++ double type. |
33 | //! It creates massive of values [value_1, value_2, ...] |
34 | //! - DUMP_FIELD_VALUES_STRING. Use it for unlimited list of fields of TCollection_AsciiString types. |
35 | //! It creates massive of values ["value_1", "value_2", ...] |
36 | //! - DUMP_FIELD_VALUES_BY_KIND. Use if Dump implementation of the class is virtual, to perform ClassName::Dump() of the parent class, |
37 | //! expected parameter is the parent class name. |
38 | //! It creates "key": { result of dump of the field } |
39 | //! - 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 DUMP_CLASS_BEGIN call. |
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 |
47 | #define CLASS_NAME(theClass) #theClass |
48 | |
49 | //! @def DUMP_CLASS_BEGIN |
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). |
53 | #define DUMP_CLASS_BEGIN(theOStream, theName) \ |
54 | Standard_DumpSentry aSentry (theOStream, CLASS_NAME(theName)); \ |
55 | |
56 | //! @def DUMP_FIELD_VALUE_NUMERICAL |
57 | //! Append into output value: "Name": Field |
58 | #define DUMP_FIELD_VALUE_NUMERICAL(theOStream, theField) \ |
59 | { \ |
60 | const char* aName = NULL; \ |
61 | Standard_Dump::DumpFieldToName (#theField, aName); \ |
62 | if (!Standard_Dump::EndsWith (theOStream, "{")) \ |
63 | theOStream << ", "; \ |
64 | theOStream << "\"" << aName << "\": " << theField; \ |
65 | } |
66 | |
67 | //! @def DUMP_FIELD_VALUE_STRING |
68 | //! Append into output value: "Name": "Field" |
69 | #define DUMP_FIELD_VALUE_STRING(theOStream, theField) \ |
70 | { \ |
71 | const char* aName = NULL; \ |
72 | Standard_Dump::DumpFieldToName (#theField, aName); \ |
73 | if (!Standard_Dump::EndsWith (theOStream, "{")) \ |
74 | theOStream << ", "; \ |
75 | theOStream << "\"" << aName << "\": \"" << theField << "\""; \ |
76 | } |
77 | |
78 | //! @def DUMP_FIELD_VALUE_POINTER |
79 | //! Append into output value: "Name": "address of the pointer" |
80 | #define DUMP_FIELD_VALUE_POINTER(theOStream, theField) \ |
81 | { \ |
82 | const char* aName = NULL; \ |
83 | Standard_Dump::DumpFieldToName (#theField, aName); \ |
84 | if (!Standard_Dump::EndsWith (theOStream, "{")) \ |
85 | theOStream << ", "; \ |
86 | theOStream << "\"" << aName << "\": \"" << Standard_Dump::GetPointerInfo (theField) << "\""; \ |
87 | } |
88 | |
89 | //! @def DUMP_FIELD_VALUES_DUMPED |
90 | //! Append into output value: "Name": { field dumped values } |
91 | //! It computes Dump of the fields. The expected field is a pointer. |
92 | //! Use this macro for fields of the dumped class which has own Dump implementation. |
93 | //! The macros is recursive. Recursion is stopped when the depth value becomes equal to zero. |
94 | //! Depth = -1 is the default value, dump here is unlimited. |
95 | #define DUMP_FIELD_VALUES_DUMPED(theOStream, theDepth, theField) \ |
96 | { \ |
97 | if (theDepth != 0) \ |
98 | { \ |
99 | Standard_SStream aFieldStream; \ |
100 | if ((theField) != NULL) \ |
101 | (theField)->DumpJson (aFieldStream, theDepth - 1); \ |
102 | const char* aName = NULL; \ |
103 | Standard_Dump::DumpFieldToName (#theField, aName); \ |
104 | Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (aFieldStream)); \ |
105 | } \ |
106 | } |
107 | |
108 | //! @def DUMP_FIELD_VALUES_NUMERICAL |
109 | //! Append real values into output values in an order: [value_1, value_2, ...] |
110 | //! It computes Dump of the parent. The expected field is a parent class name to call ClassName::Dump. |
111 | #define DUMP_FIELD_VALUES_NUMERICAL(theOStream, theName, theCount, ...) \ |
112 | { \ |
113 | if (!Standard_Dump::EndsWith (theOStream, "{")) \ |
114 | theOStream << ", "; \ |
115 | theOStream << "\"" << theName << "\": ["; \ |
116 | Standard_Dump::DumpRealValues (theOStream, theCount, __VA_ARGS__);\ |
117 | theOStream << "]"; \ |
118 | } |
119 | |
120 | //! @def DUMP_FIELD_VALUES_STRING |
121 | //! Append real values into output values in an order: ["value_1", "value_2", ...] |
122 | //! It computes Dump of the parent. The expected field is a parent class name to call ClassName::Dump. |
123 | #define DUMP_FIELD_VALUES_STRING(theOStream, theName, theCount, ...) \ |
124 | { \ |
125 | if (!Standard_Dump::EndsWith (theOStream, "{")) \ |
126 | theOStream << ", "; \ |
127 | theOStream << "\"" << theName << "\": ["; \ |
128 | Standard_Dump::DumpCharacterValues (theOStream, theCount, __VA_ARGS__);\ |
129 | theOStream << "]"; \ |
130 | } |
131 | |
132 | //! @def DUMP_FIELD_VALUES_BY_KIND |
133 | //! Append into output value: "Name": { field dumped values } |
134 | //! It computes Dump of the parent. The expected field is a parent class name to call ClassName::Dump. |
135 | //! Use this macro for parent of the current class. |
136 | //! The macros is recursive. Recursive is stoped when the depth value becomes equal to zero. |
137 | //! Depth = -1 is the default value, dump here is unlimited. |
138 | #define DUMP_FIELD_VALUES_BY_KIND(theOStream, theDepth, theField) \ |
139 | { \ |
140 | if (theDepth != 0) \ |
141 | { \ |
142 | Standard_SStream aFieldStream; \ |
143 | theField::DumpJson (aFieldStream, theDepth - 1); \ |
144 | const char* aName = NULL; \ |
145 | Standard_Dump::DumpFieldToName (#theField, aName); \ |
146 | Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (aFieldStream)); \ |
147 | } \ |
148 | } |
149 | |
150 | //! @def DUMP_VECTOR_CLASS |
151 | //! Append vector values into output value: "Name": [value_1, value_2, ...] |
152 | //! This macro is intended to have only one row for dumped object in Json. |
153 | //! It's possible to use it without necessity of DUMP_CLASS_BEGIN call, but pay attention that it should be only one row in the object dump. |
154 | #define DUMP_VECTOR_CLASS(theOStream, theName, theCount, ...) \ |
155 | { \ |
156 | theOStream << "\"" << CLASS_NAME(theName) << "\": ["; \ |
157 | Standard_Dump::DumpRealValues (theOStream, theCount, __VA_ARGS__);\ |
158 | theOStream << "]"; \ |
159 | } |
160 | |
161 | //! @brief Simple sentry class providing convenient interface to dump. |
162 | //! Appends start and last rows in dump with class name key. |
163 | //! An example of the using: for ClassName, the result is: "ClassName" { ... } |
164 | //! Create instance of that class in the first row of Dump. |
165 | class Standard_DumpSentry |
166 | { |
167 | public: |
168 | //! Constructor - add parameters of start class name definition in the stream |
169 | Standard_EXPORT Standard_DumpSentry (Standard_OStream& theOStream, const char* theClassName); |
170 | |
171 | //! Destructor - add parameters of stop class name definition in the stream |
172 | Standard_EXPORT ~Standard_DumpSentry(); |
173 | |
174 | private: |
175 | Standard_OStream* myOStream; //!< modified stream |
176 | }; |
177 | |
178 | //! This interface has some tool methods for stream (in JSON format) processing. |
179 | class Standard_Dump |
180 | { |
181 | public: |
182 | //! Converts stream value to string value. The result is original stream value. |
183 | //! @param theStream source value |
184 | //! @return text presentation |
185 | Standard_EXPORT static TCollection_AsciiString Text (const Standard_SStream& theStream); |
186 | |
187 | //! Converts stream value to string value. Improves the text presentation with the following cases: |
188 | //! - for '{' append after '\n' and indent to the next value, increment current indent value |
189 | //! - for '}' append '\n' and current indent before it, decrement indent value |
190 | //! - for ',' append after '\n' and indent to the next value. If the current symbol is in massive container [], do nothing |
191 | //! @param theStream source value |
192 | //! @param theIndent count of ' ' symbols to apply hierarchical indent of the text values |
193 | //! @return text presentation |
194 | Standard_EXPORT static TCollection_AsciiString FormatJson (const Standard_SStream& theStream, const Standard_Integer theIndent = 3); |
195 | |
196 | //! Determines whether the end of this stream matches the specified string. |
197 | //! @param theStream source value |
198 | //! @param theEndString text value to find |
199 | //! @return true if matches |
200 | static Standard_EXPORT Standard_Boolean EndsWith (const Standard_OStream& theOStream, |
201 | const TCollection_AsciiString& theEndString); |
202 | |
203 | //! Returns default prefix added for each pointer info string if short presentation of pointer used |
204 | Standard_EXPORT static TCollection_AsciiString GetPointerPrefix() { return "0x"; } |
205 | |
206 | //! Convert handle pointer to address of the pointer. If the handle is NULL, the result is an empty string. |
207 | //! @param thePointer a pointer |
208 | //! @param isShortInfo if true, all '0' symbols in the beginning of the pointer are skipped |
209 | //! @return the string value |
210 | Standard_EXPORT static TCollection_AsciiString GetPointerInfo (const Handle(Standard_Transient)& thePointer, |
211 | const bool isShortInfo = true); |
212 | |
213 | //! Convert pointer to address of the pointer. If the handle is NULL, the result is an empty string. |
214 | //! @param thePointer a pointer |
215 | //! @param isShortInfo if true, all '0' symbols in the beginning of the pointer are skipped |
216 | //! @return the string value |
217 | Standard_EXPORT static TCollection_AsciiString GetPointerInfo (const void* thePointer, |
218 | const bool isShortInfo = true); |
219 | |
220 | //! Append into output value: "Name": { Field } |
221 | //! @param theOStream [out] stream to be fill with values |
222 | //! @param theKey a source value |
223 | //! @param theField stream value |
224 | Standard_EXPORT static void DumpKeyToClass (Standard_OStream& theOStream, |
225 | const char* theKey, |
226 | const TCollection_AsciiString& theField); |
227 | |
228 | //! Unite values in one value using template: "value_1", "value_2", ..., "value_n" |
229 | //! @param theOStream [out] stream to be fill with values |
230 | //! @param theCount numer of values |
231 | Standard_EXPORT static void DumpCharacterValues (Standard_OStream& theOStream, int theCount, ...); |
232 | |
233 | //! Unite values in one value using template: value_1, value_2, ..., value_n |
234 | //! @param theOStream [out] stream to be fill with values |
235 | //! @param theCount numer of values |
236 | Standard_EXPORT static void DumpRealValues (Standard_OStream& theOStream, int theCount, ...); |
237 | |
238 | //! Convert field name into dump text value, removes "&" and "my" prefixes |
239 | //! An example, for field myValue, theName is Value, for &myCLass, the name is Class |
240 | //! @param theField a source value |
241 | //! @param theName [out] an updated name |
242 | Standard_EXPORT static void DumpFieldToName (const char* theField, const char*& theName); |
243 | }; |
244 | |
245 | #endif // _Standard_Dump_HeaderFile |