Ticket #2434: RemoveAtlasScriptInterfaceDep_v1.3.diff

File RemoveAtlasScriptInterfaceDep_v1.3.diff, 113.0 KB (added by Yves, 10 years ago)

Fixed a few issues with building on Windows

  • build/premake/premake4.lua

     
    10211021
    10221022    setup_atlas_project("AtlasObject", "StaticLib",
    10231023    {   -- src
    1024         "."
     1024        ".",
     1025        "../../../third_party/jsonspirit"
     1026       
    10251027    },{ -- include
     1028        "../../../third_party/jsonspirit"
    10261029    },{ -- extern_libs
    10271030        "boost",
    10281031        "libxml2",
    1029         "spidermonkey",
    10301032        "wxwidgets"
    10311033    },{ -- extra_params
    10321034        no_pch = 1
    10331035    })
    10341036
    1035     setup_atlas_project("AtlasScript", "StaticLib",
    1036     {   -- src
    1037         "."
    1038     },{ -- include
    1039         ".."
    1040     },{ -- extern_libs
    1041         "boost",
    1042         "spidermonkey",
    1043         "valgrind",
    1044         "wxwidgets",
    1045     },{ -- extra_params
    1046         no_pch = 1
    1047     })
    1048 
    10491037    atlas_src = {
    10501038        "ActorEditor",
    10511039        "CustomControls/Buttons",
     
    10761064        "ScenarioEditor/Tools/Common",
    10771065    }
    10781066    atlas_extra_links = {
    1079         "AtlasObject",
    1080         "AtlasScript",
     1067        "AtlasObject"
    10811068    }
    10821069
    10831070    atlas_extern_libs = {
     
    10871074        --"ffmpeg", -- disabled for now because it causes too many build difficulties
    10881075        "libxml2",
    10891076        "sdl",  -- key definitions
    1090         "spidermonkey",
    10911077        "wxwidgets",
    10921078        "zlib",
    10931079    }
     
    11171103
    11181104    local target_type = get_main_project_target_type()
    11191105    project_create(project_name, target_type)
    1120     project_add_extern_libs({
    1121         "spidermonkey",
    1122     },
    1123     target_type)
    11241106    project_add_x11_dirs()
    11251107
    11261108    local source_root = rootdir.."/source/tools/atlas/AtlasFrontends/"
  • source/third_party/jsonspirit/LICENSE.txt

     
     1The MIT License
     2
     3Copyright (c) 2007 - 2010 John W. Wilkinson
     4
     5Permission is hereby granted, free of charge, to any person
     6obtaining a copy of this software and associated documentation
     7files (the "Software"), to deal in the Software without
     8restriction, including without limitation the rights to use,
     9copy, modify, merge, publish, distribute, sublicense, and/or sell
     10copies of the Software, and to permit persons to whom the
     11Software is furnished to do so, subject to the following
     12conditions:
     13
     14The above copyright notice and this permission notice shall be
     15included in all copies or substantial portions of the Software.
     16
     17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     19OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     20NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     21HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     22WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     23FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24OTHER DEALINGS IN THE SOFTWARE.
  • source/third_party/jsonspirit/README.txt

     
     1This separate JSON library is used for Atlas to avoid the SpiderMonkey dependency.
     2SpiderMonkey is a fully featured JS engine and even though we already use it for the main engine, it's too heavy-weight to use it in Atlas.
     3The SpiderMonkey API also changes frequently and we hope that the JSON parsing code needs less changes when we use this separate library.
     4
     5Get the library from here:
     6http://www.codeproject.com/Articles/20027/JSON-Spirit-A-C-JSON-Parser-Generator-Implemented
     7
     8The currently used version was released on the 23th of May 2013.
  • source/third_party/jsonspirit/json_spirit_error_position.h

     
     1#ifndef JSON_SPIRIT_ERROR_POSITION
     2#define JSON_SPIRIT_ERROR_POSITION
     3
     4//          Copyright John W. Wilkinson 2007 - 2013
     5// Distributed under the MIT License, see accompanying file LICENSE.txt
     6
     7// json spirit version 4.06
     8
     9#if defined(_MSC_VER) && (_MSC_VER >= 1020)
     10# pragma once
     11#endif
     12
     13#include <string>
     14
     15namespace json_spirit
     16{
     17    // An Error_position exception is thrown by the "read_or_throw" functions below on finding an error.
     18    // Note the "read_or_throw" functions are around 3 times slower than the standard functions "read"
     19    // functions that return a bool.
     20    //
     21    struct Error_position
     22    {
     23        Error_position();
     24        Error_position( unsigned int line, unsigned int column, const std::string& reason );
     25        bool operator==( const Error_position& lhs ) const;
     26        unsigned int line_;
     27        unsigned int column_;
     28        std::string reason_;
     29    };
     30
     31    inline Error_position::Error_position()
     32    :   line_( 0 )
     33    ,   column_( 0 )
     34    {
     35    }
     36
     37    inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason )
     38    :   line_( line )
     39    ,   column_( column )
     40    ,   reason_( reason )
     41    {
     42    }
     43
     44    inline bool Error_position::operator==( const Error_position& lhs ) const
     45    {
     46        if( this == &lhs ) return true;
     47
     48        return ( reason_ == lhs.reason_ ) &&
     49               ( line_   == lhs.line_ ) &&
     50               ( column_ == lhs.column_ );
     51    }
     52}
     53
     54#endif
  • source/third_party/jsonspirit/json_spirit_reader_template.h

     
     1#ifndef JSON_SPIRIT_READER_TEMPLATE
     2#define JSON_SPIRIT_READER_TEMPLATE
     3
     4//          Copyright John W. Wilkinson 2007 - 2013
     5// Distributed under the MIT License, see accompanying file LICENSE.txt
     6
     7// json spirit version 4.06
     8
     9#if defined(_MSC_VER) && (_MSC_VER >= 1020)
     10# pragma once
     11#endif
     12
     13#include "json_spirit_value.h"
     14#include "json_spirit_error_position.h"
     15
     16//#define BOOST_SPIRIT_THREADSAFE  // uncomment for multithreaded use, requires linking to boost.thread
     17
     18#include <boost/bind.hpp>
     19#include <boost/function.hpp>
     20#include <boost/version.hpp>
     21
     22#if BOOST_VERSION >= 103800
     23    #include <boost/spirit/include/classic_core.hpp>
     24    #include <boost/spirit/include/classic_confix.hpp>
     25    #include <boost/spirit/include/classic_escape_char.hpp>
     26    #include <boost/spirit/include/classic_multi_pass.hpp>
     27    #include <boost/spirit/include/classic_position_iterator.hpp>
     28    #define spirit_namespace boost::spirit::classic
     29#else
     30    #include <boost/spirit/core.hpp>
     31    #include <boost/spirit/utility/confix.hpp>
     32    #include <boost/spirit/utility/escape_char.hpp>
     33    #include <boost/spirit/iterator/multi_pass.hpp>
     34    #include <boost/spirit/iterator/position_iterator.hpp>
     35    #define spirit_namespace boost::spirit
     36#endif
     37
     38namespace json_spirit
     39{
     40    const spirit_namespace::int_parser < boost::int64_t >  int64_p  = spirit_namespace::int_parser < boost::int64_t  >();
     41    const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >();
     42
     43    template< class Iter_type >
     44    bool is_eq( Iter_type first, Iter_type last, const char* c_str )
     45    {
     46        for( Iter_type i = first; i != last; ++i, ++c_str )
     47        {
     48            if( *c_str == 0 ) return false;
     49
     50            if( *i != *c_str ) return false;
     51        }
     52
     53        return true;
     54    }
     55
     56    template< class Char_type >
     57    Char_type hex_to_num( const Char_type c )
     58    {
     59        if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0';
     60        if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10;
     61        if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10;
     62        return 0;
     63    }
     64
     65    template< class Char_type, class Iter_type >
     66    Char_type hex_str_to_char( Iter_type& begin )
     67    {
     68        const Char_type c1( *( ++begin ) );
     69        const Char_type c2( *( ++begin ) );
     70
     71        return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 );
     72    }       
     73
     74    template< class Char_type, class Iter_type >
     75    Char_type unicode_str_to_char( Iter_type& begin )
     76    {
     77        const Char_type c1( *( ++begin ) );
     78        const Char_type c2( *( ++begin ) );
     79        const Char_type c3( *( ++begin ) );
     80        const Char_type c4( *( ++begin ) );
     81
     82        return ( hex_to_num( c1 ) << 12 ) +
     83               ( hex_to_num( c2 ) <<  8 ) +
     84               ( hex_to_num( c3 ) <<  4 ) +
     85               hex_to_num( c4 );
     86    }
     87
     88    template< class String_type >
     89    void append_esc_char_and_incr_iter( String_type& s,
     90                                        typename String_type::const_iterator& begin,
     91                                        typename String_type::const_iterator end )
     92    {
     93        typedef typename String_type::value_type Char_type;
     94             
     95        const Char_type c2( *begin );
     96
     97        switch( c2 )
     98        {
     99            case 't':  s += '\t'; break;
     100            case 'b':  s += '\b'; break;
     101            case 'f':  s += '\f'; break;
     102            case 'n':  s += '\n'; break;
     103            case 'r':  s += '\r'; break;
     104            case '\\': s += '\\'; break;
     105            case '/':  s += '/';  break;
     106            case '"':  s += '"';  break;
     107            case 'x': 
     108            {
     109                if( end - begin >= 3 )  //  expecting "xHH..."
     110                {
     111                    s += hex_str_to_char< Char_type >( begin ); 
     112                }
     113                break;
     114            }
     115            case 'u': 
     116            {
     117                if( end - begin >= 5 )  //  expecting "uHHHH..."
     118                {
     119                    s += unicode_str_to_char< Char_type >( begin ); 
     120                }
     121                break;
     122            }
     123        }
     124    }
     125
     126    template< class String_type >
     127    String_type substitute_esc_chars( typename String_type::const_iterator begin,
     128                                   typename String_type::const_iterator end )
     129    {
     130        typedef typename String_type::const_iterator Iter_type;
     131
     132        if( end - begin < 2 ) return String_type( begin, end );
     133
     134        String_type result;
     135       
     136        result.reserve( end - begin );
     137
     138        const Iter_type end_minus_1( end - 1 );
     139
     140        Iter_type substr_start = begin;
     141        Iter_type i = begin;
     142
     143        for( ; i < end_minus_1; ++i )
     144        {
     145            if( *i == '\\' )
     146            {
     147                result.append( substr_start, i );
     148
     149                ++i;  // skip the '\'
     150             
     151                append_esc_char_and_incr_iter( result, i, end );
     152
     153                substr_start = i + 1;
     154            }
     155        }
     156
     157        result.append( substr_start, end );
     158
     159        return result;
     160    }
     161
     162    template< class String_type >
     163    String_type get_str_( typename String_type::const_iterator begin,
     164                       typename String_type::const_iterator end )
     165    {
     166        assert( end - begin >= 2 );
     167
     168        typedef typename String_type::const_iterator Iter_type;
     169
     170        Iter_type str_without_quotes( ++begin );
     171        Iter_type end_without_quotes( --end );
     172
     173        return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes );
     174    }
     175
     176    inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end )
     177    {
     178        return get_str_< std::string >( begin, end );
     179    }
     180
     181    inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end )
     182    {
     183        return get_str_< std::wstring >( begin, end );
     184    }
     185   
     186    template< class String_type, class Iter_type >
     187    String_type get_str( Iter_type begin, Iter_type end )
     188    {
     189        const String_type tmp( begin, end );  // convert multipass iterators to string iterators
     190
     191        return get_str( tmp.begin(), tmp.end() );
     192    }
     193
     194    // this class's methods get called by the spirit parse resulting
     195    // in the creation of a JSON object or array
     196    //
     197    // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator
     198    //
     199    template< class Value_type, class Iter_type >
     200    class Semantic_actions
     201    {
     202    public:
     203
     204        typedef typename Value_type::Config_type Config_type;
     205        typedef typename Config_type::String_type String_type;
     206        typedef typename Config_type::Object_type Object_type;
     207        typedef typename Config_type::Array_type Array_type;
     208        typedef typename String_type::value_type Char_type;
     209
     210        Semantic_actions( Value_type& value )
     211        :   value_( value )
     212        ,   current_p_( 0 )
     213        {
     214        }
     215
     216        void begin_obj( Char_type c )
     217        {
     218            assert( c == '{' );
     219
     220            begin_compound< Object_type >();
     221        }
     222
     223        void end_obj( Char_type c )
     224        {
     225            assert( c == '}' );
     226
     227            end_compound();
     228        }
     229
     230        void begin_array( Char_type c )
     231        {
     232            assert( c == '[' );
     233     
     234            begin_compound< Array_type >();
     235        }
     236
     237        void end_array( Char_type c )
     238        {
     239            assert( c == ']' );
     240
     241            end_compound();
     242        }
     243
     244        void new_name( Iter_type begin, Iter_type end )
     245        {
     246            assert( current_p_->type() == obj_type );
     247
     248            name_ = get_str< String_type >( begin, end );
     249        }
     250
     251        void new_str( Iter_type begin, Iter_type end )
     252        {
     253            add_to_current( get_str< String_type >( begin, end ) );
     254        }
     255
     256        void new_true( Iter_type begin, Iter_type end )
     257        {
     258            assert( is_eq( begin, end, "true" ) );
     259
     260            add_to_current( true );
     261        }
     262
     263        void new_false( Iter_type begin, Iter_type end )
     264        {
     265            assert( is_eq( begin, end, "false" ) );
     266
     267            add_to_current( false );
     268        }
     269
     270        void new_null( Iter_type begin, Iter_type end )
     271        {
     272            assert( is_eq( begin, end, "null" ) );
     273
     274            add_to_current( Value_type() );
     275        }
     276
     277        void new_int( boost::int64_t i )
     278        {
     279            add_to_current( i );
     280        }
     281
     282        void new_uint64( boost::uint64_t ui )
     283        {
     284            add_to_current( ui );
     285        }
     286
     287        void new_real( double d )
     288        {
     289            add_to_current( d );
     290        }
     291
     292    private:
     293
     294        Semantic_actions& operator=( const Semantic_actions& );
     295                                    // to prevent "assignment operator could not be generated" warning
     296
     297        Value_type* add_first( const Value_type& value )
     298        {
     299            assert( current_p_ == 0 );
     300
     301            value_ = value;
     302            current_p_ = &value_;
     303            return current_p_;
     304        }
     305
     306        template< class Array_or_obj >
     307        void begin_compound()
     308        {
     309            if( current_p_ == 0 )
     310            {
     311                add_first( Array_or_obj() );
     312            }
     313            else
     314            {
     315                stack_.push_back( current_p_ );
     316
     317                Array_or_obj new_array_or_obj;   // avoid copy by building new array or object in place
     318
     319                current_p_ = add_to_current( new_array_or_obj );
     320            }
     321        }
     322
     323        void end_compound()
     324        {
     325            if( current_p_ != &value_ )
     326            {
     327                current_p_ = stack_.back();
     328               
     329                stack_.pop_back();
     330            }   
     331        }
     332
     333        Value_type* add_to_current( const Value_type& value )
     334        {
     335            if( current_p_ == 0 )
     336            {
     337                return add_first( value );
     338            }
     339            else if( current_p_->type() == array_type )
     340            {
     341                current_p_->get_array().push_back( value );
     342
     343                return &current_p_->get_array().back();
     344            }
     345           
     346            assert( current_p_->type() == obj_type );
     347
     348            return &Config_type::add( current_p_->get_obj(), name_, value );
     349        }
     350
     351        Value_type& value_;             // this is the object or array that is being created
     352        Value_type* current_p_;         // the child object or array that is currently being constructed
     353
     354        std::vector< Value_type* > stack_;   // previous child objects and arrays
     355
     356        String_type name_;              // of current name/value pair
     357    };
     358
     359    template< typename Iter_type >
     360    void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason )
     361    {
     362        throw Error_position( i.get_position().line, i.get_position().column, reason );
     363    }
     364
     365    template< typename Iter_type >
     366    void throw_error( Iter_type i, const std::string& reason )
     367    {
     368       throw reason;
     369    }
     370
     371    // the spirit grammer
     372    //
     373    template< class Value_type, class Iter_type >
     374    class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > >
     375    {
     376    public:
     377
     378        typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t;
     379
     380        Json_grammer( Semantic_actions_t& semantic_actions )
     381        :   actions_( semantic_actions )
     382        {
     383        }
     384
     385        static void throw_not_value( Iter_type begin, Iter_type end )
     386        {
     387            throw_error( begin, "not a value" );
     388        }
     389
     390        static void throw_not_array( Iter_type begin, Iter_type end )
     391        {
     392            throw_error( begin, "not an array" );
     393        }
     394
     395        static void throw_not_object( Iter_type begin, Iter_type end )
     396        {
     397            throw_error( begin, "not an object" );
     398        }
     399
     400        static void throw_not_pair( Iter_type begin, Iter_type end )
     401        {
     402            throw_error( begin, "not a pair" );
     403        }
     404
     405        static void throw_not_colon( Iter_type begin, Iter_type end )
     406        {
     407            throw_error( begin, "no colon in pair" );
     408        }
     409
     410        static void throw_not_string( Iter_type begin, Iter_type end )
     411        {
     412            throw_error( begin, "not a string" );
     413        }
     414
     415        template< typename ScannerT >
     416        class definition
     417        {
     418        public:
     419
     420            definition( const Json_grammer& self )
     421            {
     422                using namespace spirit_namespace;
     423
     424                typedef typename Value_type::String_type::value_type Char_type;
     425
     426                // first we convert the semantic action class methods to functors with the
     427                // parameter signature expected by spirit
     428
     429                typedef boost::function< void( Char_type )            > Char_action;
     430                typedef boost::function< void( Iter_type, Iter_type ) > Str_action;
     431                typedef boost::function< void( double )               > Real_action;
     432                typedef boost::function< void( boost::int64_t )       > Int_action;
     433                typedef boost::function< void( boost::uint64_t )      > Uint64_action;
     434
     435                Char_action   begin_obj  ( boost::bind( &Semantic_actions_t::begin_obj,   &self.actions_, _1 ) );
     436                Char_action   end_obj    ( boost::bind( &Semantic_actions_t::end_obj,     &self.actions_, _1 ) );
     437                Char_action   begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) );
     438                Char_action   end_array  ( boost::bind( &Semantic_actions_t::end_array,   &self.actions_, _1 ) );
     439                Str_action    new_name   ( boost::bind( &Semantic_actions_t::new_name,    &self.actions_, _1, _2 ) );
     440                Str_action    new_str    ( boost::bind( &Semantic_actions_t::new_str,     &self.actions_, _1, _2 ) );
     441                Str_action    new_true   ( boost::bind( &Semantic_actions_t::new_true,    &self.actions_, _1, _2 ) );
     442                Str_action    new_false  ( boost::bind( &Semantic_actions_t::new_false,   &self.actions_, _1, _2 ) );
     443                Str_action    new_null   ( boost::bind( &Semantic_actions_t::new_null,    &self.actions_, _1, _2 ) );
     444                Real_action   new_real   ( boost::bind( &Semantic_actions_t::new_real,    &self.actions_, _1 ) );
     445                Int_action    new_int    ( boost::bind( &Semantic_actions_t::new_int,     &self.actions_, _1 ) );
     446                Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64,  &self.actions_, _1 ) );
     447
     448                // actual grammer
     449
     450                json_
     451                    = value_ | eps_p[ &throw_not_value ]
     452                    ;
     453
     454                value_
     455                    = string_[ new_str ]
     456                    | number_
     457                    | object_
     458                    | array_
     459                    | str_p( "true" ) [ new_true  ]
     460                    | str_p( "false" )[ new_false ]
     461                    | str_p( "null" ) [ new_null  ]
     462                    ;
     463
     464                object_
     465                    = ch_p('{')[ begin_obj ]
     466                    >> !members_
     467                    >> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] )
     468                    ;
     469
     470                members_
     471                    = pair_ >> *( ',' >> pair_ )
     472                    ;
     473
     474                pair_
     475                    = string_[ new_name ]
     476                    >> ( ':' | eps_p[ &throw_not_colon ] )
     477                    >> ( value_ | eps_p[ &throw_not_value ] )
     478                    ;
     479
     480                array_
     481                    = ch_p('[')[ begin_array ]
     482                    >> !elements_
     483                    >> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] )
     484                    ;
     485
     486                elements_
     487                    = value_ >> *( ',' >> value_ )
     488                    ;
     489
     490                string_
     491                    = lexeme_d // this causes white space and what would appear to be comments inside a string to be retained
     492                      [
     493                          confix_p
     494                          (
     495                              '"',
     496                              *lex_escape_ch_p,
     497                              '"'
     498                          )
     499                      ]
     500                    ;
     501
     502                number_
     503                    = strict_real_p[ new_real   ]
     504                    | int64_p      [ new_int    ]
     505                    | uint64_p     [ new_uint64 ]
     506                    ;
     507            }
     508
     509            spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, string_, number_;
     510
     511            const spirit_namespace::rule< ScannerT >& start() const { return json_; }
     512        };
     513
     514    private:
     515
     516        Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning
     517
     518        Semantic_actions_t& actions_;
     519    };
     520
     521    template< class Iter_type, class Value_type >
     522    void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )
     523    {
     524        typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t;
     525
     526        const Posn_iter_t posn_begin( begin, end );
     527        const Posn_iter_t posn_end( end, end );
     528     
     529        read_range_or_throw( posn_begin, posn_end, value );
     530    }
     531
     532    template< class Istream_type >
     533    struct Multi_pass_iters
     534    {
     535        typedef typename Istream_type::char_type Char_type;
     536        typedef std::istream_iterator< Char_type, Char_type > istream_iter;
     537        typedef spirit_namespace::multi_pass< istream_iter > Mp_iter;
     538
     539        Multi_pass_iters( Istream_type& is )
     540        {
     541            is.unsetf( std::ios::skipws );
     542
     543            begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) );
     544            end_   = spirit_namespace::make_multi_pass( istream_iter() );
     545        }
     546
     547        Mp_iter begin_;
     548        Mp_iter end_;
     549    };
     550
     551    // reads a JSON Value from a pair of input iterators throwing an exception on invalid input, e.g.
     552    //
     553    // string::const_iterator start = str.begin();
     554    // const string::const_iterator next = read_range_or_throw( str.begin(), str.end(), value );
     555    //
     556    // The iterator 'next' will point to the character past the
     557    // last one read.
     558    //
     559    template< class Iter_type, class Value_type >
     560    Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )
     561    {
     562        Semantic_actions< Value_type, Iter_type > semantic_actions( value );
     563     
     564        const spirit_namespace::parse_info< Iter_type > info =
     565                            spirit_namespace::parse( begin, end,
     566                                                    Json_grammer< Value_type, Iter_type >( semantic_actions ),
     567                                                    spirit_namespace::space_p |
     568                                                    spirit_namespace::comment_p("//") |
     569                                                    spirit_namespace::comment_p("/*", "*/") );
     570
     571        if( !info.hit )
     572        {
     573            assert( false ); // in theory exception should already have been thrown
     574            throw_error( info.stop, "error" );
     575        }
     576
     577        return info.stop;
     578    }
     579
     580    // reads a JSON Value from a pair of input iterators, e.g.
     581    //
     582    // string::const_iterator start = str.begin();
     583    // const bool success = read_string( start, str.end(), value );
     584    //
     585    // The iterator 'start' will point to the character past the
     586    // last one read.
     587    //
     588    template< class Iter_type, class Value_type >
     589    bool read_range( Iter_type& begin, Iter_type end, Value_type& value )
     590    {
     591        try
     592        {
     593            begin = read_range_or_throw( begin, end, value );
     594
     595            return true;
     596        }
     597        catch( ... )
     598        {
     599            return false;
     600        }
     601    }
     602
     603    // reads a JSON Value from a string, e.g.
     604    //
     605    // const bool success = read_string( str, value );
     606    //
     607    template< class String_type, class Value_type >
     608    bool read_string( const String_type& s, Value_type& value )
     609    {
     610        typename String_type::const_iterator begin = s.begin();
     611
     612        return read_range( begin, s.end(), value );
     613    }
     614
     615    // reads a JSON Value from a string throwing an exception on invalid input, e.g.
     616    //
     617    // read_string_or_throw( is, value );
     618    //
     619    template< class String_type, class Value_type >
     620    void read_string_or_throw( const String_type& s, Value_type& value )
     621    {
     622        add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value );
     623    }
     624
     625    // reads a JSON Value from a stream, e.g.
     626    //
     627    // const bool success = read_stream( is, value );
     628    //
     629    template< class Istream_type, class Value_type >
     630    bool read_stream( Istream_type& is, Value_type& value )
     631    {
     632        Multi_pass_iters< Istream_type > mp_iters( is );
     633
     634        return read_range( mp_iters.begin_, mp_iters.end_, value );
     635    }
     636
     637    // reads a JSON Value from a stream throwing an exception on invalid input, e.g.
     638    //
     639    // read_stream_or_throw( is, value );
     640    //
     641    template< class Istream_type, class Value_type >
     642    void read_stream_or_throw( Istream_type& is, Value_type& value )
     643    {
     644        const Multi_pass_iters< Istream_type > mp_iters( is );
     645
     646        add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value );
     647    }
     648}
     649
     650#endif
  • source/third_party/jsonspirit/json_spirit_value.h

     
     1#ifndef JSON_SPIRIT_VALUE
     2#define JSON_SPIRIT_VALUE
     3
     4//          Copyright John W. Wilkinson 2007 - 2013
     5// Distributed under the MIT License, see accompanying file LICENSE.txt
     6
     7// json spirit version 4.06
     8
     9#if defined(_MSC_VER) && (_MSC_VER >= 1020)
     10# pragma once
     11#endif
     12
     13#include <vector>
     14#include <map>
     15#include <string>
     16#include <cassert>
     17#include <sstream>
     18#include <stdexcept>
     19#include <boost/config.hpp>
     20#include <boost/cstdint.hpp>
     21#include <boost/shared_ptr.hpp>
     22#include <boost/variant.hpp>
     23
     24// comment out the value types you don't need to reduce build times and intermediate file sizes
     25#define JSON_SPIRIT_VALUE_ENABLED
     26#define JSON_SPIRIT_WVALUE_ENABLED
     27#define JSON_SPIRIT_MVALUE_ENABLED
     28#define JSON_SPIRIT_WMVALUE_ENABLED
     29
     30namespace json_spirit
     31{
     32    enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };
     33
     34    static std::string value_type_to_string( Value_type vtype );
     35
     36    struct Null{};
     37   
     38    template< class Config >    // Config determines whether the value uses std::string or std::wstring and
     39                                // whether JSON Objects are represented as vectors or maps
     40    class Value_impl
     41    {
     42    public:
     43
     44        typedef Config Config_type;
     45        typedef typename Config::String_type String_type;
     46        typedef typename Config::Object_type Object;
     47        typedef typename Config::Array_type Array;
     48        typedef typename String_type::const_pointer Const_str_ptr;  // eg const char*
     49
     50        Value_impl();  // creates null value
     51        Value_impl( Const_str_ptr      value );
     52        Value_impl( const String_type& value );
     53        Value_impl( const Object&      value );
     54        Value_impl( const Array&       value );
     55        Value_impl( bool               value );
     56        Value_impl( int                value );
     57        Value_impl( boost::int64_t     value );
     58        Value_impl( boost::uint64_t    value );
     59        Value_impl( double             value );
     60
     61        template< class Iter >
     62        Value_impl( Iter first, Iter last );    // constructor from containers, e.g. std::vector or std::list
     63
     64        template< BOOST_VARIANT_ENUM_PARAMS( typename T ) >
     65        Value_impl( const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& variant ); // constructor for compatible variant types
     66
     67        Value_impl( const Value_impl& other );
     68
     69        bool operator==( const Value_impl& lhs ) const;
     70
     71        Value_impl& operator=( const Value_impl& lhs );
     72
     73        Value_type type() const;
     74
     75        bool is_uint64() const;
     76        bool is_null() const;
     77
     78        const String_type& get_str()    const;
     79        const Object&      get_obj()    const;
     80        const Array&       get_array()  const;
     81        bool               get_bool()   const;
     82        int                get_int()    const;
     83        boost::int64_t     get_int64()  const;
     84        boost::uint64_t    get_uint64() const;
     85        double             get_real()   const;
     86
     87        Object& get_obj();
     88        Array&  get_array();
     89
     90        template< typename T > T get_value() const;  // example usage: int    i = value.get_value< int >();
     91                                                     // or             double d = value.get_value< double >();
     92
     93        static const Value_impl null;
     94
     95    private:
     96
     97        void check_type( const Value_type vtype ) const;
     98
     99        typedef boost::variant< boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >,
     100                                String_type, bool, boost::int64_t, double, Null, boost::uint64_t > Variant;
     101
     102        Variant v_;
     103
     104        class Variant_converter_visitor : public boost::static_visitor< Variant >
     105        {
     106        public:
     107         
     108              template< typename T, typename A, template< typename, typename > class Cont >
     109              Variant operator()( const Cont< T, A >& cont ) const
     110              {
     111                  return Array( cont.begin(), cont.end() );
     112              }
     113             
     114              Variant operator()( int i ) const
     115              {
     116                  return static_cast< boost::int64_t >( i );
     117              }
     118           
     119              template<class T>
     120              Variant operator()( const T& t ) const
     121              {
     122                  return t;
     123              }
     124        };
     125    };
     126
     127    // vector objects
     128
     129    template< class Config >
     130    struct Pair_impl
     131    {
     132        typedef typename Config::String_type String_type;
     133        typedef typename Config::Value_type Value_type;
     134
     135        Pair_impl()
     136        {
     137        }
     138
     139        Pair_impl( const String_type& name, const Value_type& value );
     140
     141        bool operator==( const Pair_impl& lhs ) const;
     142
     143        String_type name_;
     144        Value_type value_;
     145    };
     146
     147#if defined( JSON_SPIRIT_VALUE_ENABLED ) || defined( JSON_SPIRIT_WVALUE_ENABLED )
     148    template< class String >
     149    struct Config_vector
     150    {
     151        typedef String String_type;
     152        typedef Value_impl< Config_vector > Value_type;
     153        typedef Pair_impl < Config_vector > Pair_type;
     154        typedef std::vector< Value_type > Array_type;
     155        typedef std::vector< Pair_type > Object_type;
     156
     157        static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )
     158        {
     159            obj.push_back( Pair_type( name , value ) );
     160
     161            return obj.back().value_;
     162        }
     163               
     164        static const String_type& get_name( const Pair_type& pair )
     165        {
     166            return pair.name_;
     167        }
     168               
     169        static const Value_type& get_value( const Pair_type& pair )
     170        {
     171            return pair.value_;
     172        }
     173    };
     174#endif
     175
     176    // typedefs for ASCII
     177
     178#ifdef JSON_SPIRIT_VALUE_ENABLED
     179    typedef Config_vector< std::string > Config;
     180
     181    typedef Config::Value_type  Value;
     182    typedef Config::Pair_type   Pair;
     183    typedef Config::Object_type Object;
     184    typedef Config::Array_type  Array;
     185#endif
     186
     187    // typedefs for Unicode
     188
     189#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING )
     190    typedef Config_vector< std::wstring > wConfig;
     191
     192    typedef wConfig::Value_type  wValue;
     193    typedef wConfig::Pair_type   wPair;
     194    typedef wConfig::Object_type wObject;
     195    typedef wConfig::Array_type  wArray;
     196#endif
     197
     198    // map objects
     199
     200#if defined( JSON_SPIRIT_MVALUE_ENABLED ) || defined( JSON_SPIRIT_WMVALUE_ENABLED )
     201    template< class String >
     202    struct Config_map
     203    {
     204        typedef String String_type;
     205        typedef Value_impl< Config_map > Value_type;
     206        typedef std::vector< Value_type > Array_type;
     207        typedef std::map< String_type, Value_type > Object_type;
     208        typedef std::pair< const String_type, Value_type > Pair_type;
     209
     210        static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )
     211        {
     212            return obj[ name ] = value;
     213        }
     214               
     215        static const String_type& get_name( const Pair_type& pair )
     216        {
     217            return pair.first;
     218        }
     219               
     220        static const Value_type& get_value( const Pair_type& pair )
     221        {
     222            return pair.second;
     223        }
     224    };
     225#endif
     226
     227    // typedefs for ASCII
     228
     229#ifdef JSON_SPIRIT_MVALUE_ENABLED
     230    typedef Config_map< std::string > mConfig;
     231
     232    typedef mConfig::Value_type  mValue;
     233    typedef mConfig::Object_type mObject;
     234    typedef mConfig::Array_type  mArray;
     235#endif
     236
     237    // typedefs for Unicode
     238
     239#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING )
     240    typedef Config_map< std::wstring > wmConfig;
     241
     242    typedef wmConfig::Value_type  wmValue;
     243    typedef wmConfig::Object_type wmObject;
     244    typedef wmConfig::Array_type  wmArray;
     245#endif
     246
     247    ///////////////////////////////////////////////////////////////////////////////////////////////
     248    //
     249    // implementation
     250
     251    inline bool operator==( const Null&, const Null& )
     252    {
     253        return true;
     254    }
     255
     256    template< class Config >
     257    const Value_impl< Config > Value_impl< Config >::null;
     258
     259    template< class Config >
     260    Value_impl< Config >::Value_impl()
     261    :   v_( Null() )
     262    {
     263    }
     264
     265    template< class Config >
     266    Value_impl< Config >::Value_impl( const Const_str_ptr value )
     267    :  v_( String_type( value ) )
     268    {
     269    }
     270
     271    template< class Config >
     272    Value_impl< Config >::Value_impl( const String_type& value )
     273    :   v_( value )
     274    {
     275    }
     276
     277    template< class Config >
     278    Value_impl< Config >::Value_impl( const Object& value )
     279    :   v_( value )
     280    {
     281    }
     282
     283    template< class Config >
     284    Value_impl< Config >::Value_impl( const Array& value )
     285    :   v_( value )
     286    {
     287    }
     288
     289    template< class Config >
     290    Value_impl< Config >::Value_impl( bool value )
     291    :   v_( value )
     292    {
     293    }
     294
     295    template< class Config >
     296    Value_impl< Config >::Value_impl( int value )
     297    :   v_( static_cast< boost::int64_t >( value ) )
     298    {
     299    }
     300
     301    template< class Config >
     302    Value_impl< Config >::Value_impl( boost::int64_t value )
     303    :   v_( value )
     304    {
     305    }
     306
     307    template< class Config >
     308    Value_impl< Config >::Value_impl( boost::uint64_t value )
     309    :   v_( value )
     310    {
     311    }
     312
     313    template< class Config >
     314    Value_impl< Config >::Value_impl( double value )
     315    :   v_( value )
     316    {
     317    }
     318
     319    template< class Config >
     320    Value_impl< Config >::Value_impl( const Value_impl< Config >& other )
     321    :   v_( other.v_ )
     322    {
     323    }
     324
     325    template< class Config >
     326    template< class Iter >
     327    Value_impl< Config >::Value_impl( Iter first, Iter last )
     328    :   v_( Array( first, last ) )
     329    {
     330    }
     331
     332    template< class Config >
     333    template< BOOST_VARIANT_ENUM_PARAMS( typename T ) >
     334    Value_impl< Config >::Value_impl( const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& variant )
     335    :   v_( boost::apply_visitor( Variant_converter_visitor(), variant) )
     336    {
     337    }
     338
     339    template< class Config >
     340    Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs )
     341    {
     342        Value_impl tmp( lhs );
     343
     344        std::swap( v_, tmp.v_ );
     345
     346        return *this;
     347    }
     348
     349    template< class Config >
     350    bool Value_impl< Config >::operator==( const Value_impl& lhs ) const
     351    {
     352        if( this == &lhs ) return true;
     353
     354        if( type() != lhs.type() ) return false;
     355
     356        return v_ == lhs.v_;
     357    }
     358
     359    template< class Config >
     360    Value_type Value_impl< Config >::type() const
     361    {
     362        if( is_uint64() )
     363        {
     364            return int_type;
     365        }
     366
     367        return static_cast< Value_type >( v_.which() );
     368    }
     369
     370    template< class Config >
     371    bool Value_impl< Config >::is_uint64() const
     372    {
     373        return v_.which() == null_type + 1;
     374    }
     375
     376    template< class Config >
     377    bool Value_impl< Config >::is_null() const
     378    {
     379        return type() == null_type;
     380    }
     381
     382    template< class Config >
     383    void Value_impl< Config >::check_type( const Value_type vtype ) const
     384    {
     385        if( type() != vtype )
     386        {
     387            std::ostringstream os;
     388
     389            os << "get_value< " << value_type_to_string( vtype ) << " > called on " << value_type_to_string( type() ) << " Value";
     390
     391            throw std::runtime_error( os.str() );
     392        }
     393    }
     394
     395    template< class Config >
     396    const typename Config::String_type& Value_impl< Config >::get_str() const
     397    {
     398        check_type( str_type );
     399
     400        return *boost::get< String_type >( &v_ );
     401    }
     402
     403    template< class Config >
     404    const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const
     405    {
     406        check_type( obj_type );
     407
     408        return *boost::get< Object >( &v_ );
     409    }
     410     
     411    template< class Config >
     412    const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const
     413    {
     414        check_type( array_type );
     415
     416        return *boost::get< Array >( &v_ );
     417    }
     418     
     419    template< class Config >
     420    bool Value_impl< Config >::get_bool() const
     421    {
     422        check_type( bool_type );
     423
     424        return boost::get< bool >( v_ );
     425    }
     426     
     427    template< class Config >
     428    int Value_impl< Config >::get_int() const
     429    {
     430        check_type( int_type );
     431
     432        return static_cast< int >( get_int64() );
     433    }
     434   
     435    template< class Config >
     436    boost::int64_t Value_impl< Config >::get_int64() const
     437    {
     438        check_type( int_type );
     439
     440        if( is_uint64() )
     441        {
     442            return static_cast< boost::int64_t >( get_uint64() );
     443        }
     444
     445        return boost::get< boost::int64_t >( v_ );
     446    }
     447   
     448    template< class Config >
     449    boost::uint64_t Value_impl< Config >::get_uint64() const
     450    {
     451        check_type( int_type );
     452
     453        if( !is_uint64() )
     454        {
     455            return static_cast< boost::uint64_t >( get_int64() );
     456        }
     457
     458        return boost::get< boost::uint64_t >( v_ );
     459    }
     460
     461    template< class Config >
     462    double Value_impl< Config >::get_real() const
     463    {
     464        if( type() == int_type )
     465        {
     466            return is_uint64() ? static_cast< double >( get_uint64() )
     467                               : static_cast< double >( get_int64() );
     468        }
     469
     470        check_type( real_type );
     471
     472        return boost::get< double >( v_ );
     473    }
     474
     475    template< class Config >
     476    typename Value_impl< Config >::Object& Value_impl< Config >::get_obj()
     477    {
     478        check_type( obj_type );
     479
     480        return *boost::get< Object >( &v_ );
     481    }
     482
     483    template< class Config >
     484    typename Value_impl< Config >::Array& Value_impl< Config >::get_array()
     485    {
     486        check_type( array_type );
     487
     488        return *boost::get< Array >( &v_ );
     489    }
     490
     491    template< class Config >
     492    Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value )
     493    :   name_( name )
     494    ,   value_( value )
     495    {
     496    }
     497
     498    template< class Config >
     499    bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const
     500    {
     501        if( this == &lhs ) return true;
     502
     503        return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ );
     504    }
     505
     506    // converts a C string, ie. 8 bit char array, to a string object
     507    //
     508    template < class String_type >
     509    String_type to_str( const char* c_str )
     510    {
     511        String_type result;
     512
     513        for( const char* p = c_str; *p != 0; ++p )
     514        {
     515            result += *p;
     516        }
     517
     518        return result;
     519    }
     520
     521    //
     522
     523    namespace internal_
     524    {
     525        template< typename T >
     526        struct Type_to_type
     527        {
     528        };
     529
     530        template< class Value >
     531        int get_value( const Value& value, Type_to_type< int > )
     532        {
     533            return value.get_int();
     534        }
     535       
     536        template< class Value >
     537        boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > )
     538        {
     539            return value.get_int64();
     540        }
     541       
     542        template< class Value >
     543        boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > )
     544        {
     545            return value.get_uint64();
     546        }
     547       
     548        template< class Value >
     549        double get_value( const Value& value, Type_to_type< double > )
     550        {
     551            return value.get_real();
     552        }
     553       
     554        template< class Value >
     555        typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > )
     556        {
     557            return value.get_str();
     558        }
     559       
     560        template< class Value >
     561        typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > )
     562        {
     563            return value.get_array();
     564        }
     565       
     566        template< class Value >
     567        typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > )
     568        {
     569            return value.get_obj();
     570        }
     571       
     572        template< class Value >
     573        bool get_value( const Value& value, Type_to_type< bool > )
     574        {
     575            return value.get_bool();
     576        }
     577    }
     578
     579    template< class Config >
     580    template< typename T >
     581    T Value_impl< Config >::get_value() const
     582    {
     583        return internal_::get_value( *this, internal_::Type_to_type< T >() );
     584    }
     585
     586    static std::string value_type_to_string( const Value_type vtype )
     587    {
     588        switch( vtype )
     589        {
     590            case obj_type: return "Object";
     591            case array_type: return "Array";
     592            case str_type: return "string";
     593            case bool_type: return "boolean";
     594            case int_type: return "integer";
     595            case real_type: return "real";
     596            case null_type: return "null";
     597        }
     598
     599        assert( false );
     600
     601        return "unknown type";
     602    }
     603}
     604
     605#endif
  • source/third_party/jsonspirit/json_spirit_writer_options.h

     
     1#ifndef JSON_SPIRIT_WRITER_OPTIONS
     2#define JSON_SPIRIT_WRITER_OPTIONS
     3
     4//          Copyright John W. Wilkinson 2007 - 2013
     5// Distributed under the MIT License, see accompanying file LICENSE.txt
     6
     7// json spirit version 4.06
     8
     9#if defined(_MSC_VER) && (_MSC_VER >= 1020)
     10# pragma once
     11#endif
     12
     13namespace json_spirit
     14{
     15    enum Output_options{ pretty_print = 0x01,   // Add whitespace to format the output nicely.
     16
     17                         raw_utf8 = 0x02,       // This prevents non-printable characters from being escapted using "\uNNNN" notation.
     18                                                // Note, this is an extension to the JSON standard. It disables the escaping of
     19                                                // non-printable characters allowing UTF-8 sequences held in 8 bit char strings
     20                                                // to pass through unaltered.
     21
     22                         remove_trailing_zeros = 0x04,
     23                                                // outputs e.g. "1.200000000000000" as "1.2"
     24                         single_line_arrays = 0x08,
     25                                                // pretty printing except that arrays printed on single lines unless they contain
     26                                                // composite elements, i.e. objects or arrays
     27                         always_escape_nonascii = 0x10,
     28                                                // all unicode wide characters are escaped, i.e. outputed as "\uXXXX", even if they are
     29                                                // printable under the current locale, ascii printable chars are not escaped
     30                       };
     31}
     32
     33#endif
  • source/third_party/jsonspirit/json_spirit_writer_template.h

     
     1#ifndef JSON_SPIRIT_WRITER_TEMPLATE
     2#define JSON_SPIRIT_WRITER_TEMPLATE
     3
     4//          Copyright John W. Wilkinson 2007 - 2013
     5// Distributed under the MIT License, see accompanying file LICENSE.txt
     6
     7// json spirit version 4.06
     8
     9#if defined(_MSC_VER) && (_MSC_VER >= 1020)
     10# pragma once
     11#endif
     12
     13#include "json_spirit_value.h"
     14#include "json_spirit_writer_options.h"
     15
     16#include <cassert>
     17#include <sstream>
     18#include <iomanip>
     19#include <boost/io/ios_state.hpp>
     20
     21namespace json_spirit
     22{
     23    inline char to_hex_char( unsigned int c )
     24    {
     25        assert( c <= 0xF );
     26
     27        const char ch = static_cast< char >( c );
     28
     29        if( ch < 10 ) return '0' + ch;
     30
     31        return 'A' - 10 + ch;
     32    }
     33
     34    template< class String_type >
     35    String_type non_printable_to_string( unsigned int c )
     36    {
     37        typedef typename String_type::value_type Char_type;
     38
     39        String_type result( 6, '\\' );
     40
     41        result[1] = 'u';
     42
     43        result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
     44        result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
     45        result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
     46        result[ 2 ] = to_hex_char( c & 0x000F );
     47
     48        return result;
     49    }
     50
     51    template< typename Char_type, class String_type >
     52    bool add_esc_char( Char_type c, String_type& s )
     53    {
     54        switch( c )
     55        {
     56            case '"':  s += to_str< String_type >( "\\\"" ); return true;
     57            case '\\': s += to_str< String_type >( "\\\\" ); return true;
     58            case '\b': s += to_str< String_type >( "\\b"  ); return true;
     59            case '\f': s += to_str< String_type >( "\\f"  ); return true;
     60            case '\n': s += to_str< String_type >( "\\n"  ); return true;
     61            case '\r': s += to_str< String_type >( "\\r"  ); return true;
     62            case '\t': s += to_str< String_type >( "\\t"  ); return true;
     63        }
     64
     65        return false;
     66    }
     67
     68    template< class String_type >
     69    String_type add_esc_chars( const String_type& s, bool raw_utf8, bool esc_nonascii )
     70    {
     71        typedef typename String_type::const_iterator Iter_type;
     72        typedef typename String_type::value_type     Char_type;
     73
     74        String_type result;
     75
     76        const Iter_type end( s.end() );
     77
     78        for( Iter_type i = s.begin(); i != end; ++i )
     79        {
     80            const Char_type c( *i );
     81
     82            if( add_esc_char( c, result ) ) continue;
     83
     84            if( raw_utf8 )
     85            {
     86                result += c;
     87            }
     88            else
     89            {
     90                const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
     91
     92                if( !esc_nonascii && iswprint( unsigned_c ) )
     93                {
     94                    result += c;
     95                }
     96                else
     97                {
     98                    result += non_printable_to_string< String_type >( unsigned_c );
     99                }
     100            }
     101        }
     102
     103        return result;
     104    }
     105
     106    template< class Ostream >
     107    void append_double( Ostream& os, const double d, const int precision )
     108    {
     109        os << std::showpoint << std::setprecision( precision ) << d;
     110    }
     111
     112    template< class String_type >
     113    void erase_and_extract_exponent( String_type& str, String_type& exp )
     114    {
     115        const typename String_type::size_type exp_start= str.find( 'e' );
     116
     117        if( exp_start != String_type::npos )
     118        {
     119            exp = str.substr( exp_start );
     120            str.erase( exp_start );
     121        }
     122    }
     123
     124    template< class String_type >
     125    typename String_type::size_type find_first_non_zero( const String_type& str )
     126    {
     127        typename String_type::size_type result = str.size() - 1;
     128
     129        for( ; result != 0; --result )
     130        {
     131            if( str[ result ] != '0' )
     132            {
     133                break;
     134            }
     135        }
     136
     137        return result;
     138    }
     139
     140    template< class String_type >
     141    void remove_trailing( String_type& str )
     142    {
     143        String_type exp;
     144
     145        erase_and_extract_exponent( str, exp );
     146
     147        const typename String_type::size_type first_non_zero = find_first_non_zero( str );
     148
     149        if( first_non_zero != 0 )
     150        {
     151            const int offset = str[first_non_zero] == '.' ? 2 : 1;  // note zero digits following a decimal point is non standard
     152            str.erase( first_non_zero + offset );
     153        }
     154
     155        str += exp;
     156    }
     157
     158    // this class generates the JSON text,
     159    // it keeps track of the indentation level etc.
     160    //
     161    template< class Value_type, class Ostream_type >
     162    class Generator
     163    {
     164        typedef typename Value_type::Config_type Config_type;
     165        typedef typename Config_type::String_type String_type;
     166        typedef typename Config_type::Object_type Object_type;
     167        typedef typename Config_type::Array_type Array_type;
     168        typedef typename String_type::value_type Char_type;
     169        typedef typename Object_type::value_type Obj_member_type;
     170
     171    public:
     172
     173        Generator( const Value_type& value, Ostream_type& os, unsigned int options )
     174        :   os_( os )
     175        ,   indentation_level_( 0 )
     176        ,   pretty_( ( options & pretty_print ) != 0 || ( options & single_line_arrays ) != 0 )
     177        ,   raw_utf8_( ( options & raw_utf8 ) != 0 )
     178        ,   esc_nonascii_( ( options & always_escape_nonascii ) != 0 )
     179        ,   remove_trailing_zeros_( ( options & remove_trailing_zeros ) != 0 )
     180        ,   single_line_arrays_( ( options & single_line_arrays ) != 0 )
     181        ,   ios_saver_( os )
     182        {
     183            output( value );
     184        }
     185
     186    private:
     187
     188        void output( const Value_type& value )
     189        {
     190            switch( value.type() )
     191            {
     192                case obj_type:   output( value.get_obj() );   break;
     193                case array_type: output( value.get_array() ); break;
     194                case str_type:   output( value.get_str() );   break;
     195                case bool_type:  output( value.get_bool() );  break;
     196                case real_type:  output( value.get_real() );  break;
     197                case int_type:   output_int( value );         break;
     198                case null_type:  os_ << "null";               break;
     199                default: assert( false );
     200            }
     201        }
     202
     203        void output( const Object_type& obj )
     204        {
     205            output_array_or_obj( obj, '{', '}' );
     206        }
     207
     208        void output( const Obj_member_type& member )
     209        {
     210            output( Config_type::get_name( member ) ); space();
     211            os_ << ':'; space();
     212            output( Config_type::get_value( member ) );
     213        }
     214
     215        void output_int( const Value_type& value )
     216        {
     217            if( value.is_uint64() )
     218            {
     219                os_ << value.get_uint64();
     220            }
     221            else
     222            {
     223               os_ << value.get_int64();
     224            }
     225        }
     226
     227        void output( const String_type& s )
     228        {
     229            os_ << '"' << add_esc_chars( s, raw_utf8_, esc_nonascii_ ) << '"';
     230        }
     231
     232        void output( bool b )
     233        {
     234            os_ << to_str< String_type >( b ? "true" : "false" );
     235        }
     236
     237        void output( double d )
     238        {
     239            if( remove_trailing_zeros_ )
     240            {
     241                std::basic_ostringstream< Char_type > os;
     242
     243                append_double( os, d, 16 );  // note precision is 16 so that we get some trailing space that we can remove,
     244                                             // otherwise, 0.1234 gets converted to "0.12399999..."
     245
     246                String_type str = os.str();
     247
     248                remove_trailing( str );
     249
     250                os_ << str;
     251            }
     252            else
     253            {
     254                append_double( os_, d, 17 );
     255            }
     256        }
     257
     258        static bool contains_composite_elements( const Array_type& arr )
     259        {
     260            for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i )
     261            {
     262                const Value_type& val = *i;
     263
     264                if( val.type() == obj_type ||
     265                    val.type() == array_type )
     266                {
     267                    return true;
     268                }
     269            }
     270
     271            return false;
     272        }
     273
     274        template< class Iter >
     275        void output_composite_item( Iter i, Iter last )
     276        {
     277            output( *i );
     278
     279            if( ++i != last )
     280            {
     281                os_ << ',';
     282            }
     283        }
     284
     285        void output( const Array_type& arr )
     286        {
     287            if( single_line_arrays_ && !contains_composite_elements( arr )  )
     288            {
     289                os_ << '['; space();
     290               
     291                for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i )
     292                {
     293                    output_composite_item( i, arr.end() );
     294
     295                    space();
     296                }
     297
     298                os_ << ']';
     299            }
     300            else
     301            {
     302                output_array_or_obj( arr, '[', ']' );
     303            }
     304        }
     305
     306        template< class T >
     307        void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
     308        {
     309            os_ << start_char; new_line();
     310
     311            ++indentation_level_;
     312           
     313            for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
     314            {
     315                indent();
     316
     317                output_composite_item( i, t.end() );
     318
     319                new_line();
     320            }
     321
     322            --indentation_level_;
     323
     324            indent(); os_ << end_char;
     325        }
     326       
     327        void indent()
     328        {
     329            if( !pretty_ ) return;
     330
     331            for( int i = 0; i < indentation_level_; ++i )
     332            {
     333                os_ << "    ";
     334            }
     335        }
     336
     337        void space()
     338        {
     339            if( pretty_ ) os_ << ' ';
     340        }
     341
     342        void new_line()
     343        {
     344            if( pretty_ ) os_ << '\n';
     345        }
     346
     347        Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
     348
     349        Ostream_type& os_;
     350        int indentation_level_;
     351        bool pretty_;
     352        bool raw_utf8_;
     353        bool esc_nonascii_;
     354        bool remove_trailing_zeros_;
     355        bool single_line_arrays_;
     356        boost::io::basic_ios_all_saver< Char_type > ios_saver_;  // so that ostream state is reset after control is returned to the caller
     357    };
     358
     359    // writes JSON Value to a stream, e.g.
     360    //
     361    // write_stream( value, os, pretty_print );
     362    //
     363    template< class Value_type, class Ostream_type >
     364    void write_stream( const Value_type& value, Ostream_type& os, unsigned int options = 0 )
     365    {
     366        os << std::dec;
     367        Generator< Value_type, Ostream_type >( value, os, options );
     368    }
     369
     370    // writes JSON Value to a stream, e.g.
     371    //
     372    // const string json_str = write( value, pretty_print );
     373    //
     374    template< class Value_type >
     375    typename Value_type::String_type write_string( const Value_type& value, unsigned int options = 0 )
     376    {
     377        typedef typename Value_type::String_type::value_type Char_type;
     378
     379        std::basic_ostringstream< Char_type > os;
     380
     381        write_stream( value, os, options );
     382
     383        return os.str();
     384    }
     385}
     386
     387#endif
  • source/tools/atlas/AtlasObject/AtlasObject.h

     
    2929
    3030class wxString;
    3131
    32 typedef struct JSContext JSContext;
    33 
    3432//////////////////////////////////////////////////////////////////////////
    3533// Mostly-private bits:
    3634
     
    193191    AtObj LoadFromXML(const std::string& xml);
    194192
    195193    // Returns AtObj() on failure - test with AtObj::defined()
    196     AtObj LoadFromJSON(JSContext* cx, const std::string& json);
     194    AtObj LoadFromJSON(const std::string& json);
    197195
    198196    // Returns UTF-8-encoded XML document string.
    199197    // Returns empty string on failure.
     
    201199
    202200    // Returns UTF-8-encoded JSON string.
    203201    // Returns empty string on failure.
    204     std::string SaveToJSON(JSContext* cx, AtObj& obj);
     202    std::string SaveToJSON(AtObj& obj);
    205203
    206204    AtObj TrimEmptyChildren(AtObj& obj);
    207205}
  • source/tools/atlas/AtlasObject/AtlasObjectJS.cpp

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    1818#include "AtlasObject.h"
    1919#include "AtlasObjectImpl.h"
    2020
    21 #include "../AtlasScript/ScriptInterface.h"
     21#include "JSONSpiritInclude.h"
    2222
    2323#if defined(_MSC_VER)
    2424# pragma warning(disable:4996)  // deprecated CRT
     
    2828
    2929#include <sstream>
    3030
    31 static AtSmartPtr<AtNode> ConvertNode(JSContext* cx, jsval node);
     31static AtSmartPtr<AtNode> ConvertNode(json_spirit::Value node);
    3232
    33 AtObj AtlasObject::LoadFromJSON(JSContext* cx, const std::string& json)
     33AtObj AtlasObject::LoadFromJSON(const std::string& json)
    3434{
    35     // Convert UTF8 to UTF16
    36     wxString jsonW(json.c_str(), wxConvUTF8);
    37     size_t json16len;
    38     wxCharBuffer json16 = wxMBConvUTF16().cWC2MB(jsonW.c_str(), jsonW.Length(), &json16len);
     35    json_spirit::Value rootnode;
     36    json_spirit::read_string(json, rootnode);
     37   
     38    AtObj obj;
     39    obj.p = ConvertNode(rootnode);
     40    return obj;
     41}
    3942
    40     jsval vp = JSVAL_NULL;
    41     JSONParser* parser = JS_BeginJSONParse(cx, &vp);
    42     if (!parser)
     43// Convert from a JSON to an AtNode
     44static AtSmartPtr<AtNode> ConvertNode(json_spirit::Value node)
     45{
     46    AtSmartPtr<AtNode> obj (new AtNode());
     47   
     48    if (node.type() == json_spirit::str_type)
    4349    {
    44         wxLogError(_T("ParseJSON failed to begin"));
    45         return AtObj();
     50        obj->value = std::wstring(node.get_str().begin(),node.get_str().end());
    4651    }
    47 
    48     if (!JS_ConsumeJSONText(cx, parser, reinterpret_cast<const jschar*>(json16.data()), (uint32)(json16len/2)))
     52    else if (node.type() == json_spirit::int_type || node.type() == json_spirit::real_type)
    4953    {
    50         wxLogError(_T("ParseJSON failed to consume"));
    51         return AtObj();
     54        std::wstringstream stream;
     55        if (node.type() == json_spirit::int_type)
     56            stream << node.get_int();
     57        if (node.type() == json_spirit::real_type)
     58            stream << node.get_real();
     59       
     60        obj->value = stream.str().c_str();
     61        obj->children.insert(AtNode::child_pairtype(
     62            "@number", AtSmartPtr<AtNode>(new AtNode())
     63        ));
    5264    }
    53 
    54     if (!JS_FinishJSONParse(cx, parser, JSVAL_NULL))
     65    else if (node.type() == json_spirit::bool_type)
    5566    {
    56         wxLogError(_T("ParseJSON failed to finish"));
    57         return AtObj();
     67        if (node.get_bool())
     68            obj->value = L"true";
     69        else
     70            obj->value = L"false";
     71       
     72        obj->children.insert(AtNode::child_pairtype(
     73            "@boolean", AtSmartPtr<AtNode>(new AtNode())
     74        ));
    5875    }
    59 
    60     AtObj obj;
    61     obj.p = ConvertNode(cx, vp);
    62 
    63     return obj;
    64 }
    65 
    66 // Convert from a jsval to an AtNode
    67 static AtSmartPtr<AtNode> ConvertNode(JSContext* cx, jsval node)
    68 {
    69     AtSmartPtr<AtNode> obj (new AtNode());
    70 
    71     // Non-objects get converted into strings
    72     if (!JSVAL_IS_OBJECT(node))
     76    else if (node.type() == json_spirit::array_type)
    7377    {
    74         JSString* str = JS_ValueToString(cx, node);
    75         if (!str)
    76             return obj; // error
    77         size_t valueLen;
    78         const jschar* valueChars = JS_GetStringCharsAndLength(cx, str, &valueLen);
    79         if (!valueChars)
    80             return obj; // error
    81         wxString valueWx(reinterpret_cast<const char*>(valueChars), wxMBConvUTF16(), valueLen*2);
     78        //AtSmartPtr<AtNode> child(new AtNode());
     79        obj->children.insert(AtNode::child_pairtype(
     80            "@array", AtSmartPtr<AtNode>(new AtNode())
     81        ));
    8282
    83         obj->value = valueWx.c_str();
    84 
    85         // Annotate numbers/booleans specially, to allow round-tripping
    86         if (JSVAL_IS_NUMBER(node))
     83        json_spirit::Array nodeChildren = node.get_array();
     84        json_spirit::Array::iterator itr = nodeChildren.begin();
     85       
     86        for (; itr != nodeChildren.end(); itr++)
    8787        {
    8888            obj->children.insert(AtNode::child_pairtype(
    89                 "@number", AtSmartPtr<AtNode>(new AtNode())
     89                "item", ConvertNode(*itr)
    9090            ));
    9191        }
    92         else if (JSVAL_IS_BOOLEAN(node))
    93         {
    94             obj->children.insert(AtNode::child_pairtype(
    95                 "@boolean", AtSmartPtr<AtNode>(new AtNode())
    96             ));
    97         }
    98 
    99         return obj;
    10092    }
    101 
    102     JSObject* it = JS_NewPropertyIterator(cx, JSVAL_TO_OBJECT(node));
    103     if (!it)
    104         return obj; // error
    105 
    106     while (true)
     93    else if (node.type() == json_spirit::obj_type)
    10794    {
    108         jsid idp;
    109         jsval val;
    110         if (! JS_NextProperty(cx, it, &idp) || ! JS_IdToValue(cx, idp, &val))
    111             return obj; // error
    112         if (val == JSVAL_VOID)
    113             break; // end of iteration
    114         if (! JSVAL_IS_STRING(val))
    115             continue; // ignore integer properties
    116 
    117         JSString* name = JSVAL_TO_STRING(val);
    118         size_t len;
    119         const jschar* chars = JS_GetStringCharsAndLength(cx, name, &len);
    120         wxString nameWx(reinterpret_cast<const char*>(chars), wxMBConvUTF16(), len*2);
    121         std::string nameStr(nameWx.ToUTF8().data());
    122 
    123         jsval vp;
    124         if (!JS_GetPropertyById(cx, JSVAL_TO_OBJECT(node), idp, &vp))
    125             return obj; // error
    126 
    127         // Unwrap arrays into a special format like <$name><item>$i0</item><item>...
    128         // (This assumes arrays aren't nested)
    129         if (JSVAL_IS_OBJECT(vp) && JS_IsArrayObject(cx, JSVAL_TO_OBJECT(vp)))
     95        json_spirit::Object objectProperties = node.get_obj();
     96        json_spirit::Object::iterator itr = objectProperties.begin();
     97        for (; itr != objectProperties.end(); itr++)
    13098        {
    131             AtSmartPtr<AtNode> child(new AtNode());
    132             child->children.insert(AtNode::child_pairtype(
    133                 "@array", AtSmartPtr<AtNode>(new AtNode())
    134             ));
    135 
    136             jsuint arrayLength;
    137             if (!JS_GetArrayLength(cx, JSVAL_TO_OBJECT(vp), &arrayLength))
    138                 return obj; // error
    139 
    140             for (jsuint i = 0; i < arrayLength; ++i)
    141             {
    142                 jsval val;
    143                 if (!JS_GetElement(cx, JSVAL_TO_OBJECT(vp), i, &val))
    144                     return obj; // error
    145 
    146                 child->children.insert(AtNode::child_pairtype(
    147                     "item", ConvertNode(cx, val)
    148                 ));
    149             }
    150 
    15199            obj->children.insert(AtNode::child_pairtype(
    152                 nameStr, child
     100                itr->name_, ConvertNode(itr->value_)
    153101            ));
    154102        }
    155         else
    156         {
    157             obj->children.insert(AtNode::child_pairtype(
    158                 nameStr, ConvertNode(cx, vp)
    159             ));
    160         }
    161103    }
    162 
     104    else
     105    {
     106        assert(! "Unimplemented type found when parsing JSON!");
     107    }
     108   
    163109    return obj;
    164110}
    165111
    166112
    167 jsval BuildJSVal(JSContext* cx, AtNode::Ptr p)
     113json_spirit::Value BuildJSONNode(AtNode::Ptr p)
    168114{
    169115    if (!p)
    170         return JSVAL_VOID;
     116    {
     117        json_spirit::Value rval;
     118        return rval;
     119    }
    171120
    172121    // Special case for numbers/booleans to allow round-tripping
    173122    if (p->children.count("@number"))
     
    178127        double val = 0;
    179128        str >> val;
    180129
    181         jsval rval;
    182         if (!JS_NewNumberValue(cx, val, &rval))
    183             return JSVAL_VOID; // error
     130        json_spirit::Value rval(val);
    184131        return rval;
    185132    }
    186133    else if (p->children.count("@boolean"))
     
    188135        bool val = false;
    189136        if (p->value == L"true")
    190137            val = true;
    191 
    192         return BOOLEAN_TO_JSVAL(val);
     138       
     139        json_spirit::Value rval(val);
     140        return rval;
    193141    }
    194142
    195143    // If no children, then use the value string instead
    196144    if (p->children.empty())
    197145    {
    198         size_t val16len;
    199         wxCharBuffer val16 = wxMBConvUTF16().cWC2MB(p->value.c_str(), p->value.length(), &val16len);
    200 
    201         JSString* str = JS_NewUCStringCopyN(cx, reinterpret_cast<const jschar*>(val16.data()), (uint32)(val16len/2));
    202         if (!str)
    203             return JSVAL_VOID; // error
    204         return STRING_TO_JSVAL(str);
     146        json_spirit::Value rval(std::string(p->value.begin(), p->value.end()));
     147        return rval;
    205148    }
    206149
    207150    if (p->children.find("@array") != p->children.end())
    208151    {
    209         JSObject* obj = JS_NewArrayObject(cx, 0, NULL);
    210         if (!obj)
    211             return JSVAL_VOID; // error
     152        json_spirit::Array rval;
    212153
    213154        // Find the <item> children
    214155        AtNode::child_maptype::const_iterator lower = p->children.lower_bound("item");
    215156        AtNode::child_maptype::const_iterator upper = p->children.upper_bound("item");
    216157
    217         jsint idx = 0;
     158        uint32_t idx = 0;
    218159        for (AtNode::child_maptype::const_iterator it = lower; it != upper; ++it)
    219160        {
    220             jsval val = BuildJSVal(cx, it->second);
    221             if (!JS_SetElement(cx, obj, idx, &val))
    222                 return JSVAL_VOID; // error
     161            json_spirit::Value child = BuildJSONNode(it->second);
     162            rval.push_back(child);
    223163
    224164            ++idx;
    225165        }
    226166
    227         return OBJECT_TO_JSVAL(obj);
     167        return rval;
    228168    }
    229169    else
    230170    {
    231         JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
    232         if (!obj)
    233             return JSVAL_VOID; // error
    234 
     171        json_spirit::Object rval;
     172       
    235173        for (AtNode::child_maptype::const_iterator it = p->children.begin(); it != p->children.end(); ++it)
    236174        {
    237             jsval val = BuildJSVal(cx, it->second);
    238             if (!JS_SetProperty(cx, obj, it->first.c_str(), &val))
    239                 return JSVAL_VOID; // error
     175            json_spirit::Value child = BuildJSONNode(it->second);
     176            rval.push_back(json_spirit::Pair(it->first.c_str(), child));
    240177        }
    241178
    242         return OBJECT_TO_JSVAL(obj);
     179        return rval;
    243180    }
    244181}
    245182
    246 struct Stringifier
     183std::string AtlasObject::SaveToJSON(AtObj& obj)
    247184{
    248     static JSBool callback(const jschar* buf, uint32 len, void* data)
    249     {
    250         wxString textWx(reinterpret_cast<const char*>(buf), wxMBConvUTF16(), len*2);
    251         std::string textStr(textWx.ToUTF8().data());
    252 
    253         static_cast<Stringifier*>(data)->stream << textStr;
    254         return JS_TRUE;
    255     }
    256 
    257     std::stringstream stream;
    258 };
    259 
    260 std::string AtlasObject::SaveToJSON(JSContext* cx, AtObj& obj)
    261 {
    262     jsval root = BuildJSVal(cx, obj.p);
    263 
    264     Stringifier str;
    265     if (!JS_Stringify(cx, &root, NULL, JSVAL_VOID, &Stringifier::callback, &str))
    266     {
    267         wxLogError(_T("SaveToJSON failed"));
    268         return "";
    269     }
    270 
    271     return str.stream.str();
     185    json_spirit::Value root = BuildJSONNode(obj.p);
     186    std::string ret = json_spirit::write_string(root, 0);
     187    return ret;
    272188}
  • source/tools/atlas/AtlasObject/JSONSpiritInclude.h

     
     1/* Copyright (C) 2014 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17 
     18 // We use this special header for including the JSONSpirit header because some tweaking is needed to disable warnings.
     19#ifndef JSON_SPIRIT_INCLUDE_H
     20#define JSON_SPIRIT_INCLUDE_H
     21
     22#ifdef __GNUC__
     23# define GCC_VERSION (__GNUC__*100 + __GNUC_MINOR__)
     24#else
     25# define GCC_VERSION 0
     26#endif
     27
     28#if GCC_VERSION >= 402 // (older GCCs don't support this pragma)
     29# pragma GCC diagnostic ignored "-Wunused-parameter"
     30#endif
     31
     32#ifdef _MSC_VER
     33 #pragma warning(disable: 4100)
     34 #pragma warning(disable: 4512)
     35#endif
     36
     37# include "json_spirit_writer_template.h"
     38# include "json_spirit_reader_template.h"
     39
     40#ifdef _MSC_VER
     41 #pragma warning(default: 4100)
     42 #pragma warning(default: 4512)
     43#endif
     44
     45#if GCC_VERSION >= 402
     46# pragma GCC diagnostic warning "-Wunused-parameter"
     47#endif
     48
     49#endif // JSON_SPIRIT_INCLUDE_H
     50 Kein Zeilenumbruch am Ende der Datei
  • source/tools/atlas/AtlasScript/NativeWrapper.inl

     
    1 /* Copyright (C) 2009 Wildfire Games.
    2  * This file is part of 0 A.D.
    3  *
    4  * 0 A.D. is free software: you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * 0 A.D. is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    16  */
    17 
    18 #include <boost/preprocessor/punctuation/comma_if.hpp>
    19 #include <boost/preprocessor/repetition/repeat.hpp>
    20 
    21 // Set the maximum number of function arguments that can be handled
    22 #define MAX_ARGS 3
    23 
    24 // (This is included inside the definition of class ScriptInterface)
    25 public:
    26     // Varieties of comma-separated list to fit on the head/tail/whole of another comma-separated list
    27     #define NUMBERED_LIST_TAIL(z, i, data) ,data##i
    28     #define NUMBERED_LIST_HEAD(z, i, data) data##i,
    29     #define NUMBERED_LIST_BALANCED(z, i, data) BOOST_PP_COMMA_IF(i) data##i
    30     // Some other things
    31     #define TYPED_ARGS(z, i, data) , T##i a##i
    32     #define CONVERT_ARG(z, i, data) T##i a##i; if (! ScriptInterface::FromJSVal<T##i>(cx, i < argc ? JS_ARGV(cx, vp)[i] : JSVAL_VOID, a##i)) return JS_FALSE;
    33 
    34     // List-generating macros, named roughly after their first list item
    35     #define TYPENAME_T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, typename T)
    36     #define TYPENAME_T0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, typename T)
    37     #define T0(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_BALANCED, T)
    38     #define T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, T)
    39     #define T0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, T)
    40     #define T0_A0(z, i) BOOST_PP_REPEAT_##z (i, TYPED_ARGS, ~)
    41     #define A0(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_BALANCED, a)
    42     #define A0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, a)
    43 
    44     // Define RegisterFunction<TR, T0..., f>
    45     #define OVERLOADS(z, i, data) \
    46         template <typename TR, TYPENAME_T0_HEAD(z,i)  TR (*fptr) ( void* T0_TAIL(z,i) )> \
    47         void RegisterFunction(const char* name) { \
    48             Register(name, call<TR, T0_HEAD(z,i)  fptr>, nargs<0 T0_TAIL(z,i)>()); \
    49         }
    50 
    51     BOOST_PP_REPEAT(MAX_ARGS, OVERLOADS, ~)
    52     #undef OVERLOADS
    53 
    54 private:
    55     // JSNative-compatible function that wraps the function identified in the template argument list
    56     // (Definition comes later, since it depends on some things we haven't defined yet)
    57     #define OVERLOADS(z, i, data) \
    58         template <typename TR, TYPENAME_T0_HEAD(z,i)  TR (*fptr) ( void* T0_TAIL(z,i) )> \
    59         static JSBool call(JSContext* cx, uintN argc, jsval* vp);
    60     BOOST_PP_REPEAT(MAX_ARGS, OVERLOADS, ~)
    61     #undef OVERLOADS
    62 
    63     // Argument-number counter
    64     #define OVERLOADS(z, i, data) \
    65         template <int dummy TYPENAME_T0_TAIL(z,i)> /* add a dummy parameter so we still compile with 0 template args */ \
    66         static size_t nargs() { return i; }
    67     BOOST_PP_REPEAT(MAX_ARGS, OVERLOADS, ~)
    68     #undef OVERLOADS
    69 
    70 }; // end of class ScriptInterface, because the following specialised structs
    71    // are not permitted inside non-namespace scopes
    72 
    73 
    74 // ScriptInterface_NativeWrapper<T>::call(cx, rval, fptr, args...) will call fptr(cbdata, args),
    75 // and if T != void then it will store the result in rval:
    76 
    77 // Templated on the return type so void can be handled separately
    78 template <typename TR>
    79 struct ScriptInterface_NativeWrapper {
    80     #define OVERLOADS(z, i, data) \
    81         template<TYPENAME_T0_HEAD(z,i)  typename f> \
    82         static void call(JSContext* cx, jsval& rval, f fptr  T0_A0(z,i)) { \
    83             rval = ScriptInterface::ToJSVal<TR>(cx, fptr(ScriptInterface::GetCallbackData(cx)  A0_TAIL(z,i))); \
    84         }
    85 
    86     BOOST_PP_REPEAT(MAX_ARGS, OVERLOADS, ~)
    87     #undef OVERLOADS
    88 };
    89 
    90 // Overloaded to ignore the return value from void functions
    91 template <>
    92 struct ScriptInterface_NativeWrapper<void> {
    93     #define OVERLOADS(z, i, data) \
    94         template<TYPENAME_T0_HEAD(z,i)  typename f> \
    95         static void call(JSContext* cx, jsval& /*rval*/, f fptr  T0_A0(z,i)) { \
    96             fptr(ScriptInterface::GetCallbackData(cx)  A0_TAIL(z,i)); \
    97         }
    98     BOOST_PP_REPEAT(MAX_ARGS, OVERLOADS, ~)
    99     #undef OVERLOADS
    100 };
    101 
    102 // JSNative-compatible function that wraps the function identified in the template argument list
    103 #define OVERLOADS(z, i, data) \
    104     template <typename TR, TYPENAME_T0_HEAD(z,i)  TR (*fptr) ( void* T0_TAIL(z,i) )> \
    105     JSBool ScriptInterface::call(JSContext* cx, uintN argc, jsval* vp) { \
    106         (void)cx; (void)argc; /* avoid 'unused parameter' warnings */ \
    107         BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
    108         jsval rval = JSVAL_VOID; \
    109         ScriptInterface_NativeWrapper<TR>::call(cx, rval, fptr  A0_TAIL(z,i)); \
    110         JS_SET_RVAL(cx, vp, rval); \
    111         return JS_TRUE; \
    112     }
    113 BOOST_PP_REPEAT(MAX_ARGS, OVERLOADS, ~)
    114 #undef OVERLOADS
    115 
    116 // Clean up our mess
    117 #undef NUMBERED_LIST_TAIL
    118 #undef NUMBERED_LIST_HEAD
    119 #undef NUMBERED_LIST_BALANCED
    120 #undef TYPED_ARGS
    121 #undef CONVERT_ARG
    122 #undef TYPENAME_T0_HEAD
    123 #undef TYPENAME_T0_TAIL
    124 #undef T0
    125 #undef T0_HEAD
    126 #undef T0_TAIL
    127 #undef T0_A0
    128 #undef A0
    129 #undef A0_TAIL
  • source/tools/atlas/AtlasScript/ScriptInterface.cpp

     
    1 /* Copyright (C) 2011 Wildfire Games.
    2  * This file is part of 0 A.D.
    3  *
    4  * 0 A.D. is free software: you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * 0 A.D. is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    16  */
    17 
    18 #include "ScriptInterface.h"
    19 
    20 #include <cassert>
    21 #ifndef _WIN32
    22 # include <typeinfo>
    23 # include <cxxabi.h>
    24 #endif
    25 
    26 #if defined(_MSC_VER)
    27 # pragma warning(disable:4996)  // deprecated CRT
    28 #endif
    29 
    30 #if defined(__GNUC__) && (__GNUC__*100 + __GNUC_MINOR__) >= 402 // (older GCCs don't support this pragma)
    31 # pragma GCC diagnostic ignored "-Wredundant-decls" // triggered by wx/geometry.h
    32 #endif
    33 
    34 #include "wx/wx.h"
    35 
    36 #include "GameInterface/Shareable.h"
    37 #include "GameInterface/Messages.h"
    38 
    39 
    40 #include <boost/preprocessor/punctuation/comma_if.hpp>
    41 #include <boost/preprocessor/repetition/repeat.hpp>
    42 
    43 #include "valgrind.h"
    44 
    45 #define FAIL(msg) do { JS_ReportError(cx, msg); return false; } while (false)
    46 
    47 const int RUNTIME_SIZE = 4*1024*1024; // TODO: how much memory is needed?
    48 const int STACK_CHUNK_SIZE = 8192;
    49 
    50 SubmitCommand g_SubmitCommand; // TODO: globals are ugly
    51 
    52 ////////////////////////////////////////////////////////////////
    53 
    54 namespace
    55 {
    56     template<typename T>
    57     void ReportError(JSContext* cx, const char* title)
    58     {
    59         // TODO: SetPendingException turns the error into a JS-catchable exception,
    60         // but the error report doesn't say anything useful like the line number,
    61         // so I'm just using ReportError instead for now (and failures are uncatchable
    62         // and will terminate the whole script)
    63         //JS_SetPendingException(cx, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, "%s: Unhandled type", title)));
    64 #ifdef _WIN32
    65         JS_ReportError(cx, "%s: Unhandled type", title);
    66 #else
    67         // Give a more informative message on GCC
    68         int status;
    69         char* name = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);
    70         JS_ReportError(cx, "%s: Unhandled type '%s'", title, name);
    71         free(name);
    72 #endif
    73     }
    74 
    75     // Report runtime errors for unhandled types, so we don't have to bother
    76     // defining all the types in advance. (TODO: at some point we should
    77     // define all the types and then remove this bit so the errors are found
    78     // at link-time.)
    79     template<typename T> struct FromJSVal
    80     {
    81         static bool Convert(JSContext* cx, jsval WXUNUSED(v), T& WXUNUSED(out))
    82         {
    83             ReportError<T>(cx, "FromJSVal");
    84             return false;
    85         }
    86     };
    87    
    88     template<> struct FromJSVal<bool>
    89     {
    90         static bool Convert(JSContext* cx, jsval v, bool& out)
    91         {
    92             JSBool ret;
    93             if (! JS_ValueToBoolean(cx, v, &ret)) return false;
    94             out = (ret ? true : false);
    95             return true;
    96         }
    97     };
    98 
    99     template<> struct FromJSVal<float>
    100     {
    101         static bool Convert(JSContext* cx, jsval v, float& out)
    102         {
    103             jsdouble ret;
    104             if (! JS_ValueToNumber(cx, v, &ret)) return false;
    105             out = ret;
    106             return true;
    107         }
    108     };
    109 
    110     template<> struct FromJSVal<int>
    111     {
    112         static bool Convert(JSContext* cx, jsval v, int& out)
    113         {
    114             int32 ret;
    115             if (! JS_ValueToECMAInt32(cx, v, &ret)) return false;
    116             out = ret;
    117             return true;
    118         }
    119     };
    120 
    121     template<> struct FromJSVal<size_t>
    122     {
    123         static bool Convert(JSContext* cx, jsval v, size_t& out)
    124         {
    125             uint32 ret;
    126             if (! JS_ValueToECMAUint32(cx, v, &ret)) return false;
    127             out = ret;
    128             return true;
    129         }
    130     };
    131 
    132     template<> struct FromJSVal<CScriptVal>
    133     {
    134         static bool Convert(JSContext* WXUNUSED(cx), jsval v, CScriptVal& out)
    135         {
    136             out = v;
    137             return true;
    138         }
    139     };
    140 
    141     template<> struct FromJSVal<std::wstring>
    142     {
    143         static bool Convert(JSContext* cx, jsval v, std::wstring& out)
    144         {
    145             JSString* ret = JS_ValueToString(cx, v);
    146             if (! ret)
    147                 FAIL("Argument must be convertible to a string");
    148             size_t len;
    149             const jschar* ch = JS_GetStringCharsAndLength(cx, ret, &len);
    150             if (! ch)
    151                 FAIL("JS_GetStringsCharsAndLength failed"); // probably out of memory
    152             out = std::wstring(ch, ch + len);
    153             return true;
    154         }
    155     };
    156 
    157     template<> struct FromJSVal<std::string>
    158     {
    159         static bool Convert(JSContext* cx, jsval v, std::string& out)
    160         {
    161             JSString* ret = JS_ValueToString(cx, v);
    162             if (! ret)
    163                 FAIL("Argument must be convertible to a string");
    164             size_t len = JS_GetStringEncodingLength(cx, ret);
    165             if (len == (size_t)-1)
    166                 FAIL("JS_GetStringEncodingLength failed");
    167             char* ch = JS_EncodeString(cx, ret); // chops off high byte of each jschar
    168             if (! ch)
    169                 FAIL("JS_EncodeString failed"); // probably out of memory
    170             out = std::string(ch, ch + len);
    171             JS_free(cx, ch);
    172             return true;
    173         }
    174     };
    175 
    176     template<> struct FromJSVal<wxString>
    177     {
    178         static bool Convert(JSContext* cx, jsval v, wxString& out)
    179         {
    180             JSString* ret = JS_ValueToString(cx, v);
    181             size_t len;
    182             if (! ret)
    183                 FAIL("Argument must be convertible to a string");
    184             const jschar* ch = JS_GetStringCharsAndLength(cx, ret, &len);
    185             if (! ch)
    186                 FAIL("JS_GetStringsCharsAndLength failed"); // probably out of memory
    187             out = wxString((const char*)ch, wxMBConvUTF16(), len*2);
    188             return true;
    189         }
    190     };
    191 
    192     template<typename T> struct FromJSVal<std::vector<T> >
    193     {
    194         static bool Convert(JSContext* cx, jsval v, std::vector<T>& out)
    195         {
    196             JSObject* obj;
    197             if (! JS_ValueToObject(cx, v, &obj) || obj == NULL || !JS_IsArrayObject(cx, obj))
    198                 FAIL("Argument must be an array");
    199             jsuint length;
    200             if (! JS_GetArrayLength(cx, obj, &length))
    201                 FAIL("Failed to get array length");
    202             out.reserve(length);
    203             for (jsuint i = 0; i < length; ++i)
    204             {
    205                 jsval el;
    206                 if (! JS_GetElement(cx, obj, i, &el))
    207                     FAIL("Failed to read array element");
    208                 T el2;
    209                 if (! FromJSVal<T>::Convert(cx, el, el2))
    210                     return false;
    211                 out.push_back(el2);
    212             }
    213             return true;
    214         }
    215     };
    216 
    217     ////////////////////////////////////////////////////////////////
    218 
    219     // Report runtime errors for unhandled types, so we don't have to bother
    220     // defining all the types in advance. (TODO: at some point we should
    221     // define all the types and then remove this bit so the errors are found
    222     // at link-time.)
    223     template<typename T> struct ToJSVal
    224     {
    225         static jsval Convert(JSContext* cx, const T& WXUNUSED(val))
    226         {
    227             ReportError<T>(cx, "ToJSVal");
    228             return JSVAL_VOID;
    229         }
    230     };
    231 
    232     ////////////////////////////////////////////////////////////////
    233     // Primitive types:
    234 
    235     template<> struct ToJSVal<bool>
    236     {
    237         static jsval Convert(JSContext* WXUNUSED(cx), const bool& val)
    238         {
    239             return val ? JSVAL_TRUE : JSVAL_FALSE;
    240         }
    241     };
    242 
    243     template<> struct ToJSVal<float>
    244     {
    245         static jsval Convert(JSContext* cx, const float& val)
    246         {
    247             jsval rval = JSVAL_VOID;
    248             JS_NewNumberValue(cx, val, &rval); // ignore return value
    249             return rval;
    250         }
    251     };
    252 
    253     template<> struct ToJSVal<int>
    254     {
    255         static jsval Convert(JSContext* WXUNUSED(cx), const int& val)
    256         {
    257             return INT_TO_JSVAL(val);
    258         }
    259     };
    260 
    261     template<> struct ToJSVal<size_t>
    262     {
    263         static jsval Convert(JSContext* cx, const size_t& val)
    264         {
    265             if (val <= JSVAL_INT_MAX)
    266                 return INT_TO_JSVAL(val);
    267             jsval rval = JSVAL_VOID;
    268             JS_NewNumberValue(cx, val, &rval); // ignore return value
    269             return rval;
    270         }
    271     };
    272 
    273     template<> struct ToJSVal<wxString>
    274     {
    275         static jsval Convert(JSContext* cx, const wxString& val)
    276         {
    277             wxMBConvUTF16 conv;
    278             size_t length;
    279             wxCharBuffer utf16 = conv.cWC2MB(val.c_str(), val.length()+1, &length);
    280             JSString* str = JS_NewUCStringCopyN(cx, reinterpret_cast<jschar*>(utf16.data()), length/2);
    281             if (str)
    282                 return STRING_TO_JSVAL(str);
    283             else
    284                 return JSVAL_VOID;
    285         }
    286     };
    287 
    288     template<> struct ToJSVal<std::wstring>
    289     {
    290         static jsval Convert(JSContext* cx, const std::wstring& val)
    291         {
    292             wxMBConvUTF16 conv;
    293             size_t length;
    294             wxCharBuffer utf16 = conv.cWC2MB(val.c_str(), val.length()+1, &length);
    295             JSString* str = JS_NewUCStringCopyN(cx, reinterpret_cast<jschar*>(utf16.data()), length/2);
    296             if (str)
    297                 return STRING_TO_JSVAL(str);
    298             else
    299                 return JSVAL_VOID;
    300         }
    301     };
    302 
    303     template<> struct ToJSVal<std::string>
    304     {
    305         static jsval Convert(JSContext* cx, const std::string& val)
    306         {
    307             JSString* str = JS_NewStringCopyN(cx, val.c_str(), val.length());
    308             if (str)
    309                 return STRING_TO_JSVAL(str);
    310             return JSVAL_VOID;
    311         }
    312     };
    313 
    314     ////////////////////////////////////////////////////////////////
    315     // Compound types:
    316 
    317     template<typename T> struct ToJSVal<std::vector<T> >
    318     {
    319         static jsval Convert(JSContext* cx, const std::vector<T>& val)
    320         {
    321             JSObject* obj = JS_NewArrayObject(cx, 0, NULL);
    322             if (! obj) return JSVAL_VOID;
    323             for (size_t i = 0; i < val.size(); ++i)
    324             {
    325                 jsval el = ToJSVal<T>::Convert(cx, val[i]);
    326                 JS_SetElement(cx, obj, (jsint)i, &el);
    327             }
    328             return OBJECT_TO_JSVAL(obj);
    329         }
    330     };
    331    
    332     template<typename T> struct ToJSVal<AtlasMessage::Shareable<T> >
    333     {
    334         static jsval Convert(JSContext* cx, const AtlasMessage::Shareable<T>& val)
    335         {
    336             return ToJSVal<T>::Convert(cx, val._Unwrap());
    337         }
    338     };
    339 }
    340 
    341 template<typename T> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, T& out)
    342 {
    343     return ::FromJSVal<T>::Convert(cx, v, out);
    344 }
    345 
    346 template<typename T> jsval ScriptInterface::ToJSVal(JSContext* cx, const T& v)
    347 {
    348     return ::ToJSVal<T>::Convert(cx, v);
    349 }
    350 
    351 // Explicit instantiation of functions that would otherwise be unused in this file
    352 // but are required for linking with other files
    353 template bool ScriptInterface::FromJSVal<std::string>(JSContext*, jsval, std::string&);
    354 template bool ScriptInterface::FromJSVal<wxString>(JSContext*, jsval, wxString&);
    355 template bool ScriptInterface::FromJSVal<bool>(JSContext*, jsval, bool&);
    356 template bool ScriptInterface::FromJSVal<float>(JSContext*, jsval, float&);
    357 template bool ScriptInterface::FromJSVal<CScriptVal>(JSContext*, jsval, CScriptVal&);
    358 template jsval ScriptInterface::ToJSVal<wxString>(JSContext*, wxString const&);
    359 template jsval ScriptInterface::ToJSVal<int>(JSContext*, int const&);
    360 template jsval ScriptInterface::ToJSVal<float>(JSContext*, float const&);
    361 template jsval ScriptInterface::ToJSVal<std::vector<int> >(JSContext*, std::vector<int> const&);
    362 template jsval ScriptInterface::ToJSVal<size_t>(JSContext*, size_t const&);
    363 template jsval ScriptInterface::ToJSVal<std::vector<wxString> >(JSContext*, std::vector<wxString> const&);
    364 
    365 ////////////////////////////////////////////////////////////////
    366 
    367 struct AtlasScriptInterface_impl
    368 {
    369     AtlasScriptInterface_impl();
    370     ~AtlasScriptInterface_impl();
    371     static JSBool LoadScript(JSContext* cx, const jschar* chars, uintN length, const char* filename, jsval* rval);
    372     void RegisterMessages(JSObject* parent);
    373     void Register(const char* name, JSNative fptr, uintN nargs);
    374 
    375     JSRuntime* m_rt;
    376     JSContext* m_cx;
    377     JSObject* m_glob; // global scope object
    378     JSObject* m_atlas; // Atlas scope object
    379 };
    380 
    381 namespace
    382 {
    383     JSClass global_class = {
    384         "global", JSCLASS_GLOBAL_FLAGS,
    385         JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
    386         JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
    387         NULL, NULL, NULL, NULL,
    388         NULL, NULL, NULL, NULL
    389     };
    390    
    391     void ErrorReporter(JSContext* WXUNUSED(cx), const char* message, JSErrorReport* report)
    392     {
    393         bool isWarning = JSREPORT_IS_WARNING(report->flags);
    394         wxString logMessage(isWarning ? _T("JavaScript warning: ") : _T("JavaScript error: "));
    395         if (report->filename)
    396         {
    397             logMessage << wxString::FromAscii(report->filename);
    398             logMessage << _T(" line ") << report->lineno << _T("\n");
    399         }
    400         logMessage << wxString::FromAscii(message);
    401         if (isWarning)
    402             wxLogWarning(_T("%s"), logMessage.c_str());
    403         else
    404             wxLogError(_T("%s"), logMessage.c_str());
    405         // When running under Valgrind, print more information in the error message
    406         VALGRIND_PRINTF_BACKTRACE("->");
    407         wxPrintf(_T("wxJS %s: %s\n--------\n"), isWarning ? _T("warning") : _T("error"), logMessage.c_str());
    408     }
    409 
    410     // Functions in the Atlas.* namespace:
    411    
    412     JSBool ForceGC(JSContext* cx, uintN WXUNUSED(argc), jsval* vp)
    413     {
    414         JS_GC(cx);
    415         JS_SET_RVAL(cx, vp, JSVAL_VOID);
    416         return JS_TRUE;
    417     }
    418 
    419     JSBool LoadScript(JSContext* cx, uintN argc, jsval* vp)
    420     {
    421         if (argc < 2 || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[0]) || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[1]))
    422             return JS_FALSE;
    423        
    424         std::string name;
    425         if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], name))
    426             return JS_FALSE;
    427 
    428         JSString* code = JSVAL_TO_STRING(JS_ARGV(cx, vp)[1]);
    429        
    430         size_t len;
    431         const jschar* ch = JS_GetStringCharsAndLength(cx, code, &len);
    432         if (!ch)
    433             return JS_FALSE;
    434 
    435         jsval rval = JSVAL_VOID;
    436         if (!AtlasScriptInterface_impl::LoadScript(cx,
    437                 ch, (uintN)len,
    438                 name.c_str(), &rval))
    439             return JS_FALSE;
    440 
    441         JS_SET_RVAL(cx, vp, rval);
    442         return JS_TRUE;
    443     }
    444    
    445     // Functions in the global namespace:
    446 
    447     JSBool print(JSContext* cx, uintN argc, jsval* vp)
    448     {
    449         for (uintN i = 0; i < argc; ++i)
    450         {
    451             std::string str;
    452             if (! ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[i], str))
    453                 return JS_FALSE;
    454             printf("%s", str.c_str());
    455         }
    456         fflush(stdout);
    457         JS_SET_RVAL(cx, vp, JSVAL_VOID);
    458         return JS_TRUE;
    459     }
    460 }
    461 
    462 AtlasScriptInterface_impl::AtlasScriptInterface_impl()
    463 {
    464     m_rt = JS_NewRuntime(RUNTIME_SIZE);
    465     assert(m_rt); // TODO: error handling
    466 
    467     m_cx = JS_NewContext(m_rt, STACK_CHUNK_SIZE);
    468     assert(m_cx);
    469 
    470     JS_BeginRequest(m_cx); // if you get linker errors, see the comment in ScriptInterface.h about JS_THREADSAFE
    471     // (TODO: are we using requests correctly? (Probably not; how much does it matter?))
    472 
    473     JS_SetContextPrivate(m_cx, NULL);
    474 
    475     JS_SetErrorReporter(m_cx, ErrorReporter);
    476 
    477     JS_SetOptions(m_cx,
    478           JSOPTION_STRICT // "warn on dubious practice"
    479         | JSOPTION_XML // "ECMAScript for XML support: parse <!-- --> as a token"
    480         );
    481 
    482     JS_SetVersion(m_cx, JSVERSION_LATEST);
    483 
    484     m_glob = JS_NewCompartmentAndGlobalObject(m_cx, &global_class, NULL);
    485     JS_InitStandardClasses(m_cx, m_glob);
    486    
    487     JS_DefineProperty(m_cx, m_glob, "global", OBJECT_TO_JSVAL(m_glob), NULL, NULL, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    488 
    489     JS_DefineFunction(m_cx, m_glob, "print", ::print, 0, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    490    
    491     m_atlas = JS_DefineObject(m_cx, m_glob, "Atlas", NULL, NULL, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    492     JS_DefineFunction(m_cx, m_atlas, "ForceGC", ::ForceGC, 0, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    493     JS_DefineFunction(m_cx, m_atlas, "LoadScript", ::LoadScript, 2, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    494     JS_DefineObject(m_cx, m_atlas, "State", NULL, NULL, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    495    
    496     RegisterMessages(m_atlas);
    497 }
    498 
    499 AtlasScriptInterface_impl::~AtlasScriptInterface_impl()
    500 {
    501     JS_EndRequest(m_cx);
    502     JS_DestroyContext(m_cx);
    503     JS_DestroyRuntime(m_rt);
    504 }
    505 
    506 JSBool AtlasScriptInterface_impl::LoadScript(JSContext* cx, const jschar* chars, uintN length, const char* filename, jsval* rval)
    507 {
    508     JSObject* scriptObj = JS_NewObject(cx, NULL, NULL, NULL);
    509     if (! scriptObj)
    510         return JS_FALSE;
    511     *rval = OBJECT_TO_JSVAL(scriptObj);
    512        
    513     jsval scriptRval;
    514     JSBool ok = JS_EvaluateUCScript(cx, scriptObj, chars, length, filename, 1, &scriptRval);
    515     if (! ok)
    516         return JS_FALSE;
    517        
    518     return JS_TRUE;
    519 }
    520 
    521 void AtlasScriptInterface_impl::Register(const char* name, JSNative fptr, uintN nargs)
    522 {
    523     JS_DefineFunction(m_cx, m_atlas, name, fptr, nargs, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    524 }
    525 
    526 
    527 ScriptInterface::ScriptInterface(SubmitCommand submitCommand)
    528     : m(new AtlasScriptInterface_impl())
    529 {
    530     g_SubmitCommand = submitCommand;
    531 }
    532 
    533 ScriptInterface::~ScriptInterface()
    534 {
    535 }
    536 
    537 void ScriptInterface::SetCallbackData(void* cbdata)
    538 {
    539     JS_SetContextPrivate(m->m_cx, cbdata);
    540 }
    541 
    542 void* ScriptInterface::GetCallbackData(JSContext* cx)
    543 {
    544     return JS_GetContextPrivate(cx);
    545 }
    546 
    547 void ScriptInterface::Register(const char* name, JSNative fptr, size_t nargs)
    548 {
    549     m->Register(name, fptr, (uintN)nargs);
    550 }
    551 
    552 JSContext* ScriptInterface::GetContext()
    553 {
    554     return m->m_cx;
    555 }
    556 
    557 bool ScriptInterface::AddRoot(jsval* ptr)
    558 {
    559     return JS_AddValueRoot(m->m_cx, ptr) ? true : false;
    560 }
    561 
    562 bool ScriptInterface::RemoveRoot(jsval* ptr)
    563 {
    564     return JS_RemoveValueRoot(m->m_cx, ptr) ? true : false;
    565 }
    566 
    567 
    568 bool ScriptInterface::SetValue_(const wxString& name, jsval val)
    569 {
    570     jsval jsName = ToJSVal(m->m_cx, name);
    571 
    572     const uintN argc = 2;
    573     jsval argv[argc] = { jsName, val };
    574     jsval rval;
    575     JSBool ok = JS_CallFunctionName(m->m_cx, m->m_glob, "setValue", argc, argv, &rval);
    576     return ok ? true : false;
    577 }
    578 
    579 bool ScriptInterface::GetValue_(const wxString& name, jsval& ret)
    580 {
    581     jsval jsName = ToJSVal(m->m_cx, name);
    582 
    583     const uintN argc = 1;
    584     jsval argv[argc] = { jsName };
    585     JSBool ok = JS_CallFunctionName(m->m_cx, m->m_glob, "getValue", argc, argv, &ret);
    586     return ok ? true : false;
    587 }
    588 
    589 bool ScriptInterface::CallFunction(jsval val, const char* name)
    590 {
    591     jsval jsRet;
    592     std::vector<jsval> argv;
    593     return CallFunction_(val, name, argv, jsRet);
    594 }
    595 
    596 bool ScriptInterface::CallFunction_(jsval val, const char* name, std::vector<jsval>& args, jsval& ret)
    597 {
    598     const uintN argc = (uintN)args.size();
    599     jsval* argv = NULL;
    600     if (argc)
    601         argv = &args[0];
    602     wxCHECK(JSVAL_IS_OBJECT(val), false);
    603     JSBool found;
    604     wxCHECK(JS_HasProperty(m->m_cx, JSVAL_TO_OBJECT(val), name, &found), false);
    605     if (! found)
    606         return false;
    607     JSBool ok = JS_CallFunctionName(m->m_cx, JSVAL_TO_OBJECT(val), name, argc, argv, &ret);
    608     return ok ? true : false;
    609 }
    610 
    611 bool ScriptInterface::Eval(const wxString& script)
    612 {
    613     jsval rval;
    614     JSBool ok = JS_EvaluateScript(m->m_cx, m->m_glob, script.mb_str(), (uintN)script.length(), NULL, 0, &rval);
    615     return ok ? true : false;
    616 }
    617 
    618 bool ScriptInterface::Eval_(const wxString& script, jsval& rval)
    619 {
    620     JSBool ok = JS_EvaluateScript(m->m_cx, m->m_glob, script.mb_str(), (uintN)script.length(), NULL, 0, &rval);
    621     return ok ? true : false;
    622 }
    623 
    624 void ScriptInterface::LoadScript(const wxString& filename, const wxString& code)
    625 {
    626     size_t codeLength;
    627     wxMBConvUTF16 conv;
    628     wxCharBuffer codeUTF16 = conv.cWC2MB(code.c_str(), code.length()+1, &codeLength);
    629     jsval rval;
    630     m->LoadScript(m->m_cx, reinterpret_cast<jschar*>(codeUTF16.data()), (uintN)(codeLength/2), filename.ToAscii(), &rval);
    631 }
    632 
    633 ////////////////////////////////////////////////////////////////
    634 
    635 #define TYPE(elem) BOOST_PP_TUPLE_ELEM(2, 0, elem)
    636 #define NAME(elem) BOOST_PP_TUPLE_ELEM(2, 1, elem)
    637 #define MAKE_STR_(s) #s
    638 #define MAKE_STR(s) MAKE_STR_(s)
    639 
    640 #define CONVERT_ARGS(r, data, i, elem) \
    641     TYPE(elem) a##i; \
    642     if (! ScriptInterface::FromJSVal< TYPE(elem) >(cx, i < argc ? JS_ARGV(cx, vp)[i] : JSVAL_VOID, a##i)) \
    643         return JS_FALSE;
    644        
    645 #define CONVERT_OUTPUTS(r, data, i, elem) \
    646     JS_DefineProperty(cx, ret, MAKE_STR(NAME(elem)), ScriptInterface::ToJSVal(cx, q.NAME(elem)), \
    647         NULL, NULL, JSPROP_ENUMERATE);
    648        
    649 #define ARG_LIST(r, data, i, elem) BOOST_PP_COMMA_IF(i) a##i
    650 
    651 #define MESSAGE(name, vals) \
    652     JSBool call_##name(JSContext* cx, uintN argc, jsval* vp) \
    653     { \
    654         (void)cx; (void)argc; /* avoid 'unused parameter' warnings */ \
    655         BOOST_PP_SEQ_FOR_EACH_I(CONVERT_ARGS, ~, vals) \
    656         g_MessagePasser->Add(SHAREABLE_NEW(m##name, ( BOOST_PP_SEQ_FOR_EACH_I(ARG_LIST, ~, vals) ))); \
    657         JS_SET_RVAL(cx, vp, JSVAL_VOID); \
    658         return JS_TRUE; \
    659     }
    660    
    661 #define COMMAND(name, merge, vals) \
    662     JSBool call_##name(JSContext* cx, uintN argc, jsval* vp) \
    663     { \
    664         (void)cx; (void)argc; /* avoid 'unused parameter' warnings */ \
    665         BOOST_PP_SEQ_FOR_EACH_I(CONVERT_ARGS, ~, vals) \
    666         g_SubmitCommand(new AtlasMessage::m##name (AtlasMessage::d##name ( BOOST_PP_SEQ_FOR_EACH_I(ARG_LIST, ~, vals) ))); \
    667         JS_SET_RVAL(cx, vp, JSVAL_VOID); \
    668         return JS_TRUE; \
    669     }
    670    
    671 #define QUERY(name, in_vals, out_vals) \
    672     JSBool call_##name(JSContext* cx, uintN argc, jsval* vp) \
    673     { \
    674         (void)cx; (void)argc; /* avoid 'unused parameter' warnings */ \
    675         BOOST_PP_SEQ_FOR_EACH_I(CONVERT_ARGS, ~, in_vals) \
    676         q##name q = q##name( BOOST_PP_SEQ_FOR_EACH_I(ARG_LIST, ~, in_vals) ); \
    677         q.Post(); \
    678         JSObject* ret = JS_NewObject(cx, NULL, NULL, NULL); \
    679         if (! ret) return JS_FALSE; \
    680         JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(ret)); \
    681         BOOST_PP_SEQ_FOR_EACH_I(CONVERT_OUTPUTS, ~, out_vals) \
    682         return JS_TRUE; \
    683     }
    684 
    685 #define MESSAGES_SKIP_SETUP
    686 #define MESSAGES_SKIP_STRUCTS
    687 
    688 // We want to include Messages.h again, with some different definitions,
    689 // so cheat and undefine its include-guard
    690 #undef INCLUDED_MESSAGES
    691 
    692 namespace
    693 {
    694     using namespace AtlasMessage;
    695     #include "GameInterface/Messages.h"
    696 }
    697 
    698 #undef MESSAGE
    699 #undef COMMAND
    700 #undef QUERY
    701 
    702 void AtlasScriptInterface_impl::RegisterMessages(JSObject* parent)
    703 {
    704     using namespace AtlasMessage;
    705    
    706     JSObject* obj = JS_DefineObject(m_cx, parent, "Message", NULL, NULL, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    707 
    708     #define MESSAGE(name, vals) \
    709     JS_DefineFunction(m_cx, obj, #name, call_##name, BOOST_PP_SEQ_SIZE((~)vals)-1, \
    710         JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    711 
    712     #define COMMAND(name, merge, vals) \
    713     JS_DefineFunction(m_cx, obj, #name, call_##name, BOOST_PP_SEQ_SIZE((~)vals)-1, \
    714         JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    715 
    716     #define QUERY(name, in_vals, out_vals) \
    717     JS_DefineFunction(m_cx, obj, #name, call_##name, BOOST_PP_SEQ_SIZE((~)in_vals)-1, \
    718         JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
    719 
    720     #undef INCLUDED_MESSAGES
    721      
    722     #include "GameInterface/Messages.h"
    723 
    724     #undef MESSAGE
    725     #undef COMMAND
    726     #undef QUERY
    727 }
  • source/tools/atlas/AtlasScript/ScriptInterface.h

     
    1 /* Copyright (C) 2009 Wildfire Games.
    2  * This file is part of 0 A.D.
    3  *
    4  * 0 A.D. is free software: you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * 0 A.D. is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    16  */
    17 
    18 #include <memory>
    19 #include <vector>
    20 
    21 #ifdef _WIN32
    22 # define XP_WIN
    23 # define WIN32 // SpiderMonkey expects this
    24 
    25 // The jsval struct type causes crashes due to weird miscompilation
    26 // issues in (at least) VC2008, so force it to be the less-type-safe
    27 // non-struct type instead
    28 # define JS_NO_JSVAL_JSID_STRUCT_TYPES
    29 
    30 #else
    31 
    32 # define XP_UNIX
    33 
    34 // (See comment in scriptinterface/ScriptTypes.h)
    35 # if defined(DEBUG) && defined(WITH_SYSTEM_MOZJS185)
    36 #  define JS_NO_JSVAL_JSID_STRUCT_TYPES
    37 # endif
    38 
    39 #endif // (we don't support XP_OS2 or XP_BEOS)
    40 
    41 #ifdef __GNUC__
    42 # define GCC_VERSION (__GNUC__*100 + __GNUC_MINOR__)
    43 #else
    44 # define GCC_VERSION 0
    45 #endif
    46 
    47 #ifdef _MSC_VER
    48 # define MSC_VERSION _MSC_VER
    49 #else
    50 # define MSC_VERSION 0
    51 #endif
    52 
    53 // Ignore some harmless warnings triggered by jsapi.h
    54 #if GCC_VERSION >= 402 // (older GCCs don't support this pragma)
    55 # pragma GCC diagnostic ignored "-Wunused-parameter"
    56 # pragma GCC diagnostic ignored "-Wredundant-decls"
    57 #endif
    58 #if MSC_VERSION
    59 # pragma warning(push)
    60 # pragma warning(disable:4480) // "nonstandard extension used: specifying underlying type for enum"
    61 # pragma warning(disable:4100) // "unreferenced formal parameter"
    62 #endif
    63 
    64 #include "js/jsapi.h"
    65 
    66 #if MSC_VERSION
    67 # pragma warning(pop)
    68 #endif
    69 #if GCC_VERSION >= 402
    70 # pragma GCC diagnostic warning "-Wunused-parameter"
    71 # pragma GCC diagnostic warning "-Wredundant-decls"
    72 #endif
    73 
    74 class wxString;
    75 
    76 namespace AtlasMessage { struct mWorldCommand; }
    77 typedef void (*SubmitCommand)(AtlasMessage::mWorldCommand* command);
    78 
    79 struct AtlasScriptInterface_impl;
    80 class ScriptInterface
    81 {
    82 public:
    83     ScriptInterface(SubmitCommand submitCommand);
    84     ~ScriptInterface();
    85     void SetCallbackData(void* cbdata);
    86     static void* GetCallbackData(JSContext* cx);
    87 
    88     template <typename T> bool SetValue(const wxString& name, const T& val);
    89     template <typename T> bool GetValue(const wxString& name, T& ret);
    90 
    91     bool CallFunction(jsval val, const char* name);
    92     template <typename T, typename R>
    93         bool CallFunction(jsval val, const char* name, const T& a, R& ret);
    94     template <typename T, typename S, typename R>
    95         bool CallFunction(jsval val, const char* name, const T& a, const S& b, R& ret);
    96 
    97     bool Eval(const wxString& script);
    98     template <typename T> bool Eval(const wxString& script, T& ret);
    99 
    100     // Defined elsewhere:
    101     //     template <TR, T0..., TR (*fptr) (void* cbdata, T0...)>
    102     //     void RegisterFunction(const char* functionName);
    103     // (NOTE: The return type must be defined as a ToJSVal<TR> specialisation
    104     // in ScriptInterface.cpp, else you'll end up with linker errors.)
    105 
    106     void LoadScript(const wxString& filename, const wxString& code);
    107 
    108     // Convert a jsval to a C++ type. (This might trigger GC.)
    109     template <typename T> static bool FromJSVal(JSContext* cx, jsval val, T& ret);
    110     // Convert a C++ type to a jsval. (This might trigger GC. The return
    111     // value must be rooted if you don't want it to be collected.)
    112     template <typename T> static jsval ToJSVal(JSContext* cx, const T& val);
    113 
    114     bool AddRoot(jsval* ptr);
    115     bool RemoveRoot(jsval* ptr);
    116 
    117     JSContext* GetContext();
    118 
    119 private:
    120     bool SetValue_(const wxString& name, jsval val);
    121     bool GetValue_(const wxString& name, jsval& ret);
    122     bool CallFunction_(jsval val, const char* name, std::vector<jsval>& args, jsval& ret);
    123     bool Eval_(const wxString& name, jsval& ret);
    124 
    125     void Register(const char* name, JSNative fptr, size_t nargs);
    126     std::auto_ptr<AtlasScriptInterface_impl> m;
    127 
    128 // The nasty macro/template bits are split into a separate file so you don't have to look at them
    129 #include "NativeWrapper.inl"
    130 
    131 template <typename T>
    132 bool ScriptInterface::SetValue(const wxString& name, const T& val)
    133 {
    134     return SetValue_(name, ToJSVal(GetContext(), val));
    135 }
    136 
    137 template <typename T>
    138 bool ScriptInterface::GetValue(const wxString& name, T& ret)
    139 {
    140     jsval jsRet;
    141     if (! GetValue_(name, jsRet)) return false;
    142     return FromJSVal(GetContext(), jsRet, ret);
    143 }
    144 
    145 template <typename T, typename R>
    146 bool ScriptInterface::CallFunction(jsval val, const char* name, const T& a, R& ret)
    147 {
    148     jsval jsRet;
    149     std::vector<jsval> argv;
    150     argv.push_back(ToJSVal(GetContext(), a));
    151     bool ok = CallFunction_(val, name, argv, jsRet);
    152     if (! ok) return false;
    153     return FromJSVal(GetContext(), jsRet, ret);
    154 }
    155 
    156 template <typename T, typename S, typename R>
    157 bool ScriptInterface::CallFunction(jsval val, const char* name, const T& a, const S& b, R& ret)
    158 {
    159     jsval jsRet;
    160     std::vector<jsval> argv;
    161     argv.push_back(ToJSVal(GetContext(), a));
    162     argv.push_back(ToJSVal(GetContext(), b));
    163     bool ok = CallFunction_(val, name, argv, jsRet);
    164     if (! ok) return false;
    165     return FromJSVal(GetContext(), jsRet, ret);
    166 }
    167 
    168 template <typename T>
    169 bool ScriptInterface::Eval(const wxString& script, T& ret)
    170 {
    171     jsval jsRet;
    172     if (! Eval_(script, jsRet)) return false;
    173     return FromJSVal(GetContext(), jsRet, ret);
    174 }
    175 
    176 /**
    177  * A trivial wrapper around a jsval. Used to avoid template overload ambiguities
    178  * with jsval (which is just an integer), for any code that uses
    179  * ScriptInterface::ToJSVal or ScriptInterface::FromJSVal
    180  */
    181 class CScriptVal
    182 {
    183 public:
    184     CScriptVal() : m_Val(JSVAL_VOID) { }
    185     CScriptVal(jsval val) : m_Val(val) { }
    186 
    187     jsval get() const { return m_Val; }
    188 
    189 private:
    190     jsval m_Val;
    191 };
  • source/tools/atlas/AtlasUI/Misc/DLLInterface.cpp

     
    2929
    3030#include "GameInterface/MessagePasser.h"
    3131
    32 #include "AtlasScript/ScriptInterface.h"
    33 
    3432#include "wx/config.h"
    3533#include "wx/debugrpt.h"
    3634#include "wx/file.h"
     
    173171    ///ReportError();   // janwas: disabled until ErrorReporter.cpp compiles
    174172}
    175173
    176 void ScenarioEditorSubmitCommand(AtlasMessage::mWorldCommand* command)
    177 {
    178     ScenarioEditor::GetCommandProc().Submit(new WorldCommand(command));
    179 }
    180 
    181174class AtlasDLLApp : public wxApp
    182175{
    183176public:
    184     AtlasDLLApp()
    185     : m_ScriptInterface(NULL)
    186     {
    187     }
    188    
    189     ~AtlasDLLApp()
    190     {
    191         delete m_ScriptInterface;
    192     }
    193177
    194178    virtual bool OnInit()
    195179    {
     
    242226        }
    243227        else if (g_InitialWindowType == _T("ScenarioEditor"))
    244228        {
    245             m_ScriptInterface = new ScriptInterface(&ScenarioEditorSubmitCommand);
    246             frame = new ScenarioEditor(NULL, *m_ScriptInterface);
     229            frame = new ScenarioEditor(NULL);
    247230        }
    248231        else
    249232        {
     
    315298*/
    316299
    317300private:
    318     ScriptInterface* m_ScriptInterface;
    319301
    320302    bool OpenDirectory(const wxString& dir)
    321303    {
  • source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp

     
    4040#include "GameInterface/MessagePasser.h"
    4141#include "GameInterface/Messages.h"
    4242
    43 #include "AtlasScript/ScriptInterface.h"
    44 
    4543#include "Misc/KeyMap.h"
    4644
    4745#include "Tools/Common/Tools.h"
     
    358356static AtlasWindowCommandProc g_CommandProc;
    359357AtlasWindowCommandProc& ScenarioEditor::GetCommandProc() { return g_CommandProc; }
    360358
    361 ScenarioEditor::ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterface)
     359ScenarioEditor::ScenarioEditor(wxWindow* parent)
    362360: wxFrame(parent, wxID_ANY, _T(""), wxDefaultPosition, wxSize(1024, 768))
    363 , m_FileHistory(_T("Scenario Editor")), m_ScriptInterface(scriptInterface)
     361, m_FileHistory(_T("Scenario Editor"))
    364362, m_ObjectSettings(g_SelectedObjects, AtlasMessage::eRenderView::GAME)
    365363, m_ToolManager(this)
    366364{
  • source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.h

     
    2727#include "CustomControls/FileHistory/FileHistory.h"
    2828#include "SectionLayout.h"
    2929
    30 class ScriptInterface;
    31 
    3230class ScenarioEditor : public wxFrame
    3331{
    3432public:
    35     ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterface);
     33    ScenarioEditor(wxWindow* parent);
    3634    void OnClose(wxCloseEvent& event);
    3735    void OnTimer(wxTimerEvent& event);
    3836    void OnIdle(wxIdleEvent& event);
     
    6664
    6765    static float GetSpeedModifier();
    6866
    69     ScriptInterface& GetScriptInterface() const { return m_ScriptInterface; }
    7067    Observable<ObjectSettings>& GetObjectSettings() { return m_ObjectSettings; }
    7168    Observable<AtObj>& GetMapSettings() { return m_MapSettings; }
    7269
     
    7572    void SelectPage(const wxString& classname) { m_SectionLayout.SelectPage(classname); }
    7673
    7774private:
    78     ScriptInterface& m_ScriptInterface;
    7975
    8076    ToolManager m_ToolManager;
    8177
  • source/tools/atlas/AtlasUI/ScenarioEditor/SectionLayout.cpp

     
    2525#include "CustomControls/SnapSplitterWindow/SnapSplitterWindow.h"
    2626
    2727#include "ScenarioEditor.h"
    28 #include "AtlasScript/ScriptInterface.h"
    2928
    3029#include "Sections/Environment/Environment.h"
    3130#include "Sections/Map/Map.h"
  • source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp

     
    2020#include "Map.h"
    2121
    2222#include "AtlasObject/AtlasObject.h"
    23 #include "AtlasScript/ScriptInterface.h"
    2423#include "GameInterface/Messages.h"
    2524#include "ScenarioEditor/ScenarioEditor.h"
    2625#include "ScenarioEditor/Tools/Common/Tools.h"
     
    186185    if (!(*qry.settings).empty())
    187186    {
    188187        // Prevent error if there's no map settings to parse
    189         m_MapSettings = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qry.settings);
     188        m_MapSettings = AtlasObject::LoadFromJSON(*qry.settings);
    190189    }
    191190
    192191    // map name
     
    275274{
    276275    UpdateSettingsObject();
    277276
    278     std::string json = AtlasObject::SaveToJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), m_MapSettings);
     277    std::string json = AtlasObject::SaveToJSON(m_MapSettings);
    279278
    280279    // TODO: would be nice if we supported undo for settings changes
    281280
     
    370369    // Load the map sizes list
    371370    AtlasMessage::qGetMapSizes qrySizes;
    372371    qrySizes.Post();
    373     AtObj sizes = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qrySizes.sizes);
     372    AtObj sizes = AtlasObject::LoadFromJSON(*qrySizes.sizes);
    374373    wxChoice* sizeChoice = wxDynamicCast(FindWindow(ID_RandomSize), wxChoice);
    375374    for (AtIter s = sizes["Sizes"]["item"]; s.defined(); ++s)
    376375    {
     
    388387    scriptChoice->Clear();
    389388    for (size_t i = 0; i < scripts.size(); ++i)
    390389    {
    391         AtObj data = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), scripts[i]);
     390        AtObj data = AtlasObject::LoadFromJSON(scripts[i]);
    392391        wxString name(data["settings"]["Name"]);
    393392        scriptChoice->Append(name, new AtObjClientData(*data["settings"]));
    394393    }
     
    528527
    529528    settings.setInt("Seed", wxAtoi(wxDynamicCast(FindWindow(ID_RandomSeed), wxTextCtrl)->GetValue()));
    530529
    531     std::string json = AtlasObject::SaveToJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), settings);
     530    std::string json = AtlasObject::SaveToJSON(settings);
    532531
    533532    wxBusyInfo busy(_("Generating map"));
    534533    wxBusyCursor busyc;
  • source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/Object.cpp

     
    2424#include "ScenarioEditor/ScenarioEditor.h"
    2525#include "ScenarioEditor/Tools/Common/ObjectSettings.h"
    2626#include "ScenarioEditor/Tools/Common/MiscState.h"
    27 #include "AtlasScript/ScriptInterface.h"
    2827#include "VariationControl.h"
    2928
    3029#include "GameInterface/Messages.h"
     
    479478    wxArrayString players;
    480479    AtlasMessage::qGetPlayerDefaults qryPlayers;
    481480    qryPlayers.Post();
    482     AtObj playerData = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qryPlayers.defaults);
     481    AtObj playerData = AtlasObject::LoadFromJSON(*qryPlayers.defaults);
    483482    AtObj playerDefs = *playerData["PlayerData"];
    484483    for (AtIter p = playerDefs["item"]; p.defined(); ++p)
    485484    {
  • source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Player/Player.cpp

     
    2020#include "Player.h"
    2121
    2222#include "AtlasObject/AtlasObject.h"
    23 #include "AtlasScript/ScriptInterface.h"
    2423#include "CustomControls/ColourDialog/ColourDialog.h"
    2524#include "ScenarioEditor/ScenarioEditor.h"
    2625
     
    591590    std::vector<std::string> civData = *qryCiv.data;
    592591    for (size_t i = 0; i < civData.size(); ++i)
    593592    {
    594         AtObj civ = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), civData[i]);
     593        AtObj civ = AtlasObject::LoadFromJSON(civData[i]);
    595594        civNames.Add(wxString(civ["Name"]));
    596595        civCodes.Add(wxString(civ["Code"]));
    597596    }
     
    600599    ArrayOfAIData ais(AIData::CompareAIData);
    601600    AtlasMessage::qGetAIData qryAI;
    602601    qryAI.Post();
    603     AtObj aiData = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qryAI.data);
     602    AtObj aiData = AtlasObject::LoadFromJSON(*qryAI.data);
    604603    for (AtIter a = aiData["AIData"]["item"]; a.defined(); ++a)
    605604    {
    606605        ais.Add(new AIData(wxString(a["id"]), wxString(a["data"]["name"])));
     
    646645{
    647646    AtlasMessage::qGetPlayerDefaults qryPlayers;
    648647    qryPlayers.Post();
    649     AtObj playerData = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qryPlayers.defaults);
     648    AtObj playerData = AtlasObject::LoadFromJSON(*qryPlayers.defaults);
    650649    m_PlayerDefaults = *playerData["PlayerData"];
    651650}
    652651
     
    658657    if (!(*qry.settings).empty())
    659658    {
    660659        // Prevent error if there's no map settings to parse
    661         m_MapSettings = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qry.settings);
     660        m_MapSettings = AtlasObject::LoadFromJSON(*qry.settings);
    662661    }
    663662    else
    664663    {
     
    946945{
    947946    UpdateSettingsObject();
    948947
    949     std::string json = AtlasObject::SaveToJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), m_MapSettings);
     948    std::string json = AtlasObject::SaveToJSON(m_MapSettings);
    950949
    951950    // TODO: would be nice if we supported undo for settings changes
    952951
  • source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp

     
    2323#include "ScenarioEditor/ScenarioEditor.h"
    2424#include "ScenarioEditor/Tools/Common/Brushes.h"
    2525#include "ScenarioEditor/Tools/Common/MiscState.h"
    26 #include "AtlasScript/ScriptInterface.h"
    2726
    2827#include "GameInterface/Messages.h"
    2928
     
    286285    // Load the map sizes list
    287286    AtlasMessage::qGetMapSizes qrySizes;
    288287    qrySizes.Post();
    289     AtObj sizes = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qrySizes.sizes);
     288    AtObj sizes = AtlasObject::LoadFromJSON(*qrySizes.sizes);
    290289    for (AtIter s = sizes["Sizes"]["item"]; s.defined(); ++s)
    291290    {
    292291        long tiles = 0;