9#ifndef _AUROSTD_XPARSER_JSON_CPP_
10#define _AUROSTD_XPARSER_JSON_CPP_
58 const std::shared_ptr<JSON::List> content = std::static_pointer_cast<JSON::List>(this->
obj);
59 return content->operator[](index);
76 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(this->
obj);
77 return content->operator[](key);
93 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(this->
obj);
94 return content->operator[](key);
113 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(
obj);
114 for (
const auto &entry : *content) {
120 result <<
"\"" << entry.first <<
"\":" << entry.second;
126 const std::shared_ptr<JSON::List> content = std::static_pointer_cast<JSON::List>(
obj);
127 for (
const auto &entry : *content) {
138 const std::shared_ptr<std::string> content = std::static_pointer_cast<std::string>(
obj);
140 result <<
"\"" <<
JSON::escape(*content, escape_unicode) <<
"\"";
146 const std::shared_ptr<long long int> content = std::static_pointer_cast<long long int>(
obj);
150 const std::shared_ptr<double> content = std::static_pointer_cast<double>(
obj);
181 const std::shared_ptr<std::string> new_string = std::make_shared<std::string>();
182 *new_string = content;
183 this->
obj = new_string;
191 const std::shared_ptr<JSON::List> new_list = std::make_shared<JSON::List>();
193 this->
obj = new_list;
201 const std::shared_ptr<JSON::Dictionary> new_dict = std::make_shared<JSON::Dictionary>();
203 this->
obj = new_dict;
237 this->
type = create_type;
238 switch (create_type) {
241 const std::shared_ptr<JSON::Dictionary> content = std::make_shared<JSON::Dictionary>();
246 const std::shared_ptr<JSON::List> content = std::make_shared<JSON::List>();
251 const std::shared_ptr<std::string> content = std::make_shared<std::string>();
256 const std::shared_ptr<long long int> content = std::make_shared<long long int>();
261 const std::shared_ptr<double> content = std::make_shared<double>();
273 this->fromList(content);
277 this->fromMap(content);
324 JSON::object::operator bool()
const {
328 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(
obj);
329 if (content->empty()) {
336 const std::shared_ptr<JSON::List> content = std::static_pointer_cast<JSON::List>(
obj);
337 if (content->empty()) {
344 const std::shared_ptr<std::string> content = std::static_pointer_cast<std::string>(
obj);
345 if (content->empty()) {
352 const std::shared_ptr<long long int> content = std::static_pointer_cast<long long int>(
obj);
360 const std::shared_ptr<double> content = std::static_pointer_cast<double>(
obj);
361 if (
static_cast<bool>(*content)) {
384 JSON::object::operator double()
const {
388 const std::shared_ptr<long long int> content = std::static_pointer_cast<long long int>(
obj);
389 return (
double) *content;
392 const std::shared_ptr<double> content = std::static_pointer_cast<double>(
obj);
404 JSON::object::operator
long double()
const {
405 return static_cast<double>(*this);
409 JSON::object::operator float()
const {
410 return static_cast<double>(*this);
414 JSON::object::operator
long long()
const {
418 const std::shared_ptr<long long int> content = std::static_pointer_cast<long long int>(
obj);
422 const std::shared_ptr<double> content = std::static_pointer_cast<double>(
obj);
423 if (*content >
static_cast<double>(std::numeric_limits<long long>::max())) {
424 return std::numeric_limits<long long>::max();
426 if (*content <
static_cast<double>(std::numeric_limits<long long>::lowest())) {
427 return std::numeric_limits<long long>::lowest();
429 return static_cast<long long>(*content);
439 JSON::object::operator
unsigned long long()
const {
440 const long long result =
static_cast<long long>(*this);
449 JSON::object::operator
unsigned long()
const {
450 return static_cast<unsigned long long>(*this);
454 JSON::object::operator
unsigned int()
const {
455 return static_cast<unsigned long long>(*this);
459 JSON::object::operator long()
const {
460 return static_cast<long long>(*this);
464 JSON::object::operator int()
const {
465 return static_cast<long long>(*this);
469 JSON::object::operator char()
const {
470 return static_cast<long long>(*this);
474 JSON::object::operator std::string()
const {
475 return this->
toString(
false,
false);
479 JSON::object::operator std::vector<object>()
const {
483 const std::shared_ptr<JSON::List> content = std::static_pointer_cast<JSON::List>(obj);
488 JSON::object::operator std::map<std::string, JSON::object>()
const {
492 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(obj);
499 const std::shared_ptr<JSON::List> list_obj = std::static_pointer_cast<JSON::List>(
obj);
500 list_obj->push_back(content);
510 const std::shared_ptr<JSON::Dictionary> dict_obj = std::static_pointer_cast<JSON::Dictionary>(
obj);
511 const std::shared_ptr<JSON::Dictionary> dict_content = std::static_pointer_cast<JSON::Dictionary>(content.
obj);
512 for (
auto &[key, value] : *dict_content) {
513 dict_obj->operator[](key) = value;
516 const std::shared_ptr<JSON::List> list_obj = std::static_pointer_cast<JSON::List>(
obj);
517 const std::shared_ptr<JSON::List> list_content = std::static_pointer_cast<JSON::List>(content.
obj);
518 for (
auto &it : *list_content) {
519 list_obj->push_back(it);
530 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(
obj);
531 return content->size();
534 const std::shared_ptr<JSON::List> content = std::static_pointer_cast<JSON::List>(
obj);
535 return content->size();
538 const std::shared_ptr<std::string> content = std::static_pointer_cast<std::string>(
obj);
539 return content->size();
550 return not
static_cast<bool>(*this);
559 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(
obj);
560 return content->count(key);
572 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(
obj);
573 return content->end();
585 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(
obj);
586 return content->begin();
598 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(
obj);
599 return content->find(key);
611 const std::shared_ptr<JSON::Dictionary> content = std::static_pointer_cast<JSON::Dictionary>(
obj);
612 std::vector<std::string>
keys;
613 keys.reserve(content->size());
614 for (
const auto &[key, value] : *content) {
686 static inline size_t range_find(
const char *content_ptr,
const std::pair<size_t, size_t> &border,
const char to_find) {
687 return static_cast<const char *
>(memchr(content_ptr + border.first, to_find, border.second - border.first + 1)) - content_ptr;
697 if (border.second == 0) {
698 border.second = raw_content.size() - 1;
700 size_t last_escape_pos = border.first;
701 size_t current_escape_pos =
range_find(raw_content.c_str(), border,
'\\');
703 if (current_escape_pos > border.second) {
704 return raw_content.substr(border.first, border.second - border.first + 1);
708 while (current_escape_pos <= border.second) {
709 result += raw_content.substr(last_escape_pos, current_escape_pos - last_escape_pos);
710 switch (raw_content[current_escape_pos + 1]) {
736 if (current_escape_pos + 6 > raw_content.size()) {
740 current_escape_pos += 2;
743 stringstream message;
744 message <<
"JSON parsing failed: string contains undefined escape '\\" << raw_content[current_escape_pos + 1] <<
"'";
748 last_escape_pos = current_escape_pos + 2;
749 current_escape_pos =
range_find(raw_content.c_str(), {last_escape_pos, border.second},
'\\');
751 result += raw_content.substr(last_escape_pos, border.second - last_escape_pos + 1);
759 case (
'"'):
return "\\\"";
760 case (
'\\'):
return "\\\\";
761 case (
'/'):
return "\\/";
762 case (
'\b'):
return "\\b";
763 case (
'\f'):
return "\\f";
764 case (
'\n'):
return "\\n";
765 case (
'\r'):
return "\\r";
766 case (
'\t'):
return "\\t";
777 std::stringstream out;
779 const std::u16string utf16 = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,
char16_t>{}.from_bytes(raw.data());
780 for (
const char16_t c : utf16) {
783 out << static_cast<char>(c);
788 out <<
"\\u" << std::hex << std::setw(4) << std::setfill(
'0') << c;
792 for (
const char16_t c : raw) {
794 out << static_cast<char>(c);
811 out +=
static_cast<char>(cp);
815 out +=
static_cast<char>((cp >> 6) | 0xc0);
816 out +=
static_cast<char>((cp & 0x3f) | 0x80);
820 out +=
static_cast<char>((cp >> 12) | 0xe0);
821 out +=
static_cast<char>(((cp >> 6) & 0x3f) | 0x80);
822 out +=
static_cast<char>((cp & 0x3f) | 0x80);
826 out +=
static_cast<char>((cp >> 18) | 0xf0);
827 out +=
static_cast<char>(((cp >> 12) & 0x3f) | 0x80);
828 out +=
static_cast<char>(((cp >> 6) & 0x3f) | 0x80);
829 out +=
static_cast<char>((cp & 0x3f) | 0x80);
844 if (cp < 0xd800 || cp > 0xdfff) {
846 }
else if (cp > 0xdbff) {
849 if (raw[pos + 4] ==
'\\' and raw[pos + 5] ==
'u') {
852 if (trailing_cp < 0xdc00 || trailing_cp > 0xdfff) {
855 const char32_t combo_cp = ((cp - 0xd800) << 10) + (trailing_cp - 0xdc00) + 0x10000;
869 std::pair<size_t, size_t>
JSON::find_strip(
const std::string &raw_content, std::pair<size_t, size_t> border) {
870 if (border.second == 0) {
871 border.second = raw_content.size() - 1;
873 const size_t start = raw_content.find_first_not_of(
" \n\t\r\v\f", border.first);
874 const size_t end = raw_content.find_last_not_of(
" \n\t\r\v\f", border.second);
875 return {start,
min(end, border.second)};
884 std::pair<size_t, size_t>
JSON::find_string(
const std::string &raw_content, std::pair<size_t, size_t> border) {
885 if (border.second == 0) {
886 border.second = raw_content.size() - 1;
888 const size_t start =
range_find(raw_content.c_str(), border,
'"');
889 if (start >= border.second) {
890 return {std::string::npos, std::string::npos};
893 uint escape_check = 0;
894 size_t escape_check_pos = 0;
895 if (start == std::string::npos) {
899 end =
range_find(raw_content.c_str(), {end + 1, border.second},
'"');
900 escape_check_pos = end - 1;
902 while (raw_content[escape_check_pos] ==
'\\' and escape_check_pos >= start) {
906 }
while ((escape_check % 2 != 0) && (end <= border.second));
907 if (end > border.second) {
920 std::pair<size_t, size_t>
JSON::find_bracket(
const std::string &raw_content,
const char kind_open, std::pair<size_t, size_t> border) {
923 case '[': kind_close =
']';
break;
924 case '{': kind_close =
'}';
break;
925 case '(': kind_close =
')';
break;
928 const size_t start = raw_content.find(kind_open, border.first);
930 if (start > border.second) {
931 return {std::string::npos, std::string::npos};
933 size_t next_open = 0;
934 size_t next_close = 0;
935 std::pair<size_t, size_t> string_section;
936 size_t open_count = 1;
939 string_section =
find_string(raw_content, {end + 1, border.second});
940 next_close =
range_find(raw_content.c_str(), {end + 1, border.second}, kind_close);
941 next_open =
range_find(raw_content.c_str(), {end + 1, border.second}, kind_open);
942 if (next_close > string_section.first && next_open > string_section.first) {
943 end = string_section.second;
946 if (next_close < next_open) {
947 if (next_close < string_section.first) {
951 }
else if (next_close > next_open) {
952 if (next_open < string_section.first) {
960 }
while (open_count > 0 && (end < border.second));
972 if (border.second == 0) {
973 border.second = raw_content.size() - 1;
977 result.
obj =
nullptr;
979 std::pair<size_t, size_t> section({0, 0});
980 switch (raw_content[border.first]) {
982 if (raw_content[border.second] !=
'}') {
985 const std::shared_ptr<JSON::Dictionary> new_dictionary = std::make_shared<JSON::Dictionary>();
986 border = {border.first + 1, border.second - 1};
991 if (border.first >= border.second) {
995 if (section.first == std::string::npos) {
998 const std::string key_string =
parse_string(raw_content, {section.first + 1, section.second - 1});
1000 border.first = raw_content.find(
':', section.second) + 1;
1004 switch (raw_content[border.first]) {
1015 section.first = border.first;
1016 section.second =
min(border.second,
range_find(raw_content.c_str(), border,
',') - 1);
1019 new_dictionary->insert({key_string,
parse(raw_content, section)});
1020 border.first =
range_find(raw_content.c_str(), {section.second, border.second},
',');
1021 if (border.first == std::string::npos) {
1022 border.first = border.second;
1026 }
while (border.first < border.second);
1027 result.
obj = new_dictionary;
1031 if (raw_content[border.second] !=
']') {
1034 const std::shared_ptr<JSON::List> new_list = std::make_shared<JSON::List>();
1035 border = {border.first + 1, border.second - 1};
1039 switch (raw_content[border.first]) {
1050 section.first = border.first;
1051 section.second =
min(border.second, raw_content.find(
',', border.first) - 1);
1054 new_list->emplace_back(
parse(raw_content, section));
1055 border.first = raw_content.find(
',', section.second);
1056 if (border.first == std::string::npos) {
1057 border.first = border.second;
1061 }
while (section.second < border.second);
1062 result.
obj = new_list;
1066 if (raw_content[border.second] !=
'"') {
1069 const std::shared_ptr<std::string> new_string = std::make_shared<std::string>();
1070 *new_string =
parse_string(raw_content, {border.first + 1, border.second - 1});
1071 result.
obj = new_string;
1075 result.
obj =
nullptr;
1079 result.
obj =
nullptr;
1083 result.
obj =
nullptr;
1087 if (raw_content.find(
'.', border.first) != std::string::npos || raw_content.find(
'E', border.first) != std::string::npos || raw_content.find(
'e', border.first) != std::string::npos) {
1088 const std::shared_ptr<double> new_number = std::make_shared<double>();
1089 *new_number = std::strtod(raw_content.c_str() + border.first,
nullptr);
1090 result.
obj = new_number;
1093 const std::shared_ptr<long long> new_number = std::make_shared<long long>();
1094 *new_number = std::strtoll(raw_content.c_str() + border.first,
nullptr, 10);
1095 result.
obj = new_number;
1108 return parse(raw_content);
1115 return parse(content);
1123 return root.
toString(
true, escape_unicode);
#define _FILE_WRONG_FORMAT_
std::pair< size_t, size_t > find_bracket(const std::string &raw_content, char kind_open, std::pair< size_t, size_t > border={0, 0})
find the border of an encapsulated by brackets
std::pair< size_t, size_t > find_string(const std::string &raw_content, std::pair< size_t, size_t > border={0, 0})
find the border of a JSON string
std::string toString(const object &root, bool escape_unicode=false)
convert JSON::object to string
void saveFile(const object &root, const std::string &file_path, compression_type ct=compression_type::None, bool escape_unicode=true)
save JSON::object to file
std::string parse_string(const std::string &raw_content, std::pair< size_t, size_t > border={0, 0})
parse JSON string
std::map< std::string, object > Dictionary
shortcut for JSON::object_types::DICTIONARY
object parse(const std::string &raw_content, std::pair< size_t, size_t > border={0, 0})
parse a raw JSON string
std::string unescape_unicode(const std::string &raw, size_t &pos)
unescape JSON unicode instances
std::vector< object > List
shortcut for JSON::object_types::LIST
std::string char32_to_string(char32_t cp)
convert a unicode codepoint to a series of utf8 chars
object loadString(const std::string &content)
create a JSON::object from raw string
std::pair< size_t, size_t > find_strip(const std::string &raw_content, std::pair< size_t, size_t > border={0, 0})
strip whitespaces
object loadFile(const std::string &file_path)
create a JSON::object from file
std::string escape(const std::string &raw, bool unicode=true)
prepare string for JSON output with or without Unicode escapes
std::string char_escape(char16_t c)
escape characters to JSON
bool string2file(const string &StringOUTPUT, const std::string &FileNameRawOUTPUT, const compression_type ct, const string &mode)
write string into a file
static size_t range_find(const char *content_ptr, const std::pair< size_t, size_t > &border, const char to_find)
find a char inbetween a boundary
size_t file2string(const string &FileNameIN, string &StringIN)
read the content of a file into a string
utype string2utype(const string &from, const uint base=10)
utype min(const vector< utype > vec)
b64_encoder_proxy operator<<(std::ostream &os, b64_encoder_creator)
storge container for a JSON object
size_t count(const std::string &) const
count the occurrence of key string in a JSON::object_type::DICTIONARY
JSON::object & operator[](size_t index) const
direct index access to JSON::object_types::LIST objects
void fromDictionary(const Dictionary &content)
change this JSON::object to a JSON::object_types::DICTIONARY
std::vector< std::string > keys() const
returns a vector of all keys in a JSON::object_type::DICTIONARY
size_t size() const
gives the size of JSON::object_tpe::LIST, JSON::object_tpe::DICTIONARY or JSON::object_tpe::STRING
JSON::object & operator=(const char *content)
assignment operator for char
void fromList(const List &content)
change this JSON::object to a JSON::object_types::LIST
std::map< std::string, JSON::object >::iterator begin() const
returns an iterator to the begin() of a JSON::object_type::DICTIONARY
std::map< std::string, JSON::object >::iterator find(const std::string &key) const
returns an iterator to the result of find in JSON::object_type::DICTIONARY
void push_back(const JSON::object &content) const
allow to append to JSON::object_type::LIST
std::shared_ptr< void > obj
std::string toString(bool json_format=true, bool escape_unicode=true) const
converts a JSON::object into a string
std::map< std::string, JSON::object >::iterator end() const
returns an iterator to the end() of a JSON::object_type::DICTIONARY
void fromString(const std::string &content)
change this JSON::object to a JSON::object_types::STRING
bool empty() const
checks if JSON::object_tpe::LIST, JSON::object_tpe::DICTIONARY or JSON::object_tpe::STRING is empty
void join(const JSON::object &content) const
allow to merge two dictionaries or lists
void saveFile(const std::string &file_path, compression_type ct=compression_type::None, bool escape_unicode=true) const
save JSON::object to file