summaryrefslogtreecommitdiff
path: root/modules/tools
diff options
context:
space:
mode:
authorClaudius "keldu" Holeksa <mail@keldu.de>2024-04-02 17:48:37 +0200
committerClaudius "keldu" Holeksa <mail@keldu.de>2024-04-02 17:48:37 +0200
commit57c8ff05f4b19762b6915aac83c1245a54ee7f42 (patch)
tree61bde348a73ecd69f022802277bf6dd0ef33f03b /modules/tools
parent3213bef6aa2b87cf8ea207e53ddf1b064539b46a (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.hpp86
-rw-r--r--modules/tools/examples/cli_mod.cpp73
-rw-r--r--modules/tools/examples/foo.json1
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