From 2cddd237cd7e9c58b3317b4e7dbde9c66bbc3e42 Mon Sep 17 00:00:00 2001 From: pmswga Date: Fri, 25 Nov 2022 15:22:54 +0300 Subject: [PATCH 1/4] Added function parse_ini_string, written cpp & php tests --- builtin-functions/_functions.txt | 6 + runtime/parsing_functions.cpp | 290 +++++++++++++++++++ runtime/parsing_functions.h | 40 +++ runtime/runtime.cmake | 1 + tests/cpp/runtime/parsing-functions-test.cpp | 98 +++++++ tests/cpp/runtime/runtime-tests.cmake | 3 +- tests/phpt/parsing/001_ini_parsing.php | 54 ++++ 7 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 runtime/parsing_functions.cpp create mode 100644 runtime/parsing_functions.h create mode 100644 tests/cpp/runtime/parsing-functions-test.cpp create mode 100644 tests/phpt/parsing/001_ini_parsing.php diff --git a/builtin-functions/_functions.txt b/builtin-functions/_functions.txt index c93d8403db..4487045b11 100644 --- a/builtin-functions/_functions.txt +++ b/builtin-functions/_functions.txt @@ -179,6 +179,12 @@ function kphp_backtrace($pretty ::: bool = true) ::: string[]; function ini_get ($s ::: string) ::: string | false; function ini_set ($s ::: string, $v ::: string) ::: bool; +define('INI_SCANNER_NORMAL', 0); +define('INI_SCANNER_RAW', 1); +define('INI_SCANNER_TYPED', 2); + +function parse_ini_string($ini_string ::: string, $process_sections ::: bool = false, $scanner_mode ::: int = INI_SCANNER_NORMAL) ::: mixed[]; + function memory_get_usage ($real_usage ::: bool = false) ::: int; function memory_get_peak_usage ($real_usage ::: bool = false) ::: int; function memory_get_total_usage() ::: int; diff --git a/runtime/parsing_functions.cpp b/runtime/parsing_functions.cpp new file mode 100644 index 0000000000..993b4db6d4 --- /dev/null +++ b/runtime/parsing_functions.cpp @@ -0,0 +1,290 @@ +#include "parsing_functions.h" + +/* + * Helper functions + */ + +string clearQuotes(const string &str) +{ + if (str.starts_with(string("\'"))) { + return clearSingleQuotes(str); + } + + if (str.starts_with(string("\""))) { + return clearDoubleQuotes(str); + } + + return str; +} + +string clearSingleQuotes(const string &str) +{ + if (str.empty()) { + return {}; + } + + if (str.starts_with(string("\'")) && str.ends_with(string("\'"))) { + return str.substr(1, str.size()-2); + } + + return str; +} + +string clearDoubleQuotes(const string &str) +{ + if (str.empty()) { + return {}; + } + + if (str.starts_with(string("\"")) && str.ends_with(string("\""))) { + return str.substr(1, str.size()-2); + } + + return str; +} + +string clearExtraSpaces(const string &str) +{ + if (str.empty()) { + return {}; + } + + string clear_str; + + for (string::size_type i = 0; i < str.size(); i++) { + if (str[i] != ' ') { + clear_str.push_back(str[i]); + } else { + clear_str.push_back(' '); + + while (str[i+1] == ' ') { + i++; + } + } + } + + return clear_str; +} + +string tolower(const string &str) +{ + if (str.empty()) { + return {}; + } + + string lower_str = {}; + + for (string::size_type i = 0; i < str.size(); i++) { + lower_str.push_back(tolower(str[i])); + } + + return lower_str; +} + +string trim(const string &str) +{ + if (str.empty()) { + return {}; + } + + size_t s = 0; + size_t e = str.size()-1; + + while (s != e && std::isspace(str[s])) { + s++; + } + + while (e != s && std::isspace(str[e])) { + e--; + } + + return str.substr(s, (e-s)+1); +} + +/* + * INI parsing functions + */ + +bool isINISection(const string &ini_section) +{ + return std::regex_match(ini_section.c_str(), std::regex("^\\[.+\\]$", std::regex::ECMAScript)); +} + +bool isINIVar(const string &ini_var) +{ + return std::regex_match(ini_var.c_str(), std::regex("^.+", std::regex::ECMAScript)); +} + +bool isINIVal(const string &ini_val) +{ + return std::regex_match(ini_val.c_str(), std::regex("(.*\n(?=[A-Z])|.*$)", std::regex::ECMAScript)); +} + +bool isINIBoolVal(const string &ini_val) +{ + return std::regex_match(ini_val.c_str(), std::regex("^(false|true|0|1|off|on)$", std::regex::ECMAScript|std::regex::icase)); +} + +bool isINIFloatVal(const string &ini_val) +{ + return std::regex_match(ini_val.c_str(), std::regex(R"(^\d+\.\d*$)", std::regex::ECMAScript|std::regex::icase)); +} + +bool isINIStrVal(const string &ini_val) +{ + return std::regex_match(ini_val.c_str(), std::regex("^.*$", std::regex::ECMAScript|std::regex::icase)); +} + +string get_ini_section(const string &ini_entry) +{ + if (ini_entry.empty()) { + return {}; + } + + return ini_entry.substr(1, ini_entry.size()-2); +} + +string get_ini_var(const string &ini_entry) +{ + string::size_type pos = ini_entry.find_first_of(string("="), 0); + + if (pos == string::npos) { + return {}; + } + + return ini_entry.substr(0, pos); + +} + +string get_ini_val(const string &ini_entry) +{ + string::size_type pos = ini_entry.find_first_of(string("="), 0); + + if (pos == string::npos) { + return {}; + } + + pos++; + + return ini_entry.substr(pos, ini_entry.size() - pos); +} + + +bool cast_str_to_bool(const string &ini_var) +{ + if (ini_var.empty()) { + return false; + } + + string ini_bool_var = tolower(ini_var); + + if (ini_bool_var == string("on") || ini_bool_var == string("1") || ini_bool_var == string("true")) { + return true; + } + + if (ini_bool_var == string("off") || ini_bool_var == string("0") || ini_bool_var == string("false")) { + return false; + } + + return false; +} + +array f$parse_ini_string(const string &ini_string, bool process_sections, int scanner_mode) +{ + if (ini_string.empty()) { + return {}; + } + + string ini_string_copy = trim(ini_string); + ini_string_copy = clearExtraSpaces(ini_string_copy); + + array res(array_size(0, 0, true)); + array section(array_size(0, 0, true)); + string ini_entry; + string ini_section; + + for (string::size_type i = 0; i <= ini_string_copy.size(); i++) { + if (ini_string_copy[i] == '[') { + while (ini_string_copy[i] != ']') { + ini_entry.push_back(ini_string_copy[i]); + i++; + } + } + + if (ini_string_copy[i] == '\"' || ini_string_copy[i] == '\'') { + ini_entry.push_back(ini_string_copy[i]); + + i++; + while (ini_string_copy[i] != '\"' && ini_string_copy[i] != '\'') { + ini_entry.push_back(ini_string_copy[i]); + i++; + } + } + + if (ini_string_copy[i] == ' ' || ini_string_copy[i] == '\n' || ini_string_copy[i] == '\0') { + if (isINISection(ini_entry)) { + if (process_sections && !ini_section.empty()) { + res.set_value(ini_section, section); + section.clear(); + } + + ini_section = get_ini_section(ini_entry); + } else { + string ini_var = get_ini_var(ini_entry); + string ini_val = get_ini_val(ini_entry); + + if (!isINIVar(ini_var) && !isINIVal(ini_val)) { + php_warning("Invalid ini string format %s", ini_entry.c_str()); + return {}; + } + + if (!ini_var.empty() && !ini_val.empty()) { + switch (scanner_mode) { + case INI_SCANNER_NORMAL: + if (isINIBoolVal(ini_val)) { + section.set_value(ini_var, cast_str_to_bool(ini_val) ? string("1") : string("")); + } else if (isINIStrVal(ini_val)) { + section.set_value(ini_var, clearQuotes(ini_val)); + } + + break; + case INI_SCANNER_RAW: + if (isINIStrVal(ini_val)) { + section.set_value(ini_var, clearDoubleQuotes(ini_val)); + } else { + section.set_value(ini_var, ini_val); + } + + break; + case INI_SCANNER_TYPED: + if (ini_val.is_int()) { + section.set_value(ini_var, ini_val.to_int()); + } else if (isINIFloatVal(ini_val)) { + section.set_value(ini_var, ini_val.to_float()); + } else if (isINIBoolVal(ini_val)) { + section.set_value(ini_var, cast_str_to_bool(ini_val)); + } else if (isINIStrVal(ini_val)) { + section.set_value(ini_var, clearQuotes(ini_val)); + } + + break; + } + } + } + + ini_entry = {}; + } else { + ini_entry.push_back(ini_string_copy[i]); + } + } + + if (process_sections) { + if (!ini_section.empty()) { + res.set_value(ini_section, section); + } + } else { + return section; + } + + return res; +} diff --git a/runtime/parsing_functions.h b/runtime/parsing_functions.h new file mode 100644 index 0000000000..7326cb124d --- /dev/null +++ b/runtime/parsing_functions.h @@ -0,0 +1,40 @@ +#pragma once + +#include "runtime/kphp_core.h" +#include +#include +#include + +/* + * Helper functions + */ + +string clearQuotes(const string &str); + +string clearSingleQuotes(const string &str); + +string clearDoubleQuotes(const string &str); + +string clearExtraSpaces(const string &str); + +string tolower(const string &str); + +string trim(const string &str); + +/* + * INI parsing functions + */ + +const int INI_SCANNER_NORMAL = 0; +const int INI_SCANNER_RAW = 1; +const int INI_SCANNER_TYPED = 2; + +string get_ini_section(const string &ini_entry); + +string get_ini_var(const string &ini_entry); + +string get_ini_val(const string &ini_entry); + +bool cast_str_to_bool(const string &ini_var); + +array f$parse_ini_string(const string &ini_string, bool process_sections = false, int scanner_mode = INI_SCANNER_NORMAL); diff --git a/runtime/runtime.cmake b/runtime/runtime.cmake index da6beb13c1..9b955099bd 100644 --- a/runtime/runtime.cmake +++ b/runtime/runtime.cmake @@ -83,6 +83,7 @@ prepend(KPHP_RUNTIME_SOURCES ${BASE_DIR}/runtime/ net_events.cpp on_kphp_warning_callback.cpp openssl.cpp + parsing_functions.cpp php_assert.cpp profiler.cpp regexp.cpp diff --git a/tests/cpp/runtime/parsing-functions-test.cpp b/tests/cpp/runtime/parsing-functions-test.cpp new file mode 100644 index 0000000000..0d014c982e --- /dev/null +++ b/tests/cpp/runtime/parsing-functions-test.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include "runtime/parsing_functions.h" + +/* + * Tests for helper functions + */ + +TEST(parsing_functions_test, test_clear_extra_spaces) { + ASSERT_STREQ( + string("This is string without extra spaces").c_str(), + clearExtraSpaces(string("This is string without extra spaces")).c_str() + ); +} + +TEST(parsing_functions_test, test_clear_quotes) { + ASSERT_STREQ( + string("Single quotes string").c_str(), + clearQuotes(string("\'Single quotes string\'")).c_str() + ); + ASSERT_STREQ( + string("Double quotes string").c_str(), + clearQuotes(string("\"Double quotes string\"")).c_str() + ); +} + +TEST(parsing_functions_test, test_tolower) { + ASSERT_STREQ(string("on").c_str(), tolower(string("On")).c_str()); + ASSERT_STREQ(string("off").c_str(), tolower(string("Off")).c_str()); + ASSERT_STREQ(string("true").c_str(), tolower(string("TRUE")).c_str()); + ASSERT_STREQ(string("false").c_str(), tolower(string("FALSE")).c_str()); +} + +/* + * Tests for ini parsing functions + */ + +TEST(parsing_functions_test, test_get_ini_var) { + ASSERT_STREQ(string("foo_var").c_str(), get_ini_var(string("foo_var=123")).c_str()); + ASSERT_STREQ(string("bar_var").c_str(), get_ini_var(string("bar_var=123")).c_str()); +} + +TEST(parsing_functions_test, test_get_ini_val) { + ASSERT_STREQ(string("hello world").c_str(), get_ini_val(string("str=hello world")).c_str()); + ASSERT_STREQ(string("1207").c_str(), get_ini_val(string("int=1207")).c_str()); + ASSERT_STREQ(string("3.14").c_str(), get_ini_val(string("pi=3.14")).c_str()); + ASSERT_STREQ(string("127.0.0.1").c_str(), get_ini_val(string("addr=127.0.0.1")).c_str()); +} + +TEST(parsing_functions_test, test_parse_ini_string_empty) { + array res = f$parse_ini_string(string("")); + ASSERT_TRUE(res.empty()); +} + +TEST(parsing_functions_test, test_parse_ini_string_process_section_false) { + array res(array_size(0, 0, true)); + + res = f$parse_ini_string(string("[one] hello=world world=hello [two] a=a b=b")); + ASSERT_EQ(res.size().string_size, 4); + + res = f$parse_ini_string(string("hello=world world=hello a=a b=b")); + ASSERT_EQ(res.size().string_size, 4); +} + +TEST(parsing_functions_test, test_parse_ini_string_process_section_true) { + array res(array_size(0, 0, true)); + + res = f$parse_ini_string(string("[one] [two]"), true); + ASSERT_EQ(res.size().string_size, 2); + ASSERT_TRUE(res.has_key(string("one"))); + ASSERT_TRUE(res.has_key(string("two"))); + + res = f$parse_ini_string(string("[one] hello=world world=hello [two] a=a b=b"), true); + + ASSERT_EQ(res.size().string_size, 2); + ASSERT_TRUE(res.has_key(string("one"))); + ASSERT_TRUE(res.get_value(string("one")).is_array()); + ASSERT_TRUE(res.get_value(string("one")).to_array().has_key(string("hello"))); + ASSERT_EQ(res.get_value(string("one")).to_array().get_value(string("hello")).as_string(), string("world")); + ASSERT_TRUE(res.get_value(string("one")).to_array().has_key(string("world"))); + ASSERT_EQ(res.get_value(string("one")).to_array().get_value(string("world")).as_string(), string("hello")); + + ASSERT_TRUE(res.has_key(string("two"))); + ASSERT_TRUE(res.get_value(string("two")).is_array()); + ASSERT_TRUE(res.get_value(string("two")).to_array().has_key(string("a"))); + ASSERT_EQ(res.get_value(string("two")).to_array().get_value(string("a")).as_string(), string("a")); + ASSERT_TRUE(res.get_value(string("two")).to_array().has_key(string("b"))); + ASSERT_EQ(res.get_value(string("two")).to_array().get_value(string("b")).as_string(), string("b")); +} + +TEST(parsing_functions_test, test_parse_ini_string_scanner_mode_typed) { + array res(array_size(0, 0, true)); + + res = f$parse_ini_string(string("[types vars] int=1500 float=3.14242 str=\"hello world\" bool=true"), false, INI_SCANNER_TYPED); + ASSERT_EQ(res.size().string_size, 4); + +} diff --git a/tests/cpp/runtime/runtime-tests.cmake b/tests/cpp/runtime/runtime-tests.cmake index 32f74e5d7a..9cdb7a492e 100644 --- a/tests/cpp/runtime/runtime-tests.cmake +++ b/tests/cpp/runtime/runtime-tests.cmake @@ -19,7 +19,8 @@ prepend(RUNTIME_TESTS_SOURCES ${BASE_DIR}/tests/cpp/runtime/ memory_resource/unsynchronized_pool_resource-test.cpp string-list-test.cpp string-test.cpp - zstd-test.cpp) + zstd-test.cpp + parsing-functions-test.cpp) allow_deprecated_declarations_for_apple(${BASE_DIR}/tests/cpp/runtime/inter-process-mutex-test.cpp) vk_add_unittest(runtime "${RUNTIME_LIBS};${RUNTIME_LINK_TEST_LIBS}" ${RUNTIME_TESTS_SOURCES}) diff --git a/tests/phpt/parsing/001_ini_parsing.php b/tests/phpt/parsing/001_ini_parsing.php new file mode 100644 index 0000000000..c980d1c8c2 --- /dev/null +++ b/tests/phpt/parsing/001_ini_parsing.php @@ -0,0 +1,54 @@ +@ok + Date: Mon, 28 Nov 2022 15:33:12 +0300 Subject: [PATCH 2/4] Implemented parse_ini_file function, added tests --- builtin-functions/_functions.txt | 1 + runtime/parsing_functions.cpp | 35 +++++ runtime/parsing_functions.h | 3 + tests/cpp/runtime/parsing-functions-test.cpp | 154 +++++++++++++++++-- tests/phpt/parsing/001_ini_parsing.php | 47 +++++- 5 files changed, 217 insertions(+), 23 deletions(-) diff --git a/builtin-functions/_functions.txt b/builtin-functions/_functions.txt index 4487045b11..315a4e3b1d 100644 --- a/builtin-functions/_functions.txt +++ b/builtin-functions/_functions.txt @@ -184,6 +184,7 @@ define('INI_SCANNER_RAW', 1); define('INI_SCANNER_TYPED', 2); function parse_ini_string($ini_string ::: string, $process_sections ::: bool = false, $scanner_mode ::: int = INI_SCANNER_NORMAL) ::: mixed[]; +function parse_ini_file($filename ::: string, $process_sections ::: bool = false, $scanner_mode ::: int = INI_SCANNER_NORMAL) ::: mixed[]; function memory_get_usage ($real_usage ::: bool = false) ::: int; function memory_get_peak_usage ($real_usage ::: bool = false) ::: int; diff --git a/runtime/parsing_functions.cpp b/runtime/parsing_functions.cpp index 993b4db6d4..d16bf80924 100644 --- a/runtime/parsing_functions.cpp +++ b/runtime/parsing_functions.cpp @@ -288,3 +288,38 @@ array f$parse_ini_string(const string &ini_string, bool process_sections, return res; } + + + +array f$parse_ini_file(const string &filename, bool process_sections, int scanner_mode) +{ + if (filename.empty()) { + php_warning("Filename cannot be empty"); + return {}; + } + + std::ifstream ifs(filename.c_str()); + + if (!ifs.is_open()) { + php_warning("failed to open stream: %s", filename.c_str()); + return {}; + } + + std::string str; + std::string ini_string; + + while (std::getline(ifs, str)) { + if (!str.empty()) { + ini_string.append(str); + ini_string.append(" "); + } + } + + if (!str.empty()) { + ini_string.append(str); + } + + ifs.close(); + + return f$parse_ini_string(string(ini_string.c_str()), process_sections, scanner_mode); +} diff --git a/runtime/parsing_functions.h b/runtime/parsing_functions.h index 7326cb124d..1b84e7e172 100644 --- a/runtime/parsing_functions.h +++ b/runtime/parsing_functions.h @@ -3,6 +3,7 @@ #include "runtime/kphp_core.h" #include #include +#include #include /* @@ -38,3 +39,5 @@ string get_ini_val(const string &ini_entry); bool cast_str_to_bool(const string &ini_var); array f$parse_ini_string(const string &ini_string, bool process_sections = false, int scanner_mode = INI_SCANNER_NORMAL); + +array f$parse_ini_file(const string &filename, bool process_sections = false, int scanner_mode = INI_SCANNER_NORMAL); diff --git a/tests/cpp/runtime/parsing-functions-test.cpp b/tests/cpp/runtime/parsing-functions-test.cpp index 0d014c982e..16b47da71b 100644 --- a/tests/cpp/runtime/parsing-functions-test.cpp +++ b/tests/cpp/runtime/parsing-functions-test.cpp @@ -7,13 +7,6 @@ * Tests for helper functions */ -TEST(parsing_functions_test, test_clear_extra_spaces) { - ASSERT_STREQ( - string("This is string without extra spaces").c_str(), - clearExtraSpaces(string("This is string without extra spaces")).c_str() - ); -} - TEST(parsing_functions_test, test_clear_quotes) { ASSERT_STREQ( string("Single quotes string").c_str(), @@ -25,6 +18,14 @@ TEST(parsing_functions_test, test_clear_quotes) { ); } +TEST(parsing_functions_test, test_clear_extra_spaces) { + ASSERT_STREQ( + string("This is string without extra spaces").c_str(), + clearExtraSpaces(string("This is string without extra spaces")).c_str() + ); +} + + TEST(parsing_functions_test, test_tolower) { ASSERT_STREQ(string("on").c_str(), tolower(string("On")).c_str()); ASSERT_STREQ(string("off").c_str(), tolower(string("Off")).c_str()); @@ -53,27 +54,36 @@ TEST(parsing_functions_test, test_parse_ini_string_empty) { ASSERT_TRUE(res.empty()); } -TEST(parsing_functions_test, test_parse_ini_string_process_section_false) { +TEST(parsing_functions_test, test_parse_ini_string_scanner_mode_normal) { array res(array_size(0, 0, true)); + // Sections false res = f$parse_ini_string(string("[one] hello=world world=hello [two] a=a b=b")); - ASSERT_EQ(res.size().string_size, 4); + ASSERT_EQ(4, res.size().string_size); + + ASSERT_TRUE(res.has_key(string("hello"))); + ASSERT_TRUE(res.has_key(string("world"))); + ASSERT_TRUE(res.has_key(string("a"))); + ASSERT_TRUE(res.has_key(string("b"))); res = f$parse_ini_string(string("hello=world world=hello a=a b=b")); - ASSERT_EQ(res.size().string_size, 4); -} + ASSERT_EQ(4, res.size().string_size); -TEST(parsing_functions_test, test_parse_ini_string_process_section_true) { - array res(array_size(0, 0, true)); + ASSERT_TRUE(res.has_key(string("hello"))); + ASSERT_TRUE(res.has_key(string("world"))); + ASSERT_TRUE(res.has_key(string("a"))); + ASSERT_TRUE(res.has_key(string("b"))); + // Sections true res = f$parse_ini_string(string("[one] [two]"), true); - ASSERT_EQ(res.size().string_size, 2); + + ASSERT_EQ(2, res.size().string_size); ASSERT_TRUE(res.has_key(string("one"))); ASSERT_TRUE(res.has_key(string("two"))); res = f$parse_ini_string(string("[one] hello=world world=hello [two] a=a b=b"), true); - ASSERT_EQ(res.size().string_size, 2); + ASSERT_EQ(2, res.size().string_size); ASSERT_TRUE(res.has_key(string("one"))); ASSERT_TRUE(res.get_value(string("one")).is_array()); ASSERT_TRUE(res.get_value(string("one")).to_array().has_key(string("hello"))); @@ -89,10 +99,120 @@ TEST(parsing_functions_test, test_parse_ini_string_process_section_true) { ASSERT_EQ(res.get_value(string("two")).to_array().get_value(string("b")).as_string(), string("b")); } + +TEST(parsing_functions_test, test_parse_ini_string_scanner_mode_raw) { + array res(array_size(0, 0, true)); + + // Sections false + res = f$parse_ini_string(string(R"([one] hello='world' world="hello" [two] a='a' b=Off)"), false, INI_SCANNER_RAW); + + ASSERT_EQ(4, res.size().string_size); + ASSERT_TRUE(res.has_key(string("hello"))); + ASSERT_STREQ(string("'world'").c_str(), res.get_value(string("hello")).to_string().c_str()); + ASSERT_TRUE(res.has_key(string("world"))); + ASSERT_STREQ(string("hello").c_str(), res.get_value(string("world")).to_string().c_str()); + ASSERT_TRUE(res.has_key(string("a"))); + ASSERT_STREQ(string("'a'").c_str(), res.get_value(string("a")).to_string().c_str()); + ASSERT_TRUE(res.has_key(string("b"))); + ASSERT_STREQ(string("Off").c_str(), res.get_value(string("b")).to_string().c_str()); + + // Sections true + res = f$parse_ini_string(string(R"([one] hello='world' world="hello" [two] a='a' b=Off)"), true, INI_SCANNER_RAW); + + ASSERT_EQ(2, res.size().string_size); + ASSERT_TRUE(res.has_key(string("one"))); + ASSERT_TRUE(res.get_value(string("one")).to_array().has_key(string("hello"))); + ASSERT_STREQ(string("'world'").c_str(), res.get_value(string("one")).to_array().get_value(string("hello")).to_string().c_str()); + ASSERT_TRUE(res.get_value(string("one")).to_array().has_key(string("world"))); + ASSERT_STREQ(string("hello").c_str(), res.get_value(string("one")).to_array().get_value(string("world")).to_string().c_str()); + + ASSERT_TRUE(res.has_key(string("two"))); + ASSERT_TRUE(res.get_value(string("two")).to_array().has_key(string("a"))); + ASSERT_STREQ(string("'a'").c_str(), res.get_value(string("two")).to_array().get_value(string("a")).to_string().c_str()); + ASSERT_TRUE(res.get_value(string("two")).to_array().has_key(string("b"))); + ASSERT_STREQ(string("Off").c_str(), res.get_value(string("two")).to_array().get_value(string("b")).to_string().c_str()); +} + TEST(parsing_functions_test, test_parse_ini_string_scanner_mode_typed) { array res(array_size(0, 0, true)); - res = f$parse_ini_string(string("[types vars] int=1500 float=3.14242 str=\"hello world\" bool=true"), false, INI_SCANNER_TYPED); - ASSERT_EQ(res.size().string_size, 4); + // Sections false + res = f$parse_ini_string( + string("[types vars] int=1500 float=3.14242 str=\"hello world\" bool=true"), + false, + INI_SCANNER_TYPED); + + ASSERT_EQ(4, res.size().string_size); + + ASSERT_TRUE(res.get_value(string("int")).is_int()); + ASSERT_EQ(1500, res.get_value(string("int")).to_int()); + + ASSERT_TRUE(res.get_value(string("float")).is_float()); + ASSERT_EQ(3.14242, res.get_value(string("float")).to_float()); + + ASSERT_TRUE(res.get_value(string("str")).is_string()); + ASSERT_EQ(string("hello world"), res.get_value(string("str")).to_string()); + + ASSERT_TRUE(res.get_value(string("bool")).is_bool()); + ASSERT_EQ(true, res.get_value(string("bool")).to_bool()); + + // Sections true + res = f$parse_ini_string( + string("[types vars] int=1500 float=3.14242 str=\"hello world\" bool1=true bool2=Off"), + true, + INI_SCANNER_TYPED); + + ASSERT_TRUE(res.has_key(string("types vars"))); + ASSERT_TRUE(res.get_value(string("types vars")).to_array().get_value(string("int")).is_int()); + ASSERT_EQ(1500, res.get_value(string("types vars")).to_array().get_value(string("int")).to_int()); + + ASSERT_TRUE(res.get_value(string("types vars")).to_array().get_value(string("float")).is_float()); + ASSERT_EQ(3.14242, res.get_value(string("types vars")).to_array().get_value(string("float")).to_float()); + + ASSERT_TRUE(res.get_value(string("types vars")).to_array().get_value(string("str")).is_string()); + ASSERT_EQ(string("hello world"), res.get_value(string("types vars")).to_array().get_value(string("str")).to_string()); + + ASSERT_TRUE(res.get_value(string("types vars")).to_array().get_value(string("bool1")).is_bool()); + ASSERT_EQ(true, res.get_value(string("types vars")).to_array().get_value(string("bool1")).to_bool()); + + ASSERT_TRUE(res.get_value(string("types vars")).to_array().get_value(string("bool2")).is_bool()); + ASSERT_EQ(false, res.get_value(string("types vars")).to_array().get_value(string("bool2")).to_bool()); +} + +TEST(parsing_functions_test, test_parse_ini_file) { + std::ofstream of("test.ini"); + + if (of.is_open()) { + of << "[types vars] "<< std::endl; + of << "int=1500" << std::endl; + of << "float=3.14242" << std::endl; + of << "str1=\"hello world\"" << std::endl; + of << "str2=\'hello world\'" << std::endl; + of << "bool1=true" << std::endl; + of << "bool2=Off"; + of.close(); + } + + array res(array_size(0, 0, true)); + + res = f$parse_ini_file(string("test.ini")); + + ASSERT_EQ(6, res.size().string_size); + + res = f$parse_ini_file(string("test.ini"), true); + ASSERT_EQ(1, res.size().string_size); + + res = f$parse_ini_file(string("test.ini"), false, INI_SCANNER_RAW); + + ASSERT_EQ(6, res.size().string_size); + + res = f$parse_ini_file(string("test.ini"), true, INI_SCANNER_RAW); + + ASSERT_EQ(1, res.size().string_size); + + res = f$parse_ini_file(string("test.ini"), false, INI_SCANNER_TYPED); + + ASSERT_EQ(6, res.size().string_size); } + diff --git a/tests/phpt/parsing/001_ini_parsing.php b/tests/phpt/parsing/001_ini_parsing.php index c980d1c8c2..64947df957 100644 --- a/tests/phpt/parsing/001_ini_parsing.php +++ b/tests/phpt/parsing/001_ini_parsing.php @@ -17,6 +17,13 @@ str2="double quoted string" '; +$ini_sections = ' +[one] +[two] +[three] +'; + + function test_parse_ini_string_empty() { var_dump(parse_ini_string("")); } @@ -26,11 +33,6 @@ function test_parse_ini_string_sections() { var_dump(parse_ini_string("[one] [two] [three]", true)); } -function test_parse_ini_string_values($ini_string) { - var_dump(parse_ini_string($ini_string), false); - var_dump(parse_ini_string($ini_string), true); -} - function test_parse_ini_string_scanner_normal($ini_string) { var_dump(parse_ini_string($ini_string, false, INI_SCANNER_NORMAL)); var_dump(parse_ini_string($ini_string, true, INI_SCANNER_NORMAL)); @@ -46,9 +48,42 @@ function test_parse_ini_string_scanner_typed($ini_string) { var_dump(parse_ini_string($ini_string, true, INI_SCANNER_TYPED)); } +function test_parse_ini_file_empty() { + var_dump(parse_ini_file("")); +} + +function test_parse_ini_file_sections($ini_sections) { + file_put_contents("test.ini", $ini_sections); + var_dump(parse_ini_file("test.ini", false)); + var_dump(parse_ini_file("test.ini", true)); +} + +function test_parse_ini_file_scanner_normal($ini_string) { + file_put_contents("test.ini", $ini_string); + var_dump(parse_ini_file("test.ini", false, INI_SCANNER_NORMAL)); + var_dump(parse_ini_file("test.ini", true, INI_SCANNER_NORMAL)); +} + +function test_parse_ini_file_scanner_raw($ini_string) { + file_put_contents("test.ini", $ini_string); + var_dump(parse_ini_file("test.ini", false, INI_SCANNER_RAW)); + var_dump(parse_ini_file("test.ini", true, INI_SCANNER_RAW)); +} + +function test_parse_ini_file_scanner_typed($ini_string) { + file_put_contents("test.ini", $ini_string); + var_dump(parse_ini_file("test.ini", false, INI_SCANNER_TYPED)); + var_dump(parse_ini_file("test.ini", true, INI_SCANNER_TYPED)); +} + test_parse_ini_string_empty(); test_parse_ini_string_sections(); -test_parse_ini_string_values($ini); test_parse_ini_string_scanner_normal($ini); test_parse_ini_string_scanner_raw($ini); test_parse_ini_string_scanner_typed($ini); + +//test_parse_ini_file_empty(); +test_parse_ini_file_sections($ini_sections); +test_parse_ini_file_scanner_normal($ini); +test_parse_ini_file_scanner_raw($ini); +test_parse_ini_file_scanner_typed($ini); From 077bee1a2756c5816e8440e62daf7288c7911fc5 Mon Sep 17 00:00:00 2001 From: pmswga Date: Mon, 28 Nov 2022 15:45:28 +0300 Subject: [PATCH 3/4] Added support of empty var values --- runtime/parsing_functions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/parsing_functions.cpp b/runtime/parsing_functions.cpp index d16bf80924..d75d8badab 100644 --- a/runtime/parsing_functions.cpp +++ b/runtime/parsing_functions.cpp @@ -238,7 +238,7 @@ array f$parse_ini_string(const string &ini_string, bool process_sections, return {}; } - if (!ini_var.empty() && !ini_val.empty()) { + if (!ini_var.empty()) { switch (scanner_mode) { case INI_SCANNER_NORMAL: if (isINIBoolVal(ini_val)) { From 4e12b327730032045c38291c36194cf63303ab7a Mon Sep 17 00:00:00 2001 From: pmswga Date: Fri, 2 Dec 2022 17:05:16 +0300 Subject: [PATCH 4/4] - code style fix - removed all std utils - removed all extra functions - code refactoring --- runtime/ini.cpp | 240 +++++++++++++ runtime/ini.h | 15 + runtime/parsing_functions.cpp | 325 ------------------ runtime/parsing_functions.h | 43 --- runtime/runtime.cmake | 2 +- ...nctions-test.cpp => ini-parsing-tests.cpp} | 61 +--- tests/cpp/runtime/runtime-tests.cmake | 2 +- 7 files changed, 261 insertions(+), 427 deletions(-) create mode 100644 runtime/ini.cpp create mode 100644 runtime/ini.h delete mode 100644 runtime/parsing_functions.cpp delete mode 100644 runtime/parsing_functions.h rename tests/cpp/runtime/{parsing-functions-test.cpp => ini-parsing-tests.cpp} (78%) diff --git a/runtime/ini.cpp b/runtime/ini.cpp new file mode 100644 index 0000000000..143e20ae37 --- /dev/null +++ b/runtime/ini.cpp @@ -0,0 +1,240 @@ +#include "ini.h" + +/* + * INI parsing functions + */ + +const int64_t SINGLE_QOUTES = 0; +const int64_t DOUBLE_QUOTES = 1; +const int64_t ALL_QUOTES = 2; + +string clear_quotes(const string &str, int64_t flag) { + if (str.empty()) { + return {}; + } + + Optional clear_str; + + switch (flag) { + case SINGLE_QOUTES: + clear_str = f$preg_replace(string("/'+/"), string(""), str); + break; + case DOUBLE_QUOTES: + clear_str = f$preg_replace(string("/\"+/"), string(""), str); + break; + case ALL_QUOTES: + clear_str = f$preg_replace(string("/['|\"]+/"), string(""), str); + break; + } + + if (clear_str.is_null()) { + return string(""); + } + + return clear_str.ref(); +} + +string clear_extra_spaces(const string &str) { + if (str.empty()) { + return {}; + } + + Optional clear_str; + + clear_str = f$preg_replace(string("/ +/"), string(" "), str); + + if (clear_str.is_null()) { + return string(""); + } + + return clear_str.ref(); +} + +/* + * INI parsing functions + */ + +bool is_ini_section(const string &ini_section) { + return f$preg_match(string("/^\\[.+\\]$/"), ini_section).val(); +} + +bool is_ini_var(const string &ini_var) { + return f$preg_match(string("/^.+/"), ini_var).val(); +} + +bool is_ini_val(const string &ini_val) { + return f$preg_match(string("/(.*\n(?=[A-Z])|.*$)/"), ini_val).val(); +} + +bool is_ini_bool_val(const string &ini_val) { + return f$preg_match(string("/^(false|true|0|1|off|on)$/i"), ini_val).val(); +} + +bool is_ini_float_val(const string &ini_val) { + return f$preg_match(string(R"(/^\d+\.\d*$/)"), ini_val).val(); +} + +bool is_ini_str_val(const string &ini_val) { + return f$preg_match(string("/^.*$/i"), ini_val).val(); +} + +string get_ini_section(const string &ini_entry) { + if (ini_entry.empty()) { + return {}; + } + + return ini_entry.substr(1, ini_entry.size()-2); +} + +array split_ini_entry(const string &ini_entry) { + if (ini_entry.empty()) { + return {}; + } + + array res = f$explode(string("="), ini_entry, 2); + + if (res.size().int_size != 2) { + php_warning("Error"); + return {}; + } + + return res; +} + +bool cast_str_to_bool(const string &ini_var) { + if (ini_var.empty()) { + return false; + } + + string ini_bool_var = f$strtolower(ini_var); + + if (ini_bool_var == string("on") || ini_bool_var == string("1") || ini_bool_var == string("true")) { + return true; + } + + if (ini_bool_var == string("off") || ini_bool_var == string("0") || ini_bool_var == string("false")) { + return false; + } + + return false; +} + +array f$parse_ini_string(const string &ini_string, bool process_sections, int scanner_mode) { + if (ini_string.empty()) { + return {}; + } + + string ini_string_copy = f$trim(ini_string); + ini_string_copy = clear_extra_spaces(ini_string_copy); + + array res(array_size(0, 0, true)); + array section(array_size(0, 0, true)); + string ini_entry; + string ini_section; + + for (string::size_type i = 0; i <= ini_string_copy.size(); ++i) { + if (ini_string_copy[i] == '[') { + while (ini_string_copy[i] != ']') { + ini_entry.push_back(ini_string_copy[i]); + ++i; + } + } + + if (ini_string_copy[i] == '\"' || ini_string_copy[i] == '\'') { + ini_entry.push_back(ini_string_copy[i]); + + ++i; + while (ini_string_copy[i] != '\"' && ini_string_copy[i] != '\'') { + ini_entry.push_back(ini_string_copy[i]); + ++i; + } + } + + if (ini_string_copy[i] == ' ' || ini_string_copy[i] == '\n' || ini_string_copy[i] == '\0') { + if (is_ini_section(ini_entry)) { + if (process_sections && !ini_section.empty()) { + res.set_value(ini_section, section); + section.clear(); + } + + ini_section = get_ini_section(ini_entry); + } else if (!ini_entry.empty()){ + array ini = split_ini_entry(ini_entry); + + if (ini.size().int_size != 2) { + php_warning("Invalid ini string format %s", ini_entry.c_str()); + return {}; + } + + string ini_var = ini[0]; + string ini_val = ini[1]; + + if (!is_ini_var(ini_var) && !is_ini_val(ini_val)) { + php_warning("Invalid ini string format %s", ini_entry.c_str()); + return {}; + } + + if (!ini_var.empty()) { + switch (scanner_mode) { + case INI_SCANNER_NORMAL: + if (is_ini_bool_val(ini_val)) { + section.set_value(ini_var, cast_str_to_bool(ini_val) ? string("1") : string("")); + } else if (is_ini_str_val(ini_val)) { + section.set_value(ini_var, clear_quotes(ini_val, ALL_QUOTES)); + } + break; + case INI_SCANNER_RAW: + if (is_ini_str_val(ini_val)) { + section.set_value(ini_var, clear_quotes(ini_val, DOUBLE_QUOTES)); + } else { + section.set_value(ini_var, ini_val); + } + break; + case INI_SCANNER_TYPED: + if (ini_val.is_int()) { + section.set_value(ini_var, ini_val.to_int()); + } else if (is_ini_float_val(ini_val)) { + section.set_value(ini_var, ini_val.to_float()); + } else if (is_ini_bool_val(ini_val)) { + section.set_value(ini_var, cast_str_to_bool(ini_val)); + } else if (is_ini_str_val(ini_val)) { + section.set_value(ini_var, clear_quotes(ini_val, ALL_QUOTES)); + } + break; + } + } + } + + ini_entry = {}; + } else { + ini_entry.push_back(ini_string_copy[i]); + } + } + + if (process_sections) { + if (!ini_section.empty()) { + res.set_value(ini_section, section); + } + } else { + return section; + } + + return res; +} + + + +array f$parse_ini_file(const string &filename, bool process_sections, int scanner_mode) { + if (filename.empty()) { + php_warning("Filename cannot be empty"); + return {}; + } + + Optional ini_string = f$file_get_contents(filename); + + if (ini_string.is_null()) { + return {}; + } + + return f$parse_ini_string(ini_string.ref(), process_sections, scanner_mode); +} diff --git a/runtime/ini.h b/runtime/ini.h new file mode 100644 index 0000000000..09ee6156fc --- /dev/null +++ b/runtime/ini.h @@ -0,0 +1,15 @@ +#pragma once + +#include "runtime/kphp_core.h" +#include "runtime/string_functions.h" +#include "runtime/array_functions.h" +#include "runtime/streams.h" +#include "runtime/regexp.h" + +const int INI_SCANNER_NORMAL = 0; +const int INI_SCANNER_RAW = 1; +const int INI_SCANNER_TYPED = 2; + +array f$parse_ini_string(const string &ini_string, bool process_sections = false, int scanner_mode = 0); + +array f$parse_ini_file(const string &filename, bool process_sections = false, int scanner_mode = 0); diff --git a/runtime/parsing_functions.cpp b/runtime/parsing_functions.cpp deleted file mode 100644 index d75d8badab..0000000000 --- a/runtime/parsing_functions.cpp +++ /dev/null @@ -1,325 +0,0 @@ -#include "parsing_functions.h" - -/* - * Helper functions - */ - -string clearQuotes(const string &str) -{ - if (str.starts_with(string("\'"))) { - return clearSingleQuotes(str); - } - - if (str.starts_with(string("\""))) { - return clearDoubleQuotes(str); - } - - return str; -} - -string clearSingleQuotes(const string &str) -{ - if (str.empty()) { - return {}; - } - - if (str.starts_with(string("\'")) && str.ends_with(string("\'"))) { - return str.substr(1, str.size()-2); - } - - return str; -} - -string clearDoubleQuotes(const string &str) -{ - if (str.empty()) { - return {}; - } - - if (str.starts_with(string("\"")) && str.ends_with(string("\""))) { - return str.substr(1, str.size()-2); - } - - return str; -} - -string clearExtraSpaces(const string &str) -{ - if (str.empty()) { - return {}; - } - - string clear_str; - - for (string::size_type i = 0; i < str.size(); i++) { - if (str[i] != ' ') { - clear_str.push_back(str[i]); - } else { - clear_str.push_back(' '); - - while (str[i+1] == ' ') { - i++; - } - } - } - - return clear_str; -} - -string tolower(const string &str) -{ - if (str.empty()) { - return {}; - } - - string lower_str = {}; - - for (string::size_type i = 0; i < str.size(); i++) { - lower_str.push_back(tolower(str[i])); - } - - return lower_str; -} - -string trim(const string &str) -{ - if (str.empty()) { - return {}; - } - - size_t s = 0; - size_t e = str.size()-1; - - while (s != e && std::isspace(str[s])) { - s++; - } - - while (e != s && std::isspace(str[e])) { - e--; - } - - return str.substr(s, (e-s)+1); -} - -/* - * INI parsing functions - */ - -bool isINISection(const string &ini_section) -{ - return std::regex_match(ini_section.c_str(), std::regex("^\\[.+\\]$", std::regex::ECMAScript)); -} - -bool isINIVar(const string &ini_var) -{ - return std::regex_match(ini_var.c_str(), std::regex("^.+", std::regex::ECMAScript)); -} - -bool isINIVal(const string &ini_val) -{ - return std::regex_match(ini_val.c_str(), std::regex("(.*\n(?=[A-Z])|.*$)", std::regex::ECMAScript)); -} - -bool isINIBoolVal(const string &ini_val) -{ - return std::regex_match(ini_val.c_str(), std::regex("^(false|true|0|1|off|on)$", std::regex::ECMAScript|std::regex::icase)); -} - -bool isINIFloatVal(const string &ini_val) -{ - return std::regex_match(ini_val.c_str(), std::regex(R"(^\d+\.\d*$)", std::regex::ECMAScript|std::regex::icase)); -} - -bool isINIStrVal(const string &ini_val) -{ - return std::regex_match(ini_val.c_str(), std::regex("^.*$", std::regex::ECMAScript|std::regex::icase)); -} - -string get_ini_section(const string &ini_entry) -{ - if (ini_entry.empty()) { - return {}; - } - - return ini_entry.substr(1, ini_entry.size()-2); -} - -string get_ini_var(const string &ini_entry) -{ - string::size_type pos = ini_entry.find_first_of(string("="), 0); - - if (pos == string::npos) { - return {}; - } - - return ini_entry.substr(0, pos); - -} - -string get_ini_val(const string &ini_entry) -{ - string::size_type pos = ini_entry.find_first_of(string("="), 0); - - if (pos == string::npos) { - return {}; - } - - pos++; - - return ini_entry.substr(pos, ini_entry.size() - pos); -} - - -bool cast_str_to_bool(const string &ini_var) -{ - if (ini_var.empty()) { - return false; - } - - string ini_bool_var = tolower(ini_var); - - if (ini_bool_var == string("on") || ini_bool_var == string("1") || ini_bool_var == string("true")) { - return true; - } - - if (ini_bool_var == string("off") || ini_bool_var == string("0") || ini_bool_var == string("false")) { - return false; - } - - return false; -} - -array f$parse_ini_string(const string &ini_string, bool process_sections, int scanner_mode) -{ - if (ini_string.empty()) { - return {}; - } - - string ini_string_copy = trim(ini_string); - ini_string_copy = clearExtraSpaces(ini_string_copy); - - array res(array_size(0, 0, true)); - array section(array_size(0, 0, true)); - string ini_entry; - string ini_section; - - for (string::size_type i = 0; i <= ini_string_copy.size(); i++) { - if (ini_string_copy[i] == '[') { - while (ini_string_copy[i] != ']') { - ini_entry.push_back(ini_string_copy[i]); - i++; - } - } - - if (ini_string_copy[i] == '\"' || ini_string_copy[i] == '\'') { - ini_entry.push_back(ini_string_copy[i]); - - i++; - while (ini_string_copy[i] != '\"' && ini_string_copy[i] != '\'') { - ini_entry.push_back(ini_string_copy[i]); - i++; - } - } - - if (ini_string_copy[i] == ' ' || ini_string_copy[i] == '\n' || ini_string_copy[i] == '\0') { - if (isINISection(ini_entry)) { - if (process_sections && !ini_section.empty()) { - res.set_value(ini_section, section); - section.clear(); - } - - ini_section = get_ini_section(ini_entry); - } else { - string ini_var = get_ini_var(ini_entry); - string ini_val = get_ini_val(ini_entry); - - if (!isINIVar(ini_var) && !isINIVal(ini_val)) { - php_warning("Invalid ini string format %s", ini_entry.c_str()); - return {}; - } - - if (!ini_var.empty()) { - switch (scanner_mode) { - case INI_SCANNER_NORMAL: - if (isINIBoolVal(ini_val)) { - section.set_value(ini_var, cast_str_to_bool(ini_val) ? string("1") : string("")); - } else if (isINIStrVal(ini_val)) { - section.set_value(ini_var, clearQuotes(ini_val)); - } - - break; - case INI_SCANNER_RAW: - if (isINIStrVal(ini_val)) { - section.set_value(ini_var, clearDoubleQuotes(ini_val)); - } else { - section.set_value(ini_var, ini_val); - } - - break; - case INI_SCANNER_TYPED: - if (ini_val.is_int()) { - section.set_value(ini_var, ini_val.to_int()); - } else if (isINIFloatVal(ini_val)) { - section.set_value(ini_var, ini_val.to_float()); - } else if (isINIBoolVal(ini_val)) { - section.set_value(ini_var, cast_str_to_bool(ini_val)); - } else if (isINIStrVal(ini_val)) { - section.set_value(ini_var, clearQuotes(ini_val)); - } - - break; - } - } - } - - ini_entry = {}; - } else { - ini_entry.push_back(ini_string_copy[i]); - } - } - - if (process_sections) { - if (!ini_section.empty()) { - res.set_value(ini_section, section); - } - } else { - return section; - } - - return res; -} - - - -array f$parse_ini_file(const string &filename, bool process_sections, int scanner_mode) -{ - if (filename.empty()) { - php_warning("Filename cannot be empty"); - return {}; - } - - std::ifstream ifs(filename.c_str()); - - if (!ifs.is_open()) { - php_warning("failed to open stream: %s", filename.c_str()); - return {}; - } - - std::string str; - std::string ini_string; - - while (std::getline(ifs, str)) { - if (!str.empty()) { - ini_string.append(str); - ini_string.append(" "); - } - } - - if (!str.empty()) { - ini_string.append(str); - } - - ifs.close(); - - return f$parse_ini_string(string(ini_string.c_str()), process_sections, scanner_mode); -} diff --git a/runtime/parsing_functions.h b/runtime/parsing_functions.h deleted file mode 100644 index 1b84e7e172..0000000000 --- a/runtime/parsing_functions.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "runtime/kphp_core.h" -#include -#include -#include -#include - -/* - * Helper functions - */ - -string clearQuotes(const string &str); - -string clearSingleQuotes(const string &str); - -string clearDoubleQuotes(const string &str); - -string clearExtraSpaces(const string &str); - -string tolower(const string &str); - -string trim(const string &str); - -/* - * INI parsing functions - */ - -const int INI_SCANNER_NORMAL = 0; -const int INI_SCANNER_RAW = 1; -const int INI_SCANNER_TYPED = 2; - -string get_ini_section(const string &ini_entry); - -string get_ini_var(const string &ini_entry); - -string get_ini_val(const string &ini_entry); - -bool cast_str_to_bool(const string &ini_var); - -array f$parse_ini_string(const string &ini_string, bool process_sections = false, int scanner_mode = INI_SCANNER_NORMAL); - -array f$parse_ini_file(const string &filename, bool process_sections = false, int scanner_mode = INI_SCANNER_NORMAL); diff --git a/runtime/runtime.cmake b/runtime/runtime.cmake index 9b955099bd..4207b1df78 100644 --- a/runtime/runtime.cmake +++ b/runtime/runtime.cmake @@ -83,7 +83,7 @@ prepend(KPHP_RUNTIME_SOURCES ${BASE_DIR}/runtime/ net_events.cpp on_kphp_warning_callback.cpp openssl.cpp - parsing_functions.cpp + ini.cpp php_assert.cpp profiler.cpp regexp.cpp diff --git a/tests/cpp/runtime/parsing-functions-test.cpp b/tests/cpp/runtime/ini-parsing-tests.cpp similarity index 78% rename from tests/cpp/runtime/parsing-functions-test.cpp rename to tests/cpp/runtime/ini-parsing-tests.cpp index 16b47da71b..684eb881a9 100644 --- a/tests/cpp/runtime/parsing-functions-test.cpp +++ b/tests/cpp/runtime/ini-parsing-tests.cpp @@ -1,53 +1,7 @@ +#include "runtime/ini.h" +#include #include #include -#include -#include "runtime/parsing_functions.h" - -/* - * Tests for helper functions - */ - -TEST(parsing_functions_test, test_clear_quotes) { - ASSERT_STREQ( - string("Single quotes string").c_str(), - clearQuotes(string("\'Single quotes string\'")).c_str() - ); - ASSERT_STREQ( - string("Double quotes string").c_str(), - clearQuotes(string("\"Double quotes string\"")).c_str() - ); -} - -TEST(parsing_functions_test, test_clear_extra_spaces) { - ASSERT_STREQ( - string("This is string without extra spaces").c_str(), - clearExtraSpaces(string("This is string without extra spaces")).c_str() - ); -} - - -TEST(parsing_functions_test, test_tolower) { - ASSERT_STREQ(string("on").c_str(), tolower(string("On")).c_str()); - ASSERT_STREQ(string("off").c_str(), tolower(string("Off")).c_str()); - ASSERT_STREQ(string("true").c_str(), tolower(string("TRUE")).c_str()); - ASSERT_STREQ(string("false").c_str(), tolower(string("FALSE")).c_str()); -} - -/* - * Tests for ini parsing functions - */ - -TEST(parsing_functions_test, test_get_ini_var) { - ASSERT_STREQ(string("foo_var").c_str(), get_ini_var(string("foo_var=123")).c_str()); - ASSERT_STREQ(string("bar_var").c_str(), get_ini_var(string("bar_var=123")).c_str()); -} - -TEST(parsing_functions_test, test_get_ini_val) { - ASSERT_STREQ(string("hello world").c_str(), get_ini_val(string("str=hello world")).c_str()); - ASSERT_STREQ(string("1207").c_str(), get_ini_val(string("int=1207")).c_str()); - ASSERT_STREQ(string("3.14").c_str(), get_ini_val(string("pi=3.14")).c_str()); - ASSERT_STREQ(string("127.0.0.1").c_str(), get_ini_val(string("addr=127.0.0.1")).c_str()); -} TEST(parsing_functions_test, test_parse_ini_string_empty) { array res = f$parse_ini_string(string("")); @@ -99,7 +53,6 @@ TEST(parsing_functions_test, test_parse_ini_string_scanner_mode_normal) { ASSERT_EQ(res.get_value(string("two")).to_array().get_value(string("b")).as_string(), string("b")); } - TEST(parsing_functions_test, test_parse_ini_string_scanner_mode_raw) { array res(array_size(0, 0, true)); @@ -137,10 +90,7 @@ TEST(parsing_functions_test, test_parse_ini_string_scanner_mode_typed) { array res(array_size(0, 0, true)); // Sections false - res = f$parse_ini_string( - string("[types vars] int=1500 float=3.14242 str=\"hello world\" bool=true"), - false, - INI_SCANNER_TYPED); + res = f$parse_ini_string(string("[types vars] int=1500 float=3.14242 str=\"hello world\" bool=true"), false, INI_SCANNER_TYPED); ASSERT_EQ(4, res.size().string_size); @@ -157,10 +107,7 @@ TEST(parsing_functions_test, test_parse_ini_string_scanner_mode_typed) { ASSERT_EQ(true, res.get_value(string("bool")).to_bool()); // Sections true - res = f$parse_ini_string( - string("[types vars] int=1500 float=3.14242 str=\"hello world\" bool1=true bool2=Off"), - true, - INI_SCANNER_TYPED); + res = f$parse_ini_string(string("[types vars] int=1500 float=3.14242 str=\"hello world\" bool1=true bool2=Off"), true, INI_SCANNER_TYPED); ASSERT_TRUE(res.has_key(string("types vars"))); ASSERT_TRUE(res.get_value(string("types vars")).to_array().get_value(string("int")).is_int()); diff --git a/tests/cpp/runtime/runtime-tests.cmake b/tests/cpp/runtime/runtime-tests.cmake index 9cdb7a492e..8de07ffd72 100644 --- a/tests/cpp/runtime/runtime-tests.cmake +++ b/tests/cpp/runtime/runtime-tests.cmake @@ -20,7 +20,7 @@ prepend(RUNTIME_TESTS_SOURCES ${BASE_DIR}/tests/cpp/runtime/ string-list-test.cpp string-test.cpp zstd-test.cpp - parsing-functions-test.cpp) + ini-parsing-tests.cpp) allow_deprecated_declarations_for_apple(${BASE_DIR}/tests/cpp/runtime/inter-process-mutex-test.cpp) vk_add_unittest(runtime "${RUNTIME_LIBS};${RUNTIME_LINK_TEST_LIBS}" ${RUNTIME_TESTS_SOURCES})