From c3659eedfcabca95939e57f7caa8f945f68eda9c Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Sun, 27 Jan 2013 15:28:54 -0500 Subject: [PATCH] fix json pretty print, added value::clear --- include/fc/filesystem.hpp | 3 + include/fc/json.hpp | 6 ++ include/fc/value.hpp | 1 + include/fc/value_cast.hpp | 12 +++- src/json.cpp | 128 ++++++++++++++++++++++++++++++++------ src/value.cpp | 18 ++++++ 6 files changed, 147 insertions(+), 21 deletions(-) diff --git a/include/fc/filesystem.hpp b/include/fc/filesystem.hpp index 76e168c..0174b0e 100644 --- a/include/fc/filesystem.hpp +++ b/include/fc/filesystem.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include namespace boost { @@ -98,5 +99,7 @@ namespace fc { class value; void pack( fc::value& , const fc::path& ); void unpack( const fc::value& , fc::path& ); + + template<> struct get_typename { static const char* name() { return "path"; } }; } diff --git a/include/fc/json.hpp b/include/fc/json.hpp index 1c8aa41..ccfc129 100644 --- a/include/fc/json.hpp +++ b/include/fc/json.hpp @@ -11,6 +11,7 @@ namespace fc { namespace json { string to_string( const value& o ); + string to_pretty_string( const value& v ); value from_string( const string& s ); @@ -32,6 +33,10 @@ namespace fc { string to_string( const T& o ) { return json::to_string(value(o)); } + template + string to_pretty_string( const T& o ) { + return json::to_pretty_string(value(o)); + } template T from_string( const string& s ) { @@ -43,6 +48,7 @@ namespace fc { T from_file( const fc::path& s ) { return value_cast( fc::json::from_file(s) ); } + } // namespace json } // fc diff --git a/include/fc/value.hpp b/include/fc/value.hpp index d94c2ed..3061778 100644 --- a/include/fc/value.hpp +++ b/include/fc/value.hpp @@ -147,6 +147,7 @@ namespace fc { /* sets the subkey key with v and return *this */ value& set( const char* key, fc::value v ); value& set( const fc::string& key, fc::value v ); + value& clear( const fc::string& key ); template value& set( S&& key, T&& v ) { return set( fc::forward(key), fc::value( fc::forward(v) ) ); } diff --git a/include/fc/value_cast.hpp b/include/fc/value_cast.hpp index 6c4968c..ce7afa5 100644 --- a/include/fc/value_cast.hpp +++ b/include/fc/value_cast.hpp @@ -181,7 +181,8 @@ namespace fc { int idx = 0; for( auto i = a.fields.begin(); i != a.fields.end(); ++i ) { try { - m_out.push_back( value_cast( *i ) ); + m_out.push_back(T()); + unpack( *i, m_out.back() ); } catch( fc::error_report& er ) { throw FC_REPORT_PUSH( er, "Error parsing array index ${index} to ${type}", fc::value().set("index", idx).set("type",fc::get_typename::name()) ); @@ -233,7 +234,9 @@ namespace fc { template void operator()( Member& m ) { try { - m = value_cast(_val[idx]); + //m = value_cast(_val[idx]); + unpack( _val[idx], m ); + // m = value_cast(_val[idx]); } catch ( fc::error_report& er ) { throw FC_REPORT_PUSH( er, "Error parsing tuple element ${index}", fc::value().set("index",idx) ); } @@ -329,6 +332,9 @@ namespace fc { } template T value::cast()const { - return value_cast(*this); + T tmp; + unpack(*this,tmp); + return tmp; +// return unpackvalue_cast(*this); } } diff --git a/src/json.cpp b/src/json.cpp index 77bb006..a6b93a8 100644 --- a/src/json.cpp +++ b/src/json.cpp @@ -1,8 +1,8 @@ +#include #include #include #include #include -#include #include #include #include @@ -785,6 +785,88 @@ fc::value to_value( char* start, char* end, error_collector& ec ) { } namespace fc { namespace json { +fc::string pretty_print( const fc::string& v, uint8_t indent ) { + int level = 0; + fc::stringstream ss; + bool first = false; + bool quote = false; + bool escape = false; + for( uint32_t i = 0; i < v.size(); ++i ) { + switch( v[i] ) { + case '\\': + if( !escape ) { + if( quote ) + escape = true; + } else { escape = false; } + ss<&& v, uint8_t indent ) { int level = 0; fc::stringstream ss; @@ -919,6 +1001,10 @@ fc::string pretty_print( fc::vector&& v, uint8_t indent ) { return ss.str(); } + fc::string to_pretty_string( const fc::value& v ) { + return pretty_print( to_string(v), 4 ); + } + value from_file( const fc::path& local_path ) { if( !exists(local_path) ) { FC_THROW_REPORT( "Source file ${filename} does not exist", value().set("filename",local_path.string()) ); @@ -927,23 +1013,29 @@ fc::string pretty_print( fc::vector&& v, uint8_t indent ) { FC_THROW_REPORT( "Source path ${path} is a directory; a file was expected", value().set("path",local_path.string()) ); } - - // memory map the file - size_t fsize = static_cast(file_size(local_path)); - if( fsize == 0 ) { return value(); } - file_mapping fmap( local_path.string().c_str(), read_only ); - - - mapped_region mr( fmap, fc::read_only, 0, fsize ); - - const char* pos = reinterpret_cast(mr.get_address()); - const char* end = pos + fsize; - - // TODO: implement a const version of to_value - fc::vector tmp(pos,end); - - error_collector ec; - return to_value(tmp.data(), tmp.data()+fsize,ec); + try { + // memory map the file + size_t fsize = static_cast(file_size(local_path)); + if( fsize == 0 ) { return value(); } + file_mapping fmap( local_path.string().c_str(), read_only ); + + + mapped_region mr( fmap, fc::read_only, 0, fsize ); + + const char* pos = reinterpret_cast(mr.get_address()); + const char* end = pos + fsize; + + // TODO: implement a const version of to_value + fc::vector tmp(pos,end); + + error_collector ec; + return to_value(tmp.data(), tmp.data()+fsize,ec); + } catch ( ... ) { + FC_THROW_REPORT( "Error loading JSON object from file '${path}'", + fc::value().set( "file", local_path ) + .set( "exception", fc::except_str() ) + ); + } } value from_string( const fc::string& s ) { diff --git a/src/value.cpp b/src/value.cpp index a12db0f..183cffc 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -333,6 +333,24 @@ value::object::const_iterator value::end()const { return value::object::const_iterator(); //return nullptr; } +/** + * If this value is an object, remove key from the object + * + * @return *this; + */ +value& value::clear( const fc::string& key ) { + if( strcmp(gh(holder)->type(), "object") == 0) { + detail::value_holder_impl* o = dynamic_cast*>(gh(holder)); + for( auto i = o->val.fields.begin(); + i != o->val.fields.end(); ++i ) { + if( strcmp( i->key.c_str(), key.c_str() ) == 0 ) { + o->val.fields.erase(i); + return *this; + } + } + } + return *this; +} value& value::operator[]( const char* key ) { if( strcmp(gh(holder)->type(), "object") == 0) { detail::value_holder_impl* o = dynamic_cast*>(gh(holder));