fix json pretty print, added value::clear
This commit is contained in:
parent
5c21d1d45c
commit
c3659eedfc
6 changed files with 147 additions and 21 deletions
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <fc/string.hpp>
|
||||
#include <fc/typename.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
|
||||
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<path> { static const char* name() { return "path"; } };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<typename T>
|
||||
string to_pretty_string( const T& o ) {
|
||||
return json::to_pretty_string(value(o));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T from_string( const string& s ) {
|
||||
|
|
@ -43,6 +48,7 @@ namespace fc {
|
|||
T from_file( const fc::path& s ) {
|
||||
return value_cast<T>( fc::json::from_file(s) );
|
||||
}
|
||||
|
||||
} // namespace json
|
||||
} // fc
|
||||
|
||||
|
|
|
|||
|
|
@ -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<typename S, typename T>
|
||||
value& set( S&& key, T&& v ) { return set( fc::forward<S>(key), fc::value( fc::forward<T>(v) ) ); }
|
||||
|
|
|
|||
|
|
@ -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<T>( *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<T>::name()) );
|
||||
|
|
@ -233,7 +234,9 @@ namespace fc {
|
|||
template<typename Member>
|
||||
void operator()( Member& m ) {
|
||||
try {
|
||||
m = value_cast<Member>(_val[idx]);
|
||||
//m = value_cast<Member>(_val[idx]);
|
||||
unpack( _val[idx], m );
|
||||
// m = value_cast<Member>(_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<typename T>
|
||||
T value::cast()const {
|
||||
return value_cast<T>(*this);
|
||||
T tmp;
|
||||
unpack(*this,tmp);
|
||||
return tmp;
|
||||
// return unpackvalue_cast<T>(*this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
128
src/json.cpp
128
src/json.cpp
|
|
@ -1,8 +1,8 @@
|
|||
#include <fc/filesystem.hpp>
|
||||
#include <fc/json.hpp>
|
||||
#include <fc/hex.hpp>
|
||||
#include <fc/exception.hpp>
|
||||
#include <fc/sstream.hpp>
|
||||
#include <fc/filesystem.hpp>
|
||||
#include <fc/interprocess/file_mapping.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
#include <map>
|
||||
|
|
@ -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[i];
|
||||
break;
|
||||
case ':':
|
||||
if( !quote ) {
|
||||
ss<<": ";
|
||||
} else {
|
||||
ss<<':';
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
if( first ) {
|
||||
ss<<'\n';
|
||||
for( int i = 0; i < level*indent; ++i ) ss<<' ';
|
||||
first = false;
|
||||
}
|
||||
if( !escape ) {
|
||||
quote = !quote;
|
||||
}
|
||||
escape = false;
|
||||
ss<<'"';
|
||||
break;
|
||||
case '{':
|
||||
case '[':
|
||||
ss<<v[i];
|
||||
if( !quote ) {
|
||||
++level;
|
||||
first = true;
|
||||
}else {
|
||||
escape = false;
|
||||
}
|
||||
break;
|
||||
case '}':
|
||||
case ']':
|
||||
if( !quote ) {
|
||||
if( v[i-1] != '[' && v[i-1] != '{' ) {
|
||||
ss<<'\n';
|
||||
}
|
||||
--level;
|
||||
if( !first ) {
|
||||
for( int i = 0; i < level*indent; ++i ) ss<<' ';
|
||||
}
|
||||
ss<<v[i];
|
||||
break;
|
||||
} else {
|
||||
escape = false;
|
||||
ss<<v[i];
|
||||
}
|
||||
break;
|
||||
case ',':
|
||||
if( !quote ) {
|
||||
ss<<',';
|
||||
first = true;
|
||||
} else {
|
||||
escape = false;
|
||||
ss<<',';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if( first ) {
|
||||
ss<<'\n';
|
||||
for( int i = 0; i < level*indent; ++i ) ss<<' ';
|
||||
first = false;
|
||||
}
|
||||
ss << v[i];
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
fc::string pretty_print( fc::vector<char>&& v, uint8_t indent ) {
|
||||
int level = 0;
|
||||
fc::stringstream ss;
|
||||
|
|
@ -919,6 +1001,10 @@ fc::string pretty_print( fc::vector<char>&& 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<char>&& 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<size_t>(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<const char*>(mr.get_address());
|
||||
const char* end = pos + fsize;
|
||||
|
||||
// TODO: implement a const version of to_value
|
||||
fc::vector<char> 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<size_t>(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<const char*>(mr.get_address());
|
||||
const char* end = pos + fsize;
|
||||
|
||||
// TODO: implement a const version of to_value
|
||||
fc::vector<char> 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 ) {
|
||||
|
|
|
|||
|
|
@ -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<value::object>* o = dynamic_cast<detail::value_holder_impl<value::object>*>(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<value::object>* o = dynamic_cast<detail::value_holder_impl<value::object>*>(gh(holder));
|
||||
|
|
|
|||
Loading…
Reference in a new issue