diff options
-rw-r--r-- | default.nix | 4 | ||||
-rw-r--r-- | modules/codec-json/c++/json.tmpl.hpp | 4 | ||||
-rw-r--r-- | modules/codec/.nix/derivation.nix | 10 | ||||
-rw-r--r-- | modules/codec/SConstruct | 10 | ||||
-rw-r--r-- | modules/codec/c++/csv.hpp | 44 | ||||
-rw-r--r-- | modules/codec/examples/SConscript | 33 | ||||
-rw-r--r-- | modules/codec/examples/csv_encode.cpp | 62 | ||||
-rw-r--r-- | modules/codec/tests/base64.cpp | 2 |
8 files changed, 164 insertions, 5 deletions
diff --git a/default.nix b/default.nix index f6d5818..14804f4 100644 --- a/default.nix +++ b/default.nix @@ -36,7 +36,9 @@ in rec { inherit version; inherit forstio; inherit stdenv; - inherit clang-tools; + inherit clang-tools; + + build_examples = "true"; }; codec-json = pkgs.callPackage modules/codec-json/.nix/derivation.nix { diff --git a/modules/codec-json/c++/json.tmpl.hpp b/modules/codec-json/c++/json.tmpl.hpp index 3e3a74b..fd789a4 100644 --- a/modules/codec-json/c++/json.tmpl.hpp +++ b/modules/codec-json/c++/json.tmpl.hpp @@ -813,11 +813,11 @@ struct json_decode<schema::Array<T,D>, ToDecode> { buff.read_advance(1); break; } else { - return make_error<err::invalid_state>(); + return make_error<err::invalid_state>("Expected either a ',' or a ']'."); } json_helper::skip_whitespace(buff); if ( buff.read_composite_length() == 0 ){ - return make_error<err::buffer_exhausted>(); + return make_error<err::buffer_exhausted>("Buffer empty before decoding was finished."); } } if(log_dim){ diff --git a/modules/codec/.nix/derivation.nix b/modules/codec/.nix/derivation.nix index 7f7811a..288db6a 100644 --- a/modules/codec/.nix/derivation.nix +++ b/modules/codec/.nix/derivation.nix @@ -4,6 +4,8 @@ , clang-tools , version , forstio + +, build_examples ? "false" }: let @@ -24,6 +26,14 @@ in stdenv.mkDerivation { scons clang-tools ]; + + buildPhase = '' + scons build_examples=${build_examples} + ''; + + installPhase = '' + scons prefix=$out build_examples=${build_examples} install + ''; doCheck = true; checkPhase = '' diff --git a/modules/codec/SConstruct b/modules/codec/SConstruct index 3773a17..6bc28e3 100644 --- a/modules/codec/SConstruct +++ b/modules/codec/SConstruct @@ -41,7 +41,14 @@ env_vars.Add('prefix', help='Installation target location of build results and headers', default='/usr/local/', validator=isAbsolutePath -) +); + +env_vars.Add( + BoolVariable('build_examples', + help='Build examples', + default=False + ) +); env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], CXX=['c++'], @@ -64,6 +71,7 @@ env.targets = []; Export('env') SConscript('c++/SConscript') SConscript('tests/SConscript') +SConscript('examples/SConscript') env.Alias('cdb', env.cdb); env.Alias('all', [env.targets]); diff --git a/modules/codec/c++/csv.hpp b/modules/codec/c++/csv.hpp index 2d11bff..82010d7 100644 --- a/modules/codec/c++/csv.hpp +++ b/modules/codec/c++/csv.hpp @@ -12,6 +12,23 @@ struct Csv {}; } namespace impl { +struct csv_helper { + static bool is_whitespace(int8_t ch){ + /** + * @TODO supply relevant control characters for checks. + * Newlines are whitespace technically, but also control characters in CSV. + * Contrary to JSON for example. + */ + return ch == '\t' || ch == ' '; + } + + static void skip_whitespace(buffer_view& buff){ + while(buff.read_composite_length() > 0 && csv_helper::is_whitespace(buff.read())){ + buff.read_advance(1u); + } + } +}; + template<typename Schema, typename FromDecode> struct csv_encode { static_assert(always_false<Schema, FromDecode>, "Case not supported"); @@ -176,6 +193,33 @@ struct csv_encode<schema::Primitive<T,N>, FromDecode> { return make_void(); } }; + +template<typename Schema, typename FromDecode> +struct csv_decode { + static_assert(always_false<Schema, FromDecode>, "Case not supported"); +}; + +template<typename T, size_t Dim, typename FromDecode> +struct csv_decode<schema::Array<T,Dim>, FromDecode> { + static_assert(Dim == 1, "Only one dimension is allowed."); + static_assert(!is_array<T>::value, "Array of an array is not allowed."); + static_assert(is_tuple<T>::value || is_struct<T>::value, "Only struct or tuples allowed inside a csv array"); + + using Schema = schema::Array<T,Dim>; + + static error_or<void> decode(data<Schema, encode::Csv>& from, data<Schema, FromDecode>& to){ + buffer_view view{from.get_buffer()}; + if constexpr (is_struct<T>::value) { + auto eov = csv_decode<T, FromDecode>::check_header(view); + if(eov.is_error()){ + return eov; + } + } + + uint64_t len{}; + return make_error<err::not_implemented>(); + } +}; } template<typename Schema> diff --git a/modules/codec/examples/SConscript b/modules/codec/examples/SConscript new file mode 100644 index 0000000..e06b9fb --- /dev/null +++ b/modules/codec/examples/SConscript @@ -0,0 +1,33 @@ +#!/bin/false + +import os +import os.path +import glob + + +Import('env') + +dir_path = Dir('.').abspath + +# Environment for base library +examples_env = env.Clone(); + +examples_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) +examples_env.headers = sorted(glob.glob(dir_path + "/*.hpp")) + +env.sources += examples_env.sources; +env.headers += examples_env.headers; + +examples_objects = []; +examples_env.add_source_files(examples_objects, ['csv_encode.cpp'], shared=False); + +examples_env.examples_basic = examples_env.Program('#bin/csv_encode_example', [env.library_static, examples_objects]); + +# Set Alias +env.examples = [examples_env.examples_basic]; +env.Alias('examples', env.examples); + +if env["build_examples"]: + env.targets += ['examples']; + env.Install('$prefix/bin/', env.examples); +#endif diff --git a/modules/codec/examples/csv_encode.cpp b/modules/codec/examples/csv_encode.cpp new file mode 100644 index 0000000..2761ea3 --- /dev/null +++ b/modules/codec/examples/csv_encode.cpp @@ -0,0 +1,62 @@ +#include "../c++/csv.hpp" + +#include <iostream> + +namespace sch { +using namespace saw::schema; + +using TestStruct = Struct< + Member<UInt32, "ufoo">, + Member<Float64, "double">, + Member<String, "brah"> +>; +} + +int main(){ + using namespace saw; + + using Schema = sch::Array<sch::TestStruct>; + + data<Schema> dat{4u}; + codec<Schema, encode::Csv> csv_codec; + + { + auto& row = dat.at(0u); + row.template get<"ufoo">().set(50u); + row.template get<"double">().set(50.0); + row.template get<"brah">().set("foo"); + } + { + auto& row = dat.at(1u); + row.template get<"ufoo">().set(40u); + row.template get<"double">().set(42.0); + row.template get<"brah">().set("bleh"); + } + { + auto& row = dat.at(2u); + row.template get<"ufoo">().set(42u); + row.template get<"double">().set(40.0); + row.template get<"brah">().set("arg"); + } + { + auto& row = dat.at(3u); + row.template get<"ufoo">().set(10u); + row.template get<"double">().set(20.1); + row.template get<"brah">().set("ben and anna"); + } + + data<Schema, encode::Csv> csv_dat; + + auto eov = csv_codec.encode(dat, csv_dat); + if(eov.is_error()){ + auto& err = eov.get_error(); + std::cerr<<"Error: "<<err.get_category()<<" - "<<err.get_message()<<std::endl; + return -1; + } + + auto str = convert_to_string(csv_dat.get_buffer()); + std::cout<<str; + std::cout.flush(); + + return 0; +} diff --git a/modules/codec/tests/base64.cpp b/modules/codec/tests/base64.cpp index b52a6bf..43564f8 100644 --- a/modules/codec/tests/base64.cpp +++ b/modules/codec/tests/base64.cpp @@ -6,7 +6,7 @@ namespace { namespace sch { using namespace saw::schema; } -SAW_TEST("Argon2i Hash String"){ +SAW_TEST("Base64 String"){ using namespace saw; data<sch::String> inp_data{"Hello, World!"}; |