1 // Copyright (c) 2019 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <Standard_Dump.hxx>
18 // =======================================================================
19 // function : AddValuesSeparator
21 // =======================================================================
22 void Standard_Dump::AddValuesSeparator (Standard_OStream& theOStream)
24 Standard_SStream aStream;
25 aStream << theOStream.rdbuf();
26 TCollection_AsciiString aStreamStr = Standard_Dump::Text (aStream);
27 if (!aStreamStr.IsEmpty() && !aStreamStr.EndsWith ("{"))
31 //=======================================================================
32 //function : DumpKeyToClass
34 //=======================================================================
35 void Standard_Dump::DumpKeyToClass (Standard_OStream& theOStream,
36 const TCollection_AsciiString& theKey,
37 const TCollection_AsciiString& theField)
39 AddValuesSeparator (theOStream);
40 theOStream << "\"" << theKey << "\": {" << theField << "}";
43 //=======================================================================
44 //function : DumpCharacterValues
46 //=======================================================================
47 void Standard_Dump::DumpCharacterValues (Standard_OStream& theOStream, int theCount, ...)
50 va_start(vl, theCount);
51 for(int i = 0; i < theCount; ++i)
55 theOStream << "\"" << va_arg(vl, char*) << "\"";
60 //=======================================================================
61 //function : DumpRealValues
63 //=======================================================================
64 void Standard_Dump::DumpRealValues (Standard_OStream& theOStream, int theCount, ...)
67 va_start(vl, theCount);
68 for(int i = 0; i < theCount; ++i)
72 theOStream << va_arg(vl, Standard_Real);
77 // =======================================================================
78 // function : GetPointerInfo
80 // =======================================================================
81 TCollection_AsciiString Standard_Dump::GetPointerInfo (const Handle(Standard_Transient)& thePointer,
82 const bool isShortInfo)
84 if (thePointer.IsNull())
85 return TCollection_AsciiString();
87 return GetPointerInfo (thePointer.get(), isShortInfo);
90 // =======================================================================
91 // function : GetPointerInfo
93 // =======================================================================
94 TCollection_AsciiString Standard_Dump::GetPointerInfo (const void* thePointer, const bool isShortInfo)
97 return TCollection_AsciiString();
99 std::ostringstream aPtrStr;
100 aPtrStr << thePointer;
102 return aPtrStr.str().c_str();
104 TCollection_AsciiString anInfoPtr (aPtrStr.str().c_str());
105 for (int aSymbolId = 1; aSymbolId < anInfoPtr.Length(); aSymbolId++)
107 if (anInfoPtr.Value(aSymbolId) != '0')
109 anInfoPtr = anInfoPtr.SubString (aSymbolId, anInfoPtr.Length());
110 anInfoPtr.Prepend (GetPointerPrefix());
114 return aPtrStr.str().c_str();
117 // =======================================================================
119 // =======================================================================
120 TCollection_AsciiString Standard_Dump::DumpFieldToName (const TCollection_AsciiString& theField)
122 TCollection_AsciiString aName = theField;
123 if (theField.StartsWith ('&'))
128 if (aName.Length() > 1 && aName.Value (1) == 'a')
130 if (aName.Length() > 2 && aName.Value (2) == 'n')
137 else if (aName.Length() > 2 && ::LowerCase (aName.Value (1)) == 'm' && aName.Value (2) == 'y')
142 if (aName.EndsWith (".get()"))
144 aName = aName.SubString (1, aName.Length() - TCollection_AsciiString (".get()").Length());
146 else if (aName.EndsWith ("()"))
148 aName = aName.SubString (1, aName.Length() - TCollection_AsciiString ("()").Length());
153 // =======================================================================
155 // =======================================================================
156 TCollection_AsciiString Standard_Dump::Text (const Standard_SStream& theStream)
158 return TCollection_AsciiString (theStream.str().c_str());
161 // =======================================================================
163 // =======================================================================
164 TCollection_AsciiString Standard_Dump::FormatJson (const Standard_SStream& theStream,
165 const Standard_Integer theIndent)
167 TCollection_AsciiString aStreamStr = Text (theStream);
168 TCollection_AsciiString anIndentStr;
169 for (Standard_Integer anIndentId = 0; anIndentId < theIndent; anIndentId++)
170 anIndentStr.AssignCat (' ');
172 TCollection_AsciiString aText;
174 Standard_Integer anIndentCount = 0;
175 Standard_Boolean isMassiveValues = Standard_False;
176 for (Standard_Integer anIndex = 1; anIndex < aStreamStr.Length(); anIndex++)
178 Standard_Character aSymbol = aStreamStr.Value (anIndex);
186 for (int anIndent = 0; anIndent < anIndentCount; anIndent++)
187 aText += anIndentStr;
189 else if (aSymbol == '}')
194 for (int anIndent = 0; anIndent < anIndentCount; anIndent++)
195 aText += anIndentStr;
198 else if (aSymbol == '[')
200 isMassiveValues = Standard_True;
203 else if (aSymbol == ']')
205 isMassiveValues = Standard_False;
208 else if (aSymbol == ',')
210 if (!isMassiveValues)
214 for (int anIndent = 0; anIndent < anIndentCount; anIndent++)
215 aText += anIndentStr;
216 if (anIndex + 1 < aStreamStr.Length() && aStreamStr.Value (anIndex + 1) == ' ')
217 anIndex++; // skip empty value after comma
228 // =======================================================================
230 // =======================================================================
231 Standard_Boolean Standard_Dump::SplitJson (const TCollection_AsciiString& theStreamStr,
232 NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>& theKeyToValues)
234 Standard_Integer aNextIndex = 1;
235 while (aNextIndex < theStreamStr.Length())
237 Standard_JsonKey aKey = Standard_JsonKey_None;
238 if (!jsonKey (theStreamStr, aNextIndex, aNextIndex, aKey))
239 return Standard_False;
241 Standard_Boolean aProcessed = Standard_False;
244 case Standard_JsonKey_Quote:
246 aProcessed = splitKeyToValue (theStreamStr, aNextIndex, aNextIndex, theKeyToValues);
249 case Standard_JsonKey_OpenChild:
251 Standard_Integer aStartIndex = aNextIndex;
252 Standard_Integer aClosePos = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_OpenChild, Standard_JsonKey_CloseChild);
254 return Standard_False;
256 TCollection_AsciiString aSubStreamStr = theStreamStr.SubString (aStartIndex + JsonKeyLength (aKey), aNextIndex - 2);
257 if (!SplitJson (aSubStreamStr, theKeyToValues))
258 return Standard_False;
260 aNextIndex = aClosePos + Standard_Integer (JsonKeyLength (Standard_JsonKey_CloseChild));
263 case Standard_JsonKey_SeparatorValueToValue:
271 return Standard_False;
273 return Standard_True;
276 // =======================================================================
277 // HierarchicalValueIndices
278 // =======================================================================
279 NCollection_List<Standard_Integer> Standard_Dump::HierarchicalValueIndices (
280 const NCollection_IndexedDataMap<TCollection_AsciiString, TCollection_AsciiString>& theValues)
282 NCollection_List<Standard_Integer> anIndices;
284 for (Standard_Integer anIndex = 1; anIndex <= theValues.Extent(); anIndex++)
286 if (HasChildKey (theValues.FindFromIndex (anIndex)))
287 anIndices.Append (anIndex);
292 // =======================================================================
294 // =======================================================================
295 Standard_Boolean Standard_Dump::splitKeyToValue (const TCollection_AsciiString& theStreamStr,
296 Standard_Integer theStartIndex,
297 Standard_Integer& theNextIndex,
298 NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>& theValues)
300 // find key value: "key"
301 Standard_Integer aStartIndex = theStartIndex;
302 Standard_Integer aCloseIndex = nextClosePosition (theStreamStr, aStartIndex + 1, Standard_JsonKey_None, Standard_JsonKey_Quote);
303 if (aCloseIndex == 0)
304 return Standard_False;
306 TCollection_AsciiString aSplitKey = theStreamStr.SubString (aStartIndex, aCloseIndex - 1);
309 aStartIndex = aCloseIndex + 1;
310 Standard_JsonKey aKey = Standard_JsonKey_None;
311 if (!jsonKey (theStreamStr, aStartIndex, aCloseIndex, aKey))
312 return Standard_False;
315 aStartIndex = aCloseIndex;
316 aKey = Standard_JsonKey_None;
317 jsonKey (theStreamStr, aStartIndex, aCloseIndex, aKey);
318 aStartIndex = aCloseIndex;
320 TCollection_AsciiString aSplitValue;
324 case Standard_JsonKey_OpenChild:
326 aCloseIndex = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_OpenChild, Standard_JsonKey_CloseChild);
327 if (aCloseIndex > aStartIndex)
328 aSplitValue = theStreamStr.SubString (aStartIndex, aCloseIndex);
329 theNextIndex = aCloseIndex + 1;
332 case Standard_JsonKey_OpenContainer:
334 aCloseIndex = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_OpenContainer, Standard_JsonKey_CloseContainer);
335 if (aCloseIndex > aStartIndex)
336 aSplitValue = theStreamStr.SubString (aStartIndex, aCloseIndex - 1);
337 theNextIndex = aCloseIndex + 1;
340 case Standard_JsonKey_Quote:
342 Standard_JsonKey aKeyTmp = Standard_JsonKey_None;
343 if (jsonKey (theStreamStr, aStartIndex, aCloseIndex, aKeyTmp) && aKeyTmp == Standard_JsonKey_Quote) // emptyValue
346 theNextIndex = aCloseIndex;
350 aCloseIndex = nextClosePosition (theStreamStr, aStartIndex + 1, Standard_JsonKey_None, Standard_JsonKey_Quote);
351 aSplitValue = theStreamStr.SubString (aStartIndex, aCloseIndex - 1);
352 theNextIndex = aCloseIndex + 1;
356 case Standard_JsonKey_None:
358 if (aStartIndex == theStreamStr.Length())
360 aSplitValue = aStartIndex <= aCloseIndex ? theStreamStr.SubString (aStartIndex, aCloseIndex) : "";
361 aSplitValue = theStreamStr.SubString (aStartIndex, aCloseIndex);
362 aCloseIndex = aStartIndex;
366 Standard_Integer aCloseIndex1 = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_None, Standard_JsonKey_CloseChild) - 1;
367 Standard_Integer aCloseIndex2 = nextClosePosition (theStreamStr, aStartIndex, Standard_JsonKey_None, Standard_JsonKey_SeparatorValueToValue) - 1;
368 aCloseIndex = aCloseIndex1 < aCloseIndex2 ? aCloseIndex1 : aCloseIndex2;
369 aSplitValue = aStartIndex <= aCloseIndex ? theStreamStr.SubString (aStartIndex, aCloseIndex) : "";
371 theNextIndex = aCloseIndex + 1;
375 return Standard_False;
378 Standard_DumpValue aValue;
379 if (theValues.FindFromKey (aSplitKey, aValue))
381 Standard_Integer anIndex = 1;
382 // increment key until the new key does not exist in the container
383 TCollection_AsciiString anIndexedSuffix = TCollection_AsciiString ("_") + TCollection_AsciiString (anIndex);
384 while (theValues.FindFromKey (TCollection_AsciiString (aSplitKey + anIndexedSuffix), aValue))
387 anIndexedSuffix = TCollection_AsciiString ("_") + TCollection_AsciiString (anIndex);
389 aSplitKey = aSplitKey + anIndexedSuffix;
392 theValues.Add (aSplitKey, Standard_DumpValue (aSplitValue, aStartIndex));
393 return Standard_True;
396 // =======================================================================
398 // =======================================================================
399 Standard_Boolean Standard_Dump::jsonKey (const TCollection_AsciiString& theStreamStr,
400 Standard_Integer theStartIndex,
401 Standard_Integer& theNextIndex,
402 Standard_JsonKey& theKey)
404 TCollection_AsciiString aSubStreamStr = theStreamStr.SubString (theStartIndex, theStreamStr.Length());
405 for (Standard_Integer aKeyId = (Standard_Integer)Standard_JsonKey_OpenChild; aKeyId <= Standard_JsonKey_SeparatorValueToValue; aKeyId++)
407 Standard_JsonKey aKey = (Standard_JsonKey)aKeyId;
408 Standard_CString aKeyToStr = JsonKeyToString (aKey);
409 if (!aSubStreamStr.StartsWith (aKeyToStr))
412 theNextIndex = theStartIndex + Standard_Integer (JsonKeyLength (aKey));
414 return Standard_True;
416 return Standard_False;
419 // =======================================================================
421 // =======================================================================
422 Standard_Boolean Standard_Dump::HasChildKey (const TCollection_AsciiString& theSourceValue)
424 return theSourceValue.Search (JsonKeyToString (Standard_JsonKey_SeparatorKeyToValue)) >= 0;
427 // =======================================================================
429 // =======================================================================
430 Standard_CString Standard_Dump::JsonKeyToString (const Standard_JsonKey theKey)
434 case Standard_JsonKey_None: return "";
435 case Standard_JsonKey_OpenChild: return "{";
436 case Standard_JsonKey_CloseChild: return "}";
437 case Standard_JsonKey_OpenContainer: return "[";
438 case Standard_JsonKey_CloseContainer: return "]";
439 case Standard_JsonKey_Quote: return "\"";
440 case Standard_JsonKey_SeparatorKeyToValue: return ": ";
441 case Standard_JsonKey_SeparatorValueToValue: return ", ";
447 // =======================================================================
449 // =======================================================================
450 Standard_Integer Standard_Dump::JsonKeyLength (const Standard_JsonKey theKey)
452 return (Standard_Integer)strlen (JsonKeyToString (theKey));
455 // =======================================================================
457 // =======================================================================
458 Standard_Integer Standard_Dump::nextClosePosition (const TCollection_AsciiString& theSourceValue,
459 const Standard_Integer theStartPosition,
460 const Standard_JsonKey theOpenKey,
461 const Standard_JsonKey theCloseKey)
463 Standard_CString anOpenKey = JsonKeyToString (theOpenKey);
464 Standard_CString aCloseKeyStr = JsonKeyToString (theCloseKey);
466 Standard_Integer aStartPos = theStartPosition;
467 Standard_Integer aDepthKey = 0;
469 while (aStartPos < theSourceValue.Length())
471 Standard_Integer anOpenKeyPos = theSourceValue.Location (anOpenKey, aStartPos, theSourceValue.Length());
472 Standard_Integer aCloseKeyPos = theSourceValue.Location (aCloseKeyStr, aStartPos, theSourceValue.Length());
473 if (aCloseKeyPos == 0)
476 if (anOpenKeyPos != 0 && anOpenKeyPos <= aCloseKeyPos)
479 aStartPos = anOpenKeyPos + 1;
488 aStartPos = aCloseKeyPos + 1;
492 return theSourceValue.Length();