Skip to content

Instantly share code, notes, and snippets.

@usagi
Created January 31, 2017 10:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save usagi/cf8c73d8ecdca64bc4573c9d3d16a951 to your computer and use it in GitHub Desktop.
Save usagi/cf8c73d8ecdca64bc4573c9d3d16a951 to your computer and use it in GitHub Desktop.
文字列のパスから picojson::object による階層構造に picojson::value を放り込む例 ref: http://qiita.com/usagi/items/2564e7f660c83793cfc3
/// @brief object_type に対しドット区切りのパスで object_type の階層を必要なら作成しながら辿り末梢の要素の参照を返す
static inline decltype( auto ) make_object_path
( object_type& root_object
, const std::string& dot_separated_path
)
{
// (1) ドット区切りのパス文字列を階層ごとに分離する機能
std::vector< std::string > path;
boost::split( path, dot_separated_path, boost::is_any_of( "." ) );
// (2) 分離されたパスの階層構造を組み立てる機能
auto peripheral = &root_object;
// 終端のパスを取り出しておく
const auto last_path = std::move( path.back() );
path.pop_back();
// 終端の手前のパスまで object を掘る
for ( const auto& path_part : path )
{
const auto i = peripheral->find( path_part );
// note: 末梢に必要なパスが無いか object ではない場合にのみ object を作成
if ( i == peripheral->cend() or not i->second.is< object_type >() )
(*peripheral)[ path_part ] = value_type( object_type() );
// note: root_object から末梢側へ1段階辿る
peripheral = &(*peripheral)[ path_part ].get< object_type >();
}
// 終端の value& を返す
return (*peripheral)[ last_path ];
}
}
/// @brief element_value が rvalue の場合向けの set_value
static inline auto set_value
( object_type& root_object
, const std::string& dot_separated_path
, value_type&& element_value
)
{ detail::make_object_path( root_object, dot_separated_path ) = std::move( element_value ); }
/// @brief object_type に対しドット区切りのパスで object_type の階層を辿り value_type を放り込む
static inline auto set_value
( object_type& root_object
, const std::string& dot_separated_path
, const value_type& element_value
)
{ detail::make_object_path( root_object, dot_separated_path ) = element_value; }
/// @brief value_type へ可換な T 型の値に対応する set_value の syntax sugar ラッパー
template < typename T = null_type >
static inline auto set_value( object_type& root_object, const std::string& dot_separated_path, const T& element_value = T() )
{ set_value( root_object, dot_separated_path, value_type( static_cast< double >( element_value ) ) ); }
template < >
inline auto set_value< null_type >( object_type& root_object, const std::string& dot_separated_path, const null_type& )
{ set_value( root_object, dot_separated_path, value_type() ); }
template < >
inline auto set_value< array_type >( object_type& root_object, const std::string& dot_separated_path, const array_type& element_value )
{ set_value( root_object, dot_separated_path, value_type( element_value ) ); }
template < >
inline auto set_value< object_type >( object_type& root_object, const std::string& dot_separated_path, const object_type& element_value )
{ set_value( root_object, dot_separated_path, value_type( element_value ) ); }
template < >
inline auto set_value< value_type >( object_type& root_object, const std::string& dot_separated_path, const value_type& element_value )
{ set_value( root_object, dot_separated_path, element_value ); }
template < >
inline auto set_value< std::string >( object_type& root_object, const std::string& dot_separated_path, const std::string& element_value )
{ set_value( root_object, dot_separated_path, value_type( element_value ) ); }
static inline auto set_value( object_type& root_object, const std::string& dot_separated_path, const char* element_value )
{ set_value( root_object, dot_separated_path, value_type( element_value ) ); }
static inline auto set_value( object_type& root_object, const std::string& dot_separated_path, const bool element_value )
{ set_value( root_object, dot_separated_path, value_type( element_value ) ); }
/// root_value が object_type を内包する value_type の場合に対応する set_value の syntax sugar ラッパー
template < typename T = null_type >
static inline auto set_value( value_type& root_value, const std::string& dot_separated_path, T&& element_value = T() )
{ set_value( root_value.get< object_type >(), dot_separated_path, std::move( element_value ) ); }
#include <usagi/json/picojson/set_value.hxx>
#include <iostream>
auto main() -> int
{
using namespace std::literals::string_literals;
using namespace usagi::json::picojson;
object_type a, b;
a["hoge"] = value_type( 1.0 );
a["fuga"] = value_type( 2.0 );
value_type va( a );
set_value( va, "aa.bb.xx", 1.23 );
set_value( va, "aa.bb.yy", 1.23f );
set_value( va, "aa.bb.zz", 123ull );
set_value( va, "aa.bb.ww", true );
set_value( va, "aa.cc.ss", "xyz123" );
set_value( va, "aa.cc.tt", "xyz456"s );
set_value( va, "uu.vv" );
set_value( va, "array", array_type() );
set_value( va, "object", object_type() );
std::cout << va;
}
{"aa":{"bb":{"ww":true,"xx":1.23,"yy":1.2300000190734863,"zz":123},"cc":{"ss":"xyz123","tt":"xyz456"}},"array":[],"fuga":2,"hoge":1,"object":{},"uu":{"vv":null}}
{
"aa": {
"bb": {
"ww": true,
"xx": 1.23,
"yy": 1.2300000190734863,
"zz": 123
},
"cc": {
"ss": "xyz123",
"tt": "xyz456"
}
},
"array": [],
"fuga": 2,
"hoge": 1,
"object": {},
"uu": {
"vv": null
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment