From ba7fa1c19557c2be73a53187568b800c24ca741d Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 16 Mar 2021 18:36:59 +0100 Subject: [PATCH] fixed: in serialize_json_double(): the buffer length was calculated incorrectly: sizeof(char) changed to sizeof(wchar_t) added to Space struct: void set_null(); void set_empty_string(); void set_empty_wstring(); void set_empty_table(); void set_empty_object(); void clear(); --- space/space.cpp | 55 ++++++++++++++-- space/space.h | 166 +++++++++++++++++++++--------------------------- 2 files changed, 123 insertions(+), 98 deletions(-) diff --git a/space/space.cpp b/space/space.cpp index 203eca2..584c1b4 100644 --- a/space/space.cpp +++ b/space/space.cpp @@ -156,6 +156,39 @@ Space::Space(const Space * space) } +void Space::clear() +{ + set_null(); +} + + + +void Space::set_null() +{ + initialize_value_null_if_needed(); +} + +void Space::set_empty_string() +{ + initialize_value_string_if_needed(); +} + +void Space::set_empty_wstring() +{ + initialize_value_wstring_if_needed(); +} + +void Space::set_empty_table() +{ + initialize_value_table_if_needed(); +} + +void Space::set_empty_object() +{ + initialize_value_object_if_needed(); +} + + void Space::set(bool val) @@ -220,14 +253,28 @@ void Space::set(double val) void Space::set(const char * str) { - initialize_value_string_if_needed(); - value.value_string = str; + if( str == nullptr ) + { + initialize_value_null_if_needed(); + } + else + { + initialize_value_string_if_needed(); + value.value_string = str; + } } void Space::set(const wchar_t * str) { - initialize_value_wstring_if_needed(); - value.value_wstring = str; + if( str == nullptr ) + { + initialize_value_null_if_needed(); + } + else + { + initialize_value_wstring_if_needed(); + value.value_wstring = str; + } } void Space::set(const std::string & str) diff --git a/space/space.h b/space/space.h index a6c7ec2..5f5052b 100644 --- a/space/space.h +++ b/space/space.h @@ -55,110 +55,72 @@ namespace PT /* -A parser for parsing config files. -A config file can look like this: - variable1 = value 1 - variable2 = " value 2 " - variable3 = (value 1, value 2) - variable4 = (" value 1 " , "value2", value 3) +Simple form: + key = value -sample of use: - SpaceParser parser; - parser.Parse("/path/to/config"); +If value is equal to 'null' then the internal representation is equal to Type::type_null, e.g: + key = null - if( parser.status == SpaceParser::ok ) - { - // the whole config we have in parser.table - } +If value is either 'false' or 'true' then the internal representation is Type::type_bool, e.g: + key = false + key = true -config syntax: - option = list +If value is an integer number and not an overflow has occured while parsing then type of the value +is Type::type_long (type is 'long long' internally): + key = 1000 - list can consists of any number of items, if you're using more than one item you should - use brackets () +If value is a floating point number then type is Type::type_double (type is 'double' internally): + key = 123.45 + key = 123.45e+10 - for one item the brackets can be ommited: - option = value - white characters at the beginning of the value (and at the end) will be trimmed, - or you can use quotes: - option = "value" - option2 = "value with spaces at the end " +In other cases value has Type::type_wstring type. - the form without quotes: - option = value - should be written in one line, so this is not allowed: - option = - value - you can use a new line characters only between brackets and quotes: - option = "this is - a multiline string" - option = ( value1, - value2 ) +The form with quotation marks: + key = "value" +In such a case value has Type::type_wstring type and can be multiline e.g: + key = "multiline + value" +In this form you can have spaces around value, e.g.: + key = " value with spaces " - but there is one requirement: the first character " or ( should be in the same line, - so this is not allowed - option = - "this is wrong" - but this is ok: - option = " - that is ok" - empty lists: - option = () - this creates an empty list: parser.table['option'].empty() == true +The value can be a list: + key = (value1,value2) +or the same written with spaces around: + key = ( value1 , value2 ) +or written in multiline fashion: + key = ( + value1, + value2, + ) +a colon after value2 is optional. - option = - this creates an empty list too (the same as previously) +List can be written with quotation marks too: + key = ( + "value1", + "value2", + "value3 + with a new line character inside", + ) - option = "" - but this doesn't create an empty list, it creates a list with one (empty) item +List without value: + key = () +is equal to simple form without value, e.g.: + key = - commentaries: - # this is a commentary (until the end of the line) - option = value # this is a commentary too - - commentaries are treated as white characters, other example: - option = ( # this is my list - "value 1" # this is a value one - value 2 # and this is a value two - ) # end of my list - overwriting: - option1 = some value - option1 = other value - # always the last option is used so option1 is "other value" - list delimiter: - option1 = (value1, value2, value3) - option2 = ("value1", "value2", "value3") - above we're using a comma ',' as a list delimiter but when using quotes (second line) - the commas can be omitted: - option2 = ("value1" "value2" "value3") +Difference between a simple form and a list is when parsing the colon, in simple form the colon is a part of the value, e.g.: + key = value with , a colon inside +this is equal to: + key = "value with , a colon inside" - white characters: - the name of an option cannot consist of white characters - some option = value # this is wrong - some_option = value # this is ok +and in a form of a list it would have two values: + key = (value with , a colon inside) +would be equal to: + key = ("value with" , "a colon inside") - which characters are allowed in an option name is defined by IsVariableChar() method - - you can use white characters in values - option = value with spaces or tabs - white characters at the beginning and at the end will be trimmed, - so if you want them use quotes: - option = " other value with spaces " - - special characters in quoted strings: - option = "this is a string with \" a quote inside" - the option will be: this is a string with " a quote inside - \\ - means one \ - basically: \char produces char - so: - "\a" gives "a" - "\\" gives "\" - "\Z" gives "Z" and so on - you can call UseEscapeChar(false) to turn this off */ @@ -242,7 +204,15 @@ public: Space(const Space * space); + void clear(); + // set a new value + void set_null(); + void set_empty_string(); + void set_empty_wstring(); + void set_empty_table(); + void set_empty_object(); + void set(bool val); void set(short val); void set(int val); @@ -258,7 +228,7 @@ public: void set(const wchar_t * str); void set(const std::string & str); void set(const std::wstring & str); - void set(const Space * space = nullptr); + void set(const Space * space); // add a value to the table, change to table if needed, return the reference to the new inserted item @@ -652,20 +622,28 @@ protected: template void serialize_json_float(StreamType & str) const { - wchar_t buffer[50]; + wchar_t buffer[100]; size_t buffer_len = sizeof(buffer) / sizeof(char); - std::swprintf(buffer, buffer_len, L"%f", value.value_float); + int chars_written = std::swprintf(buffer, buffer_len, L"%e", static_cast(value.value_float)); + + if( errno == EOVERFLOW || chars_written < 0 ) + buffer[0] = 0; + serialize_string_buffer(buffer, str, Escape::escape_json); } template void serialize_json_double(StreamType & str) const { - wchar_t buffer[50]; - size_t buffer_len = sizeof(buffer) / sizeof(char); + wchar_t buffer[100]; + size_t buffer_len = sizeof(buffer) / sizeof(wchar_t); + + int chars_written = std::swprintf(buffer, buffer_len, L"%e", value.value_double); + + if( errno == EOVERFLOW || chars_written < 0 ) + buffer[0] = 0; - std::swprintf(buffer, buffer_len, L"%f", value.value_double); serialize_string_buffer(buffer, str, Escape::escape_json); }