0030949: Foundation Classes - Dump improvement for OCCT classes
[occt.git] / src / Standard / Standard_Dump.cxx
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 #include <Standard_Dump.hxx>
15
16 #include <stdarg.h>
17
18 // =======================================================================
19 // function : Constructor
20 // purpose :
21 // =======================================================================
22 Standard_DumpSentry::Standard_DumpSentry (Standard_OStream& theOStream, const char* theClassName)
23 : myOStream (&theOStream)
24 {
25   (*myOStream) << "\"" << theClassName << "\": {";
26 }
27
28 // =======================================================================
29 // function : Destructor
30 // purpose :
31 // =======================================================================
32 Standard_DumpSentry::~Standard_DumpSentry()
33 {
34   (*myOStream) << "}";
35 }
36
37 // =======================================================================
38 // function : EndsWith
39 // purpose :
40 // =======================================================================
41 Standard_Boolean Standard_Dump::EndsWith (const Standard_OStream& theOStream,
42                                           const TCollection_AsciiString& theEndString)
43 {
44   Standard_SStream aStream;
45   aStream << theOStream.rdbuf();
46   TCollection_AsciiString aStreamStr = Standard_Dump::Text (aStream);
47   return aStreamStr.EndsWith (theEndString);
48 }
49
50 //=======================================================================
51 //function : DumpKeyToClass
52 //purpose  : 
53 //=======================================================================
54 void Standard_Dump::DumpKeyToClass (Standard_OStream& theOStream,
55                                     const char* theKey,
56                                     const TCollection_AsciiString& theField)
57 {
58   if (!Standard_Dump::EndsWith (theOStream, "{"))
59     theOStream << ", ";
60   theOStream << "\"" << theKey << "\": {" << theField << "}";
61 }
62
63 //=======================================================================
64 //function : DumpCharacterValues
65 //purpose  : 
66 //=======================================================================
67 void Standard_Dump::DumpCharacterValues (Standard_OStream& theOStream, int theCount, ...)
68 {
69   va_list  vl;
70   va_start(vl, theCount);
71   for(int i = 0; i < theCount; ++i)
72   {
73     if (i > 0)
74       theOStream << ", ";
75     theOStream << "\"" << va_arg(vl, char*) << "\"";
76   }
77   va_end(vl);
78 }
79
80 //=======================================================================
81 //function : DumpRealValues
82 //purpose  : 
83 //=======================================================================
84 void Standard_Dump::DumpRealValues (Standard_OStream& theOStream, int theCount, ...)
85 {
86   va_list  vl;
87   va_start(vl, theCount);
88   for(int i = 0; i < theCount; ++i)
89   {
90     if (i > 0)
91       theOStream << ", ";
92     theOStream << va_arg(vl, Standard_Real);
93   }
94   va_end(vl);
95 }
96
97 // =======================================================================
98 // function : GetPointerInfo
99 // purpose :
100 // =======================================================================
101 TCollection_AsciiString Standard_Dump::GetPointerInfo (const Handle(Standard_Transient)& thePointer,
102                                                        const bool isShortInfo)
103 {
104   if (thePointer.IsNull())
105     return TCollection_AsciiString();
106
107   return GetPointerInfo (thePointer.get(), isShortInfo);
108 }
109
110 // =======================================================================
111 // function : GetPointerInfo
112 // purpose :
113 // =======================================================================
114 TCollection_AsciiString Standard_Dump::GetPointerInfo (const void* thePointer, const bool isShortInfo)
115 {
116   std::ostringstream aPtrStr;
117   aPtrStr << thePointer;
118   if (!isShortInfo)
119     return aPtrStr.str().c_str();
120
121   TCollection_AsciiString anInfoPtr (aPtrStr.str().c_str());
122   for (int aSymbolId = 1; aSymbolId < anInfoPtr.Length(); aSymbolId++)
123   {
124     if (anInfoPtr.Value(aSymbolId) != '0')
125     {
126       anInfoPtr = anInfoPtr.SubString (aSymbolId, anInfoPtr.Length());
127       anInfoPtr.Prepend (GetPointerPrefix());
128       return anInfoPtr;
129     }
130   }
131   return aPtrStr.str().c_str();
132 }
133
134 // =======================================================================
135 // DumpFieldToName
136 // =======================================================================
137 void Standard_Dump::DumpFieldToName (const char* theField, const char*& theName)
138 {
139   theName = theField;
140
141   if (theName[0] == '&')
142   {
143     theName = theName + 1;
144   }
145   if (::LowerCase (theName[0]) == 'm' && theName[1] == 'y')
146   {
147     theName = theName + 2;
148   }
149 }
150
151 // =======================================================================
152 // Text
153 // =======================================================================
154 TCollection_AsciiString Standard_Dump::Text (const Standard_SStream& theStream)
155 {
156   return TCollection_AsciiString (theStream.str().c_str());
157 }
158
159 // =======================================================================
160 // FormatJson
161 // =======================================================================
162 TCollection_AsciiString Standard_Dump::FormatJson (const Standard_SStream& theStream,
163                                                    const Standard_Integer theIndent)
164 {
165   TCollection_AsciiString aStreamStr = Text (theStream);
166   TCollection_AsciiString anIndentStr;
167   for (Standard_Integer anIndentId = 0; anIndentId < theIndent; anIndentId++)
168     anIndentStr.AssignCat (' ');
169
170   TCollection_AsciiString aText;
171
172   Standard_Integer anIndentCount = 0;
173   Standard_Boolean isMassiveValues = Standard_False;
174   for (Standard_Integer anIndex = 1; anIndex < aStreamStr.Length(); anIndex++)
175   {
176     Standard_Character aSymbol = aStreamStr.Value (anIndex);
177     if (aSymbol == '{')
178     {
179       anIndentCount++;
180
181       aText += aSymbol;
182       aText += '\n';
183
184       for (int anIndent = 0; anIndent < anIndentCount; anIndent++)
185         aText += anIndentStr;
186     }
187     else if (aSymbol == '}')
188     {
189       anIndentCount--;
190
191       aText += '\n';
192       for (int anIndent = 0; anIndent < anIndentCount; anIndent++)
193         aText += anIndentStr;
194       aText += aSymbol;
195     }
196     else if (aSymbol == '[')
197     {
198       isMassiveValues = Standard_True;
199       aText += aSymbol;
200     }
201     else if (aSymbol == ']')
202     {
203       isMassiveValues = Standard_False;
204       aText += aSymbol;
205     }
206     else if (aSymbol == ',')
207     {
208       if (!isMassiveValues)
209       {
210         aText += aSymbol;
211         aText += '\n';
212         for (int anIndent = 0; anIndent < anIndentCount; anIndent++)
213           aText += anIndentStr;
214         if (anIndex + 1 < aStreamStr.Length() && aStreamStr.Value (anIndex + 1) == ' ')
215           anIndex++; // skip empty value after comma
216       }
217       else
218         aText += aSymbol;
219     }
220     else
221       aText += aSymbol;
222   }
223   return aText;
224 }