66 #define _GLIBCXX_USE_NOEXCEPT 69 #define svar GSLAM::Svar::instance() 70 #define SVAR_VERSION 0x000100 // 0.1.0 71 #define EXPORT_SVAR_INSTANCE extern "C" SVAR_EXPORT GSLAM::Svar* svarInstance(){return &GSLAM::Svar::instance();} 72 #define REGISTER_SVAR_MODULE(MODULE_NAME) \ 73 class SVAR_MODULE_##MODULE_NAME{\ 74 public: SVAR_MODULE_##MODULE_NAME();\ 75 }SVAR_MODULE_##MODULE_NAME##instance;\ 76 SVAR_MODULE_##MODULE_NAME::SVAR_MODULE_##MODULE_NAME() 78 # if defined(WIN32) || defined(_WIN32) 79 # define SVAR_EXPORT __declspec(dllexport) 81 # define SVAR_EXPORT __attribute__ ((visibility("default"))) 86 #ifndef DOXYGEN_IGNORE_INTERNAL 88 template <
bool B,
typename T =
void>
using enable_if_t =
typename std::enable_if<B, T>::type;
89 template <
bool B,
typename T,
typename F>
using conditional_t =
typename std::conditional<B, T, F>::type;
90 template <
typename T>
using remove_cv_t =
typename std::remove_cv<T>::type;
91 template <
typename T>
using remove_reference_t =
typename std::remove_reference<T>::type;
95 template <
typename T>
struct remove_class { };
96 template <
typename C,
typename R,
typename... A>
struct remove_class<R (C::*)(A...)> {
typedef R type(A...); };
97 template <
typename C,
typename R,
typename... A>
struct remove_class<R (C::*)(A...) const> {
typedef R type(A...); };
99 template <
typename F>
struct strip_function_object {
100 using type =
typename remove_class<decltype(&F::operator())>::type;
103 template <
typename Function,
typename F = remove_reference_t<Function>>
104 using function_signature_t = conditional_t<
105 std::is_function<F>::value,
107 typename conditional_t<
108 std::is_pointer<F>::value || std::is_member_pointer<F>::value,
109 std::remove_pointer<F>,
110 strip_function_object<F>
114 # if __cplusplus >= 201402L 115 using std::index_sequence;
116 using std::make_index_sequence;
118 template<
size_t ...>
struct index_sequence { };
119 template<
size_t N,
size_t ...S>
struct make_index_sequence_impl : make_index_sequence_impl <N - 1, N - 1, S...> { };
120 template<
size_t ...S>
struct make_index_sequence_impl <0, S...> {
typedef index_sequence<S...> type; };
121 template<
size_t N>
using make_index_sequence =
typename make_index_sequence_impl<N>::type;
125 typedef char (&no)[2];
132 no operator<<(
const anyx&,
const anyx&);
133 no operator>>(
const anyx&,
const anyx&);
139 template <
typename StreamType,
typename T>
140 struct has_loading_support {
141 static StreamType& stream;
143 static const bool value =
sizeof(check(stream >> x)) ==
sizeof(yes);
146 template <
typename StreamType,
typename T>
147 struct has_saving_support {
148 static StreamType& stream;
150 static const bool value =
sizeof(check(stream << x)) ==
sizeof(yes);
153 template <
typename StreamType,
typename T>
154 struct has_stream_operators {
155 static const bool can_load = has_loading_support<StreamType, T>::value;
156 static const bool can_save = has_saving_support<StreamType, T>::value;
157 static const bool value = can_load && can_save;
172 template <
typename T>
569 : _obj(std::shared_ptr<SvarValue>(v)){}
572 template <
typename T>
576 template <
typename T>
577 Svar(std::unique_ptr<T>&& v);
589 Svar(
const std::string& str);
592 Svar(
const std::vector<Svar>& vec);
595 Svar(
const std::map<std::string,Svar>& m);
598 Svar(
const std::map<Svar,Svar>& m);
601 Svar(
const std::initializer_list<Svar>& init);
604 template <
typename Return,
typename... Args,
typename... Extra>
605 Svar(Return (*f)(Args...),
const Extra&... extra);
608 template <
typename Func,
typename... Extra>
609 static Svar lambda(Func &&f,
const Extra&... extra);
612 template <
typename Return,
typename Class,
typename... arg,
typename... Extra>
613 Svar(Return (Class::*f)(arg...),
const Extra&... extra);
616 template <
typename Return,
typename Class,
typename... arg,
typename... Extra>
617 Svar(Return (Class::*f)(arg...)
const,
const Extra&... extra);
620 #if (__GNUC__>=5)||defined(__clang__) 622 static Svar create(T & t);
625 static Svar create(
const T & t);
629 static Svar create(T && t);
632 static Svar
object(
const std::map<std::string,Svar>& m={}){
return Svar(m);}
635 static Svar
array(
const std::vector<Svar>& vec={}){
return Svar(vec);}
638 static Svar
dict(
const std::map<Svar,Svar>& m={}){
return Svar(m);}
641 static Svar
json(
const std::string& str){
642 return svar[
"__builtin__"][
"Json"].call(
"load",str);
646 template <
typename T>
648 bool is(
const std::type_index& typeId)
const;
649 bool is(
const std::string& typeStr)
const;
652 template <
typename T>
657 template <
typename T>
661 template <
typename T>
664 Svar cast(
const std::string& typeStr)
const;
667 template <
typename T>
668 detail::enable_if_t<std::is_pointer<T>::value,T>
672 template <
typename T>
673 detail::enable_if_t<std::is_reference<T>::value,T&>
677 template <
typename T>
678 detail::enable_if_t<!std::is_reference<T>::value&&!std::is_pointer<T>::value,T>
681 bool isUndefined()
const{
return is<void>();}
683 bool isFunction()
const{
return is<SvarFunction>();}
684 bool isClass()
const{
return is<SvarClass>();}
685 bool isException()
const{
return is<SvarExeption>();}
686 bool isObject()
const;
690 Svar clone(
int depth=0)
const;
693 std::string typeName()
const;
696 std::type_index cpptype()
const;
699 const Svar& classObject()
const;
702 SvarClass* classPtr()
const;
705 size_t length()
const;
706 size_t size()
const{
return length();}
710 template <
typename T>
711 T&
get(
const std::string& name,T def,
bool parse_dot=
false);
713 Svar
get(
const std::string& name,Svar def,
bool parse_dot=
false);
716 template <
typename T>
717 void set(
const std::string& name,
const T& def,
bool parse_dot=
false);
721 bool exist(
const Svar&
id)
const;
725 void erase(
const Svar&
id);
728 void push_back(
const Svar& rh);
731 template <
typename... Args>
732 Svar call(
const std::string
function, Args... args)
const;
735 template <
typename... Args>
736 Svar operator()(Args... args)
const;
739 Svar& def(
const std::string& name,Svar funcOrClass);
742 template <
typename Func>
743 Svar&
def(
const std::string& name,Func &&f){
748 std::vector<std::string> parseMain(
int argc,
char** argv);
750 bool parseFile(
const std::string& file_path);
753 template <
typename T>
754 T arg(
const std::string& name, T def,
const std::string& help);
757 std::string helpInfo();
760 int help(){std::cout<<helpInfo();
return 0;}
763 static std::string printTable(
764 std::vector<std::pair<int, std::string>> line);
766 Svar operator -()
const;
767 Svar operator +(
const Svar& rh)
const;
768 Svar operator -(
const Svar& rh)
const;
769 Svar operator *(
const Svar& rh)
const;
770 Svar operator /(
const Svar& rh)
const;
771 Svar operator %(
const Svar& rh)
const;
772 Svar operator ^(
const Svar& rh)
const;
773 Svar operator |(
const Svar& rh)
const;
774 Svar operator &(
const Svar& rh)
const;
776 bool operator ==(
const Svar& rh)
const;
777 bool operator < (
const Svar& rh)
const;
778 bool operator !=(
const Svar& rh)
const{
return !((*this)==rh);}
779 bool operator > (
const Svar& rh)
const{
return !((*this)==rh||(*this)<rh);}
780 bool operator <=(
const Svar& rh)
const{
return ((*
this)<rh||(*
this)==rh);}
781 bool operator >=(
const Svar& rh)
const{
return !((*this)<rh);}
782 Svar operator [](
const Svar& i)
const;
783 Svar& operator[](
const Svar& name);
785 template <
typename T>
786 detail::enable_if_t<std::is_copy_assignable<T>::value,Svar&> operator =(
const T& v){
787 if(is<T>()) as<T>()=v;
788 else (*
this)=Svar(v);
792 template <
typename T>
793 detail::enable_if_t<!std::is_copy_assignable<T>::value,Svar&> operator =(
const T& v){
798 operator std::string(){
return castAs<std::string>();}
801 friend std::ostream& operator <<(std::ostream& ost,
const Svar&
self);
802 friend std::istream& operator >>(std::istream& ist,Svar&
self);
806 static const Svar& Undefined();
809 static const Svar& Null();
810 static const Svar& True();
811 static const Svar& False();
812 static Svar& instance();
813 static Svar loadFile(
const std::string& file_path);
815 template <
typename T>
816 static std::string type_id();
818 template <
typename T>
819 static std::string toString(
const T& v);
821 template <
typename T>
822 static detail::enable_if_t<detail::has_loading_support<std::istream,T>::value,T> fromString(
const std::string& str,
const T& def)
825 std::stringstream sst(str);
830 template <
typename T>
831 static detail::enable_if_t<!detail::has_loading_support<std::istream,T>::value,T> fromString(
const std::string& str,
const T& def)
837 const std::shared_ptr<SvarValue>&
value()
const{
return _obj;}
840 Svar& getOrCreate(
const std::string& name,
bool parse_dot=
false);
842 template <
typename T>
843 T Arg(
const std::string& name, T def,
const std::string& help){
return arg<T>(name,def,help);}
845 std::vector<std::string> ParseMain(
int argc,
char** argv){
return parseMain(argc,argv);}
846 bool ParseFile(
const std::string& file_path){
return parseFile(file_path);}
848 template <
typename T>
849 T& Get(
const std::string& name,T def=T()){
return get<T>(name,def);}
850 Svar Get(
const std::string& name,Svar def=Svar()){
return get(name,def);}
851 int& GetInt(
const std::string& name,
int def=0){
return get<int>(name,def);}
852 double& GetDouble(
const std::string& name,
double def=0){
return get<double>(name,def);}
853 std::string& GetString(
const std::string& name,std::string def=
""){
return get<std::string>(name,def);}
854 void*& GetPointer(
const std::string& name,
void* def=
nullptr){
return get<void*>(name,def);}
855 template <
typename T>
856 void Set(
const std::string& name,
const T& def){
return set<T>(name,def);}
857 template <
typename T>
858 void Set(
const std::string& name,
const T& def,
bool overwrite){
859 if(exist(name)&&!overwrite)
return;
860 return set<T>(name,def);
863 static std::string getFileName(
const std::string& path) {
864 auto idx = std::string::npos;
865 if ((idx = path.find_last_of(
'/')) == std::string::npos)
866 idx = path.find_last_of(
'\\');
867 if (idx != std::string::npos)
868 return path.substr(idx + 1);
872 std::shared_ptr<SvarValue> _obj;
876 #ifndef DOXYGEN_IGNORE_INTERNAL 880 virtual ~SvarValue(){}
881 typedef std::type_index TypeID;
882 virtual TypeID cpptype()
const{
return typeid(void);}
883 virtual const void* ptr()
const{
return nullptr;}
884 virtual const Svar& classObject()
const;
885 virtual size_t length()
const {
return 0;}
886 virtual std::mutex* accessMutex()
const{
return nullptr;}
887 virtual Svar clone(
int depth=0)
const{
return Svar();}
890 class SvarExeption:
public std::exception{
892 SvarExeption(
const Svar& wt=Svar())
895 virtual const char* what()
const throw(){
896 if(_wt.is<std::string>())
897 return _wt.as<std::string>().c_str();
899 return "SvarException";
905 class SvarFunction:
public SvarValue{
910 template <
typename Return,
typename... Args,
typename... Extra>
911 SvarFunction(Return (*f)(Args...),
const Extra&... extra) {
912 initialize(f, f, extra...);
916 template <
typename Func,
typename... Extra>
917 SvarFunction(Func &&f,
const Extra&... extra) {
918 initialize(std::forward<Func>(f),
919 (detail::function_signature_t<Func> *)
nullptr, extra...);
923 template <
typename Return,
typename Class,
typename... Arg,
typename... Extra>
924 SvarFunction(Return (Class::*f)(Arg...),
const Extra&... extra) {
925 initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
926 (Return (*) (Class *, Arg...))
nullptr, extra...);
930 template <
typename Return,
typename Class,
typename... Arg,
typename... Extra>
931 SvarFunction(Return (Class::*f)(Arg...)
const,
const Extra&... extra) {
932 initialize([f](
const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
933 (Return (*)(
const Class *, Arg ...))
nullptr, extra...);
936 virtual TypeID cpptype()
const{
return typeid(SvarFunction);}
937 virtual const void* ptr()
const{
return this;}
938 virtual const Svar& classObject()
const;
942 ScopedStack(std::list<const SvarFunction*>& stack,
const SvarFunction* var)
944 _stack.push_back(var);
946 ~ScopedStack(){_stack.pop_back();}
947 std::list<const SvarFunction*>& _stack;
950 Svar Call(std::vector<Svar> argv)
const{
951 thread_local
static std::list<const SvarFunction*> stack;
952 ScopedStack scoped_stack(stack,
this);
954 const SvarFunction* overload=
this;
955 std::vector<SvarExeption> catches;
956 for(;
true;overload=&overload->next.as<SvarFunction>()){
957 if(do_argcheck&&overload->arg_types.size()!=argv.size())
959 if(!overload->next.isFunction()) {
960 overload=
nullptr;
break;
965 return overload->_func(argv);
967 catch(SvarExeption e){
968 catches.push_back(e);
970 if(!overload->next.isFunction()) {
971 overload=
nullptr;
break;
976 std::stringstream stream;
977 stream<<
"Failed to call method "<<getName()<<
" with imput arguments: [";
978 for(
auto it=argv.begin();it!=argv.end();it++)
980 stream<<(it==argv.begin()?
"":
",")<<it->typeName();
982 stream<<
"]\n"<<
"Overload candidates:\n"<<(*this)<<std::endl;
983 for(
auto it:catches) stream<<it.what()<<std::endl;
985 for(
auto& l:stack) stream<<*l;
986 throw SvarExeption(stream.str());
992 template <
typename... Args>
993 Svar call(Args... args)
const{
994 std::vector<Svar> argv = {
995 (Svar(std::move(args)))...
1001 template <
typename Func,
typename Return,
typename... Args,
typename... Extra>
1002 void initialize(Func &&f, Return (*)(Args...),
const Extra&... extra);
1004 template <
typename Func,
typename Return,
typename... Args,
size_t... Is>
1005 detail::enable_if_t<std::is_void<Return>::value, Svar>
1006 call_impl(Func&& f,Return (*)(Args...),std::vector<Svar>& args,detail::index_sequence<Is...>){
1007 f(args[Is].castAs<Args>()...);
1011 template <
typename Func,
typename Return,
typename... Args,
size_t... Is>
1012 detail::enable_if_t<!std::is_void<Return>::value, Svar>
1013 call_impl(Func&& f,Return (*)(Args...),std::vector<Svar>& args,detail::index_sequence<Is...>){
1014 std::tuple<Args...> castedArgs(args[Is].castAs<Args>()...);
1015 return Svar(f(std::get<Is>(castedArgs)...));
1018 friend std::ostream& operator<<(std::ostream& sst,
const SvarFunction&
self){
1019 sst<<
self.getName()<<
"(...)\n";
1020 const SvarFunction* overload=&
self;
1022 sst<<
" "<<overload->getName()<<overload->signature<<std::endl;
1023 if(!overload->next.isFunction()) {
1026 overload=&overload->next.as<SvarFunction>();
1031 std::string getName()
const{
return name.empty()?
"function":name;}
1032 void initName(
const std::string& nm){
if(name.empty()) name=nm;}
1034 std::string name,signature;
1035 std::vector<Svar> arg_types;
1038 std::function<Svar(std::vector<Svar>&)> _func;
1039 bool is_method,is_constructor,do_argcheck=
true;
1044 SvarProperty(Svar fget,Svar fset,std::string name,std::string doc)
1045 :_fget(fget),_fset(fset),_name(name),_doc(doc){}
1048 std::string _name,_doc;
1051 class SvarClass:
public SvarValue{
1053 SvarClass(
const std::string& name,std::type_index cpp_type,
1054 std::vector<Svar> parents={})
1055 : __name__(name),_cpptype(cpp_type),
1059 virtual TypeID cpptype()
const{
return typeid(SvarClass);}
1060 virtual const void* ptr()
const{
return this;}
1061 virtual const Svar& classObject()
const{
return instance<SvarClass>();}
1063 std::string name()
const{
return __name__;}
1064 void setName(
const std::string& nm){__name__=nm;}
1066 SvarClass& def(
const std::string& name,
const Svar&
function,
bool isMethod=
true)
1068 assert(
function.isFunction());
1069 Svar* dest=&_methods[name];
1070 while(dest->isFunction())
1072 if(dest->
as<SvarFunction>().signature==
function.as<SvarFunction>().signature)
1074 dest=&dest->
as<SvarFunction>().next;
1077 dest->as<SvarFunction>().is_method=isMethod;
1078 dest->as<SvarFunction>().name=__name__+
"."+name;
1081 if(__init__.is<
void>()&&name==
"__init__") {
1083 dest->as<SvarFunction>().is_constructor=
true;
1085 if(__str__.is<
void>()&&name==
"__str__") __str__=
function;
1086 if(__getitem__.is<
void>()&&name==
"__getitem__") __getitem__=
function;
1087 if(__setitem__.is<
void>()&&name==
"__setitem__") __setitem__=
function;
1091 SvarClass& def_static(
const std::string& name,
const Svar&
function)
1093 return def(name,
function,
false);
1096 template <
typename Func>
1097 SvarClass& def(
const std::string& name,Func &&f){
1102 template <
typename Func>
1103 SvarClass& def_static(
const std::string& name,Func &&f){
1107 SvarClass& def_property(
const std::string& name,
1108 const Svar& fget,
const Svar& fset=Svar(),
1109 const std::string& doc=
""){
1110 _methods[name]=SvarProperty(fget,fset,name,doc);
1114 template <
typename C,
typename D>
1115 SvarClass& def_readwrite(
const std::string& name, D C::*pm,
const std::string& doc=
"") {
1116 Svar fget=SvarFunction([pm](
const C &c) ->
const D &{
return c.*pm; });
1117 Svar fset=SvarFunction([pm](C &c,
const D &value) { c.*pm = value;});
1118 fget.
as<SvarFunction>().is_method=
true;
1119 fset.as<SvarFunction>().is_method=
true;
1120 return def_property(name, fget, fset, doc);
1123 template <
typename C,
typename D>
1124 SvarClass& def_readonly(
const std::string& name, D C::*pm,
const std::string& doc=
"") {
1125 Svar fget=SvarFunction([pm](
const C &c) ->
const D &{
return c.*pm; });
1126 fget.
as<SvarFunction>().is_method=
true;
1127 return def_property(name, fget, Svar(), doc);
1130 template <
typename Base,
typename ChildType>
1131 SvarClass& inherit(){
1132 Svar base={SvarClass::instance<Base>(),
1134 return dynamic_cast<Base*
>(v);
1140 SvarClass& inherit(std::vector<Svar> parents={}){
1145 Svar& operator [](
const std::string& name){
1146 Svar& c=_methods[name];
1156 template <
typename... Args>
1157 Svar call(
const Svar& inst,
const std::string
function, Args... args)
const 1159 Svar f=_methods[
function];
1162 SvarFunction& func=f.
as<SvarFunction>();
1164 return func.call(inst,args...);
1165 else return func.call(args...);
1168 for(
const Svar& p:_parents){
1171 return p.as<SvarClass>().call(inst,
function,args...);
1173 return p[0].as<SvarClass>().call(p[1](inst),
function,args...);
1175 catch(SvarExeption e){
1179 throw SvarExeption(
"Class "+__name__+
" has no function "+
function);
1183 Svar Call(
const Svar& inst,
const std::string
function, std::vector<Svar> args)
const 1185 Svar f=_methods[
function];
1188 SvarFunction& func=f.
as<SvarFunction>();
1190 args.insert(args.begin(),inst);
1191 return func.Call(args);
1193 else return func.Call(args);
1196 for(
const Svar& p:_parents){
1199 return p.as<SvarClass>().Call(inst,
function,args);
1201 return p[0].as<SvarClass>().Call(p[1](inst),
function,args);
1203 catch(SvarExeption e){
1207 throw SvarExeption(
"Class "+__name__+
" has no function "+
function);
1211 template <
typename T>
1212 static Svar& instance();
1214 template <
typename T>
1215 static SvarClass& Class(){
1216 Svar& inst=instance<T>();
1217 return inst.
as<SvarClass>();
1220 friend std::ostream& operator<<(std::ostream& ost,
const SvarClass& rh);
1223 Svar __init__,__str__,__getitem__,__setitem__;
1225 std::string __name__,__doc__;
1226 std::type_index _cpptype;
1227 Svar _methods,_attr;
1228 std::vector<Svar> _parents;
1231 template <
typename C>
1235 Class(SvarClass& cls):_cls(cls){}
1237 Class():_cls(SvarClass::Class<C>()){}
1239 Class(
const std::string& name)
1240 :_cls(SvarClass::Class<C>()){
1242 svar[name]=SvarClass::instance<C>();
1245 Class& def(
const std::string& name,
const Svar&
function,
bool isMethod=
true)
1247 _cls.def(name,
function,isMethod);
1251 Class& def_static(
const std::string& name,
const Svar&
function)
1253 return def(name,
function,
false);
1256 template <
typename Func>
1257 Class& def(
const std::string& name,Func &&f){
1262 template <
typename Func>
1263 Class& def_static(
const std::string& name,Func &&f){
1267 template <
typename ChildType>
1269 _cls.inherit<C,ChildType>();
1273 template <
typename... Args>
1275 return def(
"__init__",[](Args... args){
1280 Class& def_property(
const std::string& name,
1281 const Svar& fget,
const Svar& fset=Svar(),
1282 const std::string& doc=
""){
1283 _cls.def_property(name,fget,fset,doc);
1287 template <
typename E,
typename D>
1288 Class& def_readwrite(
const std::string& name, D E::*pm,
const std::string& doc=
"") {
1289 static_assert(std::is_base_of<E, C>::value,
"def_readwrite() requires a class member (or base class member)");
1291 Svar fget=SvarFunction([pm](
const C &c) ->
const D &{
return c.*pm; });
1292 Svar fset=SvarFunction([pm](C &c,
const D &value) { c.*pm = value;});
1293 fget.
as<SvarFunction>().is_method=
true;
1294 fset.as<SvarFunction>().is_method=
true;
1295 return def_property(name, fget, fset, doc);
1298 template <
typename E,
typename D>
1299 Class& def_readonly(
const std::string& name, D E::*pm,
const std::string& doc=
"") {
1300 static_assert(std::is_base_of<E, C>::value,
"def_readonly() requires a class member (or base class member)");
1301 Svar fget=SvarFunction([pm](
const C &c) ->
const D &{
return c.*pm; });
1302 fget.
as<SvarFunction>().is_method=
true;
1303 return def_property(name, fget, Svar(), doc);
1310 template <
typename T>
1311 Svar& SvarClass::instance()
1314 if(cl.isClass())
return cl;
1317 char* realname = abi::__cxa_demangle(
typeid(T).name(), 0, 0, &status);
1318 std::string result(realname);
1321 std::string result(
typeid(T).name());
1323 cl=(SvarValue*)
new SvarClass(result,
typeid(T));
1327 template <
typename T>
1331 explicit SvarValue_(T&& v):_var(std::move(v)){}
1333 virtual TypeID cpptype()
const{
return typeid(T);}
1334 virtual const void* ptr()
const{
return &_var;}
1335 virtual const Svar& classObject()
const{
return SvarClass::instance<T>();}
1336 virtual Svar clone(
int depth=0)
const{
return _var;}
1347 template <
typename T,
typename H=std::shared_ptr<T> >
1348 class SvarPtrHolder:
public SvarValue{
1350 explicit SvarPtrHolder(
const H& v):_var(v){
1353 virtual TypeID cpptype()
const{
return typeid(T);}
1354 virtual const void* ptr()
const{
return _var.get();}
1355 virtual const Svar& classObject()
const{
return SvarClass::instance<T>();}
1356 virtual Svar clone(
int depth=0)
const{
return _var;}
1361 template <
typename T>
1362 class SvarPtrHolder<T,std::unique_ptr<T>>:
public SvarValue{
1364 explicit SvarPtrHolder(std::unique_ptr<T>&& v):_var(std::move(v)){
1367 virtual TypeID cpptype()
const{
return typeid(T);}
1368 virtual const void* ptr()
const{
return _var.get();}
1369 virtual const Svar& classObject()
const{
return SvarClass::instance<T>();}
1372 std::unique_ptr<T> _var;
1375 class SvarObject :
public SvarValue_<std::map<std::string,Svar> >{
1377 SvarObject(
const std::map<std::string,Svar>& m)
1379 virtual TypeID cpptype()
const{
return typeid(SvarObject);}
1380 virtual const void* ptr()
const{
return this;}
1381 virtual size_t length()
const {
return _var.size();}
1382 virtual std::mutex* accessMutex()
const{
return &_mutex;}
1383 virtual const Svar& classObject()
const{
1384 if(_class.isClass())
return _class;
1385 return SvarClass::instance<SvarObject>();
1388 virtual Svar clone(
int depth=0)
const{
1389 std::unique_lock<std::mutex> lock(_mutex);
1392 std::map<std::string,Svar> var=_var;
1393 for(
auto it=var.begin();it!=var.end();it++){
1394 it->second=it->second.clone(depth-1);
1399 Svar operator[](
const std::string &key)
const {
1400 std::unique_lock<std::mutex> lock(_mutex);
1401 auto it=_var.find(key);
1408 void set(
const std::string &key,
const Svar& value){
1409 std::unique_lock<std::mutex> lock(_mutex);
1413 void update(Svar rh){
1414 if(!rh.isObject())
return;
1415 std::unique_lock<std::mutex> lock(_mutex);
1416 auto cp=rh.
as<SvarObject>()._var;
1418 auto old=_var.find(it.first);
1420 _var[it.first]=it.second;
1421 else if(old->second.isObject()&&it.second.isObject())
1422 old->second.as<SvarObject>().update(it.second);
1423 else old->second=it.second;
1427 bool exist(
const std::string&
id)
const{
1428 std::unique_lock<std::mutex> lock(_mutex);
1429 return _var.count(
id);
1432 void erase(
const std::string&
id){
1433 std::unique_lock<std::mutex> lock(_mutex);
1438 static Svar objectinteratorClass;
1439 if(!objectinteratorClass.isClass()){
1440 SvarClass* cls=
new SvarClass(
"objectiterator",
typeid(SvarObject));
1441 objectinteratorClass=(SvarValue*)cls;
1442 cls->def(
"next",[](Svar iter){
1443 SvarObject* obj=iter.
as<SvarObject>()[
"object"].as<SvarObject*>();
1444 typedef std::map<std::string,Svar>::iterator Iter;
1445 Iter it=iter.
as<SvarObject>()[
"iter"].as<Iter>();
1446 if(it!=obj->_var.end()){
1454 iter.
as<SvarObject>()._class=objectinteratorClass;
1458 friend std::ostream& operator<<(std::ostream& ost,
const SvarObject& rh){
1459 std::unique_lock<std::mutex> lock(rh._mutex);
1460 if(rh._var.empty()) {
1461 ost<<
"{}";
return ost;
1464 std::stringstream context;
1465 for(
auto it=rh._var.begin();it!=rh._var.end();it++)
1467 context<<(it==rh._var.begin()?
"":
",\n")<<Svar(it->first)<<
" : "<<it->second;
1470 while(std::getline(context,line)) ost<<
" "<<line<<std::endl;
1475 mutable std::mutex _mutex;
1479 class SvarArray :
public SvarValue_<std::vector<Svar> >{
1481 SvarArray(
const std::vector<Svar>& v)
1483 virtual TypeID cpptype()
const{
return typeid(SvarArray);}
1484 virtual const void* ptr()
const{
return this;}
1485 virtual const Svar& classObject()
const{
return SvarClass::instance<SvarArray>();}
1486 virtual size_t length()
const {
return _var.size();}
1487 virtual std::mutex* accessMutex()
const{
return &_mutex;}
1488 virtual const Svar& operator[](
size_t i) {
1489 std::unique_lock<std::mutex> lock(_mutex);
1490 if(i<_var.size())
return _var[i];
1494 virtual Svar clone(
int depth=0)
const{
1495 std::unique_lock<std::mutex> lock(_mutex);
1498 std::vector<Svar> var=_var;
1505 friend std::ostream& operator<<(std::ostream& ost,
const SvarArray& rh){
1506 std::unique_lock<std::mutex> lock(rh._mutex);
1507 if(rh._var.empty()) {
1508 ost<<
"[]";
return ost;
1511 std::stringstream context;
1512 for(
size_t i=0;i<rh._var.size();++i)
1513 context<<rh._var[i]<<(i+1==rh._var.size()?
"\n":
",\n");
1515 while(std::getline(context,line)) ost<<
" "<<line<<std::endl;
1520 Svar operator+(Svar other){
1521 std::unique_lock<std::mutex> lock(_mutex);
1522 std::vector<Svar> ret=_var;
1523 if(other.isArray()){
1524 SvarArray& rh=other.
as<SvarArray>();
1525 std::unique_lock<std::mutex> lock(rh._mutex);
1526 ret.insert(ret.end(),rh._var.begin(),rh._var.end());
1528 else ret.push_back(other);
1532 void append(Svar other){
1533 std::unique_lock<std::mutex> lock(_mutex);
1534 _var.push_back(other);
1537 void erase(
int idx){
1538 std::unique_lock<std::mutex> lock(_mutex);
1539 _var.erase(_var.begin()+idx);
1542 mutable std::mutex _mutex;
1545 class SvarDict :
public SvarValue_<std::map<Svar,Svar> >{
1547 SvarDict(
const std::map<Svar,Svar>& dict)
1551 virtual size_t length()
const {
return _var.size();}
1552 virtual std::mutex* accessMutex()
const{
return &_mutex;}
1553 virtual Svar operator[](
const Svar& i) {
1554 std::unique_lock<std::mutex> lock(_mutex);
1555 auto it=_var.find(i);
1556 if(it!=_var.end())
return it->second;
1559 void erase(
const Svar&
id){
1560 std::unique_lock<std::mutex> lock(_mutex);
1563 mutable std::mutex _mutex;
1566 class SvarBuffer :
public SvarValue
1569 SvarBuffer(
const void* ptr,
size_t size,Svar holder=Svar())
1570 : _ptr(ptr),_size(size),_holder(holder){}
1572 SvarBuffer(
size_t size):_size(size){
1574 _ptr = _holder.as<std::vector<char>>().data();
1577 SvarBuffer(
const void* ptr,
size_t size,
const std::vector<int>& shape,
1578 const std::string& format,Svar holder)
1579 : _ptr(ptr),_size(size)
1581 _holder={{
"holder",holder},{
"format",format},{
"shape",shape}};
1584 static SvarBuffer load(std::string path){
1585 std::ifstream in(path,std::ios::in|std::ios::binary);
1587 std::string* file =
new std::string( (std::istreambuf_iterator<char>(in)) , std::istreambuf_iterator<char>() );
1588 return SvarBuffer(file->data(),file->size(),std::unique_ptr<std::string>(file));
1590 std::cout<<
"Wrong path!"<<std::endl;
1594 bool save(std::string path){
1595 std::ofstream out(path,std::ios_base::out);
1597 out.write((
const char*)_ptr,_size);
1605 std::string hex()
const{
1606 const std::string h =
"0123456789ABCDEF";
1607 std::string ret;ret.resize(_size*2);
1608 for(
size_t i=0;i<_size;i++){
1609 ret[i<<1]=h[((uint8_t*)_ptr)[i] >> 4];
1610 ret[(i<<1)+1]=h[((uint8_t*)_ptr)[i] & 0xf];
1615 static SvarBuffer fromHex(
const std::string& h){
1616 size_t n = h.size()>>1;
1618 for(
size_t i=0;i < n;i++){
1619 ((uint8_t*)(ret._ptr))[i]=strtol(h.substr(i<<1,2).c_str(),
nullptr,16);
1625 std::string base64()
const {
1626 const unsigned char * bytes_to_encode=(
unsigned char*)_ptr;
1627 size_t in_len=_size;
1628 const std::string chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";;
1632 unsigned char char_array_3[3];
1633 unsigned char char_array_4[4];
1636 char_array_3[i++] = *(bytes_to_encode++);
1638 char_array_4[0] = (
unsigned char) ((char_array_3[0] & 0xfc) >> 2);
1639 char_array_4[1] = (
unsigned char) ( ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 ) );
1640 char_array_4[2] = (
unsigned char) ( ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 ) );
1641 char_array_4[3] = (
unsigned char) ( char_array_3[2] & 0x3f );
1643 for(i = 0; (i <4) ; i++)
1644 ret += chars[char_array_4[i]];
1651 for(j = i; j < 3; j++)
1652 char_array_3[j] =
'\0';
1654 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
1655 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
1656 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
1657 char_array_4[3] = char_array_3[2] & 0x3f;
1659 for (j = 0; (j < i + 1); j++)
1660 ret += chars[char_array_4[j]];
1670 static SvarBuffer fromBase64(
const std::string& h){
1671 const std::string chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";;
1672 size_t in_len = h.size();
1676 unsigned char char_array_4[4], char_array_3[3];
1677 std::string* ret =
new std::string;
1678 auto is_base64=[](
unsigned char c) {
1679 return (isalnum(c) || (c ==
'+') || (c ==
'/'));
1682 while (in_len-- && ( h[in_] !=
'=') && is_base64(h[in_])) {
1683 char_array_4[i++] = h[in_]; in_++;
1685 for (i = 0; i <4; i++)
1686 char_array_4[i] = (
unsigned char) chars.find( char_array_4[i] );
1688 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
1689 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
1690 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
1692 for (i = 0; (i < 3); i++)
1693 *ret += char_array_3[i];
1699 for (j = i; j <4; j++)
1700 char_array_4[j] = 0;
1702 for (j = 0; j <4; j++)
1703 char_array_4[j] = (
unsigned char) chars.find( char_array_4[j] );
1705 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
1706 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
1707 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
1709 for (j = 0; (j < i - 1); j++) *ret += char_array_3[j];
1712 return SvarBuffer(ret->data(),ret->size(),std::unique_ptr<std::string>(ret));
1717 const std::string hexs =
"0123456789ABCDEF";
1718 uint32_t atemp=0x67452301,btemp=0xefcdab89,
1719 ctemp=0x98badcfe,dtemp=0x10325476;
1720 const unsigned int k[]={
1721 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
1722 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
1723 0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
1724 0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
1725 0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
1726 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
1727 0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
1728 0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
1729 0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
1730 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,
1731 0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
1732 0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
1733 0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391
1735 const unsigned int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
1736 12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
1737 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
1738 15,21,6,10,15,21,6,10,15,21,6,10,15,21};
1740 std::function<uint32_t(uint32_t,uint32_t)> shift = [](uint32_t x,uint32_t n){
1741 return (x<<n)|(x>>(32-n));
1743 std::vector<std::function<uint32_t(uint32_t,uint32_t,uint32_t)> > funcs ={
1744 [](uint32_t x,uint32_t y,uint32_t z){
return (x & y)| (~x & z);},
1745 [](uint32_t x,uint32_t y,uint32_t z){
return (x & z)| (y & ~z);},
1746 [](uint32_t x,uint32_t y,uint32_t z){
return (x ^ y ^ z);},
1747 [](uint32_t x,uint32_t y,uint32_t z){
return (y ^ (x | ~z));}};
1748 std::vector<std::function<uint8_t(uint8_t)> > func_g ={
1749 [](uint8_t i){
return i;},
1750 [](uint8_t i){
return (5*i+1)%16;},
1751 [](uint8_t i){
return (3*i+5)%16;},
1752 [](uint8_t i){
return (7*i)%16;}};
1754 std::function<void(std::vector<uint32_t>&,int) > mainloop = [&](std::vector<uint32_t>& v,
int step) ->
void{
1756 unsigned int a=atemp;
1757 unsigned int b=btemp;
1758 unsigned int c=ctemp;
1759 unsigned int d=dtemp;
1760 for(uint8_t i;i<64;i++){
1761 f=funcs[i>>4](b,c,d);
1766 b=b+shift((a+f+k[i]+v[step*16+g]),s[i]);
1774 std::function<std::string(int)> int2hexstr = [&](
int i) -> std::string {
1777 for(
int j=0;j<4;j++){
1778 uint8_t b = (i>>(j*8))%(1<<8);
1779 s[2*j] = hexs[b>>4];
1780 s[2*j+1] = hexs[b%16];
1787 int total_groups = (_size+8)/64+1;
1788 int total_ints = total_groups*16;
1789 std::vector<uint32_t> vec(total_ints,0);
1790 for(
size_t i = 0; i < _size; i++)
1791 vec[i>>2] |= (((
const char*)_ptr)[i]) << ((i%4)*8);
1792 vec[_size>>2] |= 0x80 << (_size%4*8);
1793 uint64_t size = _size*8;
1794 vec[total_ints-2] = size & UINT_LEAST32_MAX;
1795 vec[total_ints-1] = size>>32;
1798 for(
int i = 0; i < total_groups; i++){
1801 return int2hexstr(atemp)\
1802 .append(int2hexstr(btemp))\
1803 .append(int2hexstr(ctemp))\
1804 .append(int2hexstr(dtemp));
1807 friend std::ostream& operator<<(std::ostream& ost,
const SvarBuffer& b){
1813 SvarBuffer buf(_size);
1814 memcpy((
void*)buf._ptr,_ptr,_size);
1818 virtual TypeID cpptype()
const{
return typeid(SvarBuffer);}
1819 virtual const void* ptr()
const{
return this;}
1820 virtual const Svar& classObject()
const{
return SvarClass::instance<SvarBuffer>();}
1821 virtual size_t length()
const {
return _size;}
1828 inline const Svar& SvarValue::classObject()
const{
return SvarClass::instance<void>();}
1831 template <
typename Func,
typename Return,
typename... Args,
typename... Extra>
1832 void SvarFunction::initialize(Func &&f, Return (*)(Args...),
const Extra&... extra)
1834 std::vector<Svar> types={SvarClass::instance<Args>()...};
1835 std::stringstream signature;signature<<
"(";
1836 for(
size_t i=0;i<types.size();i++)
1837 signature<<types[i].as<SvarClass>().name()<<(i+1==types.size()?
"":
",");
1839 signature<<Svar::type_id<Return>();
1840 this->signature=signature.str();
1841 this->arg_types=types;
1842 _func=[
this,f](std::vector<Svar>& args)->Svar{
1843 using indices = detail::make_index_sequence<
sizeof...(Args)>;
1844 return call_impl(f,(Return (*) (Args...))
nullptr,args,indices{});
1846 is_constructor=
false;
1849 template <
typename T>
1850 inline std::string Svar::toString(
const T& def) {
1851 std::ostringstream sst;
1857 inline std::string Svar::toString(
const std::string& def) {
1862 inline std::string Svar::toString(
const double& def) {
1863 using namespace std;
1865 ost << setprecision(12) << def;
1870 inline std::string Svar::toString(
const bool& def) {
1871 return def ?
"true" :
"false";
1874 template <
typename T>
1875 std::string Svar::type_id(){
1876 return SvarClass::Class<T>().name();
1881 inline Svar::Svar(
const std::initializer_list<Svar>& init)
1884 bool is_an_object = std::all_of(init.begin(), init.end(),
1887 return ele.isArray() && ele.length() == 2 && ele[0].is<std::string>();
1891 std::map<std::string,Svar> obj;
1892 for(
const Svar& p:init) obj.insert(std::make_pair(p[0].as<std::string>(),p[1]));
1897 *
this=Svar(std::vector<Svar>(init));
1900 template <
typename Return,
typename... Args,
typename... Extra>
1901 Svar::Svar(Return (*f)(Args...),
const Extra&... extra)
1902 :_obj(std::make_shared<SvarFunction>(f,extra...)){}
1905 template <
typename Func,
typename... Extra>
1908 return Svar(((SvarValue*)
new SvarFunction(f,extra...)));
1912 template <
typename Return,
typename Class,
typename... Args,
typename... Extra>
1913 Svar::Svar(Return (Class::*f)(Args...),
const Extra&... extra)
1914 :_obj(std::make_shared<SvarFunction>(f,extra...)){}
1917 template <
typename Return,
typename Class,
typename... Args,
typename... Extra>
1918 Svar::Svar(Return (Class::*f)(Args...)
const,
const Extra&... extra)
1919 :_obj(std::make_shared<SvarFunction>(f,extra...)){}
1921 #if (__GNUC__>=5)||defined(__clang__) 1929 inline Svar Svar::create<const Svar>(
const Svar & t)
1935 inline Svar Svar::create<Svar>(Svar & t)
1962 inline Svar Svar::create<Svar>( Svar && t)
1964 return std::move(t);
1970 inline Svar::Svar(
const std::vector<Svar>& vec)
1971 :_obj(std::make_shared<SvarArray>(vec)){}
1973 inline Svar::Svar(
const std::map<std::string,Svar>& m)
1974 :_obj(std::make_shared<SvarObject>(m)){}
1976 inline Svar::Svar(
const std::map<Svar,Svar>& m)
1977 :_obj(std::make_shared<SvarDict>(m)){}
1979 template <
typename T>
1981 : _obj(std::make_shared<SvarPtrHolder<T,std::unique_ptr<T>>>(std::move(v))){}
1984 inline Svar::Svar(
const std::shared_ptr<SvarValue>& v)
1985 : _obj(v?v:Null().value()){}
1987 inline Svar
operator"" _svar(
const char* str,
size_t sz){
1988 return Svar::instance()[
"__builtin__"][
"Json"].call(
"load",std::string(str,sz));
1991 template <
typename T>
1992 inline bool Svar::is()
const{
return _obj->cpptype()==
typeid(T);}
1993 inline bool Svar::is(
const std::type_index& typeId)
const{
return _obj->cpptype()==typeId;}
1994 inline bool Svar::is(
const std::string& typeStr)
const{
return _obj->cpptype().name()==typeStr;}
1997 inline bool Svar::is<Svar>()
const{
return !isUndefined();}
1999 inline bool Svar::isNull()
const{
2000 return Null()==(*this);
2003 inline bool Svar::isObject()
const{
2004 return std::dynamic_pointer_cast<SvarObject>(_obj)!=
nullptr;
2007 inline bool Svar::isArray()
const{
2008 return std::dynamic_pointer_cast<SvarArray>(_obj)!=
nullptr;
2011 inline bool Svar::isDict()
const{
2012 return std::dynamic_pointer_cast<SvarDict>(_obj)!=
nullptr;
2015 template <
typename T>
2018 return *(T*)_obj->ptr();
2022 inline const Svar& Svar::as<Svar>()
const{
2026 template <
typename T>
2028 return *(T*)_obj->ptr();
2032 inline Svar& Svar::as<Svar>(){
2036 template <
typename T>
2039 static Svar from(
const Svar& var){
2040 if(var.
is<T>())
return var;
2044 SvarClass& srcClass=cl.
as<SvarClass>();
2045 Svar cvt=srcClass._methods[
"__"+Svar::type_id<T>()+
"__"];
2046 if(cvt.isFunction()){
2048 if(ret.
is<T>())
return ret;
2052 SvarClass& destClass=SvarClass::instance<T>().
template as<SvarClass>();
2053 if(destClass.__init__.isFunction()){
2054 Svar ret=destClass.__init__(var);
2055 if(ret.
is<T>())
return ret;
2061 static Svar to(
const T& var){
2066 template <
typename T>
2067 Svar::Svar(
const T& var):Svar(caster<T>::to(var))
2070 inline Svar
Svar::cast(
const std::string& typeStr)
const 2072 if(is(typeStr))
return (*
this);
2074 Svar cl=_obj->classObject();
2076 SvarClass& srcClass=cl.
as<SvarClass>();
2077 Svar cvt=srcClass._methods[
"__"+typeStr+
"__"];
2078 if(cvt.isFunction()){
2079 Svar ret=cvt(*
this);
2080 if(ret.
is(typeStr))
return ret;
2086 template <
typename T>
2088 Svar ret=caster<T>::from(*
this);
2089 if(ret.
is<T>())
return ret;
2094 template <
typename T>
2095 detail::enable_if_t<!std::is_reference<T>::value&&!std::is_pointer<T>::value,T>
2099 if(!ret.template is<T>())
2100 throw SvarExeption(
"Unable cast "+typeName()+
" to "+type_id<T>());
2101 return ret.template as<T>();
2104 template <
typename T>
2105 detail::enable_if_t<std::is_reference<T>::value,T&>
2107 if(!is<
typename std::remove_reference<T>::type>())
2108 throw SvarExeption(
"Unable cast "+typeName()+
" to "+type_id<T>());
2110 return as<typename std::remove_reference<T>::type>();
2113 template <
typename T>
2114 detail::enable_if_t<std::is_pointer<T>::value,T>
2117 if(isNull())
return (T)
nullptr;
2119 if(is<T>())
return as<T>();
2122 if(is<
typename std::remove_const<
typename std::remove_pointer<T>::type>::type*>())
2123 return as<
typename std::remove_const<
typename std::remove_pointer<T>::type>::type*>();
2126 if(is<
typename std::remove_pointer<T>::type>())
2127 return &as<
typename std::remove_pointer<T>::type>();
2130 if(!ret.template is<T>())
2131 throw SvarExeption(
"Unable cast "+typeName()+
" to "+type_id<T>());
2132 return ret.template as<T>();
2136 inline Svar Svar::castAs<Svar>()
const{
2140 inline Svar Svar::clone(
int depth)
const{
return _obj->clone(depth);}
2143 return classPtr()->name();
2147 return _obj->cpptype();
2156 auto clsObj=classObject();
2157 if(clsObj.isClass())
return &clsObj.as<SvarClass>();
2162 return _obj->length();
2165 inline Svar Svar::operator[](
const Svar& i)
const{
2166 if(isObject())
return as<SvarObject>()[i.
castAs<std::string>()];
2167 if(classObject().is<
void>())
return Undefined();
2168 const SvarClass& cl=classObject().as<SvarClass>();
2169 if(cl.__getitem__.isFunction()){
2170 return cl.__getitem__((*
this),i);
2175 inline Svar& Svar::operator[](
const Svar& name){
2181 return getOrCreate(name.
castAs<std::string>());
2183 return as<SvarArray>()._var[name.
castAs<
int>()];
2185 return as<SvarDict>()._var[name];
2187 return as<SvarClass>()[name.
castAs<std::string>()];
2188 throw SvarExeption(typeName()+
": Operator [] can't be used as a lvalue.");
2192 inline Svar
Svar::get(
const std::string& name,Svar def,
bool parse_dot)
2195 auto idx = name.find_first_of(
".");
2196 if (idx != std::string::npos) {
2197 return getOrCreate(name.substr(0, idx)).
get(name.substr(idx + 1), def,parse_dot);
2207 var=as<SvarObject>()[name];
2209 else throw SvarExeption(
"Can not get an item from "+typeName());
2211 if(var.isUndefined()){
2218 template <
typename T>
2219 T&
Svar::get(
const std::string& name,T def,
bool parse_dot){
2221 auto idx = name.find_first_of(
".");
2222 if (idx != std::string::npos) {
2223 return getOrCreate(name.substr(0, idx)).
get(name.substr(idx + 1), def,parse_dot);
2232 var=as<SvarObject>()[name];
2234 else throw SvarExeption(
"Can not get an item from "+typeName());
2236 if(var.is<T>())
return var.as<T>();
2238 if(!var.isUndefined()){
2239 Svar casted=var.cast<T>();
2243 else if(var.is<std::string>()){
2244 var=
Svar::create(fromString(var.as<std::string>(),def));
2259 auto idx = name.find_last_of(
'.');
2260 if (idx != std::string::npos) {
2261 return getOrCreate(name.substr(0, idx),parse_dot).getOrCreate(name.substr(idx + 1));
2268 throw SvarExeption(
"Svar::Get can only be called with an object, got "+ typeName());
2269 SvarObject& obj=as<SvarObject>();
2272 std::unique_lock<std::mutex> lock(obj._mutex);
2273 auto it=obj._var.find(name);
2274 if(it!=obj._var.end())
2276 auto ret=obj._var.insert(std::make_pair(name,Svar()));
2277 return ret.first->second;
2282 template <
typename T>
2283 inline void Svar::set(
const std::string& name,
const T& def,
bool parse_dot){
2285 auto idx = name.find(
".");
2286 if (idx != std::string::npos) {
2287 return getOrCreate(name.substr(0, idx)).
set(name.substr(idx + 1), def);
2295 Svar var=as<SvarObject>()[name];
2296 if(!std::is_same<T,Svar>::value&&var.
is<T>())
2306 std::string name=
id.castAs<std::string>();
2307 #ifdef SVAR_PARSE_DOT 2308 auto idx = name.find(
'.');
2309 if (idx != std::string::npos) {
2310 Svar child=as<SvarObject>()[name.substr(0, idx)];
2311 return child.
exist(name.substr(idx + 1));
2314 return as<SvarObject>().exist(name);
2316 return !(*this)[id].isUndefined();
2323 std::string name=
id.castAs<std::string>();
2324 #ifdef SVAR_PARSE_DOT 2325 auto idx = name.find(
'.');
2326 if (idx != std::string::npos) {
2327 Svar child=as<SvarObject>()[name.substr(0, idx)];
2328 return child.
erase(name.substr(idx + 1));
2331 return as<SvarObject>().erase(name);
2333 call(
"__delitem__",
id);
2339 as<SvarArray>().append(rh);
2342 template <
typename... Args>
2343 Svar
Svar::call(
const std::string
function, Args... args)
const 2346 if(isClass())
return as<SvarClass>().call(Svar(),
function,args...);
2351 auto clsPtr=classPtr();
2352 if(!clsPtr)
throw SvarExeption(
"Unable to call "+typeName()+
"."+
function);
2353 return clsPtr->call(*
this,
function,args...);
2356 template <
typename... Args>
2359 return as<SvarFunction>().call(args...);
2361 const SvarClass& cls=as<SvarClass>();
2362 if(!cls.__init__.isFunction())
2363 throw SvarExeption(
"Class "+cls.__name__+
" does not have __init__ function.");
2364 return cls.__init__(args...);
2366 throw SvarExeption(typeName()+
" can't be called as a function or constructor.");
2370 inline Svar&
Svar::def(
const std::string& name,Svar funcOrClass)
2372 if(funcOrClass.isFunction()){
2373 funcOrClass.
as<SvarFunction>().initName(name);
2374 Svar old=(*this)[name];
2375 if(!old.isFunction()){
2376 set(name,funcOrClass);
2378 SvarFunction& oldF=old.
as<SvarFunction>();
2379 if(oldF.signature!=funcOrClass.
as<SvarFunction>().signature)
2380 oldF.next=funcOrClass;
2383 else if(funcOrClass.isClass()){
2384 set(name,funcOrClass);
2386 else throw SvarExeption(
"Svar::def can only define a function or class.");
2390 inline std::vector<std::string>
Svar::parseMain(
int argc,
char** argv) {
2391 using namespace std;
2393 GetInt(
"argc") = argc;
2395 set(
"ProgramName",getFileName(argv[0]));
2396 auto setvar=[
this](std::string s)->
bool{
2398 std::string::size_type n = s.find(
"=");
2399 bool shouldOverwrite =
true;
2401 if (n != std::string::npos) {
2402 std::string var = s.substr(0, n);
2403 std::string val = s.substr(n + 1);
2406 std::string::size_type s = 0, e = var.length() - 1;
2407 if (
'?' == var[e]) {
2409 shouldOverwrite =
false;
2411 for (; std::isspace(var[s]) && s < var.length(); s++) {
2413 if (s == var.length())
2415 for (; std::isspace(var[e]); e--) {
2418 var = var.substr(s, e - s + 1);
2421 s = 0, e = val.length() - 1;
2422 for (; std::isspace(val[s]) && s < val.length(); s++) {
2424 if (s < val.length()) {
2425 for (; std::isspace(val[e]); e--) {
2427 val = val.substr(s, e - s + 1);
2439 std::vector<std::string> unParsed;
2441 for (
int i = beginIdx; i < argc; i++) {
2442 string str = argv[i];
2443 bool foundPrefix =
false;
2445 for (; j < 2 && j < str.size() && str.at(j) ==
'-'; j++) foundPrefix =
true;
2448 if (!setvar(str)) unParsed.push_back(str);
2452 str = str.substr(j);
2453 if (str.find(
'=') != string::npos) {
2458 if (i + 1 >= argc) {
2462 string str2 = argv[i + 1];
2463 if (str2.front() ==
'-') {
2469 set<std::string>(str, argv[i]);
2474 string argv0 = argv[0];
2475 std::vector<std::string> tries={argv0+
".json",
2483 auto fileExists=[](
const std::string& filename)
2485 std::ifstream f(filename.c_str());
2489 parseFile(Get<std::string>(
"conf"));
2501 inline bool Svar::parseFile(
const std::string& file_path)
2503 Svar var=loadFile(file_path);
2504 if(var.isUndefined())
return false;
2505 if(isUndefined()) {*
this=var;
return true;}
2510 template <
typename T>
2511 T
Svar::arg(
const std::string& name, T def,
const std::string& help) {
2513 Svar& args=(*this)[
"__builtin__"][
"args"];
2514 if(!args.isArray()) args=array();
2515 args.push_back(argInfo);
2516 return get(name,def);
2521 Svar args=(*this)[
"__builtin__"][
"args"];
2522 if(
get(
"complete_function_request",
false))
2525 for (
int i=0;i<(int)args.
length();i++) {
2526 str+=
" -"+args[i][0].
castAs<std::string>();
2528 str+=
" -help -conf";
2531 std::stringstream sst;
2532 int width =
get(
"help_colums", 80,
true);
2533 int namePartWidth = width / 5 - 1;
2534 int statusPartWidth = width * 2 / 5 - 1;
2535 int introPartWidth = width * 2 / 5;
2536 std::string usage = get<std::string>(
"__usage__",
"");
2537 if (usage.empty()) {
2538 usage =
"Usage:\n" + get<std::string>(
"__name__",
"exe") +
2539 " [--help] [-conf configure_file]" 2540 " [-arg_name arg_value]...\n";
2542 sst << usage << std::endl;
2545 if (exist(
"__version__"))
2546 desc +=
"Version: " + get<std::string>(
"__version__",
"1.0") +
", ";
2548 "Using Svar supported argument parsing. The following table listed " 2549 "several argument introductions.\n";
2550 sst << printTable({{width, desc}});
2552 arg<std::string>(
"conf",
"Default.cfg",
2553 "The default configure file going to parse.");
2554 arg<bool>(
"help",
false,
"Show the help information.");
2555 if(!args.isArray())
return "";
2557 sst << printTable({{namePartWidth,
"Argument"},
2558 {statusPartWidth,
"Type(default->setted)"},
2559 {introPartWidth,
"Introduction"}});
2560 for (
int i = 0; i < width; i++) sst <<
"-";
2563 for (
int i=0;i<(int)args.
length();i++) {
2565 std::stringstream defset;
2567 std::string name=info[0].
castAs<std::string>();
2569 if(setted.isUndefined()||def==setted) defset<<def;
2570 else defset<<def<<
"->"<<setted;
2571 std::string status = def.
typeName() +
"(" + defset.str() +
")";
2572 std::string intro = info[2].
castAs<std::string>();
2573 sst << printTable({{namePartWidth,
"-" +name},
2574 {statusPartWidth, status},
2575 {introPartWidth, intro}});
2581 std::vector<std::pair<int, std::string>> line) {
2582 std::stringstream sst;
2584 size_t emptyCount = 0;
2585 for (
auto& it : line) {
2586 size_t width = it.first;
2587 std::string& str = it.second;
2588 if (str.size() <= width) {
2589 sst << std::setw(width) << std::setiosflags(std::ios::left) << str
2594 sst << str.substr(0, width) <<
" ";
2595 str = str.substr(width);
2599 if (emptyCount == line.size())
break;
2604 inline Svar Svar::operator -()
const 2606 return classPtr()->call(*
this,
"__neg__");
2609 #define DEF_SVAR_OPERATOR_IMPL(SNAME)\ 2611 auto cls=classPtr();\ 2612 if(!cls) throw SvarExeption(typeName()+" has not class to operator "#SNAME".");\ 2613 Svar ret=cls->call(*this,#SNAME,rh);\ 2614 if(ret.isUndefined()) throw SvarExeption(cls->__name__+" operator "#SNAME" with rh: "+rh.typeName()+"returned Undefined.");\ 2618 inline Svar Svar::operator +(
const Svar& rh)
const 2619 DEF_SVAR_OPERATOR_IMPL(__add__)
2621 inline Svar Svar::operator -(
const Svar& rh)
const 2622 DEF_SVAR_OPERATOR_IMPL(__sub__)
2624 inline Svar Svar::operator *(
const Svar& rh)
const 2625 DEF_SVAR_OPERATOR_IMPL(__mul__)
2627 inline Svar Svar::operator /(
const Svar& rh)
const 2628 DEF_SVAR_OPERATOR_IMPL(__div__)
2630 inline Svar Svar::operator %(
const Svar& rh)
const 2631 DEF_SVAR_OPERATOR_IMPL(__mod__)
2633 inline Svar Svar::operator ^(
const Svar& rh)
const 2634 DEF_SVAR_OPERATOR_IMPL(__xor__)
2636 inline Svar Svar::operator |(
const Svar& rh)
const 2637 DEF_SVAR_OPERATOR_IMPL(__or__)
2639 inline Svar Svar::operator &(
const Svar& rh)
const 2640 DEF_SVAR_OPERATOR_IMPL(__and__)
2642 inline bool Svar::operator ==(
const Svar& rh)
const{
2643 Svar clsobj=classObject();
2644 if(!clsobj.isClass())
return _obj->ptr()==rh.
value()->ptr();
2645 Svar eq_func=clsobj.
as<SvarClass>()[
"__eq__"];
2646 if(!eq_func.isFunction())
return _obj->ptr()==rh.
value()->ptr();
2647 Svar ret=eq_func(*
this,rh);
2648 assert(ret.
is<
bool>());
2649 return ret.
as<
bool>();
2652 inline bool Svar::operator <(
const Svar& rh)
const{
2653 Svar clsobj=classObject();
2654 if(!clsobj.isClass())
return _obj->ptr()<rh.
value()->ptr();
2655 Svar lt_func=clsobj.
as<SvarClass>()[
"__lt__"];
2656 if(!lt_func.isFunction())
return _obj->ptr()<rh.
value()->ptr();
2657 Svar ret=lt_func(*
this,rh);
2658 assert(ret.
is<
bool>());
2659 return ret.
as<
bool>();
2662 inline std::ostream& operator <<(std::ostream& ost,
const Svar&
self)
2664 if(
self.isUndefined()) {
2672 auto cls=
self.classPtr();
2673 if(cls&&cls->__str__.isFunction()){
2674 Svar a = cls->__str__(
self);
2675 ost<<a.
as<std::string>();
2678 ost<<
"<"<<
self.typeName()<<
" at "<<
self.value()->ptr()<<
">";
2682 inline const Svar& Svar::True(){
2687 inline const Svar& Svar::False(){
2693 static Svar v(
new SvarValue());
2699 static Svar v=create<void*>(
nullptr);
2703 inline Svar& Svar::instance(){
2708 inline Svar Svar::loadFile(
const std::string& file_path)
2710 std::ifstream ifs(file_path);
2711 if(!ifs.is_open())
return Svar();
2713 auto getExtension=[](
const std::string& filename)->std::string{
2714 auto idx = filename.find_last_of(
'.');
2715 if (idx == std::string::npos)
2718 return filename.substr(idx+1);
2720 std::string ext=getExtension(file_path);
2726 Svar cls=Svar::instance()[
"__builtin__"][ext2cls[ext]];
2728 std::cerr<<
"Svar::loadFile don't support format "<<ext<<
".\n";
2733 if(cls.exist(
"loadFile"))
2734 return cls.call(
"loadFile",file_path);
2735 std::stringstream sst;
2737 while(std::getline(ifs,line)) sst<<line<<std::endl;
2738 return cls.call(
"load",sst.str());
2740 catch(SvarExeption e){
2741 std::cerr<<e.what();
2746 inline const Svar& SvarFunction::classObject()
const{
return SvarClass::instance<SvarFunction>();}
2748 inline std::ostream& operator<<(std::ostream& ost,
const SvarClass& rh){
2749 ost<<
"class "<<rh.__name__<<
"():\n";
2750 std::stringstream content;
2751 if(rh.__init__.isFunction()) content<<rh.__init__.as<SvarFunction>()<<std::endl<<std::endl;
2752 if(!rh.__doc__.empty()) content<<rh.__doc__<<std::endl;
2753 if(rh._methods.isObject()&&rh._methods.length()){
2754 content<<
"Methods defined here:\n";
2755 const SvarObject& methods=rh._methods.as<SvarObject>();
2756 auto varCopy=methods._var;
2757 for(std::pair<std::string,Svar> it:varCopy){
2758 content<<it.second.as<SvarFunction>()<<std::endl<<std::endl;
2762 while(std::getline(content,line)){ost<<
"| "<<line<<std::endl;}
2766 template <
typename T>
2767 class caster<std::vector<T> >{
2769 static Svar from(
const Svar& var){
2770 if(var.
is<std::vector<T>>())
return var;
2775 ret.reserve(var.
length());
2776 for(
const Svar& v:var.
as<SvarArray>()._var)
2784 static Svar to(
const std::vector<T>& var){
2790 template <
typename T>
2791 class caster<std::map<std::string,T> >{
2793 static Svar from(
const Svar& var){
2794 if(var.
is<std::map<std::string,T> >())
return var;
2798 std::map<std::string,T> ret;
2799 for(
const std::pair<std::string,Svar>& v:var.
as<SvarObject>()._var)
2801 ret.insert(std::make_pair(v.first,v.second.castAs<T>()));
2807 static Svar to(
const std::map<std::string,T>& var){
2808 return Svar::object(std::map<std::string,Svar>(var.begin(),var.end()));
2812 template <
typename K,
typename T>
2813 class caster<std::map<K,T> >{
2815 static Svar from(
const Svar& var){
2816 if(var.
is<std::map<K,T> >())
return var;
2821 for(
const std::pair<Svar,Svar>& v:var.
as<SvarObject>()._var)
2823 ret.insert(std::make_pair(v.first.castAs<K>(),v.second.castAs<T>()));
2829 static Svar to(
const std::map<K,T>& var){
2830 return Svar::dict(std::map<Svar,Svar>(var.begin(),var.end()));
2835 template <
typename T>
2836 class caster<std::shared_ptr<T> >{
2837 using H=std::shared_ptr<T>;
2839 static Svar from(
const Svar& var){
2840 if(var.
is<H>())
return var;
2843 auto h=
dynamic_cast<SvarPtrHolder<T,H>*
>(var.
value().get());
2848 static Svar to(
const std::shared_ptr<T>& var){
2850 return Svar((SvarValue*)
new SvarPtrHolder<T,std::shared_ptr<T>>(var));
2855 class caster<std::nullptr_t >{
2857 static Svar from(
const Svar& var){
2861 static Svar to(std::nullptr_t v){
2867 class caster<char[sz]>{
2869 static Svar to(
const char* v){
2870 return Svar(std::string(v));
2874 inline std::istream& operator >>(std::istream& ist,Svar&
self)
2876 Svar json=svar[
"__builtin__"][
"Json"];
2877 self=json.
call(
"load",std::string( (std::istreambuf_iterator<char>(ist)) , std::istreambuf_iterator<char>() ));
2881 #if !defined(__SVAR_NOBUILTIN__) 2890 static Svar load(
const std::string& in){
2891 Json parser(in,COMMENTS);
2892 Svar result = parser.parse_json(0);
2894 parser.consume_garbage();
2898 if (parser.i != in.size())
2899 return parser.fail(
"unexpected trailing " + esc(in[parser.i]));
2904 static std::string dump(Svar var){
2905 std::stringstream sst;
2911 Json(
const std::string& str_input, JsonParse parse_strategy=STANDARD)
2912 :str(str_input),i(0),failed(
false),strategy(parse_strategy){}
2918 const JsonParse strategy;
2919 const int max_depth = 200;
2922 Svar fail(std::string &&msg) {
2924 err = std::move(msg);
2926 throw SvarExeption(msg);
2930 template <
typename T>
2931 T fail(std::string &&msg,
const T err_ret) {
2933 err = std::move(msg);
2940 void consume_whitespace() {
2941 while (str[i] ==
' ' || str[i] ==
'\r' || str[i] ==
'\n' || str[i] ==
'\t')
2946 bool consume_comment() {
2947 bool comment_found =
false;
2948 if (str[i] ==
'/') {
2950 if (i == str.size())
2951 return fail(
"unexpected end of input after start of comment",
false);
2952 if (str[i] ==
'/') {
2955 while (i < str.size() && str[i] !=
'\n') {
2958 comment_found =
true;
2960 else if (str[i] ==
'*') {
2962 if (i > str.size()-2)
2963 return fail(
"unexpected end of input inside multi-line comment",
false);
2965 while (!(str[i] ==
'*' && str[i+1] ==
'/')) {
2967 if (i > str.size()-2)
2969 "unexpected end of input inside multi-line comment",
false);
2972 comment_found =
true;
2975 return fail(
"malformed comment",
false);
2977 return comment_found;
2981 void consume_garbage() {
2982 consume_whitespace();
2983 if(strategy == JsonParse::COMMENTS) {
2984 bool comment_found =
false;
2986 comment_found = consume_comment();
2988 consume_whitespace();
2990 while(comment_found);
2996 char get_next_token() {
2998 if (failed)
return (
char)0;
2999 if (i == str.size())
3000 return fail(
"unexpected end of input", (
char)0);
3006 void encode_utf8(
long pt, std::string & out) {
3011 out +=
static_cast<char>(pt);
3012 }
else if (pt < 0x800) {
3013 out +=
static_cast<char>((pt >> 6) | 0xC0);
3014 out +=
static_cast<char>((pt & 0x3F) | 0x80);
3015 }
else if (pt < 0x10000) {
3016 out +=
static_cast<char>((pt >> 12) | 0xE0);
3017 out +=
static_cast<char>(((pt >> 6) & 0x3F) | 0x80);
3018 out +=
static_cast<char>((pt & 0x3F) | 0x80);
3020 out +=
static_cast<char>((pt >> 18) | 0xF0);
3021 out +=
static_cast<char>(((pt >> 12) & 0x3F) | 0x80);
3022 out +=
static_cast<char>(((pt >> 6) & 0x3F) | 0x80);
3023 out +=
static_cast<char>((pt & 0x3F) | 0x80);
3028 static inline std::string esc(
char c) {
3030 if (static_cast<uint8_t>(c) >= 0x20 && static_cast<uint8_t>(c) <= 0x7f) {
3031 snprintf(buf,
sizeof buf,
"'%c' (%d)", c, c);
3033 snprintf(buf,
sizeof buf,
"(%d)", c);
3035 return std::string(buf);
3038 static inline bool in_range(
long x,
long lower,
long upper) {
3039 return (x >= lower && x <= upper);
3043 std::string parse_string() {
3045 long last_escaped_codepoint = -1;
3047 if (i == str.size())
3048 return fail(
"unexpected end of input in string",
"");
3053 encode_utf8(last_escaped_codepoint, out);
3057 if (in_range(ch, 0, 0x1f))
3058 return fail(
"unescaped " + esc(ch) +
" in string",
"");
3062 encode_utf8(last_escaped_codepoint, out);
3063 last_escaped_codepoint = -1;
3069 if (i == str.size())
3070 return fail(
"unexpected end of input in string",
"");
3076 std::string esc = str.substr(i, 4);
3080 if (esc.length() < 4) {
3081 return fail(
"bad \\u escape: " + esc,
"");
3083 for (
size_t j = 0; j < 4; j++) {
3084 if (!in_range(esc[j],
'a',
'f') && !in_range(esc[j],
'A',
'F')
3085 && !in_range(esc[j],
'0',
'9'))
3086 return fail(
"bad \\u escape: " + esc,
"");
3089 long codepoint = strtol(esc.data(),
nullptr, 16);
3095 if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF)
3096 && in_range(codepoint, 0xDC00, 0xDFFF)) {
3099 encode_utf8((((last_escaped_codepoint - 0xD800) << 10)
3100 | (codepoint - 0xDC00)) + 0x10000, out);
3101 last_escaped_codepoint = -1;
3103 encode_utf8(last_escaped_codepoint, out);
3104 last_escaped_codepoint = codepoint;
3111 encode_utf8(last_escaped_codepoint, out);
3112 last_escaped_codepoint = -1;
3116 }
else if (ch ==
'f') {
3118 }
else if (ch ==
'n') {
3120 }
else if (ch ==
'r') {
3122 }
else if (ch ==
't') {
3124 }
else if (ch ==
'"' || ch ==
'\\' || ch ==
'/') {
3127 return fail(
"invalid escape character " + esc(ch),
"");
3133 Svar parse_number() {
3134 size_t start_pos = i;
3140 if (str[i] ==
'0') {
3142 if (in_range(str[i],
'0',
'9'))
3143 return fail(
"leading 0s not permitted in numbers");
3144 }
else if (in_range(str[i],
'1',
'9')) {
3146 while (in_range(str[i],
'0',
'9'))
3149 return fail(
"invalid " + esc(str[i]) +
" in number");
3152 if (str[i] !=
'.' && str[i] !=
'e' && str[i] !=
'E' 3153 && (i - start_pos) <= static_cast<size_t>(std::numeric_limits<int>::digits10)) {
3154 return std::atoi(str.c_str() + start_pos);
3158 if (str[i] ==
'.') {
3160 if (!in_range(str[i],
'0',
'9'))
3161 return fail(
"at least one digit required in fractional part");
3163 while (in_range(str[i],
'0',
'9'))
3168 if (str[i] ==
'e' || str[i] ==
'E') {
3171 if (str[i] ==
'+' || str[i] ==
'-')
3174 if (!in_range(str[i],
'0',
'9'))
3175 return fail(
"at least one digit required in exponent");
3177 while (in_range(str[i],
'0',
'9'))
3181 return std::strtod(str.c_str() + start_pos,
nullptr);
3186 Svar expect(
const std::string &expected, Svar res) {
3189 if (str.compare(i, expected.length(), expected) == 0) {
3190 i += expected.length();
3193 return fail(
"parse error: expected " + expected +
", got " + str.substr(i, expected.length()));
3198 Svar parse_json(
int depth) {
3199 if (depth > max_depth) {
3200 return fail(
"exceeded maximum nesting depth");
3203 char ch = get_next_token();
3207 if (ch ==
'-' || (ch >=
'0' && ch <=
'9')) {
3209 return parse_number();
3213 return expect(
"true",
true);
3216 return expect(
"false",
false);
3219 return expect(
"null", Svar());
3222 return parse_string();
3225 std::map<std::string, Svar> data;
3226 ch = get_next_token();
3232 return fail(
"expected '\"' in object, got " + esc(ch));
3234 std::string key = parse_string();
3238 ch = get_next_token();
3240 return fail(
"expected ':' in object, got " + esc(ch));
3242 data[std::move(key)] = parse_json(depth + 1);
3246 ch = get_next_token();
3250 return fail(
"expected ',' in object, got " + esc(ch));
3252 ch = get_next_token();
3258 std::vector<Svar> data;
3259 ch = get_next_token();
3265 data.push_back(parse_json(depth + 1));
3269 ch = get_next_token();
3273 return fail(
"expected ',' in list, got " + esc(ch));
3275 ch = get_next_token();
3283 ch = get_next_token();
3290 return fail(
"expected value, got " + esc(ch));
3297 SvarClass::Class<int32_t>().setName(
"int");
3298 SvarClass::Class<int64_t>().setName(
"int64_t");
3299 SvarClass::Class<uint32_t>().setName(
"uint32_t");
3300 SvarClass::Class<uint64_t>().setName(
"uint64_t");
3301 SvarClass::Class<unsigned char>().setName(
"uchar");
3302 SvarClass::Class<char>().setName(
"char");
3303 SvarClass::Class<float>().setName(
"float");
3304 SvarClass::Class<double>().setName(
"double");
3305 SvarClass::Class<std::string>().setName(
"str");
3306 SvarClass::Class<bool>().setName(
"bool");
3307 SvarClass::Class<SvarDict>().setName(
"dict");
3308 SvarClass::Class<SvarObject>().setName(
"object");
3309 SvarClass::Class<SvarArray>().setName(
"array");
3310 SvarClass::Class<SvarFunction>().setName(
"function");
3311 SvarClass::Class<SvarClass>().setName(
"class");
3312 SvarClass::Class<Svar>().setName(
"svar");
3314 SvarClass::Class<void>()
3315 .def(
"__str__",[](Svar){
return "Undefined";})
3318 SvarClass::Class<int>()
3319 .def(
"__init__",&SvarBuiltin::int_create)
3320 .def(
"__double__",[](
int i){
return (
double)i;})
3321 .def(
"__bool__",[](
int i){
return (
bool)i;})
3322 .def(
"__str__",[](
int i){
return Svar::toString(i);})
3323 .def(
"__eq__",[](
int self,
int rh){
return self==rh;})
3324 .def(
"__lt__",[](
int self,
int rh){
return self<rh;})
3325 .def(
"__add__",[](
int self,Svar rh)->Svar{
3326 if(rh.
is<
int>())
return Svar(
self+rh.
as<
int>());
3327 if(rh.
is<
double>())
return Svar(
self+rh.
as<
double>());
3330 .def(
"__sub__",[](
int self,Svar rh)->Svar{
3331 if(rh.
is<
int>())
return Svar(
self-rh.
as<
int>());
3332 if(rh.
is<
double>())
return Svar(
self-rh.
as<
double>());
3335 .def(
"__mul__",[](
int self,Svar rh)->Svar{
3336 if(rh.
is<
int>())
return Svar(
self*rh.
as<
int>());
3337 if(rh.
is<
double>())
return Svar(
self*rh.
as<
double>());
3340 .def(
"__div__",[](
int self,Svar rh){
3341 if(rh.
is<
int>())
return Svar(
self/rh.
as<
int>());
3342 if(rh.
is<
double>())
return Svar(
self/rh.
as<
double>());
3345 .def(
"__mod__",[](
int self,
int rh){
3348 .def(
"__neg__",[](
int self){
return -
self;})
3349 .def(
"__xor__",[](
int self,
int rh){
return self^rh;})
3350 .def(
"__or__",[](
int self,
int rh){
return self|rh;})
3351 .def(
"__and__",[](
int self,
int rh){
return self&rh;});
3353 SvarClass::Class<bool>()
3354 .def(
"__int__",[](
bool b){
return (
int)b;})
3355 .def(
"__double__",[](
bool b){
return (
double)b;})
3356 .def(
"__str__",[](
bool b){
return Svar::toString(b);})
3357 .def(
"__eq__",[](
bool self,
bool rh){
return self==rh;});
3359 SvarClass::Class<double>()
3360 .def(
"__int__",[](
double d){
return (
int)d;})
3361 .def(
"__bool__",[](
double d){
return (
bool)d;})
3362 .def(
"__str__",[](
double d){
return Svar::toString(d);})
3363 .def(
"__eq__",[](
double self,
double rh){
return self==rh;})
3364 .def(
"__lt__",[](
double self,
double rh){
return self<rh;})
3365 .def(
"__neg__",[](
double self){
return -
self;})
3366 .def(
"__add__",[](
double self,
double rh){
return self+rh;})
3367 .def(
"__sub__",[](
double self,
double rh){
return self-rh;})
3368 .def(
"__mul__",[](
double self,
double rh){
return self*rh;})
3369 .def(
"__div__",[](
double self,
double rh){
return self/rh;})
3370 .def(
"__invert__",[](
double self){
return 1./
self;});
3372 SvarClass::Class<std::string>()
3373 .def(
"__len__",[](
const Svar&
self){
return self.as<std::string>().size();})
3374 .def(
"__str__",[](Svar
self){
3376 dump(
self.as<std::string>(),out);
3379 .def(
"__add__",[](
const std::string&
self,std::string rh){
3380 std::cerr<<
"added "<<
self<<rh;
3383 .def(
"__eq__",[](
const std::string&
self,std::string rh){
return self==rh;})
3384 .def(
"__lt__",[](
const std::string&
self,std::string rh){
return self<rh;});
3386 SvarClass::Class<char const*>()
3387 .def(
"__str__",[](
char const* str){
3388 return std::string(str);
3391 SvarClass::Class<SvarArray>()
3392 .def(
"__getitem__",[](Svar
self,
int i){
3393 SvarArray& array=
self.as<SvarArray>();
3396 .def(
"__delitem__",&SvarArray::erase)
3397 .def(
"__str__",[](Svar
self){
return Svar::toString(
self.as<SvarArray>());})
3398 .def(
"__iter__",[](Svar
self)->Svar{
3399 static Svar arrayinteratorClass;
3400 if(!arrayinteratorClass.isClass()){
3401 SvarClass* cls=
new SvarClass(
"arrayiterator",
typeid(SvarObject));
3402 arrayinteratorClass=(SvarValue*)cls;
3403 cls->def(
"next",[](Svar iter){
3404 Svar arrObj=iter[
"array"];
3405 SvarArray& array=arrObj.
as<SvarArray>();
3406 int& index=iter.
get<
int>(
"index",0);
3407 if(index<(
int)array.length()){
3408 return array[index++];
3415 iter.
as<SvarObject>()._class=arrayinteratorClass;
3418 .def(
"__add__",[](Svar
self,Svar other){
3419 return self.as<SvarArray>()+other;
3421 .def(
"append",&SvarArray::append);
3423 SvarClass::Class<SvarDict>()
3424 .def(
"__getitem__",&SvarDict::operator [])
3425 .def(
"__delitem__",&SvarDict::erase);
3428 SvarClass::Class<SvarObject>()
3429 .def(
"__getitem__",&SvarObject::operator [])
3430 .def(
"__delitem__",&SvarObject::erase)
3431 .def(
"__str__",[](Svar
self){
return Svar::toString(
self.as<SvarObject>());})
3432 .def(
"__iter__",&SvarObject::iter)
3433 .def(
"update",&SvarObject::update);
3435 SvarClass::Class<SvarFunction>()
3436 .def(
"__doc__",[](Svar
self){
return Svar::toString(
self.as<SvarFunction>());});
3438 SvarClass::Class<SvarClass>()
3439 .def(
"__getitem__",[](SvarClass&
self,
const std::string& i)->Svar{
return self[i];})
3440 .def(
"doc",[](Svar
self){
return Svar::toString(
self.as<SvarClass>());});
3442 SvarClass::Class<Json>()
3443 .def_static(
"load",&Json::load)
3444 .def_static(
"dump",&Json::dump);
3446 Svar::instance()[
"__builtin__"][
"Json"]=SvarClass::instance<Json>();
3447 Svar::instance()[
"__builtin__"][
"version"]=SVAR_VERSION;
3450 static Svar int_create(Svar rh){
3451 if(rh.
is<
int>())
return rh;
3452 if(rh.
is<std::string>())
return (Svar)std::atoi(rh.
as<std::string>().c_str());
3453 if(rh.
is<
double>())
return (Svar)(int)rh.
as<
double>();
3454 if(rh.
is<
bool>())
return (Svar)(int)rh.
as<
bool>();
3456 throw SvarExeption(
"Can't construct int from "+rh.
typeName()+
".");
3459 static void dump(
const std::string &value, std::string &out) {
3461 for (
size_t i = 0; i < value.
length(); i++) {
3462 const char ch = value[i];
3465 }
else if (ch ==
'"') {
3467 }
else if (ch ==
'\b') {
3469 }
else if (ch ==
'\f') {
3471 }
else if (ch ==
'\n') {
3473 }
else if (ch ==
'\r') {
3475 }
else if (ch ==
'\t') {
3477 }
else if (static_cast<uint8_t>(ch) <= 0x1f) {
3479 snprintf(buf,
sizeof buf,
"\\u%04x", ch);
3481 }
else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80
3482 && static_cast<uint8_t>(value[i+2]) == 0xa8) {
3485 }
else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80
3486 && static_cast<uint8_t>(value[i+2]) == 0xa9) {
3498 static SvarBuiltin SvarBuiltinInitializerinstance;
SvarClass * classPtr() const
Return the class singleton pointer, return nullptr when failed.
Svar & def(const std::string &name, Func &&f)
Define a lambda function with name.
Definition: Svar.h:743
void push_back(const Svar &rh)
Append item when this is an array.
static Svar object(const std::map< std::string, Svar > &m={})
Create an Object instance.
Definition: Svar.h:632
const Svar & classObject() const
Return the class singleton, return Undefined when failed.
detail::enable_if_t< std::is_pointer< T >::value, T > castAs()
No cast is performed, directly return the c++ pointer, throw SvarException when failed.
Svar()
Default is Undefined.
Definition: Svar.h:565
Svar & def(const std::string &name, Svar funcOrClass)
Define a class or function with name.
const T & as() const
Should always check type with "is<T>()" first.
static Svar create(const T &t)
Create any other c++ type instance, T need to be a copyable type.
static Svar dict(const std::map< Svar, Svar > &m={})
Create a Dict instance.
Definition: Svar.h:638
T arg(const std::string &name, T def, const std::string &help)
Register default required arguments.
void set(const std::string &name, const T &def, bool parse_dot=false)
Set the child "name" to "create<T>(def)".
Svar & getOrCreate(const std::string &name, bool parse_dot=false)
This is dangerous since the returned Svar may be free by other threads, TAKE CARE! ...
Svar operator()(Args...args) const
Call this as function or class.
static Svar lambda(Func &&f, const Extra &...extra)
Construct a cpp_function from a lambda function (possibly with internal state)
bool is() const
Is holding a type T value?
Svar(bool b)
Wrap bool to static instances.
Definition: Svar.h:580
Svar cast() const
Success: return a Svar holding T instance, Failed: return Undefined.
std::vector< std::string > parseMain(int argc, char **argv)
Parse the "main(int argc,char** argv)" arguments.
Svar call(const std::string function, Args...args) const
Call function or class with name and arguments.
static Svar json(const std::string &str)
Create from Json String.
Definition: Svar.h:641
size_t length() const
Return the item numbers when it is an array, object or dict.
std::string typeName() const
Return the value typename.
int help()
Format print version, usages and arguments.
Definition: Svar.h:760
void erase(const Svar &id)
For Object: dot compute and call delitem Others : directly call delitem
bool exist(const Svar &id) const
For Object: dot compute and find the member For Array, Dict and Class, check if the item is not Undef...
static const Svar & Null()
Null is corrosponding to the c++ nullptr.
The Svar class, A Tiny Modern C++ Header Brings Unified Interface for Different Languages.
Definition: Svar.h:561
const std::shared_ptr< SvarValue > & value() const
Return the raw holder.
Definition: Svar.h:837
Svar(int i)
Wrap a int.
Definition: Svar.h:583
std::type_index cpptype() const
Return the value typeid.
static std::string printTable(std::vector< std::pair< int, std::string >> line)
Format print strings as table.
T & get(const std::string &name, T def, bool parse_dot=false)
Force to return the children as type T, cast is performed, otherwise the old value will be droped and...
static Svar array(const std::vector< Svar > &vec={})
Create an Array instance.
Definition: Svar.h:635
Svar(double d)
Wrap a double.
Definition: Svar.h:586
static const Svar & Undefined()
Undefined is the default value when Svar is not assigned a valid value It corrosponding to the c++ vo...
std::string helpInfo()
Format print version, usages and arguments as string.
Svar(SvarValue *v)
Construct from SvarValue pointer.
Definition: Svar.h:568