diff --git a/doc/All-Config-Functions.md b/doc/All-Config-Functions.md index 0ab1f2b..7a34bd0 100644 --- a/doc/All-Config-Functions.md +++ b/doc/All-Config-Functions.md @@ -5,6 +5,7 @@ * [env](#env) * [jaxn](#jaxn) * [parse](#parse) + * [print](#print) * [read](#read) * [shell](#shell) * [split](#split) @@ -129,6 +130,36 @@ Further, the `parse` function can **only** be used on "top-level", not inside of For example `foo = (parse (default ...))` is allowed, but `foo = (default (parse ...) ...)` is not. + +## print + +The `print` function takes a part of the config and turns it back into a JAXN string (which is the same as a JSON string as long as the JAXN extensions to the JSON data model, binary data and non-finite floating point numbers, are **not** used). + +#### Example taoCONFIG Input File + +``` +(temporary foo) + +foo +{ + b1 = true + b2 = "Hello, Test!" + b3 = [ $00, $deadbeef ] + b4 = 42 +} + +str = (print (foo)) +``` + +#### Resulting JAXN Config Data + +```javascript +{ + str: "{b1:true,b2:\"Hello, Test!\",b3:[$00,$DEADBEEF],b4:42}" +} +``` + + ## read The `read` function returns the contents of a file as binary data. diff --git a/include/tao/config/internal/config_parser.hpp b/include/tao/config/internal/config_parser.hpp index 327c6f6..d156604 100644 --- a/include/tao/config/internal/config_parser.hpp +++ b/include/tao/config/internal/config_parser.hpp @@ -32,6 +32,7 @@ namespace tao::config::internal { "env", wrap( env_function ) }, { "env?", wrap( env_if_function ) }, { "jaxn", wrap( jaxn_function ) }, + { "print", wrap( print_function ) }, { "read", wrap( read_function ) }, { "shell", wrap( shell_function ) }, { "split", wrap( split_function ) }, diff --git a/include/tao/config/internal/function_implementations.hpp b/include/tao/config/internal/function_implementations.hpp index 0f44797..ddde923 100644 --- a/include/tao/config/internal/function_implementations.hpp +++ b/include/tao/config/internal/function_implementations.hpp @@ -15,8 +15,12 @@ #include "jaxn_to_entry.hpp" #include "json.hpp" #include "pegtl.hpp" +#include "phase5_repack.hpp" +#include "statistics.hpp" #include "system_utility.hpp" +#include "../key.hpp" + namespace tao::config::internal { [[nodiscard]] inline binary_t binary_function( const pegtl::position& p, const std::string& s ) @@ -25,11 +29,6 @@ namespace tao::config::internal return binary_t( std::vector< std::byte >( d, d + s.size() ), p ); } - // [[nodiscard]] inline json_t cbor_function( const std::vector< std::byte >& bv ) - // { - // return json::cbor::basic_from_binary< json_traits >( bv ); // TODO: Positions. - // } - [[nodiscard]] inline bool default_function( entry& e ) { array& a = e.get_array(); @@ -91,16 +90,6 @@ namespace tao::config::internal return std::move( consumer.value ).value(); } - // [[nodiscard]] inline json_t json_function( const std::string& s ) - // { - // return json::basic_from_string< json_traits >( s ); // TODO: Positions. - // } - - // [[nodiscard]] inline json_t msgpack_function( const std::vector< std::byte >& bv ) - // { - // return json::msgpack::basic_from_binary< json_traits >( bv ); // TODO: Positions. - // } - [[nodiscard]] inline binary_t read_function( const pegtl::position& p, const std::string& filename ) { const std::string d = read_file_throws( filename ); @@ -108,6 +97,23 @@ namespace tao::config::internal return binary_t( std::vector< std::byte >( x, x + d.size() ), p ); } + [[nodiscard]] inline bool print_function( entry& e ) + { + array& a = e.get_array(); + if( a.array.size() != 1 ) { + throw pegtl::parse_error( "print function requires exactly one argument", a.position ); + } + concat& c = a.array.front(); + if( statistics( c ).is_primitive() ) { + const tao::json::value v = phase5_repack< json::traits >( c ); // TODO: Optimise away this intermediate data structure. + std::string s = json::jaxn::to_string( v ); + pegtl::position p = c.position; + e = entry( string_t( std::move( s ), std::move( p ) ) ); + return true; + } + return false; + } + [[nodiscard]] inline string_t shell_function( const pegtl::position& p, [[maybe_unused]] const std::string& script ) { #if defined( _MSC_VER ) @@ -152,11 +158,6 @@ namespace tao::config::internal return string_t( s, p ); } - // [[nodiscard]] inline json_t ubjson_function( const std::vector< std::byte >& bv ) - // { - // return json::ubjson::basic_from_binary< json_traits >( bv ); // TODO: Positions. - // } - } // namespace tao::config::internal #endif diff --git a/include/tao/config/internal/function_traits.hpp b/include/tao/config/internal/function_traits.hpp index 96ef9b1..ca8a3b2 100644 --- a/include/tao/config/internal/function_traits.hpp +++ b/include/tao/config/internal/function_traits.hpp @@ -92,20 +92,6 @@ namespace tao::config::internal } }; - // template<> - // struct function_traits< std::vector< std::byte > > - // { - // [[nodiscard]] static std::vector< std::byte > get( array& f, const std::size_t i ) - // { - // const entry& e = function_traits_entry( f, i ); - - // if( e.is_binary() ) { - // return e.get_binary(); - // } - // throw pegtl::parse_error( "invalid type for binary argument", e.get_position() ); - // } - // }; - } // namespace tao::config::internal #endif diff --git a/include/tao/config/internal/statistics.hpp b/include/tao/config/internal/statistics.hpp index a3df4eb..74d1b6b 100644 --- a/include/tao/config/internal/statistics.hpp +++ b/include/tao/config/internal/statistics.hpp @@ -28,6 +28,11 @@ namespace tao::config::internal count( c ); } + explicit statistics( const array& a ) + { + count( a ); + } + void count( const entry& e ) { switch( e.kind() ) { @@ -102,7 +107,7 @@ namespace tao::config::internal [[nodiscard]] bool is_primitive() const noexcept { - return ( m_functions == 0 ) && ( m_variables == 0 ) && ( m_additions == 0 ) && ( m_asterisks == 0 ) && ( m_references == 0 ); + return ( m_functions == 0 ) && ( m_additions == 0 ) && ( m_asterisks == 0 ) && ( m_references == 0 ); } private: @@ -111,7 +116,6 @@ namespace tao::config::internal std::size_t m_arrays = 0; std::size_t m_objects = 0; std::size_t m_functions = 0; - std::size_t m_variables = 0; std::size_t m_additions = 0; std::size_t m_asterisks = 0; std::size_t m_references = 0; diff --git a/tests/serialise.jaxn b/tests/serialise.jaxn new file mode 100644 index 0000000..155731b --- /dev/null +++ b/tests/serialise.jaxn @@ -0,0 +1,3 @@ +{ + str: "{b1:true,b2:\"Hello, Test!\",b3:[$00,$DEADBEEF],b4:42}" +} diff --git a/tests/serialise.success b/tests/serialise.success new file mode 100644 index 0000000..2182d66 --- /dev/null +++ b/tests/serialise.success @@ -0,0 +1,11 @@ +(temporary foo) + +foo +{ + b1 = true + b2 = "Hello, Test!" + b3 = [ $00, $deadbeef ] + b4 = 42 +} + +str = (print (foo))