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

Go to the SVN repository for this file.

1 #ifndef JSON_OVER_UTTP__HPP
2 #define JSON_OVER_UTTP__HPP
3 
4 /* $Id: json_over_uttp.hpp 92446 2021-01-22 18:14:49Z sadyrovr $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Dmitry Kazimirov
30  *
31  * File Description: JSON to UTTP serializer/deserializer (declarations).
32  *
33  */
34 
35 /// @file json_over_uttp.hpp
36 ///
37 /// @internal
38 /// @attention
39 /// This API is designed to be used for internal
40 /// communication (mostly in GRID). It is not recommended for general use,
41 /// and its support is narrowly limited.
42 /// If you need a generic JSON serialization API please use
43 /// "JsonWrapp" (https://ncbi.github.io/cxx-toolkit/pages/ch_jsonwrapp) or
44 /// "SERIAL" (https://ncbi.github.io/cxx-toolkit/pages/ch_ser).
45 
46 #include "netcomponent.hpp"
47 
48 #include <util/uttp.hpp>
49 #include <util/util_exception.hpp>
50 
52 
53 /// Exception class for use by CJsonNode.
55 {
56 public:
57  enum EErrCode {
58  eInvalidNodeType, ///< Operation is not valid for this node type
59  eIndexOutOfRange, ///< JSON array index exceeds the maximum index
60  eKeyNotFound, ///< No such key in the object node
61  };
62 
63  virtual const char* GetErrCodeString() const override;
64 
66 };
67 
68 ///< @internal
69 struct SJsonNodeImpl;
70 
71 /// This interface should not be used directly.
72 /// @internal
73 /// @see CJsonIterator
75 {
76  virtual SJsonNodeImpl* GetNode() const = 0;
77  virtual string GetKey() const = 0;
78  virtual bool Next() = 0;
79  virtual bool IsValid() const = 0;
80 };
81 
82 /// JSON node abstraction.
83 
84 /// @internal
85 /// @attention
86 /// The CJsonNode and related API is designed to be used for internal
87 /// communication (mostly in GRID). It is not recommended for general use,
88 /// and its support is narrowly limited.
89 /// If you need a generic JSON serialization API please use
90 /// "JsonWrapp" (https://ncbi.github.io/cxx-toolkit/pages/ch_jsonwrapp).
92 {
93  NCBI_NET_COMPONENT(JsonNode);
94 
95  /// Create a new JSON object node.
96  static CJsonNode NewObjectNode();
97 
98  /// Create a new JSON array node.
99  static CJsonNode NewArrayNode();
100 
101  /// Create a new JSON string node.
102  static CJsonNode NewStringNode(const string& value) { return value; }
103 
104  /// Create a new JSON integer node.
106 
107  /// Create a new JSON double node.
108  static CJsonNode NewDoubleNode(double value) { return value; }
109 
110  /// Create a new JSON boolean node.
111  static CJsonNode NewBooleanNode(bool value) { return value; }
112 
113  /// Create a new JSON null node.
114  static CJsonNode NewNullNode();
115 
116  /// Guess the type of a JSON scalar from the string
117  /// representation of its value and initialize a new
118  /// node with this value.
119  static CJsonNode GuessType(const CTempString& value);
120 
121  /// Create new JSON string node.
122  CJsonNode(const string& value);
123  CJsonNode(const char* value);
124 
125  /// Create new JSON integer node.
126  CJsonNode(int value);
128 
129  /// Create new JSON double node.
130  CJsonNode(double value);
131 
132  /// Create new JSON boolean node.
133  CJsonNode(bool value);
134 
135  /// JSON node type.
136  enum ENodeType {
143  eNull
144  };
145 
146  /// Create new JSON node (type depends on the argument)
147  CJsonNode(ENodeType type);
148 
149  /// Return a ENodeType constant identifying the node type.
150  ENodeType GetNodeType() const;
151 
152  /// Return a string identifying the node type.
153  string GetTypeName() const;
154 
155  /// Return true for a JSON object. Return false otherwise.
156  bool IsObject() const;
157 
158  /// Return true for a JSON array. Return false otherwise.
159  bool IsArray() const;
160 
161  /// Return true for a string node. Return false otherwise.
162  bool IsString() const;
163 
164  /// Return true for an integer node. Return false otherwise.
165  bool IsInteger() const;
166 
167  /// Return true for a double node. Return false otherwise.
168  bool IsDouble() const;
169 
170  /// Return true for a boolean node. Return false otherwise.
171  bool IsBoolean() const;
172 
173  /// Return true for a null node. Return false otherwise.
174  bool IsNull() const;
175 
176  /// Return true if the node is either an object or an array.
177  bool IsContainer() const;
178 
179  /// Return true if the node is any of the JSON scalar types.
180  bool IsScalar() const;
181 
182  /// Different modes of array and object iteration.
184  eNatural, ///< Iterate array elements in ascending order
185  ///< of their indices; iterate object elements
186  ///< in the order they were added.
187  eOrdered, ///< Iterate object elements in lexicographic
188  ///< order of their keys.
189  eFlatten, ///< Iterate nested containers as if it were a
190  ///< single JSON object.
191  };
192 
193  /// For a container node (that is, either an array or an object),
194  /// begin iteration over its elements. The returned value must
195  /// be used to initialize a CJsonIterator object.
196  /// @see CJsonIterator
197  SJsonIteratorImpl* Iterate(EIterationMode mode = eNatural) const;
198 
199  /// For a container node (that is, either an array or
200  /// an object), return the number of elements in the container.
201  size_t GetSize() const;
202 
203  /// For an array node, add a string node at the end of the array.
204  void AppendString(const string& value);
205 
206  /// For an array node, add a integer node at the end of the array.
207  void AppendInteger(Int8 value);
208 
209  /// For an array node, add a floating point node at the end of the array.
210  void AppendDouble(double value);
211 
212  /// For an array node, add a boolean node at the end of the array.
213  void AppendBoolean(bool value);
214 
215  /// For an array node, add a null node at the end of the array.
216  void AppendNull();
217 
218  /// For an array node, add a new element at the end of the array.
219  void Append(CJsonNode::TInstance value);
220 
221  /// For an array node, insert a new element at the specified position.
222  void InsertAt(size_t index, CJsonNode::TInstance value);
223 
224  /// For an array node, set a new value for an existing element.
225  /// Throw an exception if the index is out of range.
226  void SetAt(size_t index, CJsonNode::TInstance value);
227 
228  /// Delete an element located at the specified index from a JSON array.
229  /// Throw an exception if the index is out of range.
230  void DeleteAt(size_t index);
231 
232  /// Return a JSON array element at the specified index.
233  /// Throw an exception if the index is out of range.
234  CJsonNode GetAt(size_t index) const;
235 
236  /// Set a JSON object element to the specified string value.
237  void SetString(const string& key, const string& value);
238 
239  /// Set a JSON object element to the specified integer value.
240  void SetInteger(const string& key, Int8 value);
241 
242  /// Set a JSON object element to the specified floating point value.
243  void SetDouble(const string& key, double value);
244 
245  /// Set a JSON object element to the specified boolean value.
246  void SetBoolean(const string& key, bool value);
247 
248  /// Set a JSON object element to the specified null value.
249  void SetNull(const string& key);
250 
251  /// For a JSON object node, insert a new element or update
252  /// an existing element.
253  void SetByKey(const string& key, CJsonNode::TInstance value);
254 
255  /// Delete an element referred to by the specified key from a JSON object.
256  void DeleteByKey(const string& key);
257 
258  /// Check if an object node has an element accessible by
259  /// the specified key.
260  bool HasKey(const string& key) const;
261 
262  /// For a JSON object node, return the value associated with
263  /// the specified key. Throw an exception if there is no
264  /// such key in this object.
265  CJsonNode GetByKey(const string& key) const;
266 
267  /// For a JSON object node, return the value associated with
268  /// the specified key. Return NULL if there is no such key
269  /// in this object.
270  CJsonNode GetByKeyOrNull(const string& key) const;
271 
272  /// For a JSON object node, return the string referred to
273  /// by the specified key. Throw an exception if the key
274  /// does not exist or refers to a non-string node.
275  string GetString(const string& key) const;
276 
277  /// For a JSON object node, return the integer referred to
278  /// by the specified key. Throw an exception if the key
279  /// does not exist or refers to a non-numeric node.
280  Int8 GetInteger(const string& key) const;
281 
282  /// For a JSON object node, return the floating point number
283  /// referred to by the specified key. Throw an exception
284  /// if the key does not exist or refers to a non-numeric node.
285  double GetDouble(const string& key) const;
286 
287  /// For a JSON object node, return the boolean referred to
288  /// by the specified key. Throw an exception if the key
289  /// does not exist or refers to a non-boolean node.
290  bool GetBoolean(const string& key) const;
291 
292  /// Provided that this is a string node, return
293  /// the string value of this node.
294  const string AsString() const;
295 
296  /// Provided that this is a numeric node (that is, either
297  /// an integer or a floating point node), return the value
298  /// of this node as an integer number.
299  Int8 AsInteger() const;
300 
301  /// Provided that this is a numeric node (that is, either
302  /// a floating point or an integer node), return the value
303  /// of this node as a floating point number.
304  double AsDouble() const;
305 
306  /// Provided that this is a boolean node, return
307  /// the boolean value of this node.
308  bool AsBoolean() const;
309 
310  /// String representation flags.
311  enum EReprFlags {
312  fVerbatimIfString = 1 << 0,
313  fOmitOutermostBrackets = 1 << 1,
314  fStandardJson = 1 << 2
315  };
316  /// Binary OR of EReprFlags.
317  typedef int TReprFlags;
318 
319  /// Return a string representation of this node.
320  string Repr(TReprFlags flags = 0) const;
321 
322  /// Parse methods flags.
323  enum class EParseFlags {
324  fStandardJson = EReprFlags::fStandardJson,
325  };
326  /// Binary OR of EParseFlags.
327  typedef int TParseFlags;
328 
329  static CJsonNode ParseObject(const string& json, TParseFlags flags = 0);
330  static CJsonNode ParseArray(const string& json, TParseFlags flags = 0);
331  static CJsonNode ParseJSON(const string& json, TParseFlags flags = 0);
332 };
333 
334 /// Iterator for JSON arrays and objects.
335 /// @see CJsonNode::Iterate()
337 {
338  NCBI_NET_COMPONENT(JsonIterator);
339 
340  /// Return the value of the current element.
341  CJsonNode GetNode() const;
342 
343  /// When iterating over a JSON object, return
344  /// the key of the current element.
345  string GetKey() const;
346 
347  /// Skip to the next element if there is one, in which
348  /// case TRUE is returned. Otherwise, return FALSE.
349  bool Next();
350 
351  /// Return true if this iterator is still valid.
352  bool IsValid() const;
353 
354  /// An alternative way to get the value of the current element.
355  CJsonNode operator *() const;
356 
357  /// An operator version of Next().
358  CJsonIterator& operator ++();
359 
360  /// An operator version of IsValid().
361  operator bool() const;
362 
363  /// An operator version of IsValid().
364  operator bool();
365 };
366 
367 inline bool CJsonNode::IsObject() const
368 {
369  return GetNodeType() == eObject;
370 }
371 
372 inline bool CJsonNode::IsArray() const
373 {
374  return GetNodeType() == eArray;
375 }
376 
377 inline bool CJsonNode::IsString() const
378 {
379  return GetNodeType() == eString;
380 }
381 
382 inline bool CJsonNode::IsInteger() const
383 {
384  return GetNodeType() == eInteger;
385 }
386 
387 inline bool CJsonNode::IsDouble() const
388 {
389  return GetNodeType() == eDouble;
390 }
391 
392 inline bool CJsonNode::IsBoolean() const
393 {
394  return GetNodeType() == eBoolean;
395 }
396 
397 inline bool CJsonNode::IsNull() const
398 {
399  return GetNodeType() == eNull;
400 }
401 
402 inline bool CJsonNode::IsContainer() const
403 {
404  return GetNodeType() <= eArray;
405 }
406 
407 inline bool CJsonNode::IsScalar() const
408 {
409  return GetNodeType() > eArray;
410 }
411 
412 inline CJsonNode CJsonNode::GetByKey(const string& key) const
413 {
415 
416  if (node)
417  return node;
418 
419  NCBI_THROW_FMT(CJsonException, eKeyNotFound,
420  "GetByKey(): no such key \"" << key << '\"');
421 }
422 
423 inline string CJsonNode::GetString(const string& key) const
424 {
425  return GetByKey(key).AsString();
426 }
427 
428 inline Int8 CJsonNode::GetInteger(const string& key) const
429 {
430  return GetByKey(key).AsInteger();
431 }
432 
433 inline double CJsonNode::GetDouble(const string& key) const
434 {
435  return GetByKey(key).AsDouble();
436 }
437 
438 inline bool CJsonNode::GetBoolean(const string& key) const
439 {
440  return GetByKey(key).AsBoolean();
441 }
442 
444 {
445  return m_Impl->GetNode();
446 }
447 
448 inline string CJsonIterator::GetKey() const
449 {
450  return m_Impl->GetKey();
451 }
452 
453 inline bool CJsonIterator::Next()
454 {
455  return m_Impl->Next();
456 }
457 
458 inline bool CJsonIterator::IsValid() const
459 {
460  return m_Impl->IsValid();
461 }
462 
464 {
465  return GetNode();
466 }
467 
469 {
470  m_Impl->Next();
471  return *this;
472 }
473 
474 inline CJsonIterator::operator bool() const
475 {
476  return m_Impl->IsValid();
477 }
478 
479 inline CJsonIterator::operator bool()
480 {
481  return m_Impl->IsValid();
482 }
483 
484 /// Exception class for use by CJsonNode.
486 {
487 public:
488  enum EErrCode {
496  };
497 
498  virtual const char* GetErrCodeString() const override;
499 
501 };
502 
504 {
505 public:
506  typedef list<CJsonNode> TNodeStack;
507 
509  bool ReadMessage(CUTTPReader& reader);
510  const CJsonNode GetMessage() const;
511  void Reset();
512 
513 private:
514  bool x_AddNewNode(CJsonNode::TInstance new_node);
515 
516  enum {
520  eMessageComplete
521  } m_State;
525  double m_Double;
526  char* m_DoublePtr;
528  string m_HashKey;
530 };
531 
533 {
534  return m_CurrentNode;
535 }
536 
538 {
539 public:
540  CJsonOverUTTPWriter(CUTTPWriter& writer) : m_UTTPWriter(writer)
541  {
542  }
543 
544  bool WriteMessage(const CJsonNode& root_node);
545  bool CompleteMessage();
546  void GetOutputBuffer(const char** output_buffer,
547  size_t* output_buffer_size);
548  bool NextOutputBuffer();
549 
550 private:
554  };
555 
556  typedef list<SOutputStackFrame> TOutputStack;
557 
558  bool x_SendNode(const CJsonNode& node);
559  void x_PushNode(const CJsonNode& node);
560  void x_PopNode();
561 
563 
566  double m_Double;
568 
569  // The member is used only to extend the lifetime of the object key in the
570  // CompleteMessage() method. A copy of the key is taken and is written to a
571  // buffer however the buffer may be too small for the control charaters
572  // together with the key value so the rest of the key is written later. On
573  // GCC 4.9.3 a local std::string copy worked fine but with GCC 7.3.0 there
574  // was a crash. So to extend the key lifetime if it did not fit the buffer
575  // this variable is introduced.
576  string m_Key;
577 };
578 
580  const char** output_buffer, size_t* output_buffer_size)
581 {
582  m_UTTPWriter.GetOutputBuffer(output_buffer, output_buffer_size);
583 }
584 
586 {
588 }
589 
591 
592 #endif /* JSON_OVER_UTTP__HPP */
Exception class for use by CJsonNode.
NCBI_EXCEPTION_DEFAULT(CJsonException, CException)
@ 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.
Iterator for JSON arrays and objects.
CJsonNode operator*() const
An alternative way to get the value of the current element.
bool Next()
Skip to the next element if there is one, in which case TRUE is returned.
CNetRef< SJsonIteratorImpl > m_Impl
CJsonIterator & operator++()
An operator version of Next().
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),...
bool IsNull() const
Return true for a null node. Return false otherwise.
int TParseFlags
Binary OR of EParseFlags.
double GetDouble(const string &key) const
For a JSON object node, return the floating point number referred to by the specified key.
bool IsArray() const
Return true for a JSON array. Return false otherwise.
int TReprFlags
Binary OR of EReprFlags.
Int8 GetInteger(const string &key) const
For a JSON object node, return the integer referred to by the specified key.
bool IsBoolean() const
Return true for a boolean node. Return false otherwise.
EParseFlags
Parse methods flags.
const string AsString() const
Provided that this is a string node, return the string value of this node.
string GetString(const string &key) const
For a JSON object node, return the string referred to by the specified key.
static CJsonNode NewDoubleNode(double value)
Create a new JSON double node.
static CJsonNode NewBooleanNode(bool value)
Create a new JSON boolean node.
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.
bool IsDouble() const
Return true for a double node. Return false otherwise.
bool GetBoolean(const string &key) const
For a JSON object node, return the boolean referred to by the specified key.
static CJsonNode NewIntegerNode(Int8 value)
Create a new JSON integer node.
bool IsInteger() const
Return true for an integer node. Return false otherwise.
bool IsObject() const
Return true for a JSON object. Return false otherwise.
static CJsonNode NewStringNode(const string &value)
Create a new JSON string node.
EIterationMode
Different modes of array and object iteration.
ENodeType
JSON node type.
bool IsContainer() const
Return true if the node is either an object or an array.
bool IsScalar() const
Return true if the node is any of the JSON scalar types.
EReprFlags
String representation flags.
CJsonNode GetByKey(const string &key) const
For a JSON object node, return the value associated with the specified key.
CJsonNode GetByKeyOrNull(const string &key) const
For a JSON object node, return the value associated with the specified key.
bool IsString() const
Return true for a string node. Return false otherwise.
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.
NCBI_EXCEPTION_DEFAULT(CJsonOverUTTPException, CException)
list< CJsonNode > TNodeStack
const CJsonNode GetMessage() const
CUTTPWriter & m_UTTPWriter
list< SOutputStackFrame > TOutputStack
CJsonOverUTTPWriter(CUTTPWriter &writer)
TOutputStack m_OutputStack
void GetOutputBuffer(const char **output_buffer, size_t *output_buffer_size)
SOutputStackFrame m_CurrentOutputNode
CObject –.
Definition: ncbiobj.hpp:180
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
Class that serializes series of chunks of data for sending over binary streams.
Definition: uttp.hpp:297
void GetOutputBuffer(const char **output_buffer, size_t *output_buffer_size)
Return data to be sent over the output stream and extend internal pointers to the next buffer.
Definition: uttp.hpp:430
bool NextOutputBuffer()
Proceed to the next output buffer.
Definition: uttp.cpp:291
static uch flags
#define bool
Definition: bool.h:34
#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
CVect2< NCBI_PROMOTE(int,U) > operator*(int v1, const CVect2< U > &v2)
Definition: globals.hpp:371
bool IsValid(const CSeq_point &pt, CScope *scope)
Checks that point >= 0 and point < length of Bioseq.
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
#define NCBI_XCONNECT_EXPORT
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
#define NCBI_NET_COMPONENT(component)
This interface should not be used directly.
virtual bool Next()=0
virtual bool IsValid() const =0
virtual SJsonNodeImpl * GetNode() const =0
virtual string GetKey() const =0
Definition: type.c:6
static bool SetInteger(wxSpinCtrl *spinctrl, int value)
static bool GetInteger(wxSpinCtrl *spinctrl, int *value)
This file contains declaration of the CDiscreteDistribution class.
Modified on Fri Sep 20 14:57:09 2024 by modify_doxy.py rev. 669887