NCBI C++ ToolKit
json_over_uttp.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: json_over_uttp.cpp 100701 2023-08-31 19:21:12Z lavr $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Dmitry Kazimirov
27  *
28  * File Description: JSON to UTTP serializer/deserializer (implementation).
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
35 
36 #include <corelib/ncbistre.hpp>
37 
38 #include <algorithm>
39 #include <set>
40 
42 
44 {
45 public:
47 
48  CJsonNode ParseObject(const string& ns_output)
49  {
50  m_Ch = (m_NSOutput = ns_output).c_str();
51 
52  return ParseObject('\0');
53  }
54 
55  CJsonNode ParseArray(const string& ns_output)
56  {
57  m_Ch = (m_NSOutput = ns_output).c_str();
58 
59  return ParseArray('\0');
60  }
61 
62  CJsonNode ParseJSON(const string& json);
63 
64 private:
65  size_t GetRemainder() const
66  {
67  return m_NSOutput.length() - (m_Ch - m_NSOutput.data());
68  }
69 
70  size_t GetPosition() const
71  {
72  return m_Ch - m_NSOutput.data() + 1;
73  }
74 
75  string ParseString(size_t max_len);
76  Int8 ParseInt(size_t len);
77  double ParseDouble(size_t len);
78  bool MoreNodes();
79 
80  CJsonNode ParseObject(char closing_char);
81  CJsonNode ParseArray(char closing_char);
83 
84  string m_NSOutput;
85  const char* m_Ch;
87 };
88 
90 {
91  switch (GetErrCode()) {
92  case eInvalidNodeType:
93  return "eInvalidNodeType";
94  case eIndexOutOfRange:
95  return "eIndexOutOfRange";
96  case eKeyNotFound:
97  return "eKeyNotFound";
98  default:
100  }
101 }
102 
104 
106  SJsonObjectElement(const string& key, SJsonNodeImpl* node_impl) :
107  m_Key(key),
108  m_Node(node_impl)
109  {
110  }
111 
112  bool operator <(const SJsonObjectElement& right_hand) const
113  {
114  return m_Key < right_hand.m_Key;
115  }
116 
117  string m_Key;
119  size_t m_Order;
120 };
121 
123  bool operator ()(const SJsonObjectElement* left_hand,
124  const SJsonObjectElement* right_hand) const
125  {
126  return left_hand->m_Order < right_hand->m_Order;
127  }
128 };
129 
131 typedef set<SJsonObjectElement*,
133 typedef vector<TJsonNodeRef> TJsonNodeVector;
134 
135 struct SJsonObjectNodeImpl;
136 struct SJsonArrayNodeImpl;
137 
138 struct SJsonNodeImpl : public CObject
139 {
140  SJsonNodeImpl(CJsonNode::ENodeType node_type) : m_NodeType(node_type) {}
141 
142  static const char* GetTypeName(CJsonNode::ENodeType node_type);
143  const char* GetTypeName() const {return GetTypeName(m_NodeType);}
144 
145  void VerifyType(const char* operation,
146  CJsonNode::ENodeType required_type) const;
147 
148  const SJsonObjectNodeImpl* GetObjectNodeImpl(const char* operation) const;
150 
151  const SJsonArrayNodeImpl* GetArrayNodeImpl(const char* operation) const;
153 
155 };
156 
158 {
159  switch (node_type) {
160  case CJsonNode::eObject:
161  return "an object";
162  case CJsonNode::eArray:
163  return "an array";
164  case CJsonNode::eString:
165  return "a string";
166  case CJsonNode::eInteger:
167  return "an integer";
168  case CJsonNode::eDouble:
169  return "a floating point";
170  case CJsonNode::eBoolean:
171  return "a boolean";
172  default: /* case CJsonNode::eNull: */
173  return "a null";
174  }
175 }
176 
178  CJsonNode::ENodeType required_type) const
179 {
180  if (m_NodeType != required_type) {
181  NCBI_THROW_FMT(CJsonException, eInvalidNodeType,
182  "Cannot call the " << operation <<
183  " method for " << GetTypeName() << " node; " <<
184  GetTypeName(required_type) << " node is required");
185  }
186 }
187 
189 {
191  SJsonNodeImpl(CJsonNode::eObject),
193  {
194  }
195 
199 };
200 
202  const char* operation) const
203 {
205 
206  return static_cast<const SJsonObjectNodeImpl*>(this);
207 }
208 
210  const char* operation)
211 {
213 
214  return static_cast<SJsonObjectNodeImpl*>(this);
215 }
216 
218 {
220 
221  void VerifyIndexBounds(const char* operation, size_t index) const;
222 
224 };
225 
227  const char* operation) const
228 {
230 
231  return static_cast<const SJsonArrayNodeImpl*>(this);
232 }
233 
235  const char* operation)
236 {
238 
239  return static_cast<SJsonArrayNodeImpl*>(this);
240 }
241 
243  const char* operation, size_t index) const
244 {
245  if (m_Array.size() <= index) {
246  NCBI_THROW_FMT(CJsonException, eIndexOutOfRange,
247  operation << ": index " << index <<
248  " is out of range (array size is " <<
249  m_Array.size() << ')');
250  }
251 }
252 
254 {
255  SJsonStringNodeImpl(const string& str) :
257  m_String(str)
258  {
259  }
260 
261  string m_String;
262 };
263 
265 {
267  SJsonNodeImpl(CJsonNode::eInteger),
269  {
270  }
271 
273  SJsonNodeImpl(CJsonNode::eDouble),
274  m_Double(value)
275  {
276  }
277 
279  SJsonNodeImpl(CJsonNode::eBoolean),
281  {
282  }
283 
285  {
286  }
287 
288  union {
290  double m_Double;
291  bool m_Boolean;
292  };
293 };
294 
296 {
297  return new SJsonObjectNodeImpl;
298 }
299 
301 {
302  return new SJsonArrayNodeImpl;
303 }
304 
306  : m_Impl(new SJsonStringNodeImpl(value))
307 {
308 }
309 
311  : m_Impl(new SJsonStringNodeImpl(value))
312 {
313 }
314 
317 {
318 }
319 
322 {
323 }
324 
327 {
328 }
329 
332 {
333 }
334 
336 {
337  return new SJsonFixedSizeNodeImpl();
338 }
339 
341 {
342  const char* ch = value.begin();
343  const char* end = value.end();
344 
345  switch (*ch) {
346  case '"':
347  case '\'':
349 
350  case '-':
351  if (++ch >= end || !isdigit(*ch))
352  return NewStringNode(value);
353 
354  case '0': case '1': case '2': case '3': case '4':
355  case '5': case '6': case '7': case '8': case '9':
356  do
357  if (++ch >= end)
359  while (isdigit(*ch));
360 
361  switch (*ch) {
362  case '.':
363  if (++ch == end || !isdigit(*ch))
364  return NewStringNode(value);
365  for (;;) {
366  if (++ch == end)
368 
369  if (!isdigit(*ch)) {
370  if (*ch == 'E' || *ch == 'e')
371  break;
372 
373  return NewStringNode(value);
374  }
375  }
376  /* FALL THROUGH */
377 
378  case 'E':
379  case 'e':
380  if (++ch < end && (*ch == '-' || *ch == '+' ?
381  ++ch < end && isdigit(*ch) : isdigit(*ch)))
382  do
383  if (++ch == end)
385  while (isdigit(*ch));
386  /* FALL THROUGH */
387 
388  default:
389  return NewStringNode(value);
390  }
391  }
392 
393  return NStr::CompareNocase(value, "false") == 0 ? NewBooleanNode(false) :
394  NStr::CompareNocase(value, "true") == 0 ? NewBooleanNode(true) :
395  NStr::CompareNocase(value, "none") == 0 ? NewNullNode() :
397 }
398 
400 {
401  switch (type)
402  {
403  case CJsonNode::eObject: return new SJsonObjectNodeImpl;
404  case CJsonNode::eArray: return new SJsonArrayNodeImpl;
405  case CJsonNode::eString: return new SJsonStringNodeImpl(string());
406  case CJsonNode::eInteger: return new SJsonFixedSizeNodeImpl(Int8());
407  case CJsonNode::eDouble: return new SJsonFixedSizeNodeImpl(double());
408  case CJsonNode::eBoolean: return new SJsonFixedSizeNodeImpl(bool());
409  case CJsonNode::eNull: return new SJsonFixedSizeNodeImpl();
410  }
411 
412  NCBI_THROW_FMT(CJsonException, eInvalidNodeType, "Unknown type: " << type);
413  return nullptr; // Not reached
414 }
415 
417  m_Impl(s_CreateImpl(type))
418 {
419 }
420 
422 {
423  return m_Impl->m_NodeType;
424 }
425 
427 {
428  return m_Impl->GetTypeName();
429 }
430 
432 {
434  m_Container(container),
435  m_Iterator(container->m_Elements.begin())
436  {
437  }
438 
439  virtual SJsonNodeImpl* GetNode() const;
440  virtual string GetKey() const;
441  virtual bool Next();
442  virtual bool IsValid() const;
443 
446 };
447 
449 {
450  return const_cast<SJsonNodeImpl*>(m_Iterator->m_Node.GetPointerOrNull());
451 }
452 
454 {
455  return m_Iterator->m_Key;
456 }
457 
459 {
460  _ASSERT(IsValid());
461 
462  return ++m_Iterator != m_Container->m_Elements.end();
463 }
464 
466 {
467  return m_Iterator != const_cast<TJsonObjectElements&>(
468  m_Container->m_Elements).end();
469 }
470 
472 {
474  m_Container(container),
475  m_Iterator(container->m_ElementOrder.begin())
476  {
477  }
478 
479  virtual SJsonNodeImpl* GetNode() const;
480  virtual string GetKey() const;
481  virtual bool Next();
482  virtual bool IsValid() const;
483 
486 };
487 
489 {
490  return (*m_Iterator)->m_Node;
491 }
492 
494 {
495  return (*m_Iterator)->m_Key;
496 }
497 
499 {
500  _ASSERT(IsValid());
501 
502  return ++m_Iterator != m_Container->m_ElementOrder.end();
503 }
504 
506 {
507  return m_Iterator != const_cast<TJsonObjectElementOrder&>(
508  m_Container->m_ElementOrder).end();
509 }
510 
512 {
514  m_Container(container),
515  m_Iterator(container->m_Array.begin())
516  {
517  }
518 
519  virtual SJsonNodeImpl* GetNode() const;
520  virtual string GetKey() const;
521  virtual bool Next();
522  virtual bool IsValid() const;
523 
525  TJsonNodeVector::iterator m_Iterator;
526 };
527 
529 {
530  return *m_Iterator;
531 }
532 
534 {
535  NCBI_THROW(CJsonException, eInvalidNodeType,
536  "Cannot get a key for an array iterator");
537 }
538 
540 {
541  _ASSERT(IsValid());
542 
543  return ++m_Iterator != m_Container->m_Array.end();
544 }
545 
547 {
548  return m_Iterator != m_Container->m_Array.end();
549 }
550 
552 {
553  struct SFrame {
555  string m_Path;
556  size_t m_Index;
557 
558  void Advance()
559  {
560  m_Iterator.Next();
561  if (m_Index != (size_t) -1)
562  ++m_Index;
563  }
564 
565  string MakePath() const;
566  };
567 
568  SFlattenIterator(const CJsonNode& container)
569  {
570  m_CurrentFrame.m_Iterator = container.Iterate();
571  m_CurrentFrame.m_Index = container.IsObject() ? (size_t) -1 : 0;
573  }
574 
575  virtual SJsonNodeImpl* GetNode() const;
576  virtual string GetKey() const;
577  virtual bool Next();
578  virtual bool IsValid() const;
579 
581 
583  vector<SFrame> m_IteratorStack;
584 };
585 
587 {
588  if (m_Index == (size_t) -1) {
589  if (m_Path.empty())
590  return m_Iterator.GetKey();
591 
592  string path(m_Path + '.');
593  path += m_Iterator.GetKey();
594  return path;
595  } else {
596  string index_str(NStr::NumericToString(m_Index));
597 
598  if (m_Path.empty())
599  return index_str;
600 
601  string path(m_Path + '.');
602  path += index_str;
603  return path;
604  }
605 }
606 
608 {
610 }
611 
613 {
614  return m_CurrentFrame.MakePath();
615 }
616 
618 {
620 
622 
624 }
625 
627 {
629 }
630 
632 {
633  for (;;) {
634  while (m_CurrentFrame.m_Iterator.IsValid()) {
636 
637  switch (node.GetNodeType()) {
638  case CJsonNode::eObject:
639  m_IteratorStack.push_back(m_CurrentFrame);
640 
642  m_CurrentFrame.m_Index = (size_t) -1;
643  break;
644 
645  case CJsonNode::eArray:
646  m_IteratorStack.push_back(m_CurrentFrame);
647 
650  break;
651 
652  default: /* Scalar type */
653  return true;
654  }
655 
657  }
658 
659  if (m_IteratorStack.empty())
660  return false;
661 
663  m_IteratorStack.pop_back();
664 
666  }
667 }
668 
670 {
671  switch (m_Impl->m_NodeType) {
672  case CJsonNode::eObject:
673  switch (mode) {
674  default: /* case eNatural: */
676  const_cast<SJsonObjectNodeImpl*>(
677  static_cast<const SJsonObjectNodeImpl*>(
678  m_Impl.GetPointerOrNull())));
679 
680  case eOrdered:
681  return new SJsonObjectKeyIterator(const_cast<SJsonObjectNodeImpl*>(
682  static_cast<const SJsonObjectNodeImpl*>(
683  m_Impl.GetPointerOrNull())));
684  case eFlatten:
685  return new SFlattenIterator(*this);
686  }
687 
688  case CJsonNode::eArray:
689  if (mode == eFlatten)
690  return new SFlattenIterator(*this);
691  else
692  return new SJsonArrayIterator(const_cast<SJsonArrayNodeImpl*>(
693  static_cast<const SJsonArrayNodeImpl*>(
694  m_Impl.GetPointerOrNull())));
695 
696  default:
697  NCBI_THROW(CJsonException, eInvalidNodeType,
698  "Cannot iterate a non-container type");
699  }
700 }
701 
702 size_t CJsonNode::GetSize() const
703 {
704  switch (m_Impl->m_NodeType) {
705  case CJsonNode::eObject:
706  return static_cast<const SJsonObjectNodeImpl*>(
707  m_Impl.GetPointerOrNull())->m_Elements.size();
708  case CJsonNode::eArray:
709  return static_cast<const SJsonArrayNodeImpl*>(
710  m_Impl.GetPointerOrNull())->m_Array.size();
711  default:
712  NCBI_THROW(CJsonException, eInvalidNodeType,
713  "GetSize() requires a container type");
714  }
715 }
716 
717 void CJsonNode::AppendString(const string& value)
718 {
719  Append(new SJsonStringNodeImpl(value));
720 }
721 
723 {
724  Append(new SJsonFixedSizeNodeImpl(value));
725 }
726 
728 {
729  Append(new SJsonFixedSizeNodeImpl(value));
730 }
731 
733 {
734  Append(new SJsonFixedSizeNodeImpl(value));
735 }
736 
738 {
739  Append(new SJsonFixedSizeNodeImpl);
740 }
741 
743 {
744  m_Impl->GetArrayNodeImpl("Append()")->
745  m_Array.push_back(TJsonNodeRef(value));
746 }
747 
749 {
750  SJsonArrayNodeImpl* impl(m_Impl->GetArrayNodeImpl("SetAt()"));
751 
752  impl->VerifyIndexBounds("InsertAt()", index);
753 
754  impl->m_Array.insert(impl->m_Array.begin() + index, TJsonNodeRef(value));
755 }
756 
758 {
759  SJsonArrayNodeImpl* impl(m_Impl->GetArrayNodeImpl("SetAt()"));
760 
761  impl->VerifyIndexBounds("SetAt()", index);
762 
763  impl->m_Array[index] = value;
764 }
765 
766 void CJsonNode::DeleteAt(size_t index)
767 {
768  SJsonArrayNodeImpl* impl(m_Impl->GetArrayNodeImpl("DeleteAt()"));
769 
770  impl->VerifyIndexBounds("DeleteAt()", index);
771 
772  impl->m_Array.erase(impl->m_Array.begin() + index);
773 }
774 
775 CJsonNode CJsonNode::GetAt(size_t index) const
776 {
777  const SJsonArrayNodeImpl* impl(m_Impl->GetArrayNodeImpl("GetAt()"));
778 
779  impl->VerifyIndexBounds("GetAt()", index);
780 
781  return const_cast<SJsonNodeImpl*>(impl->m_Array[index].GetPointerOrNull());
782 }
783 
784 void CJsonNode::SetString(const string& key, const string& value)
785 {
786  SetByKey(key, new SJsonStringNodeImpl(value));
787 }
788 
789 void CJsonNode::SetInteger(const string& key, Int8 value)
790 {
791  SetByKey(key, new SJsonFixedSizeNodeImpl(value));
792 }
793 
794 void CJsonNode::SetDouble(const string& key, double value)
795 {
796  SetByKey(key, new SJsonFixedSizeNodeImpl(value));
797 }
798 
799 void CJsonNode::SetBoolean(const string& key, bool value)
800 {
801  SetByKey(key, new SJsonFixedSizeNodeImpl(value));
802 }
803 
804 void CJsonNode::SetNull(const string& key)
805 {
806  SetByKey(key, new SJsonFixedSizeNodeImpl);
807 }
808 
810 {
811  SJsonObjectNodeImpl* impl(m_Impl->GetObjectNodeImpl("SetByKey()"));
812 
813  pair<TJsonObjectElements::iterator, bool> insertion =
814  impl->m_Elements.insert(SJsonObjectElement(key, NULL));
815 
816  SJsonObjectElement* element =
817  &const_cast<SJsonObjectElement&>(*insertion.first);
818 
819  element->m_Node = value;
820 
821  if (insertion.second) {
822  element->m_Order = impl->m_NextElementOrder++;
823  impl->m_ElementOrder.insert(element);
824  }
825 }
826 
827 void CJsonNode::DeleteByKey(const string& key)
828 {
829  SJsonObjectNodeImpl* impl(m_Impl->GetObjectNodeImpl("DeleteByKey()"));
830 
832  impl->m_Elements.find(SJsonObjectElement(key, NULL));
833 
834  if (it != impl->m_Elements.end()) {
835  impl->m_ElementOrder.erase(&const_cast<SJsonObjectElement&>(*it));
836  impl->m_Elements.erase(it);
837  }
838 }
839 
840 bool CJsonNode::HasKey(const string& key) const
841 {
842  const SJsonObjectNodeImpl* impl(m_Impl->GetObjectNodeImpl("HasKey()"));
843 
844  return impl->m_Elements.find(SJsonObjectElement(key, NULL)) !=
845  impl->m_Elements.end();
846 }
847 
849 {
850  const SJsonObjectNodeImpl* impl(m_Impl->GetObjectNodeImpl("GetByKey()"));
851 
853  impl->m_Elements.find(SJsonObjectElement(key, NULL));
854 
855  if (it == impl->m_Elements.end())
856  return CJsonNode();
857 
858  return const_cast<SJsonNodeImpl*>(it->m_Node.GetPointerOrNull());
859 }
860 
861 const string CJsonNode::AsString() const
862 {
863  m_Impl->VerifyType("AsString()", eString);
864 
865  return static_cast<const SJsonStringNodeImpl*>(
866  m_Impl.GetPointerOrNull())->m_String;
867 }
868 
870 {
871  if (m_Impl->m_NodeType == eDouble)
872  return (Int8) static_cast<const SJsonFixedSizeNodeImpl*>(
873  m_Impl.GetPointerOrNull())->m_Double;
874 
875  m_Impl->VerifyType("AsInteger()", eInteger);
876 
877  return static_cast<const SJsonFixedSizeNodeImpl*>(
878  m_Impl.GetPointerOrNull())->m_Integer;
879 }
880 
881 double CJsonNode::AsDouble() const
882 {
883  if (m_Impl->m_NodeType == eInteger)
884  return (double) static_cast<const SJsonFixedSizeNodeImpl*>(
885  m_Impl.GetPointerOrNull())->m_Integer;
886 
887  m_Impl->VerifyType("AsDouble()", eDouble);
888 
889  return static_cast<const SJsonFixedSizeNodeImpl*>(
890  m_Impl.GetPointerOrNull())->m_Double;
891 }
892 
894 {
895  m_Impl->VerifyType("AsBoolean()", eBoolean);
896 
897  return static_cast<const SJsonFixedSizeNodeImpl*>(
898  m_Impl.GetPointerOrNull())->m_Boolean;
899 }
900 
901 static void s_Repr_Value(string& os, const CJsonNode& node,
903 
904 static void s_Repr_Object(string& os, const CJsonNode& node,
906 {
907  CJsonIterator it = node.Iterate();
908  if (it) {
909  os.append(1, '"')
910  .append(it.GetKey())
911  .append("\": ");
912  s_Repr_Value(os, *it, flags);
913  while (++it) {
914  os.append(", \"")
915  .append(it.GetKey())
916  .append("\": ");
917  s_Repr_Value(os, *it, flags);
918  }
919  }
920 }
921 
922 static void s_Repr_Array(string& os, const CJsonNode& node,
924 {
925  CJsonIterator it = node.Iterate();
926  if (it) {
927  s_Repr_Value(os, *it, flags);
928  while (++it) {
929  os.append(", ");
930  s_Repr_Value(os, *it, flags);
931  }
932  }
933 }
934 
935 static void s_Repr_Value(string& os, const CJsonNode& node,
937 {
938  switch (node.GetNodeType()) {
939  case CJsonNode::eObject:
940  os.append(1, '{');
941  s_Repr_Object(os, node, flags);
942  os.append(1, '}');
943  break;
944  case CJsonNode::eArray:
945  os.append(1, '[');
946  s_Repr_Array(os, node, flags);
947  os.append(1, ']');
948  break;
949  case CJsonNode::eString:
951  os.append(NStr::JsonEncode(node.AsString(), NStr::eJsonEnc_Quoted));
952  } else {
953  os.append(1, '"');
954  os.append(NStr::PrintableString(node.AsString()));
955  os.append(1, '"');
956  }
957  break;
958  case CJsonNode::eInteger:
959  os.append(NStr::NumericToString(node.AsInteger()));
960  break;
961  case CJsonNode::eDouble:
962  os.append(NStr::DoubleToString(node.AsDouble()));
963  break;
964  case CJsonNode::eBoolean:
965  os.append(node.AsBoolean() ? "true" : "false");
966  break;
967  default: /* case CJsonNode::eNull: */
968  os.append("null");
969  }
970 }
971 
973 {
974  string os;
975 
976  switch (GetNodeType()) {
977  case CJsonNode::eObject:
978  if (flags & fOmitOutermostBrackets)
979  s_Repr_Object(os, *this, flags);
980  else {
981  os.append(1, '{');
982  s_Repr_Object(os, *this, flags);
983  os.append(1, '}');
984  }
985  break;
986  case CJsonNode::eArray:
987  if (flags & fOmitOutermostBrackets)
988  s_Repr_Array(os, *this, flags);
989  else {
990  os.append(1, '[');
991  s_Repr_Array(os, *this, flags);
992  os.append(1, ']');
993  }
994  break;
995  case CJsonNode::eString:
996  if (flags & fVerbatimIfString)
997  return (static_cast<const SJsonStringNodeImpl*>(
998  m_Impl.GetPointerOrNull())->m_String);
999  /* FALL THROUGH */
1000  default:
1001  s_Repr_Value(os, *this, flags);
1002  }
1003 
1004  return os;
1005 }
1006 
1007 #define INVALID_FORMAT_ERROR() \
1008  NCBI_THROW2(CStringException, eFormat, \
1009  (*m_Ch == '\0' ? "Unexpected end of output" : \
1010  "Syntax error in structured output"), \
1011  GetPosition())
1012 
1014 {
1015  m_Ch = (m_NSOutput = json).c_str();
1016 
1017  while (isspace((unsigned char) *m_Ch))
1018  ++m_Ch;
1019 
1020  CJsonNode root;
1021 
1022  switch (*m_Ch) {
1023  case '[':
1024  ++m_Ch;
1025  root = ParseArray(']');
1026  break;
1027 
1028  case '{':
1029  ++m_Ch;
1030  root = ParseObject('}');
1031  break;
1032 
1033  default:
1035  }
1036 
1037  while (isspace((unsigned char) *m_Ch))
1038  ++m_Ch;
1039 
1040  if (*m_Ch != '\0') {
1042  }
1043 
1044  return root;
1045 }
1046 
1047 string CJsonParser::ParseString(size_t max_len)
1048 {
1049  const bool standard_json = m_Flags & CJsonNode::fStandardJson;
1050  auto str = CTempString(m_Ch, max_len);
1051  size_t len;
1052  auto val = standard_json ? NStr::JsonDecode(std::move(str), &len) : NStr::ParseQuoted(std::move(str), &len);
1053 
1054  m_Ch += len;
1055  return val;
1056 }
1057 
1059 {
1061 
1062  if (*m_Ch == '-') {
1063  ++m_Ch;
1064  --len;
1065  }
1066  if (*m_Ch == '0' && len > 1) {
1067  NCBI_THROW2(CStringException, eFormat,
1068  "Leading zeros are not allowed", GetPosition());
1069  }
1070 
1071  m_Ch += len;
1072  return val;
1073 }
1074 
1076 {
1077  double val = NStr::StringToDouble(CTempString(m_Ch, len));
1078 
1079  m_Ch += len;
1080  return val;
1081 }
1082 
1084 {
1085  while (isspace((unsigned char) *m_Ch))
1086  ++m_Ch;
1087  if (*m_Ch != ',')
1088  return false;
1089  while (isspace((unsigned char) *++m_Ch))
1090  ;
1091  return true;
1092 }
1093 
1095 {
1097 
1098  while (isspace((unsigned char) *m_Ch))
1099  ++m_Ch;
1100 
1101  if (*m_Ch == closing_char) {
1102  ++m_Ch;
1103  return result;
1104  }
1105 
1106  while (*m_Ch == '\'' || *m_Ch == '"') {
1107  // New attribute/value pair
1108  string attr_name(ParseString(GetRemainder()));
1109 
1110  while (isspace((unsigned char) *m_Ch))
1111  ++m_Ch;
1112  if (*m_Ch == ':' || *m_Ch == '=')
1113  while (isspace((unsigned char) *++m_Ch))
1114  ;
1115 
1116  result.SetByKey(attr_name, ParseValue());
1117 
1118  if (!MoreNodes()) {
1119  if (*m_Ch != closing_char)
1120  break;
1121  ++m_Ch;
1122  return result;
1123  }
1124  }
1125 
1127 }
1128 
1130 {
1132 
1133  while (isspace((unsigned char) *m_Ch))
1134  ++m_Ch;
1135 
1136  if (*m_Ch == closing_char) {
1137  ++m_Ch;
1138  return result;
1139  }
1140 
1141  do
1142  result.Append(ParseValue());
1143  while (MoreNodes());
1144 
1145  if (*m_Ch == closing_char) {
1146  ++m_Ch;
1147  return result;
1148  }
1149 
1151 }
1152 
1154 {
1155  size_t max_len = GetRemainder();
1156  size_t len = 0;
1157 
1158  switch (*m_Ch) {
1159  /* Array */
1160  case '[':
1161  ++m_Ch;
1162  return ParseArray(']');
1163 
1164  /* Object */
1165  case '{':
1166  ++m_Ch;
1167  return ParseObject('}');
1168 
1169  /* String */
1170  case '\'':
1171  case '"':
1172  return CJsonNode::NewStringNode(ParseString(max_len));
1173 
1174  /* Number */
1175  case '-':
1176  // Check that there's at least one digit after the minus sign.
1177  if (max_len <= 1 || !isdigit((unsigned char) m_Ch[1])) {
1178  ++m_Ch;
1179  break;
1180  }
1181  len = 1;
1182 
1183  case '0': case '1': case '2': case '3': case '4':
1184  case '5': case '6': case '7': case '8': case '9':
1185  // Skim through the integer part.
1186  do
1187  if (++len >= max_len)
1188  return CJsonNode::NewIntegerNode(ParseInt(len));
1189  while (isdigit((unsigned char) m_Ch[len]));
1190 
1191  // Stumbled upon a non-digit character -- check
1192  // if it's a fraction part or an exponent part.
1193  switch (m_Ch[len]) {
1194  case '.':
1195  if (++len == max_len || !isdigit((unsigned char) m_Ch[len])) {
1196  NCBI_THROW2(CStringException, eFormat,
1197  "At least one digit after the decimal "
1198  "point is required", GetPosition());
1199  }
1200  for (;;) {
1201  if (++len == max_len)
1202  return CJsonNode::NewDoubleNode(ParseDouble(len));
1203 
1204  if (!isdigit((unsigned char) m_Ch[len])) {
1205  if (m_Ch[len] == 'E' || m_Ch[len] == 'e')
1206  break;
1207 
1208  return CJsonNode::NewDoubleNode(ParseDouble(len));
1209  }
1210  }
1211  /* FALL THROUGH */
1212 
1213  case 'E':
1214  case 'e':
1215  if (++len == max_len ||
1216  (m_Ch[len] == '-' || m_Ch[len] == '+' ?
1217  ++len == max_len ||
1218  !isdigit((unsigned char) m_Ch[len]) :
1219  !isdigit((unsigned char) m_Ch[len]))) {
1220  m_Ch += len;
1221  NCBI_THROW2(CStringException, eFormat,
1222  "Invalid exponent specification", GetPosition());
1223  }
1224  while (++len < max_len && isdigit((unsigned char) m_Ch[len]))
1225  ;
1226  return CJsonNode::NewDoubleNode(ParseDouble(len));
1227 
1228  default:
1229  return CJsonNode::NewIntegerNode(ParseInt(len));
1230  }
1231 
1232  /* Constant */
1233  case 'F': case 'f': case 'N': case 'n':
1234  case 'T': case 't': case 'Y': case 'y':
1235  while (len <= max_len && isalpha((unsigned char) m_Ch[len]))
1236  ++len;
1237 
1238  {
1239  CTempString val(m_Ch, len);
1240  m_Ch += len;
1241  return val == "null" ? CJsonNode::NewNullNode() :
1243  }
1244  }
1245 
1247 }
1248 
1250 {
1251  return CJsonParser(flags).ParseObject(json);
1252 }
1253 
1255 {
1256  return CJsonParser(flags).ParseArray(json);
1257 }
1258 
1260 {
1261  return CJsonParser(flags).ParseJSON(json);
1262 }
1263 
1265 {
1266  switch (GetErrCode()) {
1267  case eUTTPFormatError:
1268  return "eUTTPFormatError";
1269  case eChunkContinuationExpected:
1270  return "eChunkContinuationExpected";
1271  case eUnexpectedEOM:
1272  return "eUnexpectedEOM";
1273  case eUnexpectedTrailingToken:
1274  return "eUnexpectedTrailingToken";
1275  case eObjectKeyMustBeString:
1276  return "eObjectKeyMustBeString";
1277  case eUnexpectedClosingBracket:
1278  return "eUnexpectedClosingBracket";
1279  case eUnknownControlSymbol:
1280  return "eUnknownControlSymbol";
1281  default:
1283  }
1284 }
1285 
1287  m_State(eExpectNextToken),
1288  m_HashValueIsExpected(false)
1289 {
1290 }
1291 
1292 #ifdef WORDS_BIGENDIAN
1293 #define DOUBLE_PREFIX 'D'
1294 #else
1295 #define DOUBLE_PREFIX 'd'
1296 #endif
1297 
1298 #define EOM_MARKER '\n'
1299 
1301 {
1302  for (;;)
1303  switch (reader.GetNextEvent()) {
1305  switch (m_State) {
1306  case eExpectNextToken:
1308  m_CurrentChunk.assign(reader.GetChunkPart(),
1309  reader.GetChunkPartSize());
1310  break;
1311  case eReadingString:
1312  m_CurrentChunk.append(reader.GetChunkPart(),
1313  reader.GetChunkPartSize());
1314  break;
1315  case eReadingDouble:
1316  // The underlying transport protocol guarantees
1317  // that m_Double boundaries will not be exceeded.
1318  memcpy(m_DoublePtr, reader.GetChunkPart(),
1319  reader.GetChunkPartSize());
1320  m_DoublePtr += reader.GetChunkPartSize();
1321  break;
1322  default: /* case eMessageComplete: */
1323  goto ThrowUnexpectedTrailingToken;
1324  }
1325  break;
1326 
1327  case CUTTPReader::eChunk:
1328  switch (m_State) {
1329  case eExpectNextToken:
1330  m_CurrentChunk.assign(reader.GetChunkPart(),
1331  reader.GetChunkPartSize());
1332  break;
1333  case eReadingString:
1335  m_CurrentChunk.append(reader.GetChunkPart(),
1336  reader.GetChunkPartSize());
1337  break;
1338  case eReadingDouble:
1340  memcpy(m_DoublePtr, reader.GetChunkPart(),
1341  reader.GetChunkPartSize());
1343  reverse(reinterpret_cast<char*>(&m_Double),
1344  reinterpret_cast<char*>(&m_Double + 1));
1347  continue;
1348  default: /* case eMessageComplete: */
1349  goto ThrowUnexpectedTrailingToken;
1350  }
1351  if (!m_CurrentNode) {
1354  } else if (m_HashValueIsExpected) {
1355  m_HashValueIsExpected = false;
1357  } else
1358  // The current node is either a JSON object or an array,
1359  // because if it was a non-container node, m_State would
1360  // be eMessageComplete.
1361  if (m_CurrentNode.IsArray())
1363  else {
1365  m_HashValueIsExpected = true;
1366  }
1367  break;
1368 
1370  {
1371  char control_symbol = reader.GetControlSymbol();
1372 
1373  if (control_symbol == EOM_MARKER) {
1374  if (m_State != eMessageComplete) {
1375  NCBI_THROW(CJsonOverUTTPException, eUnexpectedEOM,
1376  "JSON-over-UTTP: Unexpected end of message");
1377  }
1378  return true;
1379  }
1380 
1381  if (m_State != eExpectNextToken)
1382  goto ThrowChunkContinuationExpected;
1383 
1384  switch (control_symbol) {
1385  case '[':
1386  case '{':
1387  {
1388  CJsonNode new_node(control_symbol == '[' ?
1391  if (x_AddNewNode(new_node)) {
1392  m_NodeStack.push_back(m_CurrentNode);
1393  m_CurrentNode = new_node;
1394  }
1395  }
1396  break;
1397 
1398  case ']':
1399  case '}':
1400  if (!m_CurrentNode ||
1401  (control_symbol == ']') ^ m_CurrentNode.IsArray()) {
1402  NCBI_THROW(CJsonOverUTTPException, eUnexpectedClosingBracket,
1403  "JSON-over-UTTP: Unexpected closing bracket");
1404  }
1405  if (m_NodeStack.empty())
1407  else {
1408  m_CurrentNode = m_NodeStack.back();
1409  m_NodeStack.pop_back();
1410  }
1411  break;
1412 
1413  case 'D':
1414  case 'd':
1415  switch (reader.ReadRawData(sizeof(double))) {
1416  default: /* case CUTTPReader::eEndOfBuffer: */
1418  m_DoubleEndianness = control_symbol;
1419  m_DoublePtr = reinterpret_cast<char*>(&m_Double);
1420  return false;
1423  m_DoubleEndianness = control_symbol;
1424  memcpy(&m_Double, reader.GetChunkPart(),
1425  reader.GetChunkPartSize());
1426  m_DoublePtr = reinterpret_cast<char*>(&m_Double) +
1427  reader.GetChunkPartSize();
1428  break;
1429  case CUTTPReader::eChunk:
1430  _ASSERT(reader.GetChunkPartSize() == sizeof(double));
1431 
1432  if (control_symbol == DOUBLE_PREFIX)
1433  memcpy(&m_Double, reader.GetChunkPart(),
1434  sizeof(double));
1435  else {
1436  // Copy the entire chunk to
1437  // m_Double in reverse order.
1438  const char* src = reader.GetChunkPart();
1439  char* dst = reinterpret_cast<char*>(&m_Double + 1);
1440  int count = sizeof(double);
1441 
1442  do
1443  *--dst = *src++;
1444  while (--count > 0);
1445  }
1446 
1449  }
1450  break;
1451 
1452  case 'Y':
1455  break;
1456 
1457  case 'N':
1460  break;
1461 
1462  case 'U':
1465  break;
1466 
1467  default:
1469  eUnknownControlSymbol,
1470  "JSON-over-UTTP: Unknown control symbol '" <<
1471  NStr::PrintableString(CTempString(&control_symbol,
1472  1)) << '\'');
1473  }
1474  }
1475  break;
1476 
1477  case CUTTPReader::eNumber:
1478  switch (m_State) {
1479  case eExpectNextToken:
1482  break;
1483  case eMessageComplete:
1484  goto ThrowUnexpectedTrailingToken;
1485  default:
1486  goto ThrowChunkContinuationExpected;
1487  }
1488  break;
1489 
1491  return false;
1492 
1493  default: /* case CUTTPReader::eFormatError: */
1494  NCBI_THROW(CJsonOverUTTPException, eUTTPFormatError,
1495  "JSON-over-UTTP: UTTP format error");
1496  }
1497 
1498 ThrowUnexpectedTrailingToken:
1499  NCBI_THROW(CJsonOverUTTPException, eUnexpectedTrailingToken,
1500  "JSON-over-UTTP: Received a token while expected EOM");
1501 
1502 ThrowChunkContinuationExpected:
1503  NCBI_THROW(CJsonOverUTTPException, eChunkContinuationExpected,
1504  "JSON-over-UTTP: Chunk continuation expected");
1505 }
1506 
1508 {
1510  m_NodeStack.clear();
1511  m_CurrentNode = NULL;
1512  m_HashValueIsExpected = false;
1513 }
1514 
1516 {
1517  if (!m_CurrentNode) {
1518  m_CurrentNode = new_node;
1519  return false;
1520  } else if (m_HashValueIsExpected) {
1521  m_HashValueIsExpected = false;
1522  m_CurrentNode.SetByKey(m_HashKey, new_node);
1523  } else
1524  // The current node is either a JSON object or an array,
1525  // because if it was a non-container node then this method
1526  // wouldn't have been called.
1527  if (m_CurrentNode.IsArray())
1528  m_CurrentNode.Append(new_node);
1529  else {
1530  NCBI_THROW(CJsonOverUTTPException, eObjectKeyMustBeString,
1531  "JSON-over-UTTP: Invalid object key type");
1532  }
1533  return true;
1534 }
1535 
1537 {
1539 
1540  m_SendHashValue = false;
1541 
1542  return x_SendNode(root_node) && CompleteMessage();
1543 }
1544 
1546 {
1547  while (m_CurrentOutputNode.m_Node) {
1549  case CJsonNode::eArray:
1551  x_PopNode();
1552  if (!m_UTTPWriter.SendControlSymbol(']'))
1553  return false;
1554  } else {
1556  if (!x_SendNode(*it)) {
1557  it.Next();
1558  return false;
1559  }
1560  it.Next();
1561  }
1562  break;
1563 
1564  case CJsonNode::eObject:
1565  if (!m_CurrentOutputNode.m_Iterator) { // TODO surround in a loop
1566  x_PopNode();
1567  if (!m_UTTPWriter.SendControlSymbol('}'))
1568  return false;
1569  } else {
1570  if (!m_SendHashValue) {
1572  if (!m_UTTPWriter.SendChunk(
1573  m_Key.data(), m_Key.length(), false)) {
1574  m_SendHashValue = true;
1575  return false;
1576  }
1577  } else
1578  m_SendHashValue = false;
1579 
1581  if (!x_SendNode(*it)) {
1582  it.Next();
1583  return false;
1584  }
1585  it.Next();
1586  }
1587  break;
1588 
1589  default: /* case CJsonNode::eDouble: */
1590  x_PopNode();
1591  if (!m_UTTPWriter.SendRawData(&m_Double, sizeof(m_Double)))
1592  return false;
1593  }
1594  }
1595 
1597  return true;
1598 }
1599 
1601 {
1602  switch (node.GetNodeType()) {
1603  case CJsonNode::eObject:
1604  x_PushNode(node);
1606  m_SendHashValue = false;
1607  return m_UTTPWriter.SendControlSymbol('{');
1608 
1609  case CJsonNode::eArray:
1610  x_PushNode(node);
1612  return m_UTTPWriter.SendControlSymbol('[');
1613 
1614  case CJsonNode::eString:
1615  {
1616  const string& str(static_cast<const SJsonStringNodeImpl*>(
1617  (const SJsonNodeImpl*) node)->m_String);
1618  return m_UTTPWriter.SendChunk(str.data(), str.length(), false);
1619  }
1620 
1621  case CJsonNode::eInteger:
1622  return m_UTTPWriter.SendNumber(node.AsInteger());
1623 
1624  case CJsonNode::eDouble:
1625  m_Double = node.AsDouble();
1627  x_PushNode(node);
1628  return false;
1629  }
1630  return m_UTTPWriter.SendRawData(&m_Double, sizeof(m_Double));
1631 
1632  case CJsonNode::eBoolean:
1633  return m_UTTPWriter.SendControlSymbol(node.AsBoolean() ? 'Y' : 'N');
1634 
1635  default: /* case CJsonNode::eNull: */
1636  return m_UTTPWriter.SendControlSymbol('U');
1637  }
1638 }
1639 
1641 {
1644  m_CurrentOutputNode.m_Node = node;
1645 }
1646 
1648 {
1650 
1651  if (m_OutputStack.empty())
1653  else {
1655  m_OutputStack.pop_back();
1656  }
1657 }
1658 
Exception class for use by CJsonNode.
@ eKeyNotFound
No such key in the object node.
@ eIndexOutOfRange
JSON array index exceeds the maximum index.
@ eInvalidNodeType
Operation is not valid for this node type.
virtual const char * GetErrCodeString() const override
Get error code interpreted as text.
Iterator for JSON arrays and objects.
bool Next()
Skip to the next element if there is one, in which case TRUE is returned.
bool IsValid() const
Return true if this iterator is still valid.
CJsonNode GetNode() const
Return the value of the current element.
string GetKey() const
When iterating over a JSON object, return the key of the current element.
JSON node abstraction.
Int8 AsInteger() const
Provided that this is a numeric node (that is, either an integer or a floating point node),...
void AppendBoolean(bool value)
For an array node, add a boolean node at the end of the array.
size_t GetSize() const
For a container node (that is, either an array or an object), return the number of elements in the co...
void SetAt(size_t index, CJsonNode::TInstance value)
For an array node, set a new value for an existing element.
static CJsonNode NewArrayNode()
Create a new JSON array node.
static CJsonNode GuessType(const CTempString &value)
Guess the type of a JSON scalar from the string representation of its value and initialize a new node...
void SetDouble(const string &key, double value)
Set a JSON object element to the specified floating point value.
bool HasKey(const string &key) const
Check if an object node has an element accessible by the specified key.
int TParseFlags
Binary OR of EParseFlags.
string Repr(TReprFlags flags=0) const
Return a string representation of this node.
bool IsArray() const
Return true for a JSON array. Return false otherwise.
void InsertAt(size_t index, CJsonNode::TInstance value)
For an array node, insert a new element at the specified position.
static CJsonNode ParseJSON(const string &json, TParseFlags flags=0)
int TReprFlags
Binary OR of EReprFlags.
CNetRef< SJsonNodeImpl > m_Impl
void DeleteByKey(const string &key)
Delete an element referred to by the specified key from a JSON object.
SJsonIteratorImpl * Iterate(EIterationMode mode=eNatural) const
For a container node (that is, either an array or an object), begin iteration over its elements.
static CJsonNode ParseObject(const string &json, TParseFlags flags=0)
void SetString(const string &key, const string &value)
Set a JSON object element to the specified string value.
void SetNull(const string &key)
Set a JSON object element to the specified null value.
string GetTypeName() const
Return a string identifying the node type.
void AppendInteger(Int8 value)
For an array node, add a integer node at the end of the array.
void AppendString(const string &value)
For an array node, add a string node at the end of the array.
const string AsString() const
Provided that this is a string node, return the string value of this node.
void SetBoolean(const string &key, bool value)
Set a JSON object element to the specified boolean value.
static CJsonNode NewDoubleNode(double value)
Create a new JSON double node.
static CJsonNode NewBooleanNode(bool value)
Create a new JSON boolean node.
static CJsonNode ParseArray(const string &json, TParseFlags flags=0)
bool AsBoolean() const
Provided that this is a boolean node, return the boolean value of this node.
ENodeType GetNodeType() const
Return a ENodeType constant identifying the node type.
void SetInteger(const string &key, Int8 value)
Set a JSON object element to the specified integer value.
void SetByKey(const string &key, CJsonNode::TInstance value)
For a JSON object node, insert a new element or update an existing element.
static CJsonNode NewIntegerNode(Int8 value)
Create a new JSON integer node.
bool IsObject() const
Return true for a JSON object. Return false otherwise.
void AppendDouble(double value)
For an array node, add a floating point node at the end of the array.
static CJsonNode NewStringNode(const string &value)
Create a new JSON string node.
CJsonNode GetAt(size_t index) const
Return a JSON array element at the specified index.
void DeleteAt(size_t index)
Delete an element located at the specified index from a JSON array.
EIterationMode
Different modes of array and object iteration.
ENodeType
JSON node type.
static CJsonNode NewObjectNode()
Create a new JSON object node.
void AppendNull()
For an array node, add a null node at the end of the array.
void Append(CJsonNode::TInstance value)
For an array node, add a new element at the end of the array.
CJsonNode GetByKeyOrNull(const string &key) const
For a JSON object node, return the value associated with the specified key.
static CJsonNode NewNullNode()
Create a new JSON null node.
double AsDouble() const
Provided that this is a numeric node (that is, either a floating point or an integer node),...
Exception class for use by CJsonNode.
virtual const char * GetErrCodeString() const override
Get error code interpreted as text.
bool x_AddNewNode(CJsonNode::TInstance new_node)
enum CJsonOverUTTPReader::@87 m_State
bool ReadMessage(CUTTPReader &reader)
CUTTPWriter & m_UTTPWriter
bool WriteMessage(const CJsonNode &root_node)
bool x_SendNode(const CJsonNode &node)
TOutputStack m_OutputStack
SOutputStackFrame m_CurrentOutputNode
void x_PushNode(const CJsonNode &node)
CJsonNode ParseJSON(const string &json)
CJsonParser(CJsonNode::TParseFlags flags)
CJsonNode::TParseFlags m_Flags
Int8 ParseInt(size_t len)
size_t GetPosition() const
double ParseDouble(size_t len)
const char * m_Ch
size_t GetRemainder() const
CJsonNode ParseValue()
CJsonNode ParseArray(const string &ns_output)
string ParseString(size_t max_len)
CJsonNode ParseObject(const string &ns_output)
CObject –.
Definition: ncbiobj.hpp:180
CRef –.
Definition: ncbiobj.hpp:618
CStringException –.
Definition: ncbistr.hpp:4506
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
Class for reading series of chunks sent by a CUTTPWriter instance as a stream of bytes.
Definition: uttp.hpp:94
EStreamParsingEvent GetNextEvent()
Parse the input buffer until a parsing event occurs.
Definition: uttp.cpp:44
EStreamParsingEvent ReadRawData(size_t data_size)
Tell the reader to switch to reading raw data of the specified length.
Definition: uttp.cpp:134
char GetControlSymbol() const
Return the control symbol that has been just read.
Definition: uttp.hpp:249
@ eChunk
Notify that the last part of the chunk has been read.
Definition: uttp.hpp:107
@ eEndOfBuffer
Notify that the end of the input buffer has been reached.
Definition: uttp.hpp:120
@ eChunkPart
Notify that a part of a chunk has been read and can be fetched by a call to the GetChunkPart() method...
Definition: uttp.hpp:101
@ eControlSymbol
Notify that a control symbol has been read.
Definition: uttp.hpp:112
@ eNumber
Notify that a number has been read.
Definition: uttp.hpp:116
Int8 GetNumber() const
Return the number that has been just read.
Definition: uttp.hpp:254
const char * GetChunkPart() const
Return a pointer to the buffer that contains a part of the chunk currently being read.
Definition: uttp.hpp:259
size_t GetChunkPartSize() const
Return the size of the buffer returned by the GetChunkPart() method.
Definition: uttp.hpp:264
bool SendControlSymbol(char symbol)
Send a control symbol over the output buffer.
Definition: uttp.cpp:180
bool SendNumber(Int8 number)
Send an integer over the output buffer.
Definition: uttp.cpp:235
bool SendRawData(const void *data, size_t data_size)
Mix a chunk of raw data right in the output stream.
Definition: uttp.cpp:269
bool SendChunk(const char *chunk, size_t chunk_length, bool to_be_continued)
Send a chunk of data to the output buffer.
Definition: uttp.cpp:192
parent_type::iterator iterator
Definition: set.hpp:80
parent_type::const_iterator const_iterator
Definition: set.hpp:79
static uch flags
#define false
Definition: bool.h:36
static const char * str(char *buf, int n)
Definition: stats.c:84
#define NULL
Definition: ncbistd.hpp:225
TErrCode GetErrCode(void) const
Get error code.
Definition: ncbiexpt.cpp:453
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define NCBI_THROW2(exception_class, err_code, message, extra)
Throw exception with extra parameter.
Definition: ncbiexpt.hpp:1754
#define NCBI_THROW_FMT(exception_class, err_code, message)
The same as NCBI_THROW but with message processed as output to ostream.
Definition: ncbiexpt.hpp:719
virtual const char * GetErrCodeString(void) const
Get error code interpreted as text.
Definition: ncbiexpt.cpp:444
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static bool StringToBool(const CTempString str)
Convert string to bool.
Definition: ncbistr.cpp:2821
static string PrintableString(const CTempString str, TPrintableMode mode=fNewLine_Quote|fNonAscii_Passthru)
Get a printable version of the specified string.
Definition: ncbistr.cpp:3953
static string DoubleToString(double value, int precision=-1, TNumToStringFlags flags=0)
Convert double to string.
Definition: ncbistr.hpp:5187
static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
Definition: ncbistr.cpp:219
static Int8 StringToInt8(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to Int8.
Definition: ncbistr.cpp:793
static double StringToDouble(const CTempStringEx str, TStringToNumFlags flags=0)
Convert string to double.
Definition: ncbistr.cpp:1387
static string JsonDecode(const CTempString str, size_t *n_read=NULL)
Decode a string encoded by JsonEncode.
Definition: ncbistr.cpp:4995
static string JsonEncode(const CTempString str, EJsonEncode encoding=eJsonEnc_UTF8)
Encode a string for JSON.
Definition: ncbistr.cpp:4634
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
static string ParseQuoted(const CTempString str, size_t *n_read=NULL)
Discard C-style backslash escapes and extract a quoted string.
Definition: ncbistr.cpp:4927
@ eJsonEnc_Quoted
Quote resulting string.
Definition: ncbistr.hpp:3094
operation
Bit operations.
Definition: bmconst.h:191
set< SJsonObjectElement > TJsonObjectElements
#define EOM_MARKER
CNetRef< SJsonNodeImpl > TJsonNodeRef
CJsonNode::TInstance s_CreateImpl(CJsonNode::ENodeType type)
#define INVALID_FORMAT_ERROR()
static void s_Repr_Value(string &os, const CJsonNode &node, CJsonNode::TReprFlags flags)
static void s_Repr_Object(string &os, const CJsonNode &node, CJsonNode::TReprFlags flags)
set< SJsonObjectElement *, SObjectElementLessOrder > TJsonObjectElementOrder
#define DOUBLE_PREFIX
static void s_Repr_Array(string &os, const CJsonNode &node, CJsonNode::TReprFlags flags)
vector< TJsonNodeRef > TJsonNodeVector
int len
mdb_mode_t mode
Definition: lmdb++.h:38
const struct ncbi::grid::netcache::search::fields::KEY key
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
int isalpha(Uchar c)
Definition: ncbictype.hpp:61
int isspace(Uchar c)
Definition: ncbictype.hpp:69
int isdigit(Uchar c)
Definition: ncbictype.hpp:64
NCBI C++ stream class wrappers for triggering between "new" and "old" C++ stream libraries.
bool x_DepthFirstSearchForScalar()
virtual bool Next()
virtual SJsonNodeImpl * GetNode() const
vector< SFrame > m_IteratorStack
virtual bool IsValid() const
SFlattenIterator(const CJsonNode &container)
virtual string GetKey() const
virtual string GetKey() const
virtual bool Next()
SJsonArrayIterator(SJsonArrayNodeImpl *container)
CNetRef< SJsonArrayNodeImpl > m_Container
virtual SJsonNodeImpl * GetNode() const
virtual bool IsValid() const
TJsonNodeVector::iterator m_Iterator
void VerifyIndexBounds(const char *operation, size_t index) const
TJsonNodeVector m_Array
SJsonFixedSizeNodeImpl(double value)
SJsonFixedSizeNodeImpl(Int8 value)
SJsonFixedSizeNodeImpl(bool value)
This interface should not be used directly.
const SJsonArrayNodeImpl * GetArrayNodeImpl(const char *operation) const
CJsonNode::ENodeType m_NodeType
void VerifyType(const char *operation, CJsonNode::ENodeType required_type) const
const char * GetTypeName() const
SJsonNodeImpl(CJsonNode::ENodeType node_type)
const SJsonObjectNodeImpl * GetObjectNodeImpl(const char *operation) const
virtual string GetKey() const
virtual SJsonNodeImpl * GetNode() const
TJsonObjectElementOrder::iterator m_Iterator
CNetRef< SJsonObjectNodeImpl > m_Container
SJsonObjectElementOrderIterator(SJsonObjectNodeImpl *container)
bool operator<(const SJsonObjectElement &right_hand) const
SJsonObjectElement(const string &key, SJsonNodeImpl *node_impl)
SJsonObjectKeyIterator(SJsonObjectNodeImpl *container)
virtual bool IsValid() const
CNetRef< SJsonObjectNodeImpl > m_Container
virtual string GetKey() const
virtual SJsonNodeImpl * GetNode() const
TJsonObjectElements::iterator m_Iterator
TJsonObjectElementOrder m_ElementOrder
TJsonObjectElements m_Elements
SJsonStringNodeImpl(const string &str)
bool operator()(const SJsonObjectElement *left_hand, const SJsonObjectElement *right_hand) const
Definition: type.c:6
#define _ASSERT
else result
Definition: token2.c:20
Modified on Wed Apr 17 13:08:58 2024 by modify_doxy.py rev. 669887