From 5872b020fa383e25aedc58208d690361a56a3196 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 16 Mar 2016 18:32:10 -0600 Subject: [PATCH 01/27] First pass at updating JSON lib * eliminate manual memory management --- include/chaiscript/utility/json.hpp | 244 ++++++++++++---------------- unittests/boxed_cast_test.cpp | 4 +- 2 files changed, 102 insertions(+), 146 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index bdcbb7c3..e2c7ccd3 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -68,20 +68,55 @@ namespace { class JSON { - union BackingData { - BackingData( double d ) : Float( d ){} - BackingData( long l ) : Int( l ){} - BackingData( bool b ) : Bool( b ){} - BackingData( string s ) : String( new string( s ) ){} - BackingData() : Int( 0 ){} + struct Internal { + template + auto clone(const std::unique_ptr &ptr) { + if (ptr != nullptr) { + return std::make_unique(*ptr); + } else { + return std::unique_ptr(nullptr); + } + } - deque *List; - map *Map; - string *String; + Internal( double d ) : Float( d ){} + Internal( long l ) : Int( l ){} + Internal( bool b ) : Bool( b ){} + Internal( string s ) : String(std::make_unique(std::move(s))) {} + Internal() : Int( 0 ){} + + Internal(const Internal &other) + : List(clone(other.List)), + Map(clone(other.Map)), + String(clone(other.String)), + Float(other.Float), + Int(other.Int), + Bool(other.Bool) + { + } + + Internal &operator=(const Internal &other) + { + List = clone(other.List); + Map = clone(other.Map); + String = clone(other.String); + Float = other.Float; + Int = other.Int; + Bool = other.Bool; + return *this; + } + + Internal(Internal &&) = default; + Internal &operator=(Internal &&) = default; + + std::unique_ptr> List; + std::unique_ptr> Map; + std::unique_ptr String; double Float; long Int; bool Bool; - } Internal; + }; + + Internal internal; public: enum class Class { @@ -96,11 +131,11 @@ class JSON template class JSONWrapper { - Container *object; + Container *object = nullptr; public: JSONWrapper( Container *val ) : object( val ) {} - JSONWrapper( std::nullptr_t ) : object( nullptr ) {} + JSONWrapper( std::nullptr_t ) {} typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); } typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); } @@ -110,120 +145,45 @@ class JSON template class JSONConstWrapper { - const Container *object; + const Container *object = nullptr; public: JSONConstWrapper( const Container *val ) : object( val ) {} - JSONConstWrapper( std::nullptr_t ) : object( nullptr ) {} + JSONConstWrapper( std::nullptr_t ) {} typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); } typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); } }; - JSON() : Internal(), Type( Class::Null ){} + JSON() : internal(), Type( Class::Null ){} explicit JSON(Class type) - : Internal(), Type(Class::Null) + : internal(), Type(Class::Null) { SetType( type ); } JSON( initializer_list list ) - : Internal(), Type(Class::Null) + : internal(), Type(Class::Null) { SetType( Class::Object ); for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) operator[]( i->ToString() ) = *std::next( i ); } - JSON( JSON&& other ) - : Internal( other.Internal ) - , Type( other.Type ) - { other.Type = Class::Null; other.Internal.Map = nullptr; } - - JSON& operator=( JSON&& other ) { - Internal = other.Internal; - Type = other.Type; - other.Internal.Map = nullptr; - other.Type = Class::Null; - return *this; - } - - JSON( const JSON &other ) { - switch( other.Type ) { - case Class::Object: - Internal.Map = - new map( other.Internal.Map->begin(), - other.Internal.Map->end() ); - break; - case Class::Array: - Internal.List = - new deque( other.Internal.List->begin(), - other.Internal.List->end() ); - break; - case Class::String: - Internal.String = - new string( *other.Internal.String ); - break; - default: - Internal = other.Internal; - } - Type = other.Type; - } - - JSON& operator=( const JSON &other ) { - if (&other == this) return *this; - - switch( other.Type ) { - case Class::Object: - Internal.Map = - new map( other.Internal.Map->begin(), - other.Internal.Map->end() ); - break; - case Class::Array: - Internal.List = - new deque( other.Internal.List->begin(), - other.Internal.List->end() ); - break; - case Class::String: - Internal.String = - new string( *other.Internal.String ); - break; - default: - Internal = other.Internal; - } - Type = other.Type; - return *this; - } - - ~JSON() { - switch( Type ) { - case Class::Array: - delete Internal.List; - break; - case Class::Object: - delete Internal.Map; - break; - case Class::String: - delete Internal.String; - break; - default:; - } - } + template + JSON( T b, typename enable_if::value>::type* = nullptr ) : internal( b ), Type( Class::Boolean ){} template - JSON( T b, typename enable_if::value>::type* = nullptr ) : Internal( b ), Type( Class::Boolean ){} + JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : internal( long(i) ), Type( Class::Integral ){} template - JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : Internal( long(i) ), Type( Class::Integral ){} + JSON( T f, typename enable_if::value>::type* = nullptr ) : internal( double(f) ), Type( Class::Floating ){} template - JSON( T f, typename enable_if::value>::type* = nullptr ) : Internal( double(f) ), Type( Class::Floating ){} + JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( string( s ) ), Type( Class::String ){} - template - JSON( T s, typename enable_if::value>::type* = nullptr ) : Internal( string( s ) ), Type( Class::String ){} - - JSON( std::nullptr_t ) : Internal(), Type( Class::Null ){} + JSON( std::nullptr_t ) : Type( Class::Null ){} static JSON Make( Class type ) { return JSON(type); @@ -233,7 +193,7 @@ class JSON template void append( T arg ) { - SetType( Class::Array ); Internal.List->emplace_back( arg ); + SetType( Class::Array ); internal.List->emplace_back( arg ); } template @@ -243,32 +203,32 @@ class JSON template typename enable_if::value, JSON&>::type operator=( T b ) { - SetType( Class::Boolean ); Internal.Bool = b; return *this; + SetType( Class::Boolean ); internal.Bool = b; return *this; } template typename enable_if::value && !is_same::value, JSON&>::type operator=( T i ) { - SetType( Class::Integral ); Internal.Int = i; return *this; + SetType( Class::Integral ); internal.Int = i; return *this; } template typename enable_if::value, JSON&>::type operator=( T f ) { - SetType( Class::Floating ); Internal.Float = f; return *this; + SetType( Class::Floating ); internal.Float = f; return *this; } template typename enable_if::value, JSON&>::type operator=( T s ) { - SetType( Class::String ); *Internal.String = string( s ); return *this; + SetType( Class::String ); *internal.String = string( s ); return *this; } JSON& operator[]( const string &key ) { - SetType( Class::Object ); return Internal.Map->operator[]( key ); + SetType( Class::Object ); return internal.Map->operator[]( key ); } JSON& operator[]( const size_t index ) { SetType( Class::Array ); - if( index >= Internal.List->size() ) Internal.List->resize( index + 1 ); - return Internal.List->operator[]( index ); + if( index >= internal.List->size() ) internal.List->resize( index + 1 ); + return internal.List->operator[]( index ); } JSON &at( const string &key ) { @@ -276,7 +236,7 @@ class JSON } const JSON &at( const string &key ) const { - return Internal.Map->at( key ); + return internal.Map->at( key ); } JSON &at( unsigned index ) { @@ -284,27 +244,27 @@ class JSON } const JSON &at( unsigned index ) const { - return Internal.List->at( index ); + return internal.List->at( index ); } int length() const { if( Type == Class::Array ) - return static_cast(Internal.List->size()); + return static_cast(internal.List->size()); else return -1; } bool hasKey( const string &key ) const { if( Type == Class::Object ) - return Internal.Map->find( key ) != Internal.Map->end(); + return internal.Map->find( key ) != internal.Map->end(); return false; } int size() const { if( Type == Class::Object ) - return static_cast(Internal.Map->size()); + return static_cast(internal.Map->size()); else if( Type == Class::Array ) - return static_cast(Internal.List->size()); + return static_cast(internal.List->size()); else return -1; } @@ -317,49 +277,49 @@ class JSON string ToString() const { bool b; return ToString( b ); } string ToString( bool &ok ) const { ok = (Type == Class::String); - return ok ? *Internal.String : string(""); + return ok ? *internal.String : string(""); } double ToFloat() const { bool b; return ToFloat( b ); } double ToFloat( bool &ok ) const { ok = (Type == Class::Floating); - return ok ? Internal.Float : 0.0; + return ok ? internal.Float : 0.0; } long ToInt() const { bool b; return ToInt( b ); } long ToInt( bool &ok ) const { ok = (Type == Class::Integral); - return ok ? Internal.Int : 0; + return ok ? internal.Int : 0; } bool ToBool() const { bool b; return ToBool( b ); } bool ToBool( bool &ok ) const { ok = (Type == Class::Boolean); - return ok ? Internal.Bool : false; + return ok ? internal.Bool : false; } JSONWrapper> ObjectRange() { if( Type == Class::Object ) - return JSONWrapper>( Internal.Map ); + return JSONWrapper>( internal.Map.get() ); return JSONWrapper>( nullptr ); } JSONWrapper> ArrayRange() { if( Type == Class::Array ) - return JSONWrapper>( Internal.List ); + return JSONWrapper>( internal.List.get() ); return JSONWrapper>( nullptr ); } JSONConstWrapper> ObjectRange() const { if( Type == Class::Object ) - return JSONConstWrapper>( Internal.Map ); + return JSONConstWrapper>( internal.Map.get() ); return JSONConstWrapper>( nullptr ); } JSONConstWrapper> ArrayRange() const { if( Type == Class::Array ) - return JSONConstWrapper>( Internal.List ); + return JSONConstWrapper>( internal.List.get() ); return JSONConstWrapper>( nullptr ); } @@ -373,7 +333,7 @@ class JSON string s = "{\n"; bool skip = true; - for( auto &p : *Internal.Map ) { + for( auto &p : *internal.Map ) { if( !skip ) s += ",\n"; s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) ); skip = false; @@ -384,7 +344,7 @@ class JSON case Class::Array: { string s = "["; bool skip = true; - for( auto &p : *Internal.List ) { + for( auto &p : *internal.List ) { if( !skip ) s += ", "; s += p.dump( depth + 1, tab ); skip = false; @@ -393,13 +353,13 @@ class JSON return s; } case Class::String: - return "\"" + json_escape( *Internal.String ) + "\""; + return "\"" + json_escape( *internal.String ) + "\""; case Class::Floating: - return std::to_string( Internal.Float ); + return std::to_string( internal.Float ); case Class::Integral: - return std::to_string( Internal.Int ); + return std::to_string( internal.Int ); case Class::Boolean: - return Internal.Bool ? "true" : "false"; + return internal.Bool ? "true" : "false"; } throw std::runtime_error("Unhandled JSON type"); @@ -412,28 +372,24 @@ class JSON if( type == Type ) return; - switch( Type ) { - case Class::Object: delete Internal.Map; break; - case Class::Array: delete Internal.List; break; - case Class::String: delete Internal.String; break; - default:; - } + internal.Map.reset(); + internal.List.reset(); + internal.String.reset(); switch( type ) { - case Class::Null: Internal.Map = nullptr; break; - case Class::Object: Internal.Map = new map(); break; - case Class::Array: Internal.List = new deque(); break; - case Class::String: Internal.String = new string(); break; - case Class::Floating: Internal.Float = 0.0; break; - case Class::Integral: Internal.Int = 0; break; - case Class::Boolean: Internal.Bool = false; break; + case Class::Object: internal.Map = std::make_unique>(); break; + case Class::Array: internal.List = std::make_unique>(); break; + case Class::String: internal.String = std::make_unique(); break; + case Class::Floating: internal.Float = 0.0; break; + case Class::Integral: internal.Int = 0; break; + case Class::Boolean: internal.Bool = false; break; + case Class::Null: break; } Type = type; } private: - Class Type; }; @@ -594,7 +550,7 @@ namespace { else break; } - exp = std::stol( exp_str ); + exp = chaiscript::parse_num( exp_str ); } else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) { throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'"); @@ -602,12 +558,12 @@ namespace { --offset; if( isDouble ) - Number = std::stod( val ) * std::pow( 10, exp ); + Number = chaiscript::parse_num( val ) * std::pow( 10, exp ); else { if( !exp_str.empty() ) - Number = static_cast(std::stol( val )) * std::pow( 10, exp ); + Number = static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp ); else - Number = std::stol( val ); + Number = chaiscript::parse_num( val ); } return Number; } diff --git a/unittests/boxed_cast_test.cpp b/unittests/boxed_cast_test.cpp index 1e928749..a08a45eb 100644 --- a/unittests/boxed_cast_test.cpp +++ b/unittests/boxed_cast_test.cpp @@ -205,7 +205,7 @@ bool built_in_type_test(const T &initial, bool ispod) /** shared_ptr tests **/ - std::shared_ptr ip(new T(initial)); + auto ip = std::make_shared(initial); passed &= do_test(var(ip), true, true, true, true, true, true, true, true, true, true, @@ -220,7 +220,7 @@ bool built_in_type_test(const T &initial, bool ispod) ispod, ispod, ispod, false, true); /** const shared_ptr tests **/ - std::shared_ptr ipc(new T(initial)); + auto ipc = std::make_shared(T(initial)); passed &= do_test(var(ipc), true, true, false, true, false, true, false, true, false, true, From 6507a6e68ee8278a0c33dfbb28d7e9e3728f62ba Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 16 Mar 2016 18:52:02 -0600 Subject: [PATCH 02/27] Update naming of JSON functions --- include/chaiscript/utility/json.hpp | 155 ++++++++++++----------- include/chaiscript/utility/json_wrap.hpp | 12 +- 2 files changed, 84 insertions(+), 83 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index e2c7ccd3..e18dbe43 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -23,9 +23,6 @@ namespace json { -using std::map; -using std::deque; -using std::string; using std::enable_if; using std::initializer_list; using std::is_same; @@ -34,8 +31,8 @@ using std::is_integral; using std::is_floating_point; namespace { - string json_escape( const string &str ) { - string output; + std::string json_escape( const std::string &str ) { + std::string output; for( unsigned i = 0; i < str.length(); ++i ) switch( str[i] ) { case '\"': output += "\\\""; break; @@ -81,7 +78,7 @@ class JSON Internal( double d ) : Float( d ){} Internal( long l ) : Int( l ){} Internal( bool b ) : Bool( b ){} - Internal( string s ) : String(std::make_unique(std::move(s))) {} + Internal( std::string s ) : String(std::make_unique(std::move(s))) {} Internal() : Int( 0 ){} Internal(const Internal &other) @@ -108,9 +105,9 @@ class JSON Internal(Internal &&) = default; Internal &operator=(Internal &&) = default; - std::unique_ptr> List; - std::unique_ptr> Map; - std::unique_ptr String; + std::unique_ptr> List; + std::unique_ptr> Map; + std::unique_ptr String; double Float; long Int; bool Bool; @@ -155,20 +152,20 @@ class JSON typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); } }; - JSON() : internal(), Type( Class::Null ){} + JSON() = default; explicit JSON(Class type) : internal(), Type(Class::Null) { - SetType( type ); + set_type( type ); } JSON( initializer_list list ) : internal(), Type(Class::Null) { - SetType( Class::Object ); + set_type( Class::Object ); for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) - operator[]( i->ToString() ) = *std::next( i ); + operator[]( i->to_string() ) = *std::next( i ); } template @@ -181,7 +178,7 @@ class JSON JSON( T f, typename enable_if::value>::type* = nullptr ) : internal( double(f) ), Type( Class::Floating ){} template - JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( string( s ) ), Type( Class::String ){} + JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( std::string( s ) ), Type( Class::String ){} JSON( std::nullptr_t ) : Type( Class::Null ){} @@ -189,11 +186,11 @@ class JSON return JSON(type); } - static JSON Load( const string & ); + static JSON Load( const std::string & ); template void append( T arg ) { - SetType( Class::Array ); internal.List->emplace_back( arg ); + set_type( Class::Array ); internal.List->emplace_back( arg ); } template @@ -203,39 +200,39 @@ class JSON template typename enable_if::value, JSON&>::type operator=( T b ) { - SetType( Class::Boolean ); internal.Bool = b; return *this; + set_type( Class::Boolean ); internal.Bool = b; return *this; } template typename enable_if::value && !is_same::value, JSON&>::type operator=( T i ) { - SetType( Class::Integral ); internal.Int = i; return *this; + set_type( Class::Integral ); internal.Int = i; return *this; } template typename enable_if::value, JSON&>::type operator=( T f ) { - SetType( Class::Floating ); internal.Float = f; return *this; + set_type( Class::Floating ); internal.Float = f; return *this; } template - typename enable_if::value, JSON&>::type operator=( T s ) { - SetType( Class::String ); *internal.String = string( s ); return *this; + typename enable_if::value, JSON&>::type operator=( T s ) { + set_type( Class::String ); *internal.String = std::string( s ); return *this; } - JSON& operator[]( const string &key ) { - SetType( Class::Object ); return internal.Map->operator[]( key ); + JSON& operator[]( const std::string &key ) { + set_type( Class::Object ); return internal.Map->operator[]( key ); } JSON& operator[]( const size_t index ) { - SetType( Class::Array ); + set_type( Class::Array ); if( index >= internal.List->size() ) internal.List->resize( index + 1 ); return internal.List->operator[]( index ); } - JSON &at( const string &key ) { + JSON &at( const std::string &key ) { return operator[]( key ); } - const JSON &at( const string &key ) const { + const JSON &at( const std::string &key ) const { return internal.Map->at( key ); } @@ -248,90 +245,94 @@ class JSON } int length() const { - if( Type == Class::Array ) + if( Type == Class::Array ) { return static_cast(internal.List->size()); - else + } else { return -1; + } } - bool hasKey( const string &key ) const { - if( Type == Class::Object ) + bool hasKey( const std::string &key ) const { + if( Type == Class::Object ) { return internal.Map->find( key ) != internal.Map->end(); + } + return false; } int size() const { - if( Type == Class::Object ) + if( Type == Class::Object ) { return static_cast(internal.Map->size()); - else if( Type == Class::Array ) + } else if( Type == Class::Array ) { return static_cast(internal.List->size()); - else + } else { return -1; + } } Class JSONType() const { return Type; } /// Functions for getting primitives from the JSON object. - bool IsNull() const { return Type == Class::Null; } + bool is_null() const { return Type == Class::Null; } - string ToString() const { bool b; return ToString( b ); } - string ToString( bool &ok ) const { + std::string to_string() const { bool b; return to_string( b ); } + std::string to_string( bool &ok ) const { ok = (Type == Class::String); - return ok ? *internal.String : string(""); + return ok ? *internal.String : std::string(""); } - double ToFloat() const { bool b; return ToFloat( b ); } - double ToFloat( bool &ok ) const { + double to_float() const { bool b; return to_float( b ); } + double to_float( bool &ok ) const { ok = (Type == Class::Floating); return ok ? internal.Float : 0.0; } - long ToInt() const { bool b; return ToInt( b ); } - long ToInt( bool &ok ) const { + long to_int() const { bool b; return to_int( b ); } + long to_int( bool &ok ) const { ok = (Type == Class::Integral); return ok ? internal.Int : 0; } - bool ToBool() const { bool b; return ToBool( b ); } - bool ToBool( bool &ok ) const { + bool to_bool() const { bool b; return to_bool( b ); } + bool to_bool( bool &ok ) const { ok = (Type == Class::Boolean); return ok ? internal.Bool : false; } - JSONWrapper> ObjectRange() { + JSONWrapper> object_range() { if( Type == Class::Object ) - return JSONWrapper>( internal.Map.get() ); - return JSONWrapper>( nullptr ); + return JSONWrapper>( internal.Map.get() ); + return JSONWrapper>( nullptr ); } - JSONWrapper> ArrayRange() { + JSONWrapper> array_range() { if( Type == Class::Array ) - return JSONWrapper>( internal.List.get() ); - return JSONWrapper>( nullptr ); + return JSONWrapper>( internal.List.get() ); + return JSONWrapper>( nullptr ); } - JSONConstWrapper> ObjectRange() const { + JSONConstWrapper> object_range() const { if( Type == Class::Object ) - return JSONConstWrapper>( internal.Map.get() ); - return JSONConstWrapper>( nullptr ); + return JSONConstWrapper>( internal.Map.get() ); + return JSONConstWrapper>( nullptr ); } - JSONConstWrapper> ArrayRange() const { + JSONConstWrapper> array_range() const { if( Type == Class::Array ) - return JSONConstWrapper>( internal.List.get() ); - return JSONConstWrapper>( nullptr ); + return JSONConstWrapper>( internal.List.get() ); + return JSONConstWrapper>( nullptr ); } - string dump( int depth = 1, string tab = " ") const { + std::string dump( int depth = 1, std::string tab = " ") const { switch( Type ) { case Class::Null: return "null"; case Class::Object: { - string pad = ""; + std::string pad = ""; for( int i = 0; i < depth; ++i, pad += tab ); - string s = "{\n"; + std::string s = "{\n"; bool skip = true; for( auto &p : *internal.Map ) { if( !skip ) s += ",\n"; @@ -342,7 +343,7 @@ class JSON return s; } case Class::Array: { - string s = "["; + std::string s = "["; bool skip = true; for( auto &p : *internal.List ) { if( !skip ) s += ", "; @@ -368,7 +369,7 @@ class JSON friend std::ostream& operator<<( std::ostream&, const JSON & ); private: - void SetType( Class type ) { + void set_type( Class type ) { if( type == Type ) return; @@ -377,8 +378,8 @@ class JSON internal.String.reset(); switch( type ) { - case Class::Object: internal.Map = std::make_unique>(); break; - case Class::Array: internal.List = std::make_unique>(); break; + case Class::Object: internal.Map = std::make_unique>(); break; + case Class::Array: internal.List = std::make_unique>(); break; case Class::String: internal.String = std::make_unique(); break; case Class::Floating: internal.Float = 0.0; break; case Class::Integral: internal.Int = 0; break; @@ -390,7 +391,7 @@ class JSON } private: - Class Type; + Class Type = Class::Null; }; inline JSON Array() { @@ -414,13 +415,13 @@ inline std::ostream& operator<<( std::ostream &os, const JSON &json ) { } namespace { - JSON parse_next( const string &, size_t & ); + JSON parse_next( const std::string &, size_t & ); - void consume_ws( const string &str, size_t &offset ) { + void consume_ws( const std::string &str, size_t &offset ) { while( isspace( str[offset] ) ) ++offset; } - JSON parse_object( const string &str, size_t &offset ) { + JSON parse_object( const std::string &str, size_t &offset ) { JSON Object = JSON::Make( JSON::Class::Object ); ++offset; @@ -437,7 +438,7 @@ namespace { } consume_ws( str, ++offset ); JSON Value = parse_next( str, offset ); - Object[Key.ToString()] = Value; + Object[Key.to_string()] = Value; consume_ws( str, offset ); if( str[offset] == ',' ) { @@ -454,7 +455,7 @@ namespace { return Object; } - JSON parse_array( const string &str, size_t &offset ) { + JSON parse_array( const std::string &str, size_t &offset ) { JSON Array = JSON::Make( JSON::Class::Array ); unsigned index = 0; @@ -482,8 +483,8 @@ namespace { return Array; } - JSON parse_string( const string &str, size_t &offset ) { - string val; + JSON parse_string( const std::string &str, size_t &offset ) { + std::string val; for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) { if( c == '\\' ) { switch( str[ ++offset ] ) { @@ -517,9 +518,9 @@ namespace { return JSON(val); } - JSON parse_number( const string &str, size_t &offset ) { + JSON parse_number( const std::string &str, size_t &offset ) { JSON Number; - string val, exp_str; + std::string val, exp_str; char c = '\0'; bool isDouble = false; long exp = 0; @@ -568,7 +569,7 @@ namespace { return Number; } - JSON parse_bool( const string &str, size_t &offset ) { + JSON parse_bool( const std::string &str, size_t &offset ) { JSON Bool; if( str.substr( offset, 4 ) == "true" ) { offset += 4; @@ -582,7 +583,7 @@ namespace { return Bool; } - JSON parse_null( const string &str, size_t &offset ) { + JSON parse_null( const std::string &str, size_t &offset ) { if( str.substr( offset, 4 ) != "null" ) { throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'"); } @@ -590,7 +591,7 @@ namespace { return JSON(); } - JSON parse_next( const string &str, size_t &offset ) { + JSON parse_next( const std::string &str, size_t &offset ) { char value; consume_ws( str, offset ); value = str[offset]; @@ -608,7 +609,7 @@ namespace { } } -inline JSON JSON::Load( const string &str ) { +inline JSON JSON::Load( const std::string &str ) { size_t offset = 0; return parse_next( str, offset ); } diff --git a/include/chaiscript/utility/json_wrap.hpp b/include/chaiscript/utility/json_wrap.hpp index d15528ff..3d4b0d47 100644 --- a/include/chaiscript/utility/json_wrap.hpp +++ b/include/chaiscript/utility/json_wrap.hpp @@ -30,7 +30,7 @@ namespace chaiscript { std::map m; - for (const auto &p : t_json.ObjectRange()) + for (const auto &p : t_json.object_range()) { m.insert(std::make_pair(p.first, from_json(p.second))); } @@ -41,7 +41,7 @@ namespace chaiscript { std::vector vec; - for (const auto &p : t_json.ArrayRange()) + for (const auto &p : t_json.array_range()) { vec.emplace_back(from_json(p)); } @@ -49,13 +49,13 @@ namespace chaiscript return Boxed_Value(vec); } case json::JSON::Class::String: - return Boxed_Value(t_json.ToString()); + return Boxed_Value(t_json.to_string()); case json::JSON::Class::Floating: - return Boxed_Value(t_json.ToFloat()); + return Boxed_Value(t_json.to_float()); case json::JSON::Class::Integral: - return Boxed_Value(t_json.ToInt()); + return Boxed_Value(t_json.to_int()); case json::JSON::Class::Boolean: - return Boxed_Value(t_json.ToBool()); + return Boxed_Value(t_json.to_bool()); } throw std::runtime_error("Unknown JSON type"); From bcc25222dd28d833919e587b680afd2c9a3c8da4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 16 Mar 2016 19:08:50 -0600 Subject: [PATCH 03/27] Code reorg to reduce anon namespace --- include/chaiscript/utility/json.hpp | 117 +++++++++++----------------- 1 file changed, 47 insertions(+), 70 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index e18dbe43..1cbaa6c1 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -30,38 +30,8 @@ using std::is_convertible; using std::is_integral; using std::is_floating_point; -namespace { - std::string json_escape( const std::string &str ) { - std::string output; - for( unsigned i = 0; i < str.length(); ++i ) - switch( str[i] ) { - case '\"': output += "\\\""; break; - case '\\': output += "\\\\"; break; - case '\b': output += "\\b"; break; - case '\f': output += "\\f"; break; - case '\n': output += "\\n"; break; - case '\r': output += "\\r"; break; - case '\t': output += "\\t"; break; - default : output += str[i]; break; - } - return output; - } - - bool isspace(const char c) - { -#ifdef CHAISCRIPT_MSVC - // MSVC warns on these line in some circumstances -#pragma warning(push) -#pragma warning(disable : 6330) -#endif - return ::isspace(c) != 0; -#ifdef CHAISCRIPT_MSVC -#pragma warning(pop) -#endif - } -} class JSON { @@ -153,6 +123,7 @@ class JSON }; JSON() = default; + JSON( std::nullptr_t ) {} explicit JSON(Class type) : internal(), Type(Class::Null) @@ -180,11 +151,7 @@ class JSON template JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( std::string( s ) ), Type( Class::String ){} - JSON( std::nullptr_t ) : Type( Class::Null ){} - static JSON Make( Class type ) { - return JSON(type); - } static JSON Load( const std::string & ); @@ -365,10 +332,25 @@ class JSON throw std::runtime_error("Unhandled JSON type"); } - - friend std::ostream& operator<<( std::ostream&, const JSON & ); + private: + static std::string json_escape( const std::string &str ) { + std::string output; + for( unsigned i = 0; i < str.length(); ++i ) + switch( str[i] ) { + case '\"': output += "\\\""; break; + case '\\': output += "\\\\"; break; + case '\b': output += "\\b"; break; + case '\f': output += "\\f"; break; + case '\n': output += "\\n"; break; + case '\r': output += "\\r"; break; + case '\t': output += "\\t"; break; + default : output += str[i]; break; + } + return output; + } + void set_type( Class type ) { if( type == Type ) return; @@ -394,35 +376,29 @@ class JSON Class Type = Class::Null; }; -inline JSON Array() { - return JSON::Make( JSON::Class::Array ); -} -template -inline JSON Array( T... args ) { - JSON arr = JSON::Make( JSON::Class::Array ); - arr.append( args... ); - return arr; -} +struct JSONParser { + static bool isspace(const char c) + { +#ifdef CHAISCRIPT_MSVC + // MSVC warns on these line in some circumstances +#pragma warning(push) +#pragma warning(disable : 6330) +#endif + return ::isspace(c) != 0; +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif -inline JSON Object() { - return JSON::Make( JSON::Class::Object ); -} -inline std::ostream& operator<<( std::ostream &os, const JSON &json ) { - os << json.dump(); - return os; -} - -namespace { - JSON parse_next( const std::string &, size_t & ); - - void consume_ws( const std::string &str, size_t &offset ) { - while( isspace( str[offset] ) ) ++offset; } - JSON parse_object( const std::string &str, size_t &offset ) { - JSON Object = JSON::Make( JSON::Class::Object ); + static void consume_ws( const std::string &str, size_t &offset ) { + while( isspace( str[offset] ) && offset <= str.size() ) ++offset; + } + + static JSON parse_object( const std::string &str, size_t &offset ) { + JSON Object( JSON::Class::Object ); ++offset; consume_ws( str, offset ); @@ -455,8 +431,8 @@ namespace { return Object; } - JSON parse_array( const std::string &str, size_t &offset ) { - JSON Array = JSON::Make( JSON::Class::Array ); + static JSON parse_array( const std::string &str, size_t &offset ) { + JSON Array( JSON::Class::Array ); unsigned index = 0; ++offset; @@ -483,7 +459,7 @@ namespace { return Array; } - JSON parse_string( const std::string &str, size_t &offset ) { + static JSON parse_string( const std::string &str, size_t &offset ) { std::string val; for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) { if( c == '\\' ) { @@ -518,7 +494,7 @@ namespace { return JSON(val); } - JSON parse_number( const std::string &str, size_t &offset ) { + static JSON parse_number( const std::string &str, size_t &offset ) { JSON Number; std::string val, exp_str; char c = '\0'; @@ -569,7 +545,7 @@ namespace { return Number; } - JSON parse_bool( const std::string &str, size_t &offset ) { + static JSON parse_bool( const std::string &str, size_t &offset ) { JSON Bool; if( str.substr( offset, 4 ) == "true" ) { offset += 4; @@ -583,7 +559,7 @@ namespace { return Bool; } - JSON parse_null( const std::string &str, size_t &offset ) { + static JSON parse_null( const std::string &str, size_t &offset ) { if( str.substr( offset, 4 ) != "null" ) { throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'"); } @@ -591,7 +567,7 @@ namespace { return JSON(); } - JSON parse_next( const std::string &str, size_t &offset ) { + static JSON parse_next( const std::string &str, size_t &offset ) { char value; consume_ws( str, offset ); value = str[offset]; @@ -607,11 +583,12 @@ namespace { } throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'"); } -} + +}; inline JSON JSON::Load( const std::string &str ) { - size_t offset = 0; - return parse_next( str, offset ); + size_t offset = 0; + return JSONParser::parse_next( str, offset ); } } // End Namespace json From dc8aa372c10c784ec133e1a42014bc91a0d3afa0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 16 Mar 2016 19:39:10 -0600 Subject: [PATCH 04/27] Less manual managing of JSON internal state --- include/chaiscript/utility/json.hpp | 188 ++++++++++++++++------------ 1 file changed, 109 insertions(+), 79 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 1cbaa6c1..502209e7 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -35,6 +35,18 @@ using std::is_floating_point; class JSON { + public: + enum class Class { + Null, + Object, + Array, + String, + Floating, + Integral, + Boolean + }; + + private: struct Internal { template auto clone(const std::unique_ptr &ptr) { @@ -45,11 +57,15 @@ class JSON } } - Internal( double d ) : Float( d ){} - Internal( long l ) : Int( l ){} - Internal( bool b ) : Bool( b ){} - Internal( std::string s ) : String(std::make_unique(std::move(s))) {} - Internal() : Int( 0 ){} + Internal( double d ) : Float( d ), Type(Class::Floating) {} + Internal( long l ) : Int( l ), Type(Class::Integral) {} + Internal( bool b ) : Bool( b ), Type(Class::Boolean) {} + Internal( std::string s ) : String(std::make_unique(std::move(s))), Type(Class::String) {} + Internal() : Type(Class::Null) {} + + Internal(Class t_type) { + set_type(t_type); + } Internal(const Internal &other) : List(clone(other.List)), @@ -57,7 +73,8 @@ class JSON String(clone(other.String)), Float(other.Float), Int(other.Int), - Bool(other.Bool) + Bool(other.Bool), + Type(other.Type) { } @@ -69,32 +86,48 @@ class JSON Float = other.Float; Int = other.Int; Bool = other.Bool; + Type = other.Type; return *this; } + void set_type( Class type ) { + if( type == Type ) { + return; + } + + Map.reset(); + List.reset(); + String.reset(); + + switch( type ) { + case Class::Object: Map = std::make_unique>(); break; + case Class::Array: List = std::make_unique>(); break; + case Class::String: String = std::make_unique(); break; + case Class::Floating: Float = 0.0; break; + case Class::Integral: Int = 0; break; + case Class::Boolean: Bool = false; break; + case Class::Null: break; + } + + Type = type; + } + Internal(Internal &&) = default; Internal &operator=(Internal &&) = default; std::unique_ptr> List; std::unique_ptr> Map; std::unique_ptr String; - double Float; - long Int; - bool Bool; + double Float = 0; + long Int = 0; + bool Bool = false; + + Class Type = Class::Null; }; Internal internal; public: - enum class Class { - Null, - Object, - Array, - String, - Floating, - Integral, - Boolean - }; template class JSONWrapper { @@ -126,30 +159,29 @@ class JSON JSON( std::nullptr_t ) {} explicit JSON(Class type) - : internal(), Type(Class::Null) + : internal(type) { - set_type( type ); } JSON( initializer_list list ) - : internal(), Type(Class::Null) + : internal(Class::Object) { - set_type( Class::Object ); - for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) + for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) { operator[]( i->to_string() ) = *std::next( i ); + } } template - JSON( T b, typename enable_if::value>::type* = nullptr ) : internal( b ), Type( Class::Boolean ){} + JSON( T b, typename enable_if::value>::type* = nullptr ) : internal( static_cast(b) ) {} template - JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : internal( long(i) ), Type( Class::Integral ){} + JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : internal( static_cast(i) ) {} template - JSON( T f, typename enable_if::value>::type* = nullptr ) : internal( double(f) ), Type( Class::Floating ){} + JSON( T f, typename enable_if::value>::type* = nullptr ) : internal( static_cast(f) ) {} template - JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( std::string( s ) ), Type( Class::String ){} + JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( static_cast(s) ) {} @@ -157,42 +189,53 @@ class JSON template void append( T arg ) { - set_type( Class::Array ); internal.List->emplace_back( arg ); + internal.set_type( Class::Array ); + internal.List->emplace_back( arg ); } template void append( T arg, U... args ) { - append( arg ); append( args... ); + append( arg ); + append( args... ); } template typename enable_if::value, JSON&>::type operator=( T b ) { - set_type( Class::Boolean ); internal.Bool = b; return *this; + internal = Internal(static_cast(b)); + return *this; } template typename enable_if::value && !is_same::value, JSON&>::type operator=( T i ) { - set_type( Class::Integral ); internal.Int = i; return *this; + internal = Internal(static_cast(i)); + return *this; } template typename enable_if::value, JSON&>::type operator=( T f ) { - set_type( Class::Floating ); internal.Float = f; return *this; + internal = Internal(static_cast(f)); + return *this; } template typename enable_if::value, JSON&>::type operator=( T s ) { - set_type( Class::String ); *internal.String = std::string( s ); return *this; + internal = Internal(static_cast(s)); + return *this; } JSON& operator[]( const std::string &key ) { - set_type( Class::Object ); return internal.Map->operator[]( key ); + internal.set_type( Class::Object ); + return internal.Map->operator[]( key ); } JSON& operator[]( const size_t index ) { - set_type( Class::Array ); - if( index >= internal.List->size() ) internal.List->resize( index + 1 ); + internal.set_type( Class::Array ); + if( index >= internal.List->size() ) { + internal.List->resize( index + 1 ); + } + return internal.List->operator[]( index ); + } JSON &at( const std::string &key ) { @@ -211,16 +254,16 @@ class JSON return internal.List->at( index ); } - int length() const { - if( Type == Class::Array ) { - return static_cast(internal.List->size()); + long length() const { + if( internal.Type == Class::Array ) { + return static_cast(internal.List->size()); } else { return -1; } } - bool hasKey( const std::string &key ) const { - if( Type == Class::Object ) { + bool has_key( const std::string &key ) const { + if( internal.Type == Class::Object ) { return internal.Map->find( key ) != internal.Map->end(); } @@ -228,76 +271,84 @@ class JSON } int size() const { - if( Type == Class::Object ) { + if( internal.Type == Class::Object ) { return static_cast(internal.Map->size()); - } else if( Type == Class::Array ) { + } else if( internal.Type == Class::Array ) { return static_cast(internal.List->size()); } else { return -1; } } - Class JSONType() const { return Type; } + Class JSONType() const { return internal.Type; } /// Functions for getting primitives from the JSON object. - bool is_null() const { return Type == Class::Null; } + bool is_null() const { return internal.Type == Class::Null; } std::string to_string() const { bool b; return to_string( b ); } std::string to_string( bool &ok ) const { - ok = (Type == Class::String); + ok = (internal.Type == Class::String); return ok ? *internal.String : std::string(""); } double to_float() const { bool b; return to_float( b ); } double to_float( bool &ok ) const { - ok = (Type == Class::Floating); + ok = (internal.Type == Class::Floating); return ok ? internal.Float : 0.0; } long to_int() const { bool b; return to_int( b ); } long to_int( bool &ok ) const { - ok = (Type == Class::Integral); + ok = (internal.Type == Class::Integral); return ok ? internal.Int : 0; } bool to_bool() const { bool b; return to_bool( b ); } bool to_bool( bool &ok ) const { - ok = (Type == Class::Boolean); + ok = (internal.Type == Class::Boolean); return ok ? internal.Bool : false; } JSONWrapper> object_range() { - if( Type == Class::Object ) + if( internal.Type == Class::Object ) { return JSONWrapper>( internal.Map.get() ); - return JSONWrapper>( nullptr ); + } else { + return JSONWrapper>( nullptr ); + } } JSONWrapper> array_range() { - if( Type == Class::Array ) + if( internal.Type == Class::Array ) { return JSONWrapper>( internal.List.get() ); - return JSONWrapper>( nullptr ); + } else { + return JSONWrapper>( nullptr ); + } } JSONConstWrapper> object_range() const { - if( Type == Class::Object ) + if( internal.Type == Class::Object ) { return JSONConstWrapper>( internal.Map.get() ); + } else { return JSONConstWrapper>( nullptr ); + } } JSONConstWrapper> array_range() const { - if( Type == Class::Array ) + if( internal.Type == Class::Array ) { return JSONConstWrapper>( internal.List.get() ); + } else { return JSONConstWrapper>( nullptr ); + } } - std::string dump( int depth = 1, std::string tab = " ") const { - switch( Type ) { + std::string dump( long depth = 1, std::string tab = " ") const { + switch( internal.Type ) { case Class::Null: return "null"; case Class::Object: { std::string pad = ""; - for( int i = 0; i < depth; ++i, pad += tab ); + for( long i = 0; i < depth; ++i, pad += tab ); std::string s = "{\n"; bool skip = true; @@ -351,29 +402,8 @@ class JSON return output; } - void set_type( Class type ) { - if( type == Type ) - return; - - internal.Map.reset(); - internal.List.reset(); - internal.String.reset(); - - switch( type ) { - case Class::Object: internal.Map = std::make_unique>(); break; - case Class::Array: internal.List = std::make_unique>(); break; - case Class::String: internal.String = std::make_unique(); break; - case Class::Floating: internal.Float = 0.0; break; - case Class::Integral: internal.Int = 0; break; - case Class::Boolean: internal.Bool = false; break; - case Class::Null: break; - } - - Type = type; - } private: - Class Type = Class::Null; }; From df9466e2a7351659a6ee07b103bec8b65577be7b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 16 Mar 2016 19:50:59 -0600 Subject: [PATCH 05/27] Remove unneeded overloads / make explicit --- include/chaiscript/utility/json.hpp | 70 ++++++------------------ include/chaiscript/utility/json_wrap.hpp | 16 ++---- 2 files changed, 20 insertions(+), 66 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 502209e7..22d2f93d 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -172,57 +172,21 @@ class JSON } template - JSON( T b, typename enable_if::value>::type* = nullptr ) : internal( static_cast(b) ) {} + explicit JSON( T b, typename enable_if::value>::type* = nullptr ) : internal( static_cast(b) ) {} template - JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : internal( static_cast(i) ) {} + explicit JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : internal( static_cast(i) ) {} template - JSON( T f, typename enable_if::value>::type* = nullptr ) : internal( static_cast(f) ) {} + explicit JSON( T f, typename enable_if::value>::type* = nullptr ) : internal( static_cast(f) ) {} template - JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( static_cast(s) ) {} + explicit JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( static_cast(s) ) {} static JSON Load( const std::string & ); - template - void append( T arg ) { - internal.set_type( Class::Array ); - internal.List->emplace_back( arg ); - } - - template - void append( T arg, U... args ) { - append( arg ); - append( args... ); - } - - template - typename enable_if::value, JSON&>::type operator=( T b ) { - internal = Internal(static_cast(b)); - return *this; - } - - template - typename enable_if::value && !is_same::value, JSON&>::type operator=( T i ) { - internal = Internal(static_cast(i)); - return *this; - } - - template - typename enable_if::value, JSON&>::type operator=( T f ) { - internal = Internal(static_cast(f)); - return *this; - } - - template - typename enable_if::value, JSON&>::type operator=( T s ) { - internal = Internal(static_cast(s)); - return *this; - } - JSON& operator[]( const std::string &key ) { internal.set_type( Class::Object ); return internal.Map->operator[]( key ); @@ -235,9 +199,9 @@ class JSON } return internal.List->operator[]( index ); - } + JSON &at( const std::string &key ) { return operator[]( key ); } @@ -254,6 +218,7 @@ class JSON return internal.List->at( index ); } + long length() const { if( internal.Type == Class::Array ) { return static_cast(internal.List->size()); @@ -525,7 +490,6 @@ struct JSONParser { } static JSON parse_number( const std::string &str, size_t &offset ) { - JSON Number; std::string val, exp_str; char c = '\0'; bool isDouble = false; @@ -564,29 +528,27 @@ struct JSONParser { } --offset; - if( isDouble ) - Number = chaiscript::parse_num( val ) * std::pow( 10, exp ); - else { - if( !exp_str.empty() ) - Number = static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp ); - else - Number = chaiscript::parse_num( val ); + if( isDouble ) { + return JSON(chaiscript::parse_num( val ) * std::pow( 10, exp )); + } else { + if( !exp_str.empty() ) { + return JSON(static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); + } else { + return JSON(chaiscript::parse_num( val )); + } } - return Number; } static JSON parse_bool( const std::string &str, size_t &offset ) { - JSON Bool; if( str.substr( offset, 4 ) == "true" ) { offset += 4; - Bool = true; + return JSON(true); } else if( str.substr( offset, 5 ) == "false" ) { offset += 5; - Bool = false; + return JSON(false); } else { throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'"); } - return Bool; } static JSON parse_null( const std::string &str, size_t &offset ) { diff --git a/include/chaiscript/utility/json_wrap.hpp b/include/chaiscript/utility/json_wrap.hpp index 3d4b0d47..aec927b0 100644 --- a/include/chaiscript/utility/json_wrap.hpp +++ b/include/chaiscript/utility/json_wrap.hpp @@ -102,32 +102,24 @@ namespace chaiscript try { Boxed_Number bn(t_bv); - json::JSON obj; if (Boxed_Number::is_floating_point(t_bv)) { - obj = bn.get_as(); + return json::JSON(bn.get_as()); } else { - obj = bn.get_as(); + return json::JSON(bn.get_as()); } - return obj; } catch (const chaiscript::detail::exception::bad_any_cast &) { // not a number } try { - bool b = boxed_cast(t_bv); - json::JSON obj; - obj = b; - return obj; + return json::JSON(boxed_cast(t_bv)); } catch (const chaiscript::exception::bad_boxed_cast &) { // not a bool } try { - std::string s = boxed_cast(t_bv); - json::JSON obj; - obj = s; - return obj; + return json::JSON(boxed_cast(t_bv)); } catch (const chaiscript::exception::bad_boxed_cast &) { // not a string } From 1cd7a1b97293586ebecc074ca3c490603a34fc9b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 16 Mar 2016 19:59:56 -0600 Subject: [PATCH 06/27] Change unsigned to size_t --- include/chaiscript/utility/json.hpp | 940 ++++++++++++++-------------- 1 file changed, 470 insertions(+), 470 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 22d2f93d..294901e1 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -36,19 +36,19 @@ using std::is_floating_point; class JSON { public: - enum class Class { - Null, - Object, - Array, - String, - Floating, - Integral, - Boolean - }; + enum class Class { + Null, + Object, + Array, + String, + Floating, + Integral, + Boolean + }; private: struct Internal { - template + template auto clone(const std::unique_ptr &ptr) { if (ptr != nullptr) { return std::make_unique(*ptr); @@ -57,524 +57,524 @@ class JSON } } - Internal( double d ) : Float( d ), Type(Class::Floating) {} - Internal( long l ) : Int( l ), Type(Class::Integral) {} - Internal( bool b ) : Bool( b ), Type(Class::Boolean) {} - Internal( std::string s ) : String(std::make_unique(std::move(s))), Type(Class::String) {} - Internal() : Type(Class::Null) {} + Internal( double d ) : Float( d ), Type(Class::Floating) {} + Internal( long l ) : Int( l ), Type(Class::Integral) {} + Internal( bool b ) : Bool( b ), Type(Class::Boolean) {} + Internal( std::string s ) : String(std::make_unique(std::move(s))), Type(Class::String) {} + Internal() : Type(Class::Null) {} - Internal(Class t_type) { - set_type(t_type); + Internal(Class t_type) { + set_type(t_type); + } + + Internal(const Internal &other) + : List(clone(other.List)), + Map(clone(other.Map)), + String(clone(other.String)), + Float(other.Float), + Int(other.Int), + Bool(other.Bool), + Type(other.Type) + { + } + + Internal &operator=(const Internal &other) + { + List = clone(other.List); + Map = clone(other.Map); + String = clone(other.String); + Float = other.Float; + Int = other.Int; + Bool = other.Bool; + Type = other.Type; + return *this; + } + + void set_type( Class type ) { + if( type == Type ) { + return; } - Internal(const Internal &other) - : List(clone(other.List)), - Map(clone(other.Map)), - String(clone(other.String)), - Float(other.Float), - Int(other.Int), - Bool(other.Bool), - Type(other.Type) - { + Map.reset(); + List.reset(); + String.reset(); + + switch( type ) { + case Class::Object: Map = std::make_unique>(); break; + case Class::Array: List = std::make_unique>(); break; + case Class::String: String = std::make_unique(); break; + case Class::Floating: Float = 0.0; break; + case Class::Integral: Int = 0; break; + case Class::Boolean: Bool = false; break; + case Class::Null: break; } - Internal &operator=(const Internal &other) - { - List = clone(other.List); - Map = clone(other.Map); - String = clone(other.String); - Float = other.Float; - Int = other.Int; - Bool = other.Bool; - Type = other.Type; - return *this; - } + Type = type; + } - void set_type( Class type ) { - if( type == Type ) { - return; - } + Internal(Internal &&) = default; + Internal &operator=(Internal &&) = default; - Map.reset(); - List.reset(); - String.reset(); + std::unique_ptr> List; + std::unique_ptr> Map; + std::unique_ptr String; + double Float = 0; + long Int = 0; + bool Bool = false; - switch( type ) { - case Class::Object: Map = std::make_unique>(); break; - case Class::Array: List = std::make_unique>(); break; - case Class::String: String = std::make_unique(); break; - case Class::Floating: Float = 0.0; break; - case Class::Integral: Int = 0; break; - case Class::Boolean: Bool = false; break; - case Class::Null: break; - } - - Type = type; - } - - Internal(Internal &&) = default; - Internal &operator=(Internal &&) = default; - - std::unique_ptr> List; - std::unique_ptr> Map; - std::unique_ptr String; - double Float = 0; - long Int = 0; - bool Bool = false; - - Class Type = Class::Null; + Class Type = Class::Null; }; Internal internal; - public: + public: - template - class JSONWrapper { - Container *object = nullptr; + template + class JSONWrapper { + Container *object = nullptr; - public: - JSONWrapper( Container *val ) : object( val ) {} - JSONWrapper( std::nullptr_t ) {} + public: + JSONWrapper( Container *val ) : object( val ) {} + JSONWrapper( std::nullptr_t ) {} - typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); } - typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); } - typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::iterator(); } - typename Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); } - }; + typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); } + typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); } + typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::iterator(); } + typename Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); } + }; - template - class JSONConstWrapper { - const Container *object = nullptr; + template + class JSONConstWrapper { + const Container *object = nullptr; - public: - JSONConstWrapper( const Container *val ) : object( val ) {} - JSONConstWrapper( std::nullptr_t ) {} + public: + JSONConstWrapper( const Container *val ) : object( val ) {} + JSONConstWrapper( std::nullptr_t ) {} - typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); } - typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); } - }; + typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); } + typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); } + }; - JSON() = default; - JSON( std::nullptr_t ) {} + JSON() = default; + JSON( std::nullptr_t ) {} - explicit JSON(Class type) - : internal(type) - { + explicit JSON(Class type) + : internal(type) + { + } + + JSON( initializer_list list ) + : internal(Class::Object) + { + for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) { + operator[]( i->to_string() ) = *std::next( i ); + } + } + + template + explicit JSON( T b, typename enable_if::value>::type* = nullptr ) : internal( static_cast(b) ) {} + + template + explicit JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : internal( static_cast(i) ) {} + + template + explicit JSON( T f, typename enable_if::value>::type* = nullptr ) : internal( static_cast(f) ) {} + + template + explicit JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( static_cast(s) ) {} + + + + static JSON Load( const std::string & ); + + JSON& operator[]( const std::string &key ) { + internal.set_type( Class::Object ); + return internal.Map->operator[]( key ); + } + + JSON& operator[]( const size_t index ) { + internal.set_type( Class::Array ); + if( index >= internal.List->size() ) { + internal.List->resize( index + 1 ); + } + + return internal.List->operator[]( index ); + } + + + JSON &at( const std::string &key ) { + return operator[]( key ); + } + + const JSON &at( const std::string &key ) const { + return internal.Map->at( key ); + } + + JSON &at( size_t index ) { + return operator[]( index ); + } + + const JSON &at( size_t index ) const { + return internal.List->at( index ); + } + + + long length() const { + if( internal.Type == Class::Array ) { + return static_cast(internal.List->size()); + } else { + return -1; + } + } + + bool has_key( const std::string &key ) const { + if( internal.Type == Class::Object ) { + return internal.Map->find( key ) != internal.Map->end(); + } + + return false; + } + + int size() const { + if( internal.Type == Class::Object ) { + return static_cast(internal.Map->size()); + } else if( internal.Type == Class::Array ) { + return static_cast(internal.List->size()); + } else { + return -1; + } + } + + Class JSONType() const { return internal.Type; } + + /// Functions for getting primitives from the JSON object. + bool is_null() const { return internal.Type == Class::Null; } + + std::string to_string() const { bool b; return to_string( b ); } + std::string to_string( bool &ok ) const { + ok = (internal.Type == Class::String); + return ok ? *internal.String : std::string(""); + } + + double to_float() const { bool b; return to_float( b ); } + double to_float( bool &ok ) const { + ok = (internal.Type == Class::Floating); + return ok ? internal.Float : 0.0; + } + + long to_int() const { bool b; return to_int( b ); } + long to_int( bool &ok ) const { + ok = (internal.Type == Class::Integral); + return ok ? internal.Int : 0; + } + + bool to_bool() const { bool b; return to_bool( b ); } + bool to_bool( bool &ok ) const { + ok = (internal.Type == Class::Boolean); + return ok ? internal.Bool : false; + } + + JSONWrapper> object_range() { + if( internal.Type == Class::Object ) { + return JSONWrapper>( internal.Map.get() ); + } else { + return JSONWrapper>( nullptr ); + } + } + + JSONWrapper> array_range() { + if( internal.Type == Class::Array ) { + return JSONWrapper>( internal.List.get() ); + } else { + return JSONWrapper>( nullptr ); + } + } + + JSONConstWrapper> object_range() const { + if( internal.Type == Class::Object ) { + return JSONConstWrapper>( internal.Map.get() ); + } else { + return JSONConstWrapper>( nullptr ); + } + } + + + JSONConstWrapper> array_range() const { + if( internal.Type == Class::Array ) { + return JSONConstWrapper>( internal.List.get() ); + } else { + return JSONConstWrapper>( nullptr ); + } + } + + std::string dump( long depth = 1, std::string tab = " ") const { + switch( internal.Type ) { + case Class::Null: + return "null"; + case Class::Object: { + std::string pad = ""; + for( long i = 0; i < depth; ++i, pad += tab ); + + std::string s = "{\n"; + bool skip = true; + for( auto &p : *internal.Map ) { + if( !skip ) s += ",\n"; + s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) ); + skip = false; + } + s += ( "\n" + pad.erase( 0, 2 ) + "}" ) ; + return s; + } + case Class::Array: { + std::string s = "["; + bool skip = true; + for( auto &p : *internal.List ) { + if( !skip ) s += ", "; + s += p.dump( depth + 1, tab ); + skip = false; + } + s += "]"; + return s; + } + case Class::String: + return "\"" + json_escape( *internal.String ) + "\""; + case Class::Floating: + return std::to_string( internal.Float ); + case Class::Integral: + return std::to_string( internal.Int ); + case Class::Boolean: + return internal.Bool ? "true" : "false"; + } + + throw std::runtime_error("Unhandled JSON type"); + } + + + private: + static std::string json_escape( const std::string &str ) { + std::string output; + for( size_t i = 0; i < str.length(); ++i ) + switch( str[i] ) { + case '\"': output += "\\\""; break; + case '\\': output += "\\\\"; break; + case '\b': output += "\\b"; break; + case '\f': output += "\\f"; break; + case '\n': output += "\\n"; break; + case '\r': output += "\\r"; break; + case '\t': output += "\\t"; break; + default : output += str[i]; break; } - - JSON( initializer_list list ) - : internal(Class::Object) - { - for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) { - operator[]( i->to_string() ) = *std::next( i ); - } - } - - template - explicit JSON( T b, typename enable_if::value>::type* = nullptr ) : internal( static_cast(b) ) {} - - template - explicit JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : internal( static_cast(i) ) {} - - template - explicit JSON( T f, typename enable_if::value>::type* = nullptr ) : internal( static_cast(f) ) {} - - template - explicit JSON( T s, typename enable_if::value>::type* = nullptr ) : internal( static_cast(s) ) {} + return output; + } - - static JSON Load( const std::string & ); - - JSON& operator[]( const std::string &key ) { - internal.set_type( Class::Object ); - return internal.Map->operator[]( key ); - } - - JSON& operator[]( const size_t index ) { - internal.set_type( Class::Array ); - if( index >= internal.List->size() ) { - internal.List->resize( index + 1 ); - } - - return internal.List->operator[]( index ); - } - - - JSON &at( const std::string &key ) { - return operator[]( key ); - } - - const JSON &at( const std::string &key ) const { - return internal.Map->at( key ); - } - - JSON &at( unsigned index ) { - return operator[]( index ); - } - - const JSON &at( unsigned index ) const { - return internal.List->at( index ); - } - - - long length() const { - if( internal.Type == Class::Array ) { - return static_cast(internal.List->size()); - } else { - return -1; - } - } - - bool has_key( const std::string &key ) const { - if( internal.Type == Class::Object ) { - return internal.Map->find( key ) != internal.Map->end(); - } - - return false; - } - - int size() const { - if( internal.Type == Class::Object ) { - return static_cast(internal.Map->size()); - } else if( internal.Type == Class::Array ) { - return static_cast(internal.List->size()); - } else { - return -1; - } - } - - Class JSONType() const { return internal.Type; } - - /// Functions for getting primitives from the JSON object. - bool is_null() const { return internal.Type == Class::Null; } - - std::string to_string() const { bool b; return to_string( b ); } - std::string to_string( bool &ok ) const { - ok = (internal.Type == Class::String); - return ok ? *internal.String : std::string(""); - } - - double to_float() const { bool b; return to_float( b ); } - double to_float( bool &ok ) const { - ok = (internal.Type == Class::Floating); - return ok ? internal.Float : 0.0; - } - - long to_int() const { bool b; return to_int( b ); } - long to_int( bool &ok ) const { - ok = (internal.Type == Class::Integral); - return ok ? internal.Int : 0; - } - - bool to_bool() const { bool b; return to_bool( b ); } - bool to_bool( bool &ok ) const { - ok = (internal.Type == Class::Boolean); - return ok ? internal.Bool : false; - } - - JSONWrapper> object_range() { - if( internal.Type == Class::Object ) { - return JSONWrapper>( internal.Map.get() ); - } else { - return JSONWrapper>( nullptr ); - } - } - - JSONWrapper> array_range() { - if( internal.Type == Class::Array ) { - return JSONWrapper>( internal.List.get() ); - } else { - return JSONWrapper>( nullptr ); - } - } - - JSONConstWrapper> object_range() const { - if( internal.Type == Class::Object ) { - return JSONConstWrapper>( internal.Map.get() ); - } else { - return JSONConstWrapper>( nullptr ); - } - } - - - JSONConstWrapper> array_range() const { - if( internal.Type == Class::Array ) { - return JSONConstWrapper>( internal.List.get() ); - } else { - return JSONConstWrapper>( nullptr ); - } - } - - std::string dump( long depth = 1, std::string tab = " ") const { - switch( internal.Type ) { - case Class::Null: - return "null"; - case Class::Object: { - std::string pad = ""; - for( long i = 0; i < depth; ++i, pad += tab ); - - std::string s = "{\n"; - bool skip = true; - for( auto &p : *internal.Map ) { - if( !skip ) s += ",\n"; - s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) ); - skip = false; - } - s += ( "\n" + pad.erase( 0, 2 ) + "}" ) ; - return s; - } - case Class::Array: { - std::string s = "["; - bool skip = true; - for( auto &p : *internal.List ) { - if( !skip ) s += ", "; - s += p.dump( depth + 1, tab ); - skip = false; - } - s += "]"; - return s; - } - case Class::String: - return "\"" + json_escape( *internal.String ) + "\""; - case Class::Floating: - return std::to_string( internal.Float ); - case Class::Integral: - return std::to_string( internal.Int ); - case Class::Boolean: - return internal.Bool ? "true" : "false"; - } - - throw std::runtime_error("Unhandled JSON type"); - } - - - private: - static std::string json_escape( const std::string &str ) { - std::string output; - for( unsigned i = 0; i < str.length(); ++i ) - switch( str[i] ) { - case '\"': output += "\\\""; break; - case '\\': output += "\\\\"; break; - case '\b': output += "\\b"; break; - case '\f': output += "\\f"; break; - case '\n': output += "\\n"; break; - case '\r': output += "\\r"; break; - case '\t': output += "\\t"; break; - default : output += str[i]; break; - } - return output; - } - - - private: + private: }; struct JSONParser { - static bool isspace(const char c) - { + static bool isspace(const char c) + { #ifdef CHAISCRIPT_MSVC - // MSVC warns on these line in some circumstances + // MSVC warns on these line in some circumstances #pragma warning(push) #pragma warning(disable : 6330) #endif - return ::isspace(c) != 0; + return ::isspace(c) != 0; #ifdef CHAISCRIPT_MSVC #pragma warning(pop) #endif + } + + static void consume_ws( const std::string &str, size_t &offset ) { + while( isspace( str[offset] ) && offset <= str.size() ) ++offset; + } + + static JSON parse_object( const std::string &str, size_t &offset ) { + JSON Object( JSON::Class::Object ); + + ++offset; + consume_ws( str, offset ); + if( str[offset] == '}' ) { + ++offset; return Object; } - static void consume_ws( const std::string &str, size_t &offset ) { - while( isspace( str[offset] ) && offset <= str.size() ) ++offset; + for (;offset= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) - val += c; - else { - throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'"); - } - } - offset += 4; - } break; - default : val += '\\'; break; - } - } - else - val += c; + return Array; + } + + static JSON parse_string( const std::string &str, size_t &offset ) { + std::string val; + for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) { + if( c == '\\' ) { + switch( str[ ++offset ] ) { + case '\"': val += '\"'; break; + case '\\': val += '\\'; break; + case '/' : val += '/' ; break; + case 'b' : val += '\b'; break; + case 'f' : val += '\f'; break; + case 'n' : val += '\n'; break; + case 'r' : val += '\r'; break; + case 't' : val += '\t'; break; + case 'u' : { + val += "\\u" ; + for( size_t i = 1; i <= 4; ++i ) { + c = str[offset+i]; + if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) + val += c; + else { + throw std::runtime_error(std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'"); + } + } + offset += 4; + } break; + default : val += '\\'; break; } - ++offset; - return JSON(val); + } + else + val += c; } + ++offset; + return JSON(val); + } - static JSON parse_number( const std::string &str, size_t &offset ) { - std::string val, exp_str; - char c = '\0'; - bool isDouble = false; - long exp = 0; - for (; offset < str.size() ;) { - c = str[offset++]; - if( (c == '-') || (c >= '0' && c <= '9') ) - val += c; - else if( c == '.' ) { - val += c; - isDouble = true; - } - else - break; - } - if( offset < str.size() && (c == 'E' || c == 'e' )) { - c = str[ offset++ ]; - if( c == '-' ) { exp_str += '-';} - else if( c == '+' ) { } - else --offset; - - for (; offset < str.size() ;) { - c = str[ offset++ ]; - if( c >= '0' && c <= '9' ) - exp_str += c; - else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) { - throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'"); - } - else - break; - } - exp = chaiscript::parse_num( exp_str ); - } - else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) { - throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'"); - } - --offset; - - if( isDouble ) { - return JSON(chaiscript::parse_num( val ) * std::pow( 10, exp )); - } else { - if( !exp_str.empty() ) { - return JSON(static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); - } else { - return JSON(chaiscript::parse_num( val )); - } - } + static JSON parse_number( const std::string &str, size_t &offset ) { + std::string val, exp_str; + char c = '\0'; + bool isDouble = false; + long exp = 0; + for (; offset < str.size() ;) { + c = str[offset++]; + if( (c == '-') || (c >= '0' && c <= '9') ) + val += c; + else if( c == '.' ) { + val += c; + isDouble = true; + } + else + break; } + if( offset < str.size() && (c == 'E' || c == 'e' )) { + c = str[ offset++ ]; + if( c == '-' ) { exp_str += '-';} + else if( c == '+' ) { } + else --offset; - static JSON parse_bool( const std::string &str, size_t &offset ) { - if( str.substr( offset, 4 ) == "true" ) { - offset += 4; - return JSON(true); - } else if( str.substr( offset, 5 ) == "false" ) { - offset += 5; - return JSON(false); - } else { - throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'"); + for (; offset < str.size() ;) { + c = str[ offset++ ]; + if( c >= '0' && c <= '9' ) + exp_str += c; + else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) { + throw std::runtime_error(std::string("JSON ERROR: Number: Expected a number for exponent, found '") + c + "'"); } + else + break; + } + exp = chaiscript::parse_num( exp_str ); } + else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) { + throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'"); + } + --offset; - static JSON parse_null( const std::string &str, size_t &offset ) { - if( str.substr( offset, 4 ) != "null" ) { - throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'"); - } - offset += 4; - return JSON(); + if( isDouble ) { + return JSON(chaiscript::parse_num( val ) * std::pow( 10, exp )); + } else { + if( !exp_str.empty() ) { + return JSON(static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); + } else { + return JSON(chaiscript::parse_num( val )); + } } + } - static JSON parse_next( const std::string &str, size_t &offset ) { - char value; - consume_ws( str, offset ); - value = str[offset]; - switch( value ) { - case '[' : return parse_array( str, offset ); - case '{' : return parse_object( str, offset ); - case '\"': return parse_string( str, offset ); - case 't' : - case 'f' : return parse_bool( str, offset ); - case 'n' : return parse_null( str, offset ); - default : if( ( value <= '9' && value >= '0' ) || value == '-' ) - return parse_number( str, offset ); - } - throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'"); + static JSON parse_bool( const std::string &str, size_t &offset ) { + if( str.substr( offset, 4 ) == "true" ) { + offset += 4; + return JSON(true); + } else if( str.substr( offset, 5 ) == "false" ) { + offset += 5; + return JSON(false); + } else { + throw std::runtime_error(std::string("JSON ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'"); } + } + + static JSON parse_null( const std::string &str, size_t &offset ) { + if( str.substr( offset, 4 ) != "null" ) { + throw std::runtime_error(std::string("JSON ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'"); + } + offset += 4; + return JSON(); + } + + static JSON parse_next( const std::string &str, size_t &offset ) { + char value; + consume_ws( str, offset ); + value = str[offset]; + switch( value ) { + case '[' : return parse_array( str, offset ); + case '{' : return parse_object( str, offset ); + case '\"': return parse_string( str, offset ); + case 't' : + case 'f' : return parse_bool( str, offset ); + case 'n' : return parse_null( str, offset ); + default : if( ( value <= '9' && value >= '0' ) || value == '-' ) + return parse_number( str, offset ); + } + throw std::runtime_error(std::string("JSON ERROR: Parse: Unexpected starting character '") + value + "'"); + } }; From 3627efe03bd9ec40514d1d6315bf636a4b239a6f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 16 Mar 2016 20:14:48 -0600 Subject: [PATCH 07/27] Move away from shared_lock It's not supported by enough standard library implementations yet --- include/chaiscript/chaiscript_threading.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 126edb95..22506936 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -13,7 +13,6 @@ #ifndef CHAISCRIPT_NO_THREADS #include #include -#include #else #ifndef CHAISCRIPT_NO_THREADS_WARNING #pragma message ("ChaiScript is compiling without thread safety.") @@ -46,13 +45,13 @@ namespace chaiscript using unique_lock = std::unique_lock; template - using shared_lock = std::shared_lock; + using shared_lock = std::unique_lock; template using lock_guard = std::lock_guard; - using shared_mutex = std::shared_timed_mutex; + using shared_mutex = std::mutex; using std::mutex; From a45c76721f5488112f84956def2a01da32a5b8b3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 25 Mar 2016 07:02:41 -0600 Subject: [PATCH 08/27] Add fuzzy test files --- .../codeanalysis/fuzzy_tests/chaiscript.dict | 61 +++++++++++++++++++ contrib/codeanalysis/fuzzy_tests/use.inc | 5 ++ 2 files changed, 66 insertions(+) create mode 100644 contrib/codeanalysis/fuzzy_tests/chaiscript.dict create mode 100644 contrib/codeanalysis/fuzzy_tests/use.inc diff --git a/contrib/codeanalysis/fuzzy_tests/chaiscript.dict b/contrib/codeanalysis/fuzzy_tests/chaiscript.dict new file mode 100644 index 00000000..b6091fa3 --- /dev/null +++ b/contrib/codeanalysis/fuzzy_tests/chaiscript.dict @@ -0,0 +1,61 @@ +# My dict + + +for="for" +while="while" +def="def" +fun="fun" +if="if" +else="else" +and="&&" +or="||" +auto="auto" +var="var" +begin_block="{" +end_block="}" +empty_vec="[]" +string="string" +vector="Vector" +map="Map" +return="return" +break="break" +true="true" +false="false" +class="class" +attr="attr" +var="var" +global="global" +empty_lambda=" fun(){} " +empty_fun=" def empty_fun() {} " +continue="continue" +float=" 1.1f " +double=" 2.2 " +long_double=" 2.2ll " +unsigned=" 3u " +unsigned_long=" 4ul " +unsigned_long_long=" 4ull " +long_long=" 5ll " +attr="attr" +reference_del="auto &" +int8=" int8_t(1) " +int16=" int16_t(2) " +int32=" int32_t(3) " +int64=" int64_t(4) " +uint8=" uint8_t(1) " +uint16=" uint16_t(2) " +uint32=" uint32_t(3) " +uint64=" uint64_t(4) " +int8t="int8_t" +int16t="int16_t" +int32t="int32_t" +int64t="int64_t" +uint8t="uint8_t" +uint16t="uint16_t" +uint32t="uint32_t" +uint64t="uint64_t" + + + + + + diff --git a/contrib/codeanalysis/fuzzy_tests/use.inc b/contrib/codeanalysis/fuzzy_tests/use.inc new file mode 100644 index 00000000..0f9fea77 --- /dev/null +++ b/contrib/codeanalysis/fuzzy_tests/use.inc @@ -0,0 +1,5 @@ +def greet { + return("hello") +} + +fun(){ "world" } From 06783b7f65caf82b5d4df0ff88ed6b5429bc56f7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 25 Mar 2016 07:04:39 -0600 Subject: [PATCH 09/27] Add fuzzy testing notes --- contrib/codeanalysis/fuzzy_tests/notes.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 contrib/codeanalysis/fuzzy_tests/notes.txt diff --git a/contrib/codeanalysis/fuzzy_tests/notes.txt b/contrib/codeanalysis/fuzzy_tests/notes.txt new file mode 100644 index 00000000..db721c50 --- /dev/null +++ b/contrib/codeanalysis/fuzzy_tests/notes.txt @@ -0,0 +1,17 @@ +Command line used to find this crash: + +../../Downloads/afl-1.80b/afl-fuzz -i- -o findings -x chaiscript.dict -- ../a.out unit_test.inc @@ + +If you can't reproduce a bug outside of afl-fuzz, be sure to set the same +memory limit. The limit used for this fuzzing session was 50.0 MB. + +Need a tool to minimize test cases before investigating the crashes or sending +them to a vendor? Check out the afl-tmin that comes with the fuzzer! + +Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop +me a mail at once the issues are fixed - I'd love to +add your finds to the gallery at: + + http://lcamtuf.coredump.cx/afl/ + +Thanks :-) From 2f2f789f489b850bab1f4f18556e1f20f6695caa Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 26 Mar 2016 17:34:36 -0600 Subject: [PATCH 10/27] Fix parsing of '' strings. found by AFL --- include/chaiscript/language/chaiscript_parser.hpp | 6 +++++- src/main.cpp | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index c1da4272..5f4e5e49 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1196,7 +1196,7 @@ namespace chaiscript std::string match; { - // scope for cparser destrutor + // scope for cparser destructor Char_Parser cparser(match, false); for (auto s = start + 1, end = m_position - 1; s != end; ++s) { @@ -1204,6 +1204,10 @@ namespace chaiscript } } + if (match.size() != 1) { + throw exception::eval_error("Single-quoted strings must be 1 character long", File_Position(m_position.line, m_position.col), *m_filename); + } + m_match_stack.push_back(make_node(match, start.line, start.col)); return true; } diff --git a/src/main.cpp b/src/main.cpp index b4d5fa80..7ac9b2b6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -371,6 +371,9 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } } + catch (const chaiscript::exception::load_module_error &e) { + std::cout << "Unhandled module load error\n" << e.what() << '\n'; + } // catch (std::exception &e) { // std::cout << e.what() << '\n'; From 328aef10d767872be1fc9a8773ee295ee4699582 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 27 Mar 2016 18:24:38 -0600 Subject: [PATCH 11/27] Add failing test for non-const shared_ptr & --- src/test_module.cpp | 14 ++++++++++++++ unittests/shared_ptr_update.chai | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 unittests/shared_ptr_update.chai diff --git a/src/test_module.cpp b/src/test_module.cpp index ebccf736..5109baa0 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -114,6 +114,16 @@ std::shared_ptr null_factory() return std::shared_ptr(); } +void update_shared_ptr(std::shared_ptr &ptr) +{ + ptr = std::make_shared(); +} + +void nullify_shared_ptr(std::shared_ptr &ptr) +{ + ptr = nullptr; +} + std::string hello_world() { return "Hello World"; @@ -209,6 +219,10 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::type_conversion()); m->add(chaiscript::constructor(), "Type2"); + m->add(chaiscript::fun(&update_shared_ptr), "update_shared_ptr"); + m->add(chaiscript::fun(&nullify_shared_ptr), "nullify_shared_ptr"); + + return m; } diff --git a/unittests/shared_ptr_update.chai b/unittests/shared_ptr_update.chai new file mode 100644 index 00000000..6378be6c --- /dev/null +++ b/unittests/shared_ptr_update.chai @@ -0,0 +1,24 @@ +load_module("test_module") + +auto o := null_factory(); + +assert_true(o.is_var_null()); + +update_shared_ptr(o); + +assert_false(o.is_var_null()); +assert_true(o.base_only_func() == -9); + +nullify_shared_ptr(o); + +assert_true(o.is_var_null()); + +try { + o.func(); +} catch (e) { + exit(0); +} + +assert_true(false); + + From 91a3ae1f14c9aca383d6f8f257d46d4007c29902 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 27 Mar 2016 20:02:27 -0600 Subject: [PATCH 12/27] Add ability to take non-const & shared_ptr params --- cheatsheet.md | 22 ++++++++++ .../dispatchkit/boxed_cast_helper.hpp | 12 +++++ .../chaiscript/dispatchkit/boxed_value.hpp | 44 +++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/cheatsheet.md b/cheatsheet.md index ce8e04a0..c37045f7 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -163,6 +163,28 @@ chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as(); // works with an static_cast(chai.eval("5.3+2.1")); // this version only works if we know that it's a double ``` +### Conversion Caveats + +Conversion to `std::shared_ptr &` is supported for function calls, but if you attempt to keep a reference to a `shared_ptr<>` you might invoke undefined behavior + +```cpp +// ok this is supported, you can register it with chaiscript engine +void nullify_shared_ptr(std::shared_ptr &t) { + t == nullptr +} +``` + +```cpp +int main() +{ + // do some stuff and create a chaiscript instance + std::shared_ptr &ptr = chai.eval &>(somevalue); + // DO NOT do this. Taking a non-const reference to a shared_ptr is not + // supported and causes undefined behavior in the chaiscript engine +} +``` + + ## Sharing Values ``` diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 505b1e1f..b4e1826b 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -173,6 +173,18 @@ namespace chaiscript { }; + template + struct Cast_Helper_Inner &> + { + typedef Boxed_Value::Sentinel Result_Type; + + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) + { + std::shared_ptr &res = ob.get().cast >(); + return ob.pointer_sentinel(res); + } + }; + /// Cast_Helper_Inner for casting to a const std::shared_ptr & type template struct Cast_Helper_Inner > : Cast_Helper_Inner > diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 5a49119f..ff09cc19 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -231,6 +231,50 @@ namespace chaiscript return m_data->m_type_info.bare_equal(ti); } + template + struct Sentinel { + Sentinel(std::shared_ptr &ptr, Data &data) + : m_ptr(ptr), m_data(data) + { + } + + ~Sentinel() + { + // save new pointer data + m_data.get().m_data_ptr = m_ptr.get().get(); + m_data.get().m_const_data_ptr = m_ptr.get().get(); + } + + Sentinel& operator=(Sentinel&&s) { + m_ptr = std::move(s.m_ptr); + m_data = std::move(s.m_data); + } + + Sentinel(Sentinel &&s) + : m_ptr(std::move(s.m_ptr)), + m_data(std::move(s.m_data)) + { + } + + operator std::shared_ptr&() const + { + return m_ptr.get(); + } + + Sentinel &operator=(const Sentinel &) = delete; + Sentinel(Sentinel&) = delete; + + std::reference_wrapper> m_ptr; + std::reference_wrapper m_data; + }; + + + template + Sentinel pointer_sentinel(std::shared_ptr &ptr) const + { + return Sentinel(ptr, *(m_data.get())); + } + bool is_null() const CHAISCRIPT_NOEXCEPT { return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr); From 46c45e8fc786c867c898e1fa217fc01c35952cb5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 27 Mar 2016 20:50:15 -0600 Subject: [PATCH 13/27] Update boxed_cast_tests to account for new features --- .../dispatchkit/boxed_cast_helper.hpp | 3 ++ unittests/boxed_cast_test.cpp | 51 ++++++++++--------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index b4e1826b..da1e222e 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -176,6 +176,8 @@ namespace chaiscript template struct Cast_Helper_Inner &> { + static_assert(!std::is_const::value, "Non-const reference to std::shared_ptr is not supported"); + typedef Boxed_Value::Sentinel Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) @@ -185,6 +187,7 @@ namespace chaiscript } }; + /// Cast_Helper_Inner for casting to a const std::shared_ptr & type template struct Cast_Helper_Inner > : Cast_Helper_Inner > diff --git a/unittests/boxed_cast_test.cpp b/unittests/boxed_cast_test.cpp index 1e928749..11978eff 100644 --- a/unittests/boxed_cast_test.cpp +++ b/unittests/boxed_cast_test.cpp @@ -54,12 +54,13 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass) } template -bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr, bool ConstTPtr, bool TPtrConst, - bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT, - bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef, - bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, - bool ConstWrappedRefRef, bool ConstWrappedConstRefRef, bool Number, - bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef, bool ConstTPtrConstRef) +bool do_test(const Boxed_Value &bv, + bool T, bool ConstT, bool TRef, bool ConstTRef, bool TPtr, + bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT, + bool SharedPtrTRef, bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef, + bool WrappedRef, bool WrappedConstRef, bool ConstWrappedRef, bool ConstWrappedConstRef, bool ConstWrappedRefRef, + bool ConstWrappedConstRefRef, bool Number, bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef, + bool ConstTPtrConstRef) { bool passed = true; passed &= test_type_conversion(bv, T); @@ -72,8 +73,8 @@ bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTR passed &= test_type_conversion(bv, ConstTPtrConst); passed &= test_type_conversion >(bv, SharedPtrT); passed &= test_type_conversion >(bv, SharedConstPtrT); - passed &= test_type_conversion &>(bv, false); - passed &= test_type_conversion &>(bv, false); + passed &= test_type_conversion &>(bv, SharedPtrTRef); + //passed &= test_type_conversion &>(bv, false); passed &= test_type_conversion >(bv, ConstSharedPtrT); passed &= test_type_conversion >(bv, ConstSharedConstPtrT); passed &= test_type_conversion &>(bv, ConstSharedPtrTRef); @@ -115,37 +116,37 @@ bool built_in_type_test(const T &initial, bool ispod) T i = T(initial); passed &= do_test(var(i), true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, ispod, ispod, ispod, true, true); passed &= do_test(const_var(i), true, true, false, true, false, true, false, true, false, true, - false, true, false, true, false, + false, false, true, false, true, false, true, false, true, false, true, ispod, ispod, ispod, false, true); passed &= do_test(var(&i), true, true, true, true, true, true, true, true, false, false, - false, false, false, false, true, + false, false, false, false, false, true, true, true, true, true, true, ispod, ispod, ispod, true, true); passed &= do_test(const_var(&i), true, true, false, true, false, true, false, true, false, false, - false, false, false, false, false, + false, false, false, false, false, false, true, false, true, false, true, ispod, ispod, ispod, false, true); passed &= do_test(var(std::ref(i)), true, true, true, true, true, true, true, true, false, false, - false, false, false, false, true, + false, false, false, false, false, true, true, true, true, true, true, ispod, ispod, ispod, true, true); passed &= do_test(var(std::cref(i)), true, true, false, true, false, true, false, true, false, false, - false, false, false, false, false, + false, false, false, false, false, false, true, false, true, false, true, ispod, ispod, ispod, false, true); @@ -156,33 +157,33 @@ bool built_in_type_test(const T &initial, bool ispod) passed &= do_test(var(i), true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, ispod, ispod, ispod, true, true); // But a pointer or reference to it should be necessarily const passed &= do_test(var(&ir), true, true, false, true, false, true, false, true, false, false, - false, false, false, false, false, + false, false, false, false, false, false, true, false, true, false, true, ispod, ispod, ispod, false, true); passed &= do_test(var(std::ref(ir)), true, true, false, true, false, true, false, true, false, false, - false, false, false, false, false, + false, false, false, false, false, false, true, false, true, false, true, ispod, ispod, ispod, false, true); // Make sure const of const works too passed &= do_test(const_var(&ir), true, true, false, true, false, true, false, true, false, false, - false, false, false, false, false, + false, false, false, false, false, false, true, false, true, false, true, ispod, ispod, ispod, false, true); passed &= do_test(const_var(std::ref(ir)), true, true, false, true, false, true, false, true, false, false, - false, false, false, false, false, + false, false, false, false, false, false, true, false, true, false, true, ispod, ispod, ispod, false, true); @@ -192,14 +193,14 @@ bool built_in_type_test(const T &initial, bool ispod) const T*cip = &i; passed &= do_test(var(cip), true, true, false, true, false, true, false, true, false, false, - false, false, false, false, false, + false, false, false, false, false, false, true, false, true, false, true, ispod, ispod, ispod, false, true); // make sure const of const works passed &= do_test(const_var(cip), true, true, false, true, false, true, false, true, false, false, - false, false, false, false, false, + false, false, false, false, false, false, true, false, true, false, true, ispod, ispod, ispod, false, true); @@ -209,13 +210,13 @@ bool built_in_type_test(const T &initial, bool ispod) passed &= do_test(var(ip), true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, ispod, ispod, ispod, true, true); passed &= do_test(const_var(ip), true, true, false, true, false, true, false, true, false, true, - false, true, false, true, false, + false, false, true, false, true, false, true, false, true, false, true, ispod, ispod, ispod, false, true); @@ -224,14 +225,14 @@ bool built_in_type_test(const T &initial, bool ispod) passed &= do_test(var(ipc), true, true, false, true, false, true, false, true, false, true, - false, true, false, true, false, + false, false, true, false, true, false, true, false, true, false, true, ispod, ispod, ispod, false, true); // const of this should be the same, making sure it compiles passed &= do_test(const_var(ipc), true, true, false, true, false, true, false, true, false, true, - false, true, false, true, false, + false, false, true, false, true, false, true, false, true, false, true, ispod, ispod, ispod, false, true); From c07c2a9cc2e6e05290c33810cb601912748f96b6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 28 Mar 2016 15:57:26 -0600 Subject: [PATCH 14/27] Make sure type_info works with shared_ptr & --- include/chaiscript/dispatchkit/type_info.hpp | 5 +++++ unittests/shared_ptr_update.chai | 1 + 2 files changed, 6 insertions(+) diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index c91a444c..c43767a3 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -162,6 +162,11 @@ namespace chaiscript } }; + template + struct Get_Type_Info &> : Get_Type_Info> + { + }; + template struct Get_Type_Info &> { diff --git a/unittests/shared_ptr_update.chai b/unittests/shared_ptr_update.chai index 6378be6c..cf7432ac 100644 --- a/unittests/shared_ptr_update.chai +++ b/unittests/shared_ptr_update.chai @@ -10,6 +10,7 @@ assert_false(o.is_var_null()); assert_true(o.base_only_func() == -9); nullify_shared_ptr(o); +o.nullify_shared_ptr(); assert_true(o.is_var_null()); From 33c966b8d65123fea3609b4bdfbb0ac9de5981ff Mon Sep 17 00:00:00 2001 From: Eduard Date: Wed, 30 Mar 2016 18:14:12 +0300 Subject: [PATCH 15/27] Fix description of get_guard() --- include/chaiscript/language/chaiscript_prelude_docs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_prelude_docs.hpp b/include/chaiscript/language/chaiscript_prelude_docs.hpp index 25d32d10..7df56521 100644 --- a/include/chaiscript/language/chaiscript_prelude_docs.hpp +++ b/include/chaiscript/language/chaiscript_prelude_docs.hpp @@ -505,7 +505,7 @@ class Function /// \endcode Vector get_contained_functions() const; - /// \brief Returns a vector of the contained functions + /// \brief Returns a function guard as function /// /// Example: /// \code From 1e62eb4e12c9726ccd84e2df4c6d3e9ca2fb84df Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 30 Mar 2016 12:52:53 -0600 Subject: [PATCH 16/27] Update to 5.8.2 release notes --- CMakeLists.txt | 2 +- include/chaiscript/chaiscript_defines.hpp | 2 +- releasenotes.md | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b00ce4ea..e3fde8cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt" set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MINOR 8) -set(CPACK_PACKAGE_VERSION_PATCH 1) +set(CPACK_PACKAGE_VERSION_PATCH 2) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_VENDOR "ChaiScript.com") diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 724185f3..9184f50e 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -99,7 +99,7 @@ namespace chaiscript { static const int version_major = 5; static const int version_minor = 8; - static const int version_patch = 1; + static const int version_patch = 2; static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION; static const char *compiler_name = CHAISCRIPT_COMPILER_NAME; diff --git a/releasenotes.md b/releasenotes.md index ea831972..d448be4a 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,10 @@ Notes: ======= -Current Version: 5.8.1 +Current Version: 5.8.2 + +### Changes since 5.8.1 +* Allow casting to non-const & std::shared_ptr + ### Changes since 5.8.0 * Fix parsing of floats to be locale independent #250 From 5a947b5035dc99d2dbef35a220340036886e189c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 4 Apr 2016 15:36:38 -0600 Subject: [PATCH 17/27] Prefer make_unique over make_shared --- .../chaiscript/dispatchkit/boxed_value.hpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 5b88f9d0..538391f6 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -77,9 +77,9 @@ namespace chaiscript struct Object_Data { - static std::shared_ptr get(Boxed_Value::Void_Type, bool t_return_value) + static std::unique_ptr get(Boxed_Value::Void_Type, bool t_return_value) { - return std::make_shared( + return std::make_unique( detail::Get_Type_Info::get(), chaiscript::detail::Any(), false, @@ -89,15 +89,15 @@ namespace chaiscript } template - static std::shared_ptr get(const std::shared_ptr *obj, bool t_return_value) + static std::unique_ptr get(const std::shared_ptr *obj, bool t_return_value) { return get(*obj, t_return_value); } template - static std::shared_ptr get(const std::shared_ptr &obj, bool t_return_value) + static std::unique_ptr get(const std::shared_ptr &obj, bool t_return_value) { - return std::make_shared( + return std::make_unique( detail::Get_Type_Info::get(), chaiscript::detail::Any(obj), false, @@ -107,10 +107,10 @@ namespace chaiscript } template - static std::shared_ptr get(std::shared_ptr &&obj, bool t_return_value) + static std::unique_ptr get(std::shared_ptr &&obj, bool t_return_value) { auto ptr = obj.get(); - return std::make_shared( + return std::make_unique( detail::Get_Type_Info::get(), chaiscript::detail::Any(std::move(obj)), false, @@ -120,23 +120,23 @@ namespace chaiscript } template - static std::shared_ptr get(T *t, bool t_return_value) + static std::unique_ptr get(T *t, bool t_return_value) { return get(std::ref(*t), t_return_value); } template - static std::shared_ptr get(const T *t, bool t_return_value) + static std::unique_ptr get(const T *t, bool t_return_value) { return get(std::cref(*t), t_return_value); } template - static std::shared_ptr get(std::reference_wrapper obj, bool t_return_value) + static std::unique_ptr get(std::reference_wrapper obj, bool t_return_value) { auto p = &obj.get(); - return std::make_shared( + return std::make_unique( detail::Get_Type_Info::get(), chaiscript::detail::Any(std::move(obj)), true, @@ -146,11 +146,11 @@ namespace chaiscript } template - static std::shared_ptr get(T t, bool t_return_value) + static std::unique_ptr get(T t, bool t_return_value) { auto p = std::make_shared(std::move(t)); auto ptr = p.get(); - return std::make_shared( + return std::make_unique( detail::Get_Type_Info::get(), chaiscript::detail::Any(std::move(p)), false, @@ -159,9 +159,9 @@ namespace chaiscript ); } - static std::shared_ptr get() + static std::unique_ptr get() { - return std::make_shared( + return std::make_unique( Type_Info(), chaiscript::detail::Any(), false, From 5567e767a3745e3c2e92e11420a5810ad4ebe07b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 4 Apr 2016 15:57:14 -0600 Subject: [PATCH 18/27] Change some {{ code --- include/chaiscript/language/chaiscript_parser.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 5f4e5e49..715d90cf 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -147,7 +147,7 @@ namespace chaiscript static const std::array &create_operators() { - static const std::array operators = {{ + static const std::array operators = { { AST_Node_Type::Ternary_Cond, AST_Node_Type::Logical_Or, AST_Node_Type::Logical_And, @@ -159,7 +159,7 @@ namespace chaiscript AST_Node_Type::Shift, AST_Node_Type::Addition, AST_Node_Type::Multiplication - }}; + } }; return operators; } @@ -320,7 +320,7 @@ namespace chaiscript static std::map count_fun_calls(const AST_NodePtr &p, bool in_loop) { if (p->identifier == AST_Node_Type::Fun_Call) { if (p->children[0]->identifier == AST_Node_Type::Id) { - return std::map{{p->children[0]->text, in_loop?99:1}}; + return std::map{ {p->children[0]->text, in_loop?99:1} }; } return std::map(); } else { From 5ff97979fd85db218112f0a69d21fe2f95ef9abc Mon Sep 17 00:00:00 2001 From: Bjorn Fahller Date: Sat, 9 Apr 2016 15:42:55 +0200 Subject: [PATCH 19/27] Pass Module by reference instead of shared ptr This gives a small but noticeable compile time improvement as well as a measurable, albeit not great, reduction in size of the stdlib. --- include/chaiscript/chaiscript_stdlib.hpp | 15 +- include/chaiscript/dispatchkit/bootstrap.hpp | 282 +++++++++--------- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 154 +++++----- .../chaiscript/dispatchkit/dispatchkit.hpp | 6 - include/chaiscript/dispatchkit/operators.hpp | 165 ++++------ include/chaiscript/utility/json_wrap.hpp | 6 +- include/chaiscript/utility/utility.hpp | 5 +- src/stl_extra.cpp | 6 +- src/test_module.cpp | 6 +- 9 files changed, 301 insertions(+), 344 deletions(-) diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index ca0214af..50aa087a 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -40,19 +40,20 @@ namespace chaiscript { using namespace bootstrap; - ModulePtr lib = Bootstrap::bootstrap(); + auto lib = std::make_shared(); + Bootstrap::bootstrap(*lib); - lib->add(standard_library::vector_type >("Vector")); - lib->add(standard_library::string_type("string")); - lib->add(standard_library::map_type >("Map")); - lib->add(standard_library::pair_type >("Pair")); + standard_library::vector_type >("Vector", *lib); + standard_library::string_type("string", *lib); + standard_library::map_type >("Map", *lib); + standard_library::pair_type >("Pair", *lib); #ifndef CHAISCRIPT_NO_THREADS - lib->add(standard_library::future_type>("future")); + standard_library::future_type>("future", *lib); lib->add(chaiscript::fun([](const std::function &t_func){ return std::async(std::launch::async, t_func);}), "async"); #endif - lib->add(json_wrap::library()); + json_wrap::library(*lib); lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ ); diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 1f519dc8..1eab977c 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -52,12 +52,12 @@ namespace chaiscript } template::value>::type > - ModulePtr array(const std::string &type, ModulePtr m = std::make_shared()) + Module& array(const std::string &type, Module& m) { typedef typename std::remove_extent::type ReturnType; const auto extent = std::extent::value; - m->add(user_type(), type); - m->add(fun( + m.add(user_type(), type); + m.add(fun( [extent](T& t, size_t index)->ReturnType &{ if (extent > 0 && index >= extent) { throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent)); @@ -68,7 +68,7 @@ namespace chaiscript ), "[]" ); - m->add(fun( + m.add(fun( [extent](const T &t, size_t index)->const ReturnType &{ if (extent > 0 && index >= extent) { throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent)); @@ -79,7 +79,7 @@ namespace chaiscript ), "[]" ); - m->add(fun( + m.add(fun( [extent](const T &) { return extent; }), "size"); @@ -92,20 +92,19 @@ namespace chaiscript /// \param[in] type The name of the type. The copy constructor will be named "type". /// \param[in,out] m The Module to add the copy constructor to /// \tparam T The type to add a copy constructor for - /// \returns The passed in ModulePtr, or the newly constructed one if the default param is used + /// \returns The passed in Module template - ModulePtr copy_constructor(const std::string &type, ModulePtr m = std::make_shared()) + Module& copy_constructor(const std::string &type, Module& m) { - m->add(constructor(), type); - return m; + return m.add(constructor(), type); } /// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users. /// \tparam T Type to create comparison operators for /// \param[in,out] m module to add comparison operators to - /// \returns the passed in ModulePtr or the newly constructed one if the default params are used. + /// \returns the passed in Module. template - ModulePtr opers_comparison(ModulePtr m = std::make_shared()) + Module& opers_comparison(Module& m) { operators::equal(m); operators::greater_than(m); @@ -122,13 +121,13 @@ namespace chaiscript /// \param[in] type The name of the type to add the constructors for. /// \param[in,out] m The Module to add the basic constructors to /// \tparam T Type to generate basic constructors for - /// \returns The passed in ModulePtr, or the newly constructed one if the default param is used + /// \returns The passed in Module /// \sa copy_constructor /// \sa constructor template - ModulePtr basic_constructors(const std::string &type, ModulePtr m = std::make_shared()) + Module& basic_constructors(const std::string &type, Module& m) { - m->add(constructor(), type); + m.add(constructor(), type); copy_constructor(type, m); return m; } @@ -138,10 +137,9 @@ namespace chaiscript /// \param[in] type The name of the type /// \param[in,out] m The Module to add the constructor to template - ModulePtr construct_pod(const std::string &type, ModulePtr m = std::make_shared()) + Module& construct_pod(const std::string &type, Module& m) { - m->add(fun(&detail::construct_pod), type); - return m; + return m.add(fun(&detail::construct_pod), type); } @@ -185,13 +183,13 @@ namespace chaiscript /// Add all common functions for a POD type. All operators, and /// common conversions template - ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = std::make_shared()) + Module& bootstrap_pod_type(const std::string &name, Module& m) { - m->add(user_type(), name); - m->add(constructor(), name); + m.add(user_type(), name); + m.add(constructor(), name); construct_pod(name, m); - m->add(fun(&parse_string), "to_" + name); + m.add(fun(&parse_string), "to_" + name); return m; } @@ -261,41 +259,41 @@ namespace chaiscript /// Add all arithmetic operators for PODs - static void opers_arithmetic_pod(ModulePtr m = std::make_shared()) + static void opers_arithmetic_pod(Module& m) { - m->add(fun(&Boxed_Number::equals), "=="); - m->add(fun(&Boxed_Number::less_than), "<"); - m->add(fun(&Boxed_Number::greater_than), ">"); - m->add(fun(&Boxed_Number::greater_than_equal), ">="); - m->add(fun(&Boxed_Number::less_than_equal), "<="); - m->add(fun(&Boxed_Number::not_equal), "!="); + m.add(fun(&Boxed_Number::equals), "=="); + m.add(fun(&Boxed_Number::less_than), "<"); + m.add(fun(&Boxed_Number::greater_than), ">"); + m.add(fun(&Boxed_Number::greater_than_equal), ">="); + m.add(fun(&Boxed_Number::less_than_equal), "<="); + m.add(fun(&Boxed_Number::not_equal), "!="); - m->add(fun(&Boxed_Number::pre_decrement), "--"); - m->add(fun(&Boxed_Number::pre_increment), "++"); - m->add(fun(&Boxed_Number::sum), "+"); - m->add(fun(&Boxed_Number::unary_plus), "+"); - m->add(fun(&Boxed_Number::unary_minus), "-"); - m->add(fun(&Boxed_Number::difference), "-"); - m->add(fun(&Boxed_Number::assign_bitwise_and), "&="); - m->add(fun(&Boxed_Number::assign), "="); - m->add(fun(&Boxed_Number::assign_bitwise_or), "|="); - m->add(fun(&Boxed_Number::assign_bitwise_xor), "^="); - m->add(fun(&Boxed_Number::assign_remainder), "%="); - m->add(fun(&Boxed_Number::assign_shift_left), "<<="); - m->add(fun(&Boxed_Number::assign_shift_right), ">>="); - m->add(fun(&Boxed_Number::bitwise_and), "&"); - m->add(fun(&Boxed_Number::bitwise_complement), "~"); - m->add(fun(&Boxed_Number::bitwise_xor), "^"); - m->add(fun(&Boxed_Number::bitwise_or), "|"); - m->add(fun(&Boxed_Number::assign_product), "*="); - m->add(fun(&Boxed_Number::assign_quotient), "/="); - m->add(fun(&Boxed_Number::assign_sum), "+="); - m->add(fun(&Boxed_Number::assign_difference), "-="); - m->add(fun(&Boxed_Number::quotient), "/"); - m->add(fun(&Boxed_Number::shift_left), "<<"); - m->add(fun(&Boxed_Number::product), "*"); - m->add(fun(&Boxed_Number::remainder), "%"); - m->add(fun(&Boxed_Number::shift_right), ">>"); + m.add(fun(&Boxed_Number::pre_decrement), "--"); + m.add(fun(&Boxed_Number::pre_increment), "++"); + m.add(fun(&Boxed_Number::sum), "+"); + m.add(fun(&Boxed_Number::unary_plus), "+"); + m.add(fun(&Boxed_Number::unary_minus), "-"); + m.add(fun(&Boxed_Number::difference), "-"); + m.add(fun(&Boxed_Number::assign_bitwise_and), "&="); + m.add(fun(&Boxed_Number::assign), "="); + m.add(fun(&Boxed_Number::assign_bitwise_or), "|="); + m.add(fun(&Boxed_Number::assign_bitwise_xor), "^="); + m.add(fun(&Boxed_Number::assign_remainder), "%="); + m.add(fun(&Boxed_Number::assign_shift_left), "<<="); + m.add(fun(&Boxed_Number::assign_shift_right), ">>="); + m.add(fun(&Boxed_Number::bitwise_and), "&"); + m.add(fun(&Boxed_Number::bitwise_complement), "~"); + m.add(fun(&Boxed_Number::bitwise_xor), "^"); + m.add(fun(&Boxed_Number::bitwise_or), "|"); + m.add(fun(&Boxed_Number::assign_product), "*="); + m.add(fun(&Boxed_Number::assign_quotient), "/="); + m.add(fun(&Boxed_Number::assign_sum), "+="); + m.add(fun(&Boxed_Number::assign_difference), "-="); + m.add(fun(&Boxed_Number::quotient), "/"); + m.add(fun(&Boxed_Number::shift_left), "<<"); + m.add(fun(&Boxed_Number::product), "*"); + m.add(fun(&Boxed_Number::remainder), "%"); + m.add(fun(&Boxed_Number::shift_right), ">>"); } @@ -403,57 +401,57 @@ namespace chaiscript public: /// \brief perform all common bootstrap functions for std::string, void and POD types /// \param[in,out] m Module to add bootstrapped functions to - /// \returns passed in ModulePtr, or newly created one if default argument is used - static ModulePtr bootstrap(ModulePtr m = std::make_shared()) + /// \returns passed in Module + static Module& bootstrap(Module& m) { - m->add(user_type(), "void"); - m->add(user_type(), "bool"); - m->add(user_type(), "Object"); - m->add(user_type(), "Number"); - m->add(user_type(), "Function"); - m->add(user_type(), "Assignable_Function"); - m->add(user_type(), "exception"); + m.add(user_type(), "void"); + m.add(user_type(), "bool"); + m.add(user_type(), "Object"); + m.add(user_type(), "Number"); + m.add(user_type(), "Function"); + m.add(user_type(), "Assignable_Function"); + m.add(user_type(), "exception"); - m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity"); - m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation"); - m->add(fun(&dispatch::Proxy_Function_Base::operator==), "=="); + m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity"); + m.add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation"); + m.add(fun(&dispatch::Proxy_Function_Base::operator==), "=="); - m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types"); - m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions"); + m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types"); + m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions"); - m->add(user_type(), "out_of_range"); - m->add(user_type(), "logic_error"); - m->add(chaiscript::base_class()); - m->add(chaiscript::base_class()); - m->add(chaiscript::base_class()); + m.add(user_type(), "out_of_range"); + m.add(user_type(), "logic_error"); + m.add(chaiscript::base_class()); + m.add(chaiscript::base_class()); + m.add(chaiscript::base_class()); - m->add(user_type(), "runtime_error"); - m->add(chaiscript::base_class()); + m.add(user_type(), "runtime_error"); + m.add(chaiscript::base_class()); - m->add(constructor(), "runtime_error"); - m->add(fun(std::function(&what)), "what"); + m.add(constructor(), "runtime_error"); + m.add(fun(std::function(&what)), "what"); - m->add(user_type(), "Dynamic_Object"); - m->add(constructor(), "Dynamic_Object"); - m->add(constructor(), "Dynamic_Object"); - m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name"); - m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs"); - m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit"); - m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit"); - m->add(fun(&dispatch::Dynamic_Object::has_attr), "has_attr"); + m.add(user_type(), "Dynamic_Object"); + m.add(constructor(), "Dynamic_Object"); + m.add(constructor(), "Dynamic_Object"); + m.add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name"); + m.add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs"); + m.add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit"); + m.add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit"); + m.add(fun(&dispatch::Dynamic_Object::has_attr), "has_attr"); - m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "get_attr"); - m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "get_attr"); + m.add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "get_attr"); + m.add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "get_attr"); - m->add(fun(static_cast(&dispatch::Dynamic_Object::method_missing)), "method_missing"); - m->add(fun(static_cast(&dispatch::Dynamic_Object::method_missing)), "method_missing"); + m.add(fun(static_cast(&dispatch::Dynamic_Object::method_missing)), "method_missing"); + m.add(fun(static_cast(&dispatch::Dynamic_Object::method_missing)), "method_missing"); - m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); - m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); + m.add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); + m.add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); - m->eval(R"chaiscript( + m.eval(R"chaiscript( def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } ); @@ -490,37 +488,37 @@ namespace chaiscript } )chaiscript"); - m->add(fun(&has_guard), "has_guard"); - m->add(fun(&get_guard), "get_guard"); + m.add(fun(&has_guard), "has_guard"); + m.add(fun(&get_guard), "get_guard"); - m->add(fun(&Boxed_Value::is_undef), "is_var_undef"); - m->add(fun(&Boxed_Value::is_null), "is_var_null"); - m->add(fun(&Boxed_Value::is_const), "is_var_const"); - m->add(fun(&Boxed_Value::is_ref), "is_var_reference"); - m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer"); - m->add(fun(&Boxed_Value::is_return_value), "is_var_return_value"); - m->add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value"); - m->add(fun(&Boxed_Value::is_type), "is_type"); - m->add(fun(&Boxed_Value::get_attr), "get_var_attr"); - m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs"); - m->add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs"); + m.add(fun(&Boxed_Value::is_undef), "is_var_undef"); + m.add(fun(&Boxed_Value::is_null), "is_var_null"); + m.add(fun(&Boxed_Value::is_const), "is_var_const"); + m.add(fun(&Boxed_Value::is_ref), "is_var_reference"); + m.add(fun(&Boxed_Value::is_pointer), "is_var_pointer"); + m.add(fun(&Boxed_Value::is_return_value), "is_var_return_value"); + m.add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value"); + m.add(fun(&Boxed_Value::is_type), "is_type"); + m.add(fun(&Boxed_Value::get_attr), "get_var_attr"); + m.add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs"); + m.add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs"); - m->add(fun(&Boxed_Value::get_type_info), "get_type_info"); - m->add(user_type(), "Type_Info"); - m->add(constructor(), "Type_Info"); + m.add(fun(&Boxed_Value::get_type_info), "get_type_info"); + m.add(user_type(), "Type_Info"); + m.add(constructor(), "Type_Info"); operators::equal(m); - m->add(fun(&Type_Info::is_const), "is_type_const"); - m->add(fun(&Type_Info::is_reference), "is_type_reference"); - m->add(fun(&Type_Info::is_void), "is_type_void"); - m->add(fun(&Type_Info::is_undef), "is_type_undef"); - m->add(fun(&Type_Info::is_pointer), "is_type_pointer"); - m->add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic"); - m->add(fun(&Type_Info::name), "cpp_name"); - m->add(fun(&Type_Info::bare_name), "cpp_bare_name"); - m->add(fun(&Type_Info::bare_equal), "bare_equal"); + m.add(fun(&Type_Info::is_const), "is_type_const"); + m.add(fun(&Type_Info::is_reference), "is_type_reference"); + m.add(fun(&Type_Info::is_void), "is_type_void"); + m.add(fun(&Type_Info::is_undef), "is_type_undef"); + m.add(fun(&Type_Info::is_pointer), "is_type_pointer"); + m.add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic"); + m.add(fun(&Type_Info::name), "cpp_name"); + m.add(fun(&Type_Info::bare_name), "cpp_bare_name"); + m.add(fun(&Type_Info::bare_equal), "bare_equal"); basic_constructors("bool", m); @@ -528,14 +526,14 @@ namespace chaiscript operators::equal(m); operators::not_equal(m); - m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string"); - m->add(fun(&Bootstrap::bool_to_string), "to_string"); - m->add(fun(&unknown_assign), "="); - m->add(fun(&throw_exception), "throw"); - m->add(fun(&what), "what"); + m.add(fun([](const std::string &s) -> std::string { return s; }), "to_string"); + m.add(fun(&Bootstrap::bool_to_string), "to_string"); + m.add(fun(&unknown_assign), "="); + m.add(fun(&throw_exception), "throw"); + m.add(fun(&what), "what"); - m->add(fun(&to_string), "to_string"); - m->add(fun(&Boxed_Number::to_string), "to_string"); + m.add(fun(&to_string), "to_string"); + m.add(fun(&Boxed_Number::to_string), "to_string"); bootstrap_pod_type("double", m); bootstrap_pod_type("long_double", m); @@ -565,38 +563,38 @@ namespace chaiscript opers_arithmetic_pod(m); - m->add(fun(&print), "print_string"); - m->add(fun(&println), "println_string"); + m.add(fun(&print), "print_string"); + m.add(fun(&println), "println_string"); - m->add(dispatch::make_dynamic_proxy_function(&bind_function), "bind"); + m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind"); - m->add(fun(&shared_ptr_unconst_clone), "clone"); - m->add(fun(&ptr_assign::type>), "="); - m->add(fun(&ptr_assign::type>), "="); - m->add(chaiscript::base_class()); - m->add(fun( + m.add(fun(&shared_ptr_unconst_clone), "clone"); + m.add(fun(&ptr_assign::type>), "="); + m.add(fun(&ptr_assign::type>), "="); + m.add(chaiscript::base_class()); + m.add(fun( [](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr &t_rhs) { t_lhs.assign(t_rhs); } ), "=" ); - m->add(fun(&Boxed_Value::type_match), "type_match"); + m.add(fun(&Boxed_Value::type_match), "type_match"); - m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree"); - m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree"); + m.add(chaiscript::fun(&has_parse_tree), "has_parse_tree"); + m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree"); - m->add(chaiscript::base_class()); + m.add(chaiscript::base_class()); - m->add(chaiscript::user_type(), "arithmetic_error"); - m->add(chaiscript::base_class()); + m.add(chaiscript::user_type(), "arithmetic_error"); + m.add(chaiscript::base_class()); // chaiscript::bootstrap::standard_library::vector_type > >("AST_NodeVector", m); - chaiscript::utility::add_class(*m, + chaiscript::utility::add_class(m, "eval_error", { }, { {fun(&chaiscript::exception::eval_error::reason), "reason"}, @@ -611,7 +609,7 @@ namespace chaiscript ); - chaiscript::utility::add_class(*m, + chaiscript::utility::add_class(m, "File_Position", { constructor(), constructor() }, @@ -620,7 +618,7 @@ namespace chaiscript ); - chaiscript::utility::add_class(*m, + chaiscript::utility::add_class(m, "AST_Node", { }, { {fun(&AST_Node::text), "text"}, @@ -641,7 +639,7 @@ namespace chaiscript ); - chaiscript::utility::add_class(*m, + chaiscript::utility::add_class(m, "ChaiScript_Parser", { constructor() }, { {fun(&parser::ChaiScript_Parser::parse), "parse"}, diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 1823c9da..d7f82f08 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -177,19 +177,19 @@ namespace chaiscript /// Add Bidir_Range support for the given ContainerType template - ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = std::make_shared()) + Module& input_range_type_impl(const std::string &type, Module& m) { - m->add(user_type(), type + "_Range"); + m.add(user_type(), type + "_Range"); copy_constructor(type + "_Range", m); - m->add(constructor(), "range_internal"); + m.add(constructor(), "range_internal"); - m->add(fun(&Bidir_Type::empty), "empty"); - m->add(fun(&Bidir_Type::pop_front), "pop_front"); - m->add(fun(&Bidir_Type::front), "front"); - m->add(fun(&Bidir_Type::pop_back), "pop_back"); - m->add(fun(&Bidir_Type::back), "back"); + m.add(fun(&Bidir_Type::empty), "empty"); + m.add(fun(&Bidir_Type::pop_front), "pop_front"); + m.add(fun(&Bidir_Type::front), "front"); + m.add(fun(&Bidir_Type::pop_back), "pop_back"); + m.add(fun(&Bidir_Type::back), "back"); return m; } @@ -230,7 +230,7 @@ namespace chaiscript } template - ModulePtr input_range_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& input_range_type(const std::string &type, Module& m) { detail::input_range_type_impl >(type,m); detail::input_range_type_impl >("Const_" + type, m); @@ -241,11 +241,11 @@ namespace chaiscript /// Add random_access_container concept to the given ContainerType /// http://www.sgi.com/tech/stl/RandomAccessContainer.html template - ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) + Module& random_access_container_type(const std::string &/*type*/, Module& m) { //In the interest of runtime safety for the m, we prefer the at() method for [] access, //to throw an exception in an out of bounds condition. - m->add( + m.add( fun( [](ContainerType &c, int index) -> typename ContainerType::reference { /// \todo we are prefering to keep the key as 'int' to avoid runtime conversions @@ -253,7 +253,7 @@ namespace chaiscript return c.at(static_cast(index)); }), "[]"); - m->add( + m.add( fun( [](const ContainerType &c, int index) -> typename ContainerType::const_reference { /// \todo we are prefering to keep the key as 'int' to avoid runtime conversions @@ -268,7 +268,7 @@ namespace chaiscript /// Add assignable concept to the given ContainerType /// http://www.sgi.com/tech/stl/Assignable.html template - ModulePtr assignable_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& assignable_type(const std::string &type, Module& m) { copy_constructor(type, m); operators::assign(m); @@ -279,11 +279,11 @@ namespace chaiscript /// Add container concept to the given ContainerType /// http://www.sgi.com/tech/stl/Container.html template - ModulePtr container_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) + Module& container_type(const std::string &/*type*/, Module& m) { - m->add(fun([](const ContainerType *a) { return a->size(); } ), "size"); - m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty"); - m->add(fun([](ContainerType *a) { a->clear(); } ), "clear"); + m.add(fun([](const ContainerType *a) { return a->size(); } ), "size"); + m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty"); + m.add(fun([](ContainerType *a) { a->clear(); } ), "clear"); return m; } @@ -291,9 +291,9 @@ namespace chaiscript /// Add default constructable concept to the given Type /// http://www.sgi.com/tech/stl/DefaultConstructible.html template - ModulePtr default_constructible_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& default_constructible_type(const std::string &type, Module& m) { - m->add(constructor(), type); + m.add(constructor(), type); return m; } @@ -303,9 +303,9 @@ namespace chaiscript /// Add sequence concept to the given ContainerType /// http://www.sgi.com/tech/stl/Sequence.html template - ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) + Module& sequence_type(const std::string &/*type*/, Module& m) { - m->add(fun(&detail::insert_at), + m.add(fun(&detail::insert_at), []()->std::string{ if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { return "insert_ref_at"; @@ -314,7 +314,7 @@ namespace chaiscript } }()); - m->add(fun(&detail::erase_at), "erase_at"); + m.add(fun(&detail::erase_at), "erase_at"); return m; } @@ -323,18 +323,18 @@ namespace chaiscript /// Add back insertion sequence concept to the given ContainerType /// http://www.sgi.com/tech/stl/BackInsertionSequence.html template - ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& back_insertion_sequence_type(const std::string &type, Module& m) { typedef typename ContainerType::reference (ContainerType::*backptr)(); - m->add(fun(static_cast(&ContainerType::back)), "back"); + m.add(fun(static_cast(&ContainerType::back)), "back"); typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &); - m->add(fun(static_cast(&ContainerType::push_back)), + m.add(fun(static_cast(&ContainerType::push_back)), [&]()->std::string{ if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { - m->eval( + m.eval( "# Pushes the second value onto the container while making a clone of the value\n" "def push_back(" + type + " container, x)\n" "{ \n" @@ -353,7 +353,7 @@ namespace chaiscript } }()); - m->add(fun(&ContainerType::pop_back), "pop_back"); + m.add(fun(&ContainerType::pop_back), "pop_back"); return m; } @@ -362,20 +362,20 @@ namespace chaiscript /// Front insertion sequence /// http://www.sgi.com/tech/stl/FrontInsertionSequence.html template - ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& front_insertion_sequence_type(const std::string &type, Module& m) { typedef typename ContainerType::reference (ContainerType::*front_ptr)(); typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const; typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference); typedef void (ContainerType::*pop_ptr)(); - m->add(fun(static_cast(&ContainerType::front)), "front"); - m->add(fun(static_cast(&ContainerType::front)), "front"); + m.add(fun(static_cast(&ContainerType::front)), "front"); + m.add(fun(static_cast(&ContainerType::front)), "front"); - m->add(fun(static_cast(&ContainerType::push_front)), + m.add(fun(static_cast(&ContainerType::push_front)), [&]()->std::string{ if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { - m->eval( + m.eval( "# Pushes the second value onto the front of container while making a clone of the value\n" "def push_front(" + type + " container, x)\n" "{ \n" @@ -393,7 +393,7 @@ namespace chaiscript } }()); - m->add(fun(static_cast(&ContainerType::pop_front)), "pop_front"); + m.add(fun(static_cast(&ContainerType::pop_front)), "pop_front"); return m; } @@ -401,19 +401,19 @@ namespace chaiscript /// bootstrap a given PairType /// http://www.sgi.com/tech/stl/pair.html template - ModulePtr pair_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& pair_type(const std::string &type, Module& m) { - m->add(user_type(), type); + m.add(user_type(), type); typename PairType::first_type PairType::* f = &PairType::first; typename PairType::second_type PairType::* s = &PairType::second; - m->add(fun(f), "first"); - m->add(fun(s), "second"); + m.add(fun(f), "first"); + m.add(fun(s), "second"); basic_constructors(type, m); - m->add(constructor(), type); + m.add(constructor(), type); return m; } @@ -424,7 +424,7 @@ namespace chaiscript /// http://www.sgi.com/tech/stl/PairAssociativeContainer.html template - ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& pair_associative_container_type(const std::string &type, Module& m) { pair_type(type + "_Pair", m); @@ -435,17 +435,17 @@ namespace chaiscript /// Add unique associative container concept to the given ContainerType /// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html template - ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) + Module& unique_associative_container_type(const std::string &/*type*/, Module& m) { - m->add(fun(detail::count), "count"); + m.add(fun(detail::count), "count"); typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &); - m->add(fun(static_cast(&ContainerType::erase)), "erase"); + m.add(fun(static_cast(&ContainerType::erase)), "erase"); - m->add(fun(&detail::insert), "insert"); + m.add(fun(&detail::insert), "insert"); - m->add(fun(&detail::insert_ref), + m.add(fun(&detail::insert_ref), []()->std::string{ if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) { return "insert_ref"; @@ -462,21 +462,21 @@ namespace chaiscript /// Add a MapType container /// http://www.sgi.com/tech/stl/Map.html template - ModulePtr map_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& map_type(const std::string &type, Module& m) { - m->add(user_type(), type); + m.add(user_type(), type); typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &); typedef const typename MapType::mapped_type &(MapType::*const_elem_access)(const typename MapType::key_type &) const; - m->add(fun(static_cast(&MapType::operator[])), "[]"); + m.add(fun(static_cast(&MapType::operator[])), "[]"); - m->add(fun(static_cast(&MapType::at)), "at"); - m->add(fun(static_cast(&MapType::at)), "at"); + m.add(fun(static_cast(&MapType::at)), "at"); + m.add(fun(static_cast(&MapType::at)), "at"); if (typeid(MapType) == typeid(std::map)) { - m->eval(R"( + m.eval(R"( def Map::`==`(Map rhs) { if ( rhs.size() != this.size() ) { return false; @@ -512,9 +512,9 @@ namespace chaiscript /// hopefully working List type /// http://www.sgi.com/tech/stl/List.html template - ModulePtr list_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& list_type(const std::string &type, Module& m) { - m->add(user_type(), type); + m.add(user_type(), type); front_insertion_sequence_type(type, m); back_insertion_sequence_type(type, m); @@ -531,15 +531,15 @@ namespace chaiscript /// Create a vector type with associated concepts /// http://www.sgi.com/tech/stl/Vector.html template - ModulePtr vector_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& vector_type(const std::string &type, Module& m) { - m->add(user_type(), type); + m.add(user_type(), type); typedef typename VectorType::reference (VectorType::*frontptr)(); typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const; - m->add(fun(static_cast(&VectorType::front)), "front"); - m->add(fun(static_cast(&VectorType::front)), "front"); + m.add(fun(static_cast(&VectorType::front)), "front"); + m.add(fun(static_cast(&VectorType::front)), "front"); back_insertion_sequence_type(type, m); @@ -552,7 +552,7 @@ namespace chaiscript if (typeid(VectorType) == typeid(std::vector)) { - m->eval(R"( + m.eval(R"( def Vector::`==`(Vector rhs) { if ( rhs.size() != this.size() ) { return false; @@ -580,9 +580,9 @@ namespace chaiscript /// Add a String container /// http://www.sgi.com/tech/stl/basic_string.html template - ModulePtr string_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& string_type(const std::string &type, Module& m) { - m->add(user_type(), type); + m.add(user_type(), type); operators::addition(m); operators::assign_sum(m); opers_comparison(m); @@ -594,7 +594,7 @@ namespace chaiscript input_range_type(type, m); //Special case: add push_back to string (which doesn't support other back_insertion operations - m->add(fun(&String::push_back), + m.add(fun(&String::push_back), []()->std::string{ if (typeid(typename String::value_type) == typeid(Boxed_Value)) { return "push_back_ref"; @@ -604,20 +604,20 @@ namespace chaiscript }()); - m->add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find"); - m->add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind"); - m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of"); - m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of"); - m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of"); - m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of"); + m.add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find"); + m.add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind"); + m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of"); + m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of"); + m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of"); + m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of"); - m->add(fun([](String *s) { s->clear(); } ), "clear"); - m->add(fun([](const String *s) { return s->empty(); } ), "empty"); - m->add(fun([](const String *s) { return s->size(); } ), "size"); + m.add(fun([](String *s) { s->clear(); } ), "clear"); + m.add(fun([](const String *s) { return s->empty(); } ), "empty"); + m.add(fun([](const String *s) { return s->size(); } ), "size"); - m->add(fun([](const String *s) { return s->c_str(); } ), "c_str"); - m->add(fun([](const String *s) { return s->data(); } ), "data"); - m->add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr"); + m.add(fun([](const String *s) { return s->c_str(); } ), "c_str"); + m.add(fun([](const String *s) { return s->data(); } ), "data"); + m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr"); return m; } @@ -627,13 +627,13 @@ namespace chaiscript /// Add a MapType container /// http://www.sgi.com/tech/stl/Map.html template - ModulePtr future_type(const std::string &type, ModulePtr m = std::make_shared()) + Module& future_type(const std::string &type, Module& m) { - m->add(user_type(), type); + m.add(user_type(), type); - m->add(fun([](const FutureType &t) { return t.valid(); }), "valid"); - m->add(fun(&FutureType::get), "get"); - m->add(fun(&FutureType::wait), "wait"); + m.add(fun([](const FutureType &t) { return t.valid(); }), "valid"); + m.add(fun(&FutureType::get), "get"); + m.add(fun(&FutureType::wait), "wait"); return m; } diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 352b086f..b4808098 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -178,12 +178,6 @@ namespace chaiscript return *this; } - Module &add(const std::shared_ptr &m) - { - m->apply(*this, *this); - return *m; - } - template void apply(Eval &t_eval, Engine &t_engine) const { diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index 2d4401ee..25094cb6 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -229,234 +229,201 @@ namespace chaiscript template - ModulePtr assign(ModulePtr m = std::make_shared()) + Module& assign(Module& m) { - m->add(chaiscript::fun(&detail::assign), "="); - return m; + return m.add(chaiscript::fun(&detail::assign), "="); } template - ModulePtr assign_bitwise_and(ModulePtr m = std::make_shared()) + Module& assign_bitwise_and(Module& m) { - m->add(chaiscript::fun(&detail::assign_bitwise_and), "&="); - return m; + return m.add(chaiscript::fun(&detail::assign_bitwise_and), "&="); } template - ModulePtr assign_xor(ModulePtr m = std::make_shared()) + Module& assign_xor(Module& m) { - m->add(chaiscript::fun(&detail::assign_xor), "^="); - return m; + return m.add(chaiscript::fun(&detail::assign_xor), "^="); } template - ModulePtr assign_bitwise_or(ModulePtr m = std::make_shared()) + Module& assign_bitwise_or(Module& m) { - m->add(chaiscript::fun(&detail::assign_bitwise_or), "|="); - return m; + return m.add(chaiscript::fun(&detail::assign_bitwise_or), "|="); } template - ModulePtr assign_difference(ModulePtr m = std::make_shared()) + Module& assign_difference(Module& m) { - m->add(chaiscript::fun(&detail::assign_difference), "-="); - return m; + return m.add(chaiscript::fun(&detail::assign_difference), "-="); } template - ModulePtr assign_left_shift(ModulePtr m = std::make_shared()) + Module& assign_left_shift(Module& m) { - m->add(chaiscript::fun(&detail::assign_left_shift), "<<="); - return m; + return m.add(chaiscript::fun(&detail::assign_left_shift), "<<="); } template - ModulePtr assign_product(ModulePtr m = std::make_shared()) + Module& assign_product(Module& m) { - m->add(chaiscript::fun(&detail::assign_product), "*="); - return m; + return m.add(chaiscript::fun(&detail::assign_product), "*="); } template - ModulePtr assign_quotient(ModulePtr m = std::make_shared()) + Module& assign_quotient(Module& m) { - m->add(chaiscript::fun(&detail::assign_quotient), "/="); - return m; + return m.add(chaiscript::fun(&detail::assign_quotient), "/="); } template - ModulePtr assign_remainder(ModulePtr m = std::make_shared()) + Module& assign_remainder(Module& m) { - m->add(chaiscript::fun(&detail::assign_remainder), "%="); - return m; + return m.add(chaiscript::fun(&detail::assign_remainder), "%="); } template - ModulePtr assign_right_shift(ModulePtr m = std::make_shared()) + Module& assign_right_shift(Module& m) { - m->add(chaiscript::fun(&detail::assign_right_shift), ">>="); - return m; + return m.add(chaiscript::fun(&detail::assign_right_shift), ">>="); } template - ModulePtr assign_sum(ModulePtr m = std::make_shared()) + Module& assign_sum(Module& m) { - m->add(chaiscript::fun(&detail::assign_sum), "+="); - return m; + return m.add(chaiscript::fun(&detail::assign_sum), "+="); } template - ModulePtr prefix_decrement(ModulePtr m = std::make_shared()) + Module& prefix_decrement(Module& m) { - m->add(chaiscript::fun(&detail::prefix_decrement), "--"); - return m; + return m.add(chaiscript::fun(&detail::prefix_decrement), "--"); } template - ModulePtr prefix_increment(ModulePtr m = std::make_shared()) + Module& prefix_increment(Module& m) { - m->add(chaiscript::fun(&detail::prefix_increment), "++"); - return m; + return m.add(chaiscript::fun(&detail::prefix_increment), "++"); } template - ModulePtr equal(ModulePtr m = std::make_shared()) + Module& equal(Module& m) { - m->add(chaiscript::fun(&detail::equal), "=="); - return m; + return m.add(chaiscript::fun(&detail::equal), "=="); } template - ModulePtr greater_than(ModulePtr m = std::make_shared()) + Module& greater_than(Module& m) { - m->add(chaiscript::fun(&detail::greater_than), ">"); - return m; + return m.add(chaiscript::fun(&detail::greater_than), ">"); } template - ModulePtr greater_than_equal(ModulePtr m = std::make_shared()) + Module& greater_than_equal(Module& m) { - m->add(chaiscript::fun(&detail::greater_than_equal), ">="); - return m; + return m.add(chaiscript::fun(&detail::greater_than_equal), ">="); } template - ModulePtr less_than(ModulePtr m = std::make_shared()) + Module& less_than(Module& m) { - m->add(chaiscript::fun(&detail::less_than), "<"); - return m; + return m.add(chaiscript::fun(&detail::less_than), "<"); } template - ModulePtr less_than_equal(ModulePtr m = std::make_shared()) + Module& less_than_equal(Module& m) { - m->add(chaiscript::fun(&detail::less_than_equal), "<="); - return m; + return m.add(chaiscript::fun(&detail::less_than_equal), "<="); } template - ModulePtr logical_compliment(ModulePtr m = std::make_shared()) + Module& logical_compliment(Module& m) { - m->add(chaiscript::fun(&detail::logical_compliment), "!"); - return m; + return m.add(chaiscript::fun(&detail::logical_compliment), "!"); } template - ModulePtr not_equal(ModulePtr m = std::make_shared()) + Module& not_equal(Module& m) { - m->add(chaiscript::fun(&detail::not_equal), "!="); - return m; + return m.add(chaiscript::fun(&detail::not_equal), "!="); } template - ModulePtr addition(ModulePtr m = std::make_shared()) + Module& addition(Module& m) { - m->add(chaiscript::fun(&detail::addition), "+"); - return m; + return m.add(chaiscript::fun(&detail::addition), "+"); } template - ModulePtr unary_plus(ModulePtr m = std::make_shared()) + Module& unary_plus(Module& m) { - m->add(chaiscript::fun(&detail::unary_plus), "+"); - return m; + return m.add(chaiscript::fun(&detail::unary_plus), "+"); } template - ModulePtr subtraction(ModulePtr m = std::make_shared()) + Module& subtraction(Module& m) { - m->add(chaiscript::fun(&detail::subtraction), "-"); - return m; + return m.add(chaiscript::fun(&detail::subtraction), "-"); } template - ModulePtr unary_minus(ModulePtr m = std::make_shared()) + Module& unary_minus(Module& m) { - m->add(chaiscript::fun(&detail::unary_minus), "-"); - return m; + return m.add(chaiscript::fun(&detail::unary_minus), "-"); } template - ModulePtr bitwise_and(ModulePtr m = std::make_shared()) + Module& bitwise_and(Module& m) { - m->add(chaiscript::fun(&detail::bitwise_and), "&"); - return m; + return m.add(chaiscript::fun(&detail::bitwise_and), "&"); } template - ModulePtr bitwise_compliment(ModulePtr m = std::make_shared()) + Module& bitwise_compliment(Module& m) { - m->add(chaiscript::fun(&detail::bitwise_compliment), "~"); - return m; + return m.add(chaiscript::fun(&detail::bitwise_compliment), "~"); } template - ModulePtr bitwise_xor(ModulePtr m = std::make_shared()) + Module& bitwise_xor(Module& m) { - m->add(chaiscript::fun(&detail::bitwise_xor), "^"); - return m; + return m.add(chaiscript::fun(&detail::bitwise_xor), "^"); } template - ModulePtr bitwise_or(ModulePtr m = std::make_shared()) + Module& bitwise_or(Module& m) { - m->add(chaiscript::fun(&detail::bitwise_or), "|"); - return m; + return m.add(chaiscript::fun(&detail::bitwise_or), "|"); } template - ModulePtr division(ModulePtr m = std::make_shared()) + Module& division(Module& m) { - m->add(chaiscript::fun(&detail::division), "/"); - return m; + return m.add(chaiscript::fun(&detail::division), "/"); } template - ModulePtr left_shift(ModulePtr m = std::make_shared()) + Module& left_shift(Module& m) { - m->add(chaiscript::fun(&detail::left_shift), "<<"); - return m; + return m.add(chaiscript::fun(&detail::left_shift), "<<"); } template - ModulePtr multiplication(ModulePtr m = std::make_shared()) + Module& multiplication(Module& m) { - m->add(chaiscript::fun(&detail::multiplication), "*"); - return m; + return m.add(chaiscript::fun(&detail::multiplication), "*"); } template - ModulePtr remainder(ModulePtr m = std::make_shared()) + Module& remainder(Module& m) { - m->add(chaiscript::fun(&detail::remainder), "%"); - return m; + return m.add(chaiscript::fun(&detail::remainder), "%"); } template - ModulePtr right_shift(ModulePtr m = std::make_shared()) + Module& right_shift(Module& m) { - m->add(chaiscript::fun(&detail::right_shift), ">>"); - return m; + return m.add(chaiscript::fun(&detail::right_shift), ">>"); } } } diff --git a/include/chaiscript/utility/json_wrap.hpp b/include/chaiscript/utility/json_wrap.hpp index aec927b0..c0af1cd8 100644 --- a/include/chaiscript/utility/json_wrap.hpp +++ b/include/chaiscript/utility/json_wrap.hpp @@ -9,11 +9,11 @@ namespace chaiscript { public: - static ModulePtr library(ModulePtr m = std::make_shared()) + static Module& library(Module& m) { - m->add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json"); - m->add(chaiscript::fun(&json_wrap::to_json), "to_json"); + m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json"); + m.add(chaiscript::fun(&json_wrap::to_json), "to_json"); return m; diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 17950e21..b68f8d58 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -78,10 +78,7 @@ namespace chaiscript t_module.add(chaiscript::constructor(), t_class_name); using namespace chaiscript::bootstrap::operators; - t_module.add([](){ - // add some comparison and assignment operators - return assign(not_equal(equal())); - }()); + assign(not_equal(equal(t_module))); t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "=="); t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "=="); diff --git a/src/stl_extra.cpp b/src/stl_extra.cpp index ec38db77..d3ee3754 100644 --- a/src/stl_extra.cpp +++ b/src/stl_extra.cpp @@ -23,9 +23,9 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra() { - - auto module = chaiscript::bootstrap::standard_library::list_type >("List"); - module->add(chaiscript::bootstrap::standard_library::vector_type >("u16vector")); + auto module = std::make_shared(); + chaiscript::bootstrap::standard_library::list_type >("List", *module); + chaiscript::bootstrap::standard_library::vector_type >("u16vector", *module); module->add(chaiscript::vector_conversion>()); return module; } diff --git a/src/test_module.cpp b/src/test_module.cpp index 589437e3..731e3271 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -189,9 +189,9 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val"); m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray"); - m->add(chaiscript::bootstrap::array("IntArray_2_3_5")); - m->add(chaiscript::bootstrap::array("IntArray_3_5")); - m->add(chaiscript::bootstrap::array("IntArray_5")); + chaiscript::bootstrap::array("IntArray_2_3_5", *m); + chaiscript::bootstrap::array("IntArray_3_5", *m); + chaiscript::bootstrap::array("IntArray_5", *m); // member that is a function m->add(chaiscript::fun(&TestBaseType::func_member), "func_member"); From 7865f8e7f214848d6ed035e8b054ab25e9a07e9d Mon Sep 17 00:00:00 2001 From: Bjorn Fahller Date: Sat, 9 Apr 2016 21:09:45 +0200 Subject: [PATCH 20/27] Keep ModulePtr kompatible functions Since use of (one of) the functions in bootstrap_stl.hpp is in a sample, chances are there are people using them in real world application code. Thus the backwards compatible versions. --- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 115 +++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index d7f82f08..3c5f52b3 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -236,6 +236,13 @@ namespace chaiscript detail::input_range_type_impl >("Const_" + type, m); return m; } + template + ModulePtr input_range_type(const std::string &type) + { + auto m = std::make_shared(); + input_range_type(type, *m); + return m; + } /// Add random_access_container concept to the given ContainerType @@ -263,6 +270,14 @@ namespace chaiscript return m; } + template + ModulePtr random_access_container_type(const std::string &type) + { + auto m = std::make_shared(); + random_access_container_type(type, *m); + return m; + } + /// Add assignable concept to the given ContainerType @@ -274,6 +289,13 @@ namespace chaiscript operators::assign(m); return m; } + template + ModulePtr assignable_type(const std::string &type) + { + auto m = std::make_shared(); + assignable_type(type, *m); + return m; + } /// Add container concept to the given ContainerType @@ -286,6 +308,13 @@ namespace chaiscript m.add(fun([](ContainerType *a) { a->clear(); } ), "clear"); return m; } + template + ModulePtr container_type(const std::string& type) + { + auto m = std::make_shared(); + container_type(type, *m); + return m; + } /// Add default constructable concept to the given Type @@ -296,7 +325,13 @@ namespace chaiscript m.add(constructor(), type); return m; } - + template + ModulePtr default_constructible_type(const std::string& type) + { + auto m = std::make_shared(); + default_constructible_type(type, *m); + return m; + } @@ -318,7 +353,13 @@ namespace chaiscript return m; } - + template + ModulePtr sequence_type(const std::string &type) + { + auto m = std::make_shared(); + sequence_type(type, *m); + return m; + } /// Add back insertion sequence concept to the given ContainerType /// http://www.sgi.com/tech/stl/BackInsertionSequence.html @@ -356,6 +397,13 @@ namespace chaiscript m.add(fun(&ContainerType::pop_back), "pop_back"); return m; } + template + ModulePtr back_insertion_sequence_type(const std::string &type) + { + auto m = std::make_shared(); + back_insertion_sequence_type(type, *m); + return m; + } @@ -396,6 +444,13 @@ namespace chaiscript m.add(fun(static_cast(&ContainerType::pop_front)), "pop_front"); return m; } + template + ModulePtr front_insertion_sequence_type(const std::string &type) + { + auto m = std::make_shared(); + front_insertion_sequence_type(type, *m); + return m; + } /// bootstrap a given PairType @@ -417,6 +472,13 @@ namespace chaiscript return m; } + template + ModulePtr pair_type(const std::string &type) + { + auto m = std::make_shared(); + pair_type(type, *m); + return m; + } @@ -430,6 +492,13 @@ namespace chaiscript return m; } + template + ModulePtr pair_associative_container_type(const std::string &type) + { + auto m = std::make_shared(); + pair_associative_container_type(type, *m); + return m; + } /// Add unique associative container concept to the given ContainerType @@ -457,6 +526,13 @@ namespace chaiscript return m; } + template + ModulePtr unique_associative_container_type(const std::string &type) + { + auto m = std::make_shared(); + unique_associative_container_type(type, *m); + return m; + } /// Add a MapType container @@ -507,6 +583,13 @@ namespace chaiscript return m; } + template + ModulePtr map_type(const std::string &type) + { + auto m = std::make_shared(); + map_type(type, *m); + return m; + } /// hopefully working List type @@ -526,6 +609,13 @@ namespace chaiscript return m; } + template + ModulePtr list_type(const std::string &type) + { + auto m = std::make_shared(); + list_type(type, m); + return m; + } /// Create a vector type with associated concepts @@ -576,6 +666,13 @@ namespace chaiscript return m; } + template + ModulePtr vector_type(const std::string &type) + { + auto m = std::make_shared(); + vector_type(type, *m); + return m; + } /// Add a String container /// http://www.sgi.com/tech/stl/basic_string.html @@ -621,6 +718,13 @@ namespace chaiscript return m; } + template + ModulePtr string_type(const std::string &type) + { + auto m = std::make_shared(); + string_type(type, *m); + return m; + } @@ -635,6 +739,13 @@ namespace chaiscript m.add(fun(&FutureType::get), "get"); m.add(fun(&FutureType::wait), "wait"); + return m; + } + template + ModulePtr future_type(const std::string &type) + { + auto m = std::make_shared(); + future_type(type, *m); return m; } } From 2fe794fcaedddbb5d6717f40da8f2dd9dae625b5 Mon Sep 17 00:00:00 2001 From: Bjorn Fahller Date: Mon, 11 Apr 2016 18:16:30 +0200 Subject: [PATCH 21/27] Do not return Module& from internal funcs on Module& A slight improvement in built binary size is achieved by not having to generate code for the return. --- include/chaiscript/dispatchkit/bootstrap.hpp | 28 ++-- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 65 +++------ include/chaiscript/dispatchkit/operators.hpp | 132 +++++++++--------- include/chaiscript/utility/utility.hpp | 4 +- 4 files changed, 96 insertions(+), 133 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 1eab977c..4bee74d3 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -52,7 +52,7 @@ namespace chaiscript } template::value>::type > - Module& array(const std::string &type, Module& m) + void array(const std::string &type, Module& m) { typedef typename std::remove_extent::type ReturnType; const auto extent = std::extent::value; @@ -83,9 +83,6 @@ namespace chaiscript [extent](const T &) { return extent; }), "size"); - - - return m; } /// \brief Adds a copy constructor for the given type to the given Model @@ -94,9 +91,9 @@ namespace chaiscript /// \tparam T The type to add a copy constructor for /// \returns The passed in Module template - Module& copy_constructor(const std::string &type, Module& m) + void copy_constructor(const std::string &type, Module& m) { - return m.add(constructor(), type); + m.add(constructor(), type); } /// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users. @@ -104,7 +101,7 @@ namespace chaiscript /// \param[in,out] m module to add comparison operators to /// \returns the passed in Module. template - Module& opers_comparison(Module& m) + void opers_comparison(Module& m) { operators::equal(m); operators::greater_than(m); @@ -112,7 +109,6 @@ namespace chaiscript operators::less_than(m); operators::less_than_equal(m); operators::not_equal(m); - return m; } @@ -125,11 +121,10 @@ namespace chaiscript /// \sa copy_constructor /// \sa constructor template - Module& basic_constructors(const std::string &type, Module& m) + void basic_constructors(const std::string &type, Module& m) { m.add(constructor(), type); copy_constructor(type, m); - return m; } /// \brief Adds a constructor for a POD type @@ -137,9 +132,9 @@ namespace chaiscript /// \param[in] type The name of the type /// \param[in,out] m The Module to add the constructor to template - Module& construct_pod(const std::string &type, Module& m) + void construct_pod(const std::string &type, Module& m) { - return m.add(fun(&detail::construct_pod), type); + m.add(fun(&detail::construct_pod), type); } @@ -183,14 +178,13 @@ namespace chaiscript /// Add all common functions for a POD type. All operators, and /// common conversions template - Module& bootstrap_pod_type(const std::string &name, Module& m) + void bootstrap_pod_type(const std::string &name, Module& m) { m.add(user_type(), name); m.add(constructor(), name); construct_pod(name, m); m.add(fun(&parse_string), "to_" + name); - return m; } @@ -402,7 +396,7 @@ namespace chaiscript /// \brief perform all common bootstrap functions for std::string, void and POD types /// \param[in,out] m Module to add bootstrapped functions to /// \returns passed in Module - static Module& bootstrap(Module& m) + static void bootstrap(Module& m) { m.add(user_type(), "void"); m.add(user_type(), "bool"); @@ -645,10 +639,6 @@ namespace chaiscript { {fun(&parser::ChaiScript_Parser::parse), "parse"}, {fun(&parser::ChaiScript_Parser::ast), "ast"} } ); - - - - return m; } }; } diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 3c5f52b3..7ba588b7 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -177,7 +177,7 @@ namespace chaiscript /// Add Bidir_Range support for the given ContainerType template - Module& input_range_type_impl(const std::string &type, Module& m) + void input_range_type_impl(const std::string &type, Module& m) { m.add(user_type(), type + "_Range"); @@ -190,9 +190,7 @@ namespace chaiscript m.add(fun(&Bidir_Type::front), "front"); m.add(fun(&Bidir_Type::pop_back), "pop_back"); m.add(fun(&Bidir_Type::back), "back"); - - return m; - } + } /// Algorithm for inserting at a specific position into a container @@ -230,11 +228,10 @@ namespace chaiscript } template - Module& input_range_type(const std::string &type, Module& m) + void input_range_type(const std::string &type, Module& m) { detail::input_range_type_impl >(type,m); detail::input_range_type_impl >("Const_" + type, m); - return m; } template ModulePtr input_range_type(const std::string &type) @@ -248,7 +245,7 @@ namespace chaiscript /// Add random_access_container concept to the given ContainerType /// http://www.sgi.com/tech/stl/RandomAccessContainer.html template - Module& random_access_container_type(const std::string &/*type*/, Module& m) + void random_access_container_type(const std::string &/*type*/, Module& m) { //In the interest of runtime safety for the m, we prefer the at() method for [] access, //to throw an exception in an out of bounds condition. @@ -267,8 +264,6 @@ namespace chaiscript /// during dispatch. reevaluate return c.at(static_cast(index)); }), "[]"); - - return m; } template ModulePtr random_access_container_type(const std::string &type) @@ -283,11 +278,10 @@ namespace chaiscript /// Add assignable concept to the given ContainerType /// http://www.sgi.com/tech/stl/Assignable.html template - Module& assignable_type(const std::string &type, Module& m) + void assignable_type(const std::string &type, Module& m) { copy_constructor(type, m); operators::assign(m); - return m; } template ModulePtr assignable_type(const std::string &type) @@ -301,12 +295,11 @@ namespace chaiscript /// Add container concept to the given ContainerType /// http://www.sgi.com/tech/stl/Container.html template - Module& container_type(const std::string &/*type*/, Module& m) + void container_type(const std::string &/*type*/, Module& m) { m.add(fun([](const ContainerType *a) { return a->size(); } ), "size"); m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty"); m.add(fun([](ContainerType *a) { a->clear(); } ), "clear"); - return m; } template ModulePtr container_type(const std::string& type) @@ -320,10 +313,9 @@ namespace chaiscript /// Add default constructable concept to the given Type /// http://www.sgi.com/tech/stl/DefaultConstructible.html template - Module& default_constructible_type(const std::string &type, Module& m) + void default_constructible_type(const std::string &type, Module& m) { m.add(constructor(), type); - return m; } template ModulePtr default_constructible_type(const std::string& type) @@ -338,7 +330,7 @@ namespace chaiscript /// Add sequence concept to the given ContainerType /// http://www.sgi.com/tech/stl/Sequence.html template - Module& sequence_type(const std::string &/*type*/, Module& m) + void sequence_type(const std::string &/*type*/, Module& m) { m.add(fun(&detail::insert_at), []()->std::string{ @@ -350,8 +342,6 @@ namespace chaiscript }()); m.add(fun(&detail::erase_at), "erase_at"); - - return m; } template ModulePtr sequence_type(const std::string &type) @@ -364,7 +354,7 @@ namespace chaiscript /// Add back insertion sequence concept to the given ContainerType /// http://www.sgi.com/tech/stl/BackInsertionSequence.html template - Module& back_insertion_sequence_type(const std::string &type, Module& m) + void back_insertion_sequence_type(const std::string &type, Module& m) { typedef typename ContainerType::reference (ContainerType::*backptr)(); @@ -395,7 +385,6 @@ namespace chaiscript }()); m.add(fun(&ContainerType::pop_back), "pop_back"); - return m; } template ModulePtr back_insertion_sequence_type(const std::string &type) @@ -410,7 +399,7 @@ namespace chaiscript /// Front insertion sequence /// http://www.sgi.com/tech/stl/FrontInsertionSequence.html template - Module& front_insertion_sequence_type(const std::string &type, Module& m) + void front_insertion_sequence_type(const std::string &type, Module& m) { typedef typename ContainerType::reference (ContainerType::*front_ptr)(); typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const; @@ -442,7 +431,6 @@ namespace chaiscript }()); m.add(fun(static_cast(&ContainerType::pop_front)), "pop_front"); - return m; } template ModulePtr front_insertion_sequence_type(const std::string &type) @@ -456,7 +444,7 @@ namespace chaiscript /// bootstrap a given PairType /// http://www.sgi.com/tech/stl/pair.html template - Module& pair_type(const std::string &type, Module& m) + void pair_type(const std::string &type, Module& m) { m.add(user_type(), type); @@ -469,8 +457,6 @@ namespace chaiscript basic_constructors(type, m); m.add(constructor(), type); - - return m; } template ModulePtr pair_type(const std::string &type) @@ -486,11 +472,9 @@ namespace chaiscript /// http://www.sgi.com/tech/stl/PairAssociativeContainer.html template - Module& pair_associative_container_type(const std::string &type, Module& m) + void pair_associative_container_type(const std::string &type, Module& m) { pair_type(type + "_Pair", m); - - return m; } template ModulePtr pair_associative_container_type(const std::string &type) @@ -504,7 +488,7 @@ namespace chaiscript /// Add unique associative container concept to the given ContainerType /// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html template - Module& unique_associative_container_type(const std::string &/*type*/, Module& m) + void unique_associative_container_type(const std::string &/*type*/, Module& m) { m.add(fun(detail::count), "count"); @@ -522,9 +506,6 @@ namespace chaiscript return "insert"; } }()); - - - return m; } template ModulePtr unique_associative_container_type(const std::string &type) @@ -538,7 +519,7 @@ namespace chaiscript /// Add a MapType container /// http://www.sgi.com/tech/stl/Map.html template - Module& map_type(const std::string &type, Module& m) + void map_type(const std::string &type, Module& m) { m.add(user_type(), type); @@ -580,8 +561,6 @@ namespace chaiscript unique_associative_container_type(type, m); pair_associative_container_type(type, m); input_range_type(type, m); - - return m; } template ModulePtr map_type(const std::string &type) @@ -595,7 +574,7 @@ namespace chaiscript /// hopefully working List type /// http://www.sgi.com/tech/stl/List.html template - Module& list_type(const std::string &type, Module& m) + void list_type(const std::string &type, Module& m) { m.add(user_type(), type); @@ -606,8 +585,6 @@ namespace chaiscript default_constructible_type(type, m); assignable_type(type, m); input_range_type(type, m); - - return m; } template ModulePtr list_type(const std::string &type) @@ -621,7 +598,7 @@ namespace chaiscript /// Create a vector type with associated concepts /// http://www.sgi.com/tech/stl/Vector.html template - Module& vector_type(const std::string &type, Module& m) + void vector_type(const std::string &type, Module& m) { m.add(user_type(), type); @@ -663,8 +640,6 @@ namespace chaiscript } )" ); } - - return m; } template ModulePtr vector_type(const std::string &type) @@ -677,7 +652,7 @@ namespace chaiscript /// Add a String container /// http://www.sgi.com/tech/stl/basic_string.html template - Module& string_type(const std::string &type, Module& m) + void string_type(const std::string &type, Module& m) { m.add(user_type(), type); operators::addition(m); @@ -715,8 +690,6 @@ namespace chaiscript m.add(fun([](const String *s) { return s->c_str(); } ), "c_str"); m.add(fun([](const String *s) { return s->data(); } ), "data"); m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr"); - - return m; } template ModulePtr string_type(const std::string &type) @@ -731,15 +704,13 @@ namespace chaiscript /// Add a MapType container /// http://www.sgi.com/tech/stl/Map.html template - Module& future_type(const std::string &type, Module& m) + void future_type(const std::string &type, Module& m) { m.add(user_type(), type); m.add(fun([](const FutureType &t) { return t.valid(); }), "valid"); m.add(fun(&FutureType::get), "get"); m.add(fun(&FutureType::wait), "wait"); - - return m; } template ModulePtr future_type(const std::string &type) diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index 25094cb6..8dc54ba0 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -229,201 +229,201 @@ namespace chaiscript template - Module& assign(Module& m) + void assign(Module& m) { - return m.add(chaiscript::fun(&detail::assign), "="); + m.add(chaiscript::fun(&detail::assign), "="); } template - Module& assign_bitwise_and(Module& m) + void assign_bitwise_and(Module& m) { - return m.add(chaiscript::fun(&detail::assign_bitwise_and), "&="); + m.add(chaiscript::fun(&detail::assign_bitwise_and), "&="); } template - Module& assign_xor(Module& m) + void assign_xor(Module& m) { - return m.add(chaiscript::fun(&detail::assign_xor), "^="); + m.add(chaiscript::fun(&detail::assign_xor), "^="); } template - Module& assign_bitwise_or(Module& m) + void assign_bitwise_or(Module& m) { - return m.add(chaiscript::fun(&detail::assign_bitwise_or), "|="); + m.add(chaiscript::fun(&detail::assign_bitwise_or), "|="); } template - Module& assign_difference(Module& m) + void assign_difference(Module& m) { - return m.add(chaiscript::fun(&detail::assign_difference), "-="); + m.add(chaiscript::fun(&detail::assign_difference), "-="); } template - Module& assign_left_shift(Module& m) + void assign_left_shift(Module& m) { - return m.add(chaiscript::fun(&detail::assign_left_shift), "<<="); + m.add(chaiscript::fun(&detail::assign_left_shift), "<<="); } template - Module& assign_product(Module& m) + void assign_product(Module& m) { - return m.add(chaiscript::fun(&detail::assign_product), "*="); + m.add(chaiscript::fun(&detail::assign_product), "*="); } template - Module& assign_quotient(Module& m) + void assign_quotient(Module& m) { - return m.add(chaiscript::fun(&detail::assign_quotient), "/="); + m.add(chaiscript::fun(&detail::assign_quotient), "/="); } template - Module& assign_remainder(Module& m) + void assign_remainder(Module& m) { - return m.add(chaiscript::fun(&detail::assign_remainder), "%="); + m.add(chaiscript::fun(&detail::assign_remainder), "%="); } template - Module& assign_right_shift(Module& m) + void assign_right_shift(Module& m) { - return m.add(chaiscript::fun(&detail::assign_right_shift), ">>="); + m.add(chaiscript::fun(&detail::assign_right_shift), ">>="); } template - Module& assign_sum(Module& m) + void assign_sum(Module& m) { - return m.add(chaiscript::fun(&detail::assign_sum), "+="); + m.add(chaiscript::fun(&detail::assign_sum), "+="); } template - Module& prefix_decrement(Module& m) + void prefix_decrement(Module& m) { - return m.add(chaiscript::fun(&detail::prefix_decrement), "--"); + m.add(chaiscript::fun(&detail::prefix_decrement), "--"); } template - Module& prefix_increment(Module& m) + void prefix_increment(Module& m) { - return m.add(chaiscript::fun(&detail::prefix_increment), "++"); + m.add(chaiscript::fun(&detail::prefix_increment), "++"); } template - Module& equal(Module& m) + void equal(Module& m) { - return m.add(chaiscript::fun(&detail::equal), "=="); + m.add(chaiscript::fun(&detail::equal), "=="); } template - Module& greater_than(Module& m) + void greater_than(Module& m) { - return m.add(chaiscript::fun(&detail::greater_than), ">"); + m.add(chaiscript::fun(&detail::greater_than), ">"); } template - Module& greater_than_equal(Module& m) + void greater_than_equal(Module& m) { - return m.add(chaiscript::fun(&detail::greater_than_equal), ">="); + m.add(chaiscript::fun(&detail::greater_than_equal), ">="); } template - Module& less_than(Module& m) + void less_than(Module& m) { - return m.add(chaiscript::fun(&detail::less_than), "<"); + m.add(chaiscript::fun(&detail::less_than), "<"); } template - Module& less_than_equal(Module& m) + void less_than_equal(Module& m) { - return m.add(chaiscript::fun(&detail::less_than_equal), "<="); + m.add(chaiscript::fun(&detail::less_than_equal), "<="); } template - Module& logical_compliment(Module& m) + void logical_compliment(Module& m) { - return m.add(chaiscript::fun(&detail::logical_compliment), "!"); + m.add(chaiscript::fun(&detail::logical_compliment), "!"); } template - Module& not_equal(Module& m) + void not_equal(Module& m) { - return m.add(chaiscript::fun(&detail::not_equal), "!="); + m.add(chaiscript::fun(&detail::not_equal), "!="); } template - Module& addition(Module& m) + void addition(Module& m) { - return m.add(chaiscript::fun(&detail::addition), "+"); + m.add(chaiscript::fun(&detail::addition), "+"); } template - Module& unary_plus(Module& m) + void unary_plus(Module& m) { - return m.add(chaiscript::fun(&detail::unary_plus), "+"); + m.add(chaiscript::fun(&detail::unary_plus), "+"); } template - Module& subtraction(Module& m) + void subtraction(Module& m) { - return m.add(chaiscript::fun(&detail::subtraction), "-"); + m.add(chaiscript::fun(&detail::subtraction), "-"); } template - Module& unary_minus(Module& m) + void unary_minus(Module& m) { - return m.add(chaiscript::fun(&detail::unary_minus), "-"); + m.add(chaiscript::fun(&detail::unary_minus), "-"); } template - Module& bitwise_and(Module& m) + void bitwise_and(Module& m) { - return m.add(chaiscript::fun(&detail::bitwise_and), "&"); + m.add(chaiscript::fun(&detail::bitwise_and), "&"); } template - Module& bitwise_compliment(Module& m) + void bitwise_compliment(Module& m) { - return m.add(chaiscript::fun(&detail::bitwise_compliment), "~"); + m.add(chaiscript::fun(&detail::bitwise_compliment), "~"); } template - Module& bitwise_xor(Module& m) + void bitwise_xor(Module& m) { - return m.add(chaiscript::fun(&detail::bitwise_xor), "^"); + m.add(chaiscript::fun(&detail::bitwise_xor), "^"); } template - Module& bitwise_or(Module& m) + void bitwise_or(Module& m) { - return m.add(chaiscript::fun(&detail::bitwise_or), "|"); + m.add(chaiscript::fun(&detail::bitwise_or), "|"); } template - Module& division(Module& m) + void division(Module& m) { - return m.add(chaiscript::fun(&detail::division), "/"); + m.add(chaiscript::fun(&detail::division), "/"); } template - Module& left_shift(Module& m) + void left_shift(Module& m) { - return m.add(chaiscript::fun(&detail::left_shift), "<<"); + m.add(chaiscript::fun(&detail::left_shift), "<<"); } template - Module& multiplication(Module& m) + void multiplication(Module& m) { - return m.add(chaiscript::fun(&detail::multiplication), "*"); + m.add(chaiscript::fun(&detail::multiplication), "*"); } template - Module& remainder(Module& m) + void remainder(Module& m) { - return m.add(chaiscript::fun(&detail::remainder), "%"); + m.add(chaiscript::fun(&detail::remainder), "%"); } template - Module& right_shift(Module& m) + void right_shift(Module& m) { - return m.add(chaiscript::fun(&detail::right_shift), ">>"); + m.add(chaiscript::fun(&detail::right_shift), ">>"); } } } diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index b68f8d58..1ca0dfbb 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -78,7 +78,9 @@ namespace chaiscript t_module.add(chaiscript::constructor(), t_class_name); using namespace chaiscript::bootstrap::operators; - assign(not_equal(equal(t_module))); + equal(t_module); + not_equal(t_module); + assign(t_module); t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "=="); t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "=="); From 49ef5306a9c7b7f9c7c5dde37c2f52b9be85366d Mon Sep 17 00:00:00 2001 From: ELynx Date: Fri, 15 Apr 2016 13:15:30 +0300 Subject: [PATCH 22/27] Add resize to stl list and vector; add reserve to stl vector --- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 24 +++++++++++++++++++ unittests/list_resize.chai | 13 ++++++++++ unittests/vector_reserve.chai | 7 ++++++ unittests/vector_resize.chai | 13 ++++++++++ 4 files changed, 57 insertions(+) create mode 100644 unittests/list_resize.chai create mode 100644 unittests/vector_reserve.chai create mode 100644 unittests/vector_resize.chai diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 7ba588b7..3c93c919 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -292,6 +292,27 @@ namespace chaiscript } + /// Add container resize concept to the given ContainerType + /// http://www.cplusplus.com/reference/stl/ + template + ModulePtr resizable_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) + { + m->add(fun([](ContainerType *a, ContainerType::size_type n, ContainerType::value_type val) { return a->resize(n, val); } ), "resize"); + m->add(fun([](ContainerType *a, ContainerType::size_type n) { return a->resize(n, ContainerType::value_type()); } ), "resize"); + return m; + } + + + /// Add container reserve concept to the given ContainerType + /// http://www.cplusplus.com/reference/stl/ + template + ModulePtr reservable_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) + { + m->add(fun([](ContainerType *a, ContainerType::size_type n) { return a->reserve(n); } ), "reserve"); + return m; + } + + /// Add container concept to the given ContainerType /// http://www.sgi.com/tech/stl/Container.html template @@ -581,6 +602,7 @@ namespace chaiscript front_insertion_sequence_type(type, m); back_insertion_sequence_type(type, m); sequence_type(type, m); + resizable_type(type, m); container_type(type, m); default_constructible_type(type, m); assignable_type(type, m); @@ -612,6 +634,8 @@ namespace chaiscript back_insertion_sequence_type(type, m); sequence_type(type, m); random_access_container_type(type, m); + resizable_type(type, m); + reservable_type(type, m); container_type(type, m); default_constructible_type(type, m); assignable_type(type, m); diff --git a/unittests/list_resize.chai b/unittests/list_resize.chai new file mode 100644 index 00000000..f34e77aa --- /dev/null +++ b/unittests/list_resize.chai @@ -0,0 +1,13 @@ +load_module("stl_extra"); + +auto list = List(); + +list.resize(2); +assert_equal(list.size(), 2); + +list.resize(6, "AAA"); +assert_equal(list[5], "AAA"); + +list.resize(0); +assert_equal(list.size(), 0); + diff --git a/unittests/vector_reserve.chai b/unittests/vector_reserve.chai new file mode 100644 index 00000000..764002af --- /dev/null +++ b/unittests/vector_reserve.chai @@ -0,0 +1,7 @@ +load_module("stl_extra"); + +auto uint16v = u16vector(); + +uint16v.reserve(5); +assert_true(uint16v.size() >= 5); + diff --git a/unittests/vector_resize.chai b/unittests/vector_resize.chai new file mode 100644 index 00000000..577ae6df --- /dev/null +++ b/unittests/vector_resize.chai @@ -0,0 +1,13 @@ +load_module("stl_extra"); + +auto uint16v = u16vector(); + +uint16v.resize(2); +assert_equal(uint16v.size(), 2); + +uint16v.resize(6, 3); +assert_equal(uint16v[5], 3); + +uint16v.resize(0); +assert_equal(uint16v.size(), 0); + From e8ff1f9d7e4849781300efe1b12dcb67dc5717a0 Mon Sep 17 00:00:00 2001 From: ELynx Date: Fri, 15 Apr 2016 13:39:51 +0300 Subject: [PATCH 23/27] Proper template types for resizable_type and reservable_type --- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 3c93c919..f9a209bf 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -295,22 +295,34 @@ namespace chaiscript /// Add container resize concept to the given ContainerType /// http://www.cplusplus.com/reference/stl/ template - ModulePtr resizable_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) - { - m->add(fun([](ContainerType *a, ContainerType::size_type n, ContainerType::value_type val) { return a->resize(n, val); } ), "resize"); - m->add(fun([](ContainerType *a, ContainerType::size_type n) { return a->resize(n, ContainerType::value_type()); } ), "resize"); + void resizable_type(const std::string &/*type*/, Module& m) + { + m.add(fun([](ContainerType *a, ContainerType::size_type n, ContainerType::value_type val) { return a->resize(n, val); } ), "resize"); + m.add(fun([](ContainerType *a, ContainerType::size_type n) { return a->resize(n, ContainerType::value_type()); } ), "resize"); + } + template + ModulePtr resizable_type(const std::string &type) + { + auto m = std::make_shared(); + resizable_type(type, *m); return m; - } + } /// Add container reserve concept to the given ContainerType /// http://www.cplusplus.com/reference/stl/ template - ModulePtr reservable_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) - { - m->add(fun([](ContainerType *a, ContainerType::size_type n) { return a->reserve(n); } ), "reserve"); + void reservable_type(const std::string &/*type*/, Module& m) + { + m.add(fun([](ContainerType *a, ContainerType::size_type n) { return a->reserve(n); } ), "reserve"); + } + template + ModulePtr reservable_type(const std::string &type) + { + auto m = std::make_shared(); + reservable_type(type, *m); return m; - } + } /// Add container concept to the given ContainerType From 14d429853bc5d2399b23a187c6215511bb52ad01 Mon Sep 17 00:00:00 2001 From: ELynx Date: Fri, 15 Apr 2016 14:00:01 +0300 Subject: [PATCH 24/27] Add typename; pass value to resize by const referene --- include/chaiscript/dispatchkit/bootstrap_stl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index f9a209bf..b86b1e44 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -297,8 +297,8 @@ namespace chaiscript template void resizable_type(const std::string &/*type*/, Module& m) { - m.add(fun([](ContainerType *a, ContainerType::size_type n, ContainerType::value_type val) { return a->resize(n, val); } ), "resize"); - m.add(fun([](ContainerType *a, ContainerType::size_type n) { return a->resize(n, ContainerType::value_type()); } ), "resize"); + m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type& val) { return a->resize(n, val); } ), "resize"); + m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); } ), "resize"); } template ModulePtr resizable_type(const std::string &type) @@ -314,7 +314,7 @@ namespace chaiscript template void reservable_type(const std::string &/*type*/, Module& m) { - m.add(fun([](ContainerType *a, ContainerType::size_type n) { return a->reserve(n); } ), "reserve"); + m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve"); } template ModulePtr reservable_type(const std::string &type) From cdb9dcc15443d927e892e65ade6b1b8e421bb6aa Mon Sep 17 00:00:00 2001 From: ELynx Date: Fri, 15 Apr 2016 14:08:03 +0300 Subject: [PATCH 25/27] Fix list unittest --- unittests/list_resize.chai | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/list_resize.chai b/unittests/list_resize.chai index f34e77aa..0d6f05cf 100644 --- a/unittests/list_resize.chai +++ b/unittests/list_resize.chai @@ -6,7 +6,7 @@ list.resize(2); assert_equal(list.size(), 2); list.resize(6, "AAA"); -assert_equal(list[5], "AAA"); +assert_equal(list.back(), "AAA"); list.resize(0); assert_equal(list.size(), 0); From 62e34c097cb2fdd9c26776024589d4fdd9574b7c Mon Sep 17 00:00:00 2001 From: ELynx Date: Fri, 15 Apr 2016 14:12:07 +0300 Subject: [PATCH 26/27] Add capacity check; fix vector_reserve unittest --- include/chaiscript/dispatchkit/bootstrap_stl.hpp | 1 + unittests/vector_reserve.chai | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index b86b1e44..b9e0a9f5 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -315,6 +315,7 @@ namespace chaiscript void reservable_type(const std::string &/*type*/, Module& m) { m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve"); + m.add(fun([](const ContainerType *a) { return a->capacity(); } ), "capacity"); } template ModulePtr reservable_type(const std::string &type) diff --git a/unittests/vector_reserve.chai b/unittests/vector_reserve.chai index 764002af..68c8dbdb 100644 --- a/unittests/vector_reserve.chai +++ b/unittests/vector_reserve.chai @@ -3,5 +3,5 @@ load_module("stl_extra"); auto uint16v = u16vector(); uint16v.reserve(5); -assert_true(uint16v.size() >= 5); +assert_true(uint16v.capacity() >= 5); From 6d6f79b1a45348a8b3d4120a9241a2ab9113e4ac Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 18 Apr 2016 14:38:25 -0600 Subject: [PATCH 27/27] Only pop min/max if they were defined previously --- include/chaiscript/language/chaiscript_parser.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 715d90cf..1ea73716 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -23,6 +23,7 @@ #if defined(CHAISCRIPT_MSVC) && defined(max) && defined(min) +#define CHAISCRIPT_PUSHED_MIN_MAX #pragma push_macro("max") // Why Microsoft? why? This is worse than bad #undef max #pragma push_macro("min") @@ -2454,7 +2455,8 @@ namespace chaiscript } -#ifdef CHAISCRIPT_MSVC +#if defined(CHAISCRIPT_MSVC) && defined(CHAISCRIPT_PUSHED_MIN_MAX) +#undef CHAISCRIPT_PUSHED_MIN_MAX #pragma pop_macro("min") #pragma pop_macro("max") #endif