diff options
author | Claudius "keldu" Holeksa <mail@keldu.de> | 2024-04-02 17:48:37 +0200 |
---|---|---|
committer | Claudius "keldu" Holeksa <mail@keldu.de> | 2024-04-02 17:48:37 +0200 |
commit | 57c8ff05f4b19762b6915aac83c1245a54ee7f42 (patch) | |
tree | 61bde348a73ecd69f022802277bf6dd0ef33f03b /modules/tools | |
parent | 3213bef6aa2b87cf8ea207e53ddf1b064539b46a (diff) |
tools, codec-json: Initial whitespace is also valid json. Also fixed
reading for cli manip as well
Diffstat (limited to 'modules/tools')
-rw-r--r-- | modules/tools/c++/cli_analyzer.hpp | 86 | ||||
-rw-r--r-- | modules/tools/examples/cli_mod.cpp | 73 | ||||
-rw-r--r-- | modules/tools/examples/foo.json | 1 |
3 files changed, 143 insertions, 17 deletions
diff --git a/modules/tools/c++/cli_analyzer.hpp b/modules/tools/c++/cli_analyzer.hpp index 4aa3d6c..9a0998b 100644 --- a/modules/tools/c++/cli_analyzer.hpp +++ b/modules/tools/c++/cli_analyzer.hpp @@ -6,6 +6,7 @@ #include <forstio/codec/json/json.hpp> #include <deque> +#include <fstream> #include <iostream> namespace saw { @@ -42,8 +43,6 @@ struct cli_modifier { } json_data_str = convert_to_string(json_data.get_buffer()); - - std::cout<<json_data_str<<std::endl; } return void_t{}; @@ -66,6 +65,28 @@ struct cli_modifier { } }; +template<typename Encoding> +struct cli_traverser<schema::String, Encoding> { + using Schema = schema::String; + + template<typename Traversal> + static error_or<void> traverse(std::deque<std::string>& sch_path, data<Schema,Encoding>& enc_data, std::string& json_data){ + if(not sch_path.empty()){ + return make_error<err::invalid_state>("Schema path too long"); + } + + cli_modifier<Schema, Encoding> mod; + if constexpr (std::is_same_v<Traversal, cli_mode::read>){ + return mod.read(sch_path, enc_data, json_data); + } else if constexpr (std::is_same_v<Traversal, cli_mode::write>) { + return mod.write(sch_path, enc_data, json_data); + } else { + return make_error<err::invalid_state>("We only support cli_mode::read and cli_mode::write"); + } + } + +}; + template<typename... T, typename Encoding> struct cli_traverser<schema::Tuple<T...>, Encoding> { using Schema = schema::Tuple<T...>; @@ -146,27 +167,66 @@ struct parsed_args { }; template<typename Schema, typename Encoding> -int modify_data_on_cli(bool read_mode, const std::string_view& file_path, std::deque<std::string> sch_path, std::string& json_data){ - /** +error_or<void> modify_data_on_cli(bool read_mode, const std::string_view& file_path, std::deque<std::string> sch_path, std::string& json_data){ + /** * Read data from file */ - + std::string file_data = [&]() -> std::string { + std::fstream fstr{std::string{file_path}, fstr.binary | fstr.in}; + if(!fstr.is_open()){ + return {}; + } + std::stringstream sstr; + sstr << fstr.rdbuf(); + return sstr.str(); + }(); + if(file_data.empty()){ + return make_error<err::not_found>("File exists, but is empty."); + } + data<Schema, Encoding> enc_data{std::string_view{file_data}}; + codec<Schema, Encoding> enc_codec; - data<Schema, Encoding> enc_data; data<Schema, encode::Native> native_data; + { + auto eov = enc_codec.template decode<encode::Native>(enc_data, native_data); + if(eov.is_error()){ + return eov; + } + } if (read_mode) { - auto eov = impl::cli_traverser<Schema, encode::Native>::template traverse<impl::cli_mode::read>(sch_path, native_data, json_data); - if(eov.is_error()){ - return -1; + { + auto eov = impl::cli_traverser<Schema, encode::Native>::template traverse<impl::cli_mode::read>(sch_path, native_data, json_data); + if(eov.is_error()){ + return eov; + } } } else { - auto eov = impl::cli_traverser<Schema, encode::Native>::template traverse<impl::cli_mode::write>(sch_path, native_data, json_data); - if(eov.is_error()){ - return -1; + { + auto eov = impl::cli_traverser<Schema, encode::Native>::template traverse<impl::cli_mode::write>(sch_path, native_data, json_data); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = enc_codec.template encode<encode::Native>(native_data, enc_data); + if(eov.is_error()){ + return eov; + } + } + { + std::fstream fstr{std::string{file_path}, fstr.binary | fstr.out | fstr.trunc }; + if(!fstr.is_open()){ + return make_error<err::invalid_state>("Couldn't open file"); + } + std::stringstream sstr; + std::string enc_str = convert_to_string(enc_data.get_buffer()); + + fstr << enc_str; + fstr.close(); } } - return 0; + return void_t{}; } } diff --git a/modules/tools/examples/cli_mod.cpp b/modules/tools/examples/cli_mod.cpp index 42d4370..45114a0 100644 --- a/modules/tools/examples/cli_mod.cpp +++ b/modules/tools/examples/cli_mod.cpp @@ -8,16 +8,59 @@ namespace schema { using namespace saw::schema; +using AnalyzeInner = Struct< + Member<String, "bar">, + Member<String, "baz"> +>; + using AnalyzeTest = Struct< - Member<String, "foo"> + Member<String, "foo">, + Member<AnalyzeInner, "inner"> >; } +std::deque<std::string> split_schema_path(const std::string_view& sch_arg){ + std::deque<std::string> split; + + bool escape = false; + uint64_t last_pick = 0; + for(uint64_t i = 0; i < sch_arg.size(); ++i){ + if(escape){ + escape = false; + } else { + if(sch_arg.at(i) == '\\'){ + escape = true; + }else if(sch_arg.at(i) == '.'){ + std::string sub_str{sch_arg.substr(last_pick, i - last_pick)}; + if(sub_str.empty()){ + /// @todo return error + return {}; + } + split.emplace_back(std::move(sub_str)); + last_pick = i+1u; + } + } + } + + if( ( sch_arg.size() == last_pick ) || escape ){ + return {}; + } + + std::string sub_str{sch_arg.substr(last_pick)}; + split.emplace_back(std::move(sub_str)); + + return split; +} + int main(int argc, char** argv){ /** * Basic checking and wrapping args into an array of string_view + * 1. mode + * 2. file_path + * 3. schema_path + * 4. data if it's write */ - int min_amount_args = 2; + int min_amount_args = 3; if( argc < (min_amount_args + 1) ) { std::cerr<<"Not enough arguments"<<std::endl; @@ -47,6 +90,11 @@ int main(int argc, char** argv){ return -1; } + if( (1u+args_size) != ( static_cast<uint64_t>(argc) ) ){ + std::cerr<<"Invalid amount argument. Need "<<args_size<<" arguments. Have "<<(argc-1)<<std::endl; + return -1; + } + bool is_read_mode = [&]() -> bool { if(args_view.at(1) == "w"){ return false; @@ -55,12 +103,29 @@ int main(int argc, char** argv){ }(); std::string json_data; - std::deque<std::string> sch_path; - int rc = saw::modify_data_on_cli<schema::AnalyzeTest, saw::encode::Json>(is_read_mode, args_view.at(2), sch_path, json_data); + if ( not is_read_mode ){ + json_data = std::string{args_view.at(4)}; + } + + std::deque<std::string> sch_path = split_schema_path(args_view.at(3)); + { + auto eov = saw::modify_data_on_cli<schema::AnalyzeTest, saw::encode::Json>(is_read_mode, args_view.at(2), sch_path, json_data); + if(eov.is_error()){ + auto& err = eov.get_error(); + std::cerr<<"Modification failed: "<<err.get_category()<<" - "<<err.get_message()<<std::endl; + return err.get_id(); + } + } + + if( is_read_mode ){ + std::cout<<json_data<<std::endl; + } +/* for(int i = 0; i < argc; ++i){ std::cout<<args_view.at(i)<<std::endl; } +*/ return 0; } diff --git a/modules/tools/examples/foo.json b/modules/tools/examples/foo.json new file mode 100644 index 0000000..beeba89 --- /dev/null +++ b/modules/tools/examples/foo.json @@ -0,0 +1 @@ +{"foo":"yohohohohoho","inner":{"bar":"written3","baz":"brooo"}}
\ No newline at end of file |