fix json pretty print, added value::clear

This commit is contained in:
Daniel Larimer 2013-01-27 15:28:54 -05:00
parent 5c21d1d45c
commit c3659eedfc
6 changed files with 147 additions and 21 deletions

View file

@ -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"; } };
}

View file

@ -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

View file

@ -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) ) ); }

View file

@ -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);
}
}

View file

@ -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 ) {

View file

@ -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));