NDEVR
API Documentation
JSONParser.h
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: JSONParser
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include "DLLInfo.h"
34#include <NDEVR/Scanner.h>
35#include <NDEVR/String.h>
36#include <NDEVR/Buffer.h>
37#include <NDEVR/Dictionary.h>
38#include <NDEVR/Vertex.h>
39#include <NDEVR/StringView.h>
40#include <NDEVR/Time.h>
41namespace NDEVR
42{
43 class TranslatedString;
44
48 template<class t_type>
50 {
51 public:
57 static t_type Convert(const String& value)
58 {
59 return value.getAs<t_type>();
60 }
61 };
62
65 template<class t_type>
67 {
68 public:
74 static Angle<t_type> Convert(const String& value)
75 {
76 return Angle<t_type>(DEGREES, value.getAs<fltp08>());
77 }
78 };
79
82 template<>
84 {
85 public:
91 static StringView Convert(const String& value)
92 {
93 return StringView(value);
94 }
95 };
96
99 template<>
101 {
102 public:
111 static Time Convert(const String& value)
112 {
113 //There are 3 different types of times we support. As JSON does not specify a
114 //time format each of these could be valid. We will do some tests to guess which to use
115 if (value.contains('.'))//Option 1) JavaScript built-in JSON object
116 return Time(value, false, "YYYY/MM/DDTHH:mm:ss.fffZ");
117 else if (value.contains('T'))//Option 2) JavaScript built-in JSON object with no millisecond
118 return Time(value, false, "YYYY/MM/DDTHH:mm:ss");
119 uint04 sub_value = value.indexOf("Date(");//Option 3) date sub value expressed as seconds)
120 if (IsValid(sub_value))
121 {
122 return Time(value.substr(sub_value + 5).getAs<uint08>() * Time::SECOND);
123 }
124 Time time_val = value.getAs<Time>();
125 lib_assert(IsValid(time_val), "Could not parse time value");
126 return time_val;//Return an invalid time as we were unable to parse
127 }
128 };
129
148 class NDEVR_BASE_API JSONNode
149 {
150 static const uint04 s_number_of_decimals = 10;
151 public:
164 public:
165
174
182 protected:
183 JSONNode(const StringView& name);
191 public:
192 JSONNode(const JSONNode& node);
193
201 JSONNode(JSONNode&& node) noexcept;
202
218 JSONNode(const String& node, const StringView& json_string);
227
232
241 NodeType type() const;
242
253 void write(String& stream) const;
258 void writeValue(String& stream) const;
259
270 void write(File& file);
271
276 void write(std::ostream& file);
277
290 void writePretty(String& stream, const uint04 tab_indention = 0) const;
301 void writePretty(File& file);
306 void writePretty(std::ostream& file);
314 template<class t_type>
315 decltype(auto) getAs() const
316 {
318 }
319
330 const JSONNode& get(const StringView& child_node) const
331 {
332 return *m_json_children[child_node];
333 }
334
344 const JSONNode& operator[](const StringView& child_node) const
345 {
346 return *m_json_children[child_node];
347 }
348
353 JSONNode& operator[](const StringView& child_node)
354 {
355 auto iter = m_json_children.find(child_node);
356 if (iter == m_json_children.end())
357 {
358 JSONNode* node = new JSONNode(child_node);
359 m_sorted_json_children.add(node);
360 iter = m_json_children.insert(iter, { node->nodeName(), node });
361 }
362 return *iter.value();
363 }
364
374 JSONNode& operator[](const uint04& child_idx)
375 {
376 return *m_sorted_json_children[child_idx];
377 }
378
383 const JSONNode& operator[](const uint04& child_idx) const
384 {
385 return *m_sorted_json_children[child_idx];
386 }
387
393 {
395 }
396
401 bool hasNode(const StringView& child_node) const
402 {
403 return m_json_children.hasKey(child_node);
404 }
405
410 const String& nodeName() const
411 {
412 return m_name;
413 }
414
417 template<class t_type>
418 void setOrClearIfDefault(const StringView& child_node, const t_type& value, const t_type& default_value)
419 {
420 if (AreSame(value, default_value))
421 remove(child_node);
422 else
423 (*this)[child_node] = value;
424 }
425
428 template<class t_type>
429 t_type get(const StringView& child_node, const t_type& default_value) const
430 {
431 auto iter = m_json_children.find(child_node);
432 if (iter != m_json_children.end())
433 return iter.value()->getAs<t_type>();
434 else
435 return default_value;
436 }
437
443 template<class t_type>
444 bool getIfExists(const StringView& child_node, t_type& value) const
445 {
446 auto iter = m_json_children.find(child_node);
447 if (iter == m_json_children.end())
448 return false;
449 value = iter.value()->getAs<t_type>();
450 return true;
451 }
452
456 void remove(const StringView& child_node);
466
478 {
479 m_value = node.m_value;
480 if (node.m_type == e_root)
481 m_type = e_node;//convert root to node
482 else
483 m_type = node.m_type;
484 for (const JSONNode* iter : m_sorted_json_children)
485 delete iter;
487 m_json_children.clear();
488 for (const auto& iter : node.m_sorted_json_children)
489 {
490 JSONNode* new_node = new JSONNode(*iter);
491 m_sorted_json_children.add(new_node);
492 auto json_child = m_json_children.find(new_node->nodeName());
493 if (json_child == m_json_children.end())
494 m_json_children.insert(json_child, { new_node->nodeName(), new_node });
495 }
496 return *this;
497 }
498
499
506 {
508 m_value = value;
509 return *this;
510 }
511
516 template<class t_type>
518 {
520 m_value.setFrom(value.template as<DEGREES>());
521 return *this;
522 }
523
531 JSONNode& operator=(const Time& time)
532 {
534 m_value = time.getAsString(false, "YYYY/MM/DDTHH:mm:ss.fffZ");;
535 return *this;
536 }
537
543 template<class t_type, class t_allocator>
545 {
546 m_type = e_array;
547 m_value.clear();
548 m_value.append(buffer[0]);
549 for (uint01 i = 1; i < buffer.size(); i++)
550 {
551 m_value.append(',');
552 m_value.append(buffer[i]);
553 }
554 m_value.setFrom(buffer);
555 return *this;
556 }
557
562 template<class String>
564 {
565 m_type = e_array;
566 m_value.clear();
567 m_value.append("\"");
568 m_value.append(buffer[0]);
569 for (uint01 i = 1; i < buffer.size(); i++)
570 {
571 m_value.append("\",\"");
572 m_value.append(buffer[i]);
573 }
574 m_value.append("\"");
575 return *this;
576 }
577
582 template<class String>
584 {
585 m_type = e_array;
586 m_value.clear();
587 m_value.append("\"");
588 m_value.append(buffer[0]);
589 for (uint01 i = 1; i < buffer.size(); i++)
590 {
591 m_value.append("\",\"");
592 m_value.append(buffer[i]);
593 }
594 m_value.append("\"");
595 return *this;
596 }
597
602 template<uint01 t_dims, class t_type>
604 {
605 setVector(buffer);
606 return *this;
607 }
608
613 template<uint01 t_dims, class t_type>
615 {
616 setVector(buffer);
617 return *this;
618 }
619
624 template<uint01 t_dims, class t_type>
625 JSONNode& operator=(const Ray<t_dims, t_type>& buffer)
626 {
627 setVector(buffer);
628 return *this;
629 }
630
637 [[nodiscard]] bool isEmpty() const
638 {
639 return m_value.size() == 0 && m_json_children.size() == 0;
640 }
641
649 template<class t_type>
650 JSONNode& operator=(const t_type& value)
651 {
655 m_type = e_bool;
657 m_type = e_array;
658 else if (ObjectInfo<t_type>::Color)//An RGBColor is converted into an array of integers {red, green, blue, alpha}
659 m_type = e_array;
660 else
662 m_value.setFrom(value);
663 return *this;
664 }
665
674 {
675 return cast<uint04>(m_json_children.size());
676 }
677
681 [[nodiscard]] decltype(auto) begin()
682 {
683 return m_json_children.begin();
684 }
685
689 [[nodiscard]] decltype(auto) begin() const
690 {
691 return m_json_children.begin();
692 }
693
698 [[nodiscard]] decltype(auto) end()
699 {
700 return m_json_children.end();
701 }
702
706 [[nodiscard]] decltype(auto) end() const
707 {
708 return m_json_children.end();
709 }
710
716
717 protected:
732 bool parseJSON(Scanner& scan);
739 bool parseJSONContent(char start, Scanner& scan);
740
755 bool parseYAMLContent(uint04 indentention, Scanner& scan);
761
774
786 void readData(Scanner& scan);
787
799 void readArray(Scanner& scan);
800
812 static void WriteTabs(String& stream, uint04 tab_indention);
817 static void ConvertToJSONString(String& string);
822 static void ConvertFromJSONString(String& string);
823 protected:
828 template<uint01 t_dims, class t_type>
830 {
831 m_type = e_array;
832 m_value.clear();
833 m_value.append(buffer[0]);
834 for (uint01 i = 1; i < t_dims; i++)
835 {
836 m_value.append(',');
837 m_value.append(buffer[i]);
838 }
839 }
840
846 static TranslatedString UnexpectedCharErrorString(char current_char, const Scanner& scan);
860 protected:
866 private:
867
868 };
869
870}
871
872
Stores an angle in an optimized internal format with support for efficient trigonometric operations.
Definition Angle.h:83
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
A hash-based key-value store, useful for quick associative lookups.
Definition Dictionary.h:64
Logic for reading or writing to a file as well as navigating filesystems or other common file operati...
Definition File.h:53
String m_value
The stored value of this node as a string.
Definition JSONParser.h:864
JSONNode & operator=(const StringView &value)
Assigns a string value to this node, setting the type to e_object.
Definition JSONParser.h:505
void setVector(const Vector< t_dims, t_type > &buffer)
Sets the node value from a Vector, storing it as a comma-separated array string.
Definition JSONParser.h:829
JSONNode(File &file)
JSONNode & createChildNode(NodeType type=NodeType::e_node)
Creates an unnamed child node with the specified type.
Definition JSONParser.h:462
decltype(auto) begin()
Returns a mutable iterator to the beginning of the children dictionary.
Definition JSONParser.h:681
JSONNode(const StringView &name)
decltype(auto) getAs() const
Definition JSONParser.h:315
const Buffer< JSONNode * > & children() const
Returns the ordered list of child node pointers.
Definition JSONParser.h:392
void readChildrenNodes(Scanner &scan)
static TranslatedString BadChildErrorString(const Scanner &scan)
Generates a translated error message for a malformed child node.
bool hasNode(const StringView &child_node) const
Checks whether a child node with the given name exists.
Definition JSONParser.h:401
NodeType m_type
The type classification of this node.
Definition JSONParser.h:865
JSONNode & operator=(const Buffer< StringView > &buffer)
Assigns a Buffer of StringViews to this node as a quoted comma-separated array.
Definition JSONParser.h:583
void write(String &stream) const
const JSONNode & get(const StringView &child_node) const
Definition JSONParser.h:330
decltype(auto) end() const
Returns a const iterator to the end of the children dictionary.
Definition JSONParser.h:706
JSONNode & operator=(const Buffer< t_type, t_allocator > &buffer)
Assigns a typed Buffer to this node as a comma-separated array.
Definition JSONParser.h:544
bool parseJSON(Scanner &scan)
t_type get(const StringView &child_node, const t_type &default_value) const
Gets the value if it exists, otherwise returns the default value.
Definition JSONParser.h:429
JSONNode(const JSONNode &node)
JSONNode(JSONNode &&node) noexcept
bool parseJSONContent(char start, Scanner &scan)
Parses JSON content starting from the given character.
JSONNode & operator=(const JSONNode &node)
A special case of the = operator for nodes.
Definition JSONParser.h:477
JSONNode & operator=(const Vertex< t_dims, t_type > &buffer)
Assigns a Vertex value to this node as a comma-separated array.
Definition JSONParser.h:614
const String m_name
The name of this node.
Definition JSONParser.h:863
void writePretty(File &file)
Writes our structure out to a file using tabs and new lines.
void readData(Scanner &scan)
Buffer< JSONNode * > m_sorted_json_children
Ordered list of child node pointers preserving insertion order.
Definition JSONParser.h:861
void parseYAMLContent(StringView value)
Parses a YAML value from a string view and sets this node accordingly.
JSONNode & operator=(const Vector< t_dims, t_type > &buffer)
Assigns a Vector value to this node as a comma-separated array.
Definition JSONParser.h:603
static TranslatedString DuplicateChildErrorString(const StringView &child, const Scanner &scan)
Generates a translated error message for a duplicate child node name.
bool parseYAMLContent(uint04 indentention, Scanner &scan)
JSONNode & createChildNode(const StringView &child_node, NodeType type)
Creates a named child node with the specified type.
void readArray(Scanner &scan)
JSONNode & operator=(const t_type &value)
Definition JSONParser.h:650
static JSONNode ParseYAML(Scanner &scan)
Parses a YAML document from the given scanner and returns it as a JSONNode tree.
const JSONNode & operator[](const uint04 &child_idx) const
Returns a const reference to the child node at the given index.
Definition JSONParser.h:383
bool isEmpty() const
Definition JSONParser.h:637
uint04 size()
Definition JSONParser.h:673
static void ConvertToJSONString(String &string)
Escapes special characters in the string for JSON output.
void setOrClearIfDefault(const StringView &child_node, const t_type &value, const t_type &default_value)
Sets the value of the child node if value differs from the default value, otherwise clears the child.
Definition JSONParser.h:418
JSONNode & operator=(const Buffer< String > &buffer)
Assigns a Buffer of Strings to this node as a quoted comma-separated array.
Definition JSONParser.h:563
JSONNode(const String &node, const StringView &json_string)
Creates a JSONNode by parsing a named node from a JSON string.
~JSONNode()
Destroys the JSONNode and frees all child nodes.
Dictionary< StringView, JSONNode * > m_json_children
Dictionary of child nodes keyed by name. Empty if the node type is not e_node or e_root.
Definition JSONParser.h:862
NodeType type() const
JSONNode & operator=(const Ray< t_dims, t_type > &buffer)
Assigns a Ray value to this node as a comma-separated array.
Definition JSONParser.h:625
void remove(const StringView &child_node)
Removes the child node with the given name from this node.
JSONNode & operator=(const Time &time)
Definition JSONParser.h:531
void writePretty(std::ostream &file)
Writes the JSON structure to an output stream with human-readable formatting.
void writePretty(String &stream, const uint04 tab_indention=0) const
Same as write, but adds tabs and new lines to make it easier to read, though will result in larger fi...
decltype(auto) begin() const
Returns a const iterator to the beginning of the children dictionary.
Definition JSONParser.h:689
JSONNode & operator[](const StringView &child_node)
Returns a mutable reference to the named child node, creating it if it does not exist.
Definition JSONParser.h:353
static void ConvertFromJSONString(String &string)
Unescapes JSON escape sequences in the string back to their original characters.
const String & nodeName() const
Returns the name of this node.
Definition JSONParser.h:410
JSONNode & operator[](const uint04 &child_idx)
Definition JSONParser.h:374
void write(File &file)
Writes the JSON structure out to a file with no frills.
decltype(auto) end()
Returns a mutable iterator to the end of the children dictionary.
Definition JSONParser.h:698
JSONNode & operator=(const Angle< t_type > &value)
Assigns an Angle value to this node, storing it as degrees.
Definition JSONParser.h:517
static TranslatedString UnexpectedCharErrorString(char current_char, const Scanner &scan)
Generates a translated error message for an unexpected character during parsing.
static void WriteTabs(String &stream, uint04 tab_indention)
JSONNode(Scanner &scan)
void writeValue(String &stream) const
Writes only the value portion of this node to the given string stream.
void write(std::ostream &file)
Writes the JSON structure to an output stream.
NodeType
Describes the type of data stored by a JSONNode.
Definition JSONParser.h:156
@ e_number
Stores a number (may be integer or floating point).
Definition JSONParser.h:157
@ e_root
Is a root node, meaning it has no parent.
Definition JSONParser.h:162
@ e_node
Is a node storing a number of children JSON nodes.
Definition JSONParser.h:161
@ e_object
Stores an object with data that is not a number type.
Definition JSONParser.h:160
@ e_array
Stores an array of values.
Definition JSONParser.h:158
@ e_bool
Stores a boolean true/false.
Definition JSONParser.h:159
bool getIfExists(const StringView &child_node, t_type &value) const
Retrieves a child value if the node exists, returning whether it was found.
Definition JSONParser.h:444
const JSONNode & operator[](const StringView &child_node) const
Definition JSONParser.h:344
static Angle< t_type > Convert(const String &value)
Converts a JSON string to an Angle by interpreting the value as degrees.
Definition JSONParser.h:74
static StringView Convert(const String &value)
Converts a JSON string value to a StringView without transformation.
Definition JSONParser.h:91
static Time Convert(const String &value)
Template specialization for time, as the format for time in JSON is not entirely specified,...
Definition JSONParser.h:111
Helper template for converting a JSON string value to a specific type.
Definition JSONParser.h:50
static t_type Convert(const String &value)
Converts a JSON string representation to the target type.
Definition JSONParser.h:57
Contains methods for easily reading objects in an ascii stream using set deliminators and line logic.
Definition Scanner.h:47
The core String View class for the NDEVR API.
Definition StringView.h:58
t_type getAs() const
Converts a string into an object.
Definition StringView.h:125
The core String class for the NDEVR API.
Definition String.h:95
StringView substr(uint04 start) const
Creates a substring from a given start position, to the end of the string.
uint04 indexOf(const StringView &sub_string, bool ignore_case=false, uint04 start_index=0) const
Given a substring specified by the input, returns the first index of that string, if it exists.
decltype(auto) getAs() const
Converts a string into an object.
Definition String.h:188
Represents a timestamp with utilities for manipulation and conversion.
Definition Time.h:62
StringAllocatingView getAsString(bool get_local_time, const StringView &format_string) const
Converts the timestamp to a string representation.
Any text displayed to the user should be defined as a TranslatedString which allows the program to lo...
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
Definition Vector.hpp:62
A point in N-dimensional space, used primarily for spatial location information.
Definition Vertex.hpp:44
The primary namespace for the NDEVR SDK.
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
uint64_t uint08
-Defines an alias representing an 8 byte, unsigned integer
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
double fltp08
Defines an alias representing an 8 byte floating-point number.
@ DEGREES
Angle measured in degrees (0 to 360 for a full circle).
Definition Angle.h:58
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408
Information about the object.
Definition ObjectInfo.h:55