diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/error_macros.h | 5 | ||||
-rw-r--r-- | core/globals.cpp | 12 | ||||
-rw-r--r-- | core/io/resource_format_binary.cpp | 2 | ||||
-rw-r--r-- | core/io/resource_format_xml.cpp | 1 | ||||
-rw-r--r-- | core/object.cpp | 32 | ||||
-rw-r--r-- | core/object.h | 2 | ||||
-rw-r--r-- | core/object_type_db.cpp | 39 | ||||
-rw-r--r-- | core/object_type_db.h | 4 | ||||
-rw-r--r-- | core/os/os.h | 1 | ||||
-rw-r--r-- | core/ring_buffer.h | 6 | ||||
-rw-r--r-- | core/script_language.cpp | 14 | ||||
-rw-r--r-- | core/script_language.h | 3 | ||||
-rw-r--r-- | core/variant.h | 2 | ||||
-rw-r--r-- | core/variant_call.cpp | 15 | ||||
-rw-r--r-- | core/variant_op.cpp | 6 | ||||
-rw-r--r-- | core/variant_parser.cpp | 1495 | ||||
-rw-r--r-- | core/variant_parser.h | 103 | ||||
-rw-r--r-- | core/vector.h | 38 |
18 files changed, 1742 insertions, 38 deletions
diff --git a/core/error_macros.h b/core/error_macros.h index 76da88287b..cc88686301 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -207,6 +207,11 @@ extern bool _err_error_exists; _err_error_exists=false;\ } \ +#define ERR_PRINTS(m_string) \ + { \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data()); \ + _err_error_exists=false;\ + } \ /** Print a warning string. */ diff --git a/core/globals.cpp b/core/globals.cpp index ffd4cf5d5e..aee708d0cd 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -332,6 +332,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) { String candidate = d->get_current_dir(); String current_dir = d->get_current_dir(); + String exec_name = OS::get_singleton()->get_executable_path().get_file().basename(); bool found = false; bool first_time=true; @@ -339,7 +340,16 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) { //try to load settings in ascending through dirs shape! //tries to open pack, but only first time - if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.pcz") )) { + if (first_time && (_load_resource_pack(current_dir+"/"+exec_name+".pck") || _load_resource_pack(current_dir+"/"+exec_name+".pcz") )) { + if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) { + + _load_settings("res://override.cfg"); + found=true; + + + } + break; + } else if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.pcz") )) { if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) { _load_settings("res://override.cfg"); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 1a0552e8d1..4cd3cd595f 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -905,7 +905,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) { error=ERR_FILE_UNRECOGNIZED; ERR_EXPLAIN("Unrecognized binary resource file: "+local_path); - ERR_FAIL_V(); + ERR_FAIL(); } bool big_endian = f->get_32(); diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index 66ae014dbc..48917a19ea 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -1955,7 +1955,6 @@ void ResourceFormatLoaderXML::get_recognized_extensions_for_type(const String& p if (ext=="res") continue; p_extensions->push_back("x"+ext); - p_extensions->push_back(ext); } p_extensions->push_back("xml"); diff --git a/core/object.cpp b/core/object.cpp index 07ac430d7a..96f0c86832 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -314,6 +314,7 @@ void Object::set(const StringName& p_name, const Variant& p_value, bool *r_valid _edited=true; #endif + if (script_instance) { if (script_instance->set(p_name,p_value)) { @@ -326,9 +327,9 @@ void Object::set(const StringName& p_name, const Variant& p_value, bool *r_valid //try built-in setgetter { - if (ObjectTypeDB::set_property(this,p_name,p_value)) { - if (r_valid) - *r_valid=true; + if (ObjectTypeDB::set_property(this,p_name,p_value,r_valid)) { + //if (r_valid) + // *r_valid=true; return; } } @@ -970,7 +971,10 @@ void Object::set_script_instance(ScriptInstance *p_instance) { script_instance=p_instance; - script=p_instance->get_script().get_ref_ptr(); + if (p_instance) + script=p_instance->get_script().get_ref_ptr(); + else + script=RefPtr(); } RefPtr Object::get_script() const { @@ -1691,6 +1695,26 @@ void Object::get_translatable_strings(List<String> *p_strings) const { } +Variant::Type Object::get_static_property_type(const StringName& p_property, bool *r_valid) const { + + bool valid; + Variant::Type t = ObjectTypeDB::get_property_type(get_type_name(),p_property,&valid); + if (valid) { + if (r_valid) + *r_valid=true; + return t; + } + + if (get_script_instance()) { + return get_script_instance()->get_property_type(p_property,r_valid); + } + if (r_valid) + *r_valid=false; + + return Variant::NIL; + +} + bool Object::is_queued_for_deletion() const { return _is_queued_for_deletion; } diff --git a/core/object.h b/core/object.h index 981a83958c..5b6361796f 100644 --- a/core/object.h +++ b/core/object.h @@ -606,6 +606,8 @@ public: void set_block_signals(bool p_block); bool is_blocking_signals() const; + Variant::Type get_static_property_type(const StringName& p_property,bool *r_valid=NULL) const; + virtual void get_translatable_strings(List<String> *p_strings) const; virtual void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index a64b3d2715..f8ba0a9b15 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -612,6 +612,7 @@ void ObjectTypeDB::add_property(StringName p_type,const PropertyInfo& p_pinfo, c psg._setptr=mb_set; psg._getptr=mb_get; psg.index=p_index; + psg.type=p_pinfo.type; type->property_setget[p_pinfo.name]=psg; @@ -634,7 +635,7 @@ void ObjectTypeDB::get_property_list(StringName p_type,List<PropertyInfo> *p_lis } } -bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, const Variant& p_value) { +bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, const Variant& p_value,bool *r_valid) { TypeInfo *type=types.getptr(p_object->get_type_name()); @@ -643,13 +644,17 @@ bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, c const PropertySetGet *psg = check->property_setget.getptr(p_property); if (psg) { - if (!psg->setter) + if (!psg->setter) { + if (r_valid) + *r_valid=false; return true; //return true but do nothing + } + + Variant::CallError ce; if (psg->index>=0) { Variant index=psg->index; const Variant* arg[2]={&index,&p_value}; - Variant::CallError ce; // p_object->call(psg->setter,arg,2,ce); if (psg->_setptr) { psg->_setptr->call(p_object,arg,2,ce); @@ -660,13 +665,16 @@ bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, c } else { const Variant* arg[1]={&p_value}; - Variant::CallError ce; if (psg->_setptr) { psg->_setptr->call(p_object,arg,1,ce); } else { p_object->call(psg->setter,arg,1,ce); } } + + if (r_valid) + *r_valid=ce.error==Variant::CallError::CALL_OK; + return true; } @@ -718,6 +726,29 @@ bool ObjectTypeDB::get_property(Object* p_object,const StringName& p_property, V return false; } +Variant::Type ObjectTypeDB::get_property_type(const StringName& p_type, const StringName& p_property,bool *r_is_valid) { + + TypeInfo *type=types.getptr(p_type); + TypeInfo *check=type; + while(check) { + const PropertySetGet *psg = check->property_setget.getptr(p_property); + if (psg) { + + if (r_is_valid) + *r_is_valid=true; + + return psg->type; + } + + check=check->inherits_ptr; + } + if (r_is_valid) + *r_is_valid=false; + + return Variant::NIL; + +} + void ObjectTypeDB::set_method_flags(StringName p_type,StringName p_method,int p_flags) { diff --git a/core/object_type_db.h b/core/object_type_db.h index bfa0f921e5..319e3ec02c 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -117,6 +117,7 @@ class ObjectTypeDB { StringName getter; MethodBind *_setptr; MethodBind *_getptr; + Variant::Type type; }; struct TypeInfo { @@ -456,8 +457,9 @@ public: static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1); static void get_property_list(StringName p_type,List<PropertyInfo> *p_list,bool p_no_inheritance=false); - static bool set_property(Object* p_object,const StringName& p_property, const Variant& p_value); + static bool set_property(Object* p_object, const StringName& p_property, const Variant& p_value, bool *r_valid=NULL); static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value); + static Variant::Type get_property_type(const StringName& p_type, const StringName& p_property,bool *r_is_valid=NULL); diff --git a/core/os/os.h b/core/os/os.h index e5338b4a02..e908177df7 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -184,6 +184,7 @@ public: virtual void set_low_processor_usage_mode(bool p_enabled); virtual bool is_in_low_processor_usage_mode() const; + virtual String get_installed_templates_path() const { return ""; }; virtual String get_executable_path() const; virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL)=0; virtual Error kill(const ProcessID& p_pid)=0; diff --git a/core/ring_buffer.h b/core/ring_buffer.h index 3cf9cf9064..5cbd261ec8 100644 --- a/core/ring_buffer.h +++ b/core/ring_buffer.h @@ -155,6 +155,12 @@ public: inline int size() { return data.size(); }; + + inline void clear() { + read_pos = 0; + write_pos = 0; + + } void resize(int p_power) { int old_size = size(); diff --git a/core/script_language.cpp b/core/script_language.cpp index 35c50b1022..b7a0f579f4 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -267,6 +267,20 @@ void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properti } } +Variant::Type PlaceHolderScriptInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const { + + if (values.has(p_name)) { + if (r_is_valid) + *r_is_valid=true; + return values[p_name].get_type(); + } + if (r_is_valid) + *r_is_valid=false; + + return Variant::NIL; +} + + void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties,const Map<StringName,Variant>& p_values) { diff --git a/core/script_language.h b/core/script_language.h index 5a0f673b94..9660f141c7 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -82,6 +82,7 @@ public: virtual StringName get_instance_base_type() const=0; // this may not work in all scripts, will return empty if so virtual ScriptInstance* instance_create(Object *p_this)=0; virtual bool instance_has(const Object *p_this) const=0; + virtual bool has_source_code() const=0; virtual String get_source_code() const=0; @@ -109,6 +110,7 @@ public: virtual bool set(const StringName& p_name, const Variant& p_value)=0; virtual bool get(const StringName& p_name, Variant &r_ret) const=0; virtual void get_property_list(List<PropertyInfo> *p_properties) const=0; + virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const=0; virtual void get_method_list(List<MethodInfo> *p_list) const=0; virtual bool has_method(const StringName& p_method) const=0; @@ -208,6 +210,7 @@ public: virtual bool set(const StringName& p_name, const Variant& p_value); virtual bool get(const StringName& p_name, Variant &r_ret) const; virtual void get_property_list(List<PropertyInfo> *p_properties) const; + virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const; virtual void get_method_list(List<MethodInfo> *p_list) const {} virtual bool has_method(const StringName& p_method) const { return false; } diff --git a/core/variant.h b/core/variant.h index 8fd9662c36..e75a2b1c92 100644 --- a/core/variant.h +++ b/core/variant.h @@ -390,7 +390,7 @@ public: Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,CallError &r_error); Variant call(const StringName& p_method,const Variant& p_arg1=Variant(),const Variant& p_arg2=Variant(),const Variant& p_arg3=Variant(),const Variant& p_arg4=Variant(),const Variant& p_arg5=Variant()); - static Variant construct(const Variant::Type,const Variant** p_args,int p_argcount,CallError &r_error); + static Variant construct(const Variant::Type,const Variant** p_args,int p_argcount,CallError &r_error,bool p_strict=true); void get_method_list(List<MethodInfo> *p_list) const; bool has_method(const StringName& p_method) const; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 51d683f1fe..2d10cf4d44 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -858,6 +858,11 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var r_ret=Transform(p_args[0]->operator Matrix3(),p_args[1]->operator Vector3()); } + static void Image_init1(Variant& r_ret, const Variant** p_args) { + + r_ret=Image(*p_args[0],*p_args[1],*p_args[2],Image::Format(p_args[3]->operator int())); + } + static void add_constructor(VariantConstructFunc p_func,const Variant::Type p_type, const String& p_name1="", const Variant::Type p_type1=Variant::NIL, const String& p_name2="", const Variant::Type p_type2=Variant::NIL, @@ -959,7 +964,7 @@ Variant Variant::call(const StringName& p_method,const Variant** p_args,int p_ar #define VCALL(m_type,m_method) _VariantCall::_call_##m_type##_##m_method -Variant Variant::construct(const Variant::Type p_type,const Variant** p_args,int p_argcount,CallError &r_error) { +Variant Variant::construct(const Variant::Type p_type, const Variant** p_args, int p_argcount, CallError &r_error, bool p_strict) { r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; ERR_FAIL_INDEX_V(p_type,VARIANT_MAX,Variant()); @@ -1035,7 +1040,7 @@ Variant Variant::construct(const Variant::Type p_type,const Variant** p_args,int } else if (p_argcount==1 && p_args[0]->type==p_type) { return *p_args[0]; //copy construct - } else if (p_argcount==1 && Variant::can_convert(p_args[0]->type,p_type)) { + } else if (p_argcount==1 && (!p_strict || Variant::can_convert(p_args[0]->type,p_type))) { //near match construct switch(p_type) { @@ -1291,8 +1296,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC1(STRING,STRING,String,pad_decimals,INT,"digits",varray()); ADDFUNC1(STRING,STRING,String,pad_zeros,INT,"digits",varray()); - ADDFUNC0(STRING,STRING,String,to_ascii,varray()); - ADDFUNC0(STRING,STRING,String,to_utf8,varray()); + ADDFUNC0(STRING,RAW_ARRAY,String,to_ascii,varray()); + ADDFUNC0(STRING,RAW_ARRAY,String,to_utf8,varray()); ADDFUNC0(VECTOR2,VECTOR2,Vector2,normalized,varray()); @@ -1583,6 +1588,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl _VariantCall::add_constructor(_VariantCall::Transform_init1,Variant::TRANSFORM,"x_axis",Variant::VECTOR3,"y_axis",Variant::VECTOR3,"z_axis",Variant::VECTOR3,"origin",Variant::VECTOR3); _VariantCall::add_constructor(_VariantCall::Transform_init2,Variant::TRANSFORM,"basis",Variant::MATRIX3,"origin",Variant::VECTOR3); + _VariantCall::add_constructor(_VariantCall::Image_init1,Variant::IMAGE,"width",Variant::INT,"height",Variant::INT,"mipmaps",Variant::BOOL,"format",Variant::INT); + /* REGISTER CONSTANTS */ _VariantCall::constant_data[Variant::VECTOR3].value["AXIS_X"]=Vector3::AXIS_X; diff --git a/core/variant_op.cpp b/core/variant_op.cpp index eabd647837..1bcfa7d2ae 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -2818,9 +2818,9 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { } break; case MATRIX32: { - p_list->push_back( PropertyInfo(Variant::REAL,"x")); - p_list->push_back( PropertyInfo(Variant::REAL,"y")); - p_list->push_back( PropertyInfo(Variant::REAL,"o")); + p_list->push_back( PropertyInfo(Variant::VECTOR2,"x")); + p_list->push_back( PropertyInfo(Variant::VECTOR2,"y")); + p_list->push_back( PropertyInfo(Variant::VECTOR2,"o")); } break; case PLANE: { diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp new file mode 100644 index 0000000000..fed8c28740 --- /dev/null +++ b/core/variant_parser.cpp @@ -0,0 +1,1495 @@ +#include "variant_parser.h" +#include "io/resource_loader.h" +#include "os/keyboard.h" + + + +CharType VariantParser::StreamFile::get_char() { + + return f->get_8(); +} + +bool VariantParser::StreamFile::is_utf8() const { + + return true; +} +bool VariantParser::StreamFile::is_eof() const { + + return f->eof_reached(); +} + + + + +///////////////////////////////////////////////////////////////////////////////////////////////// + + + +const char * VariantParser::tk_name[TK_MAX] = { + "'{'", + "'}'", + "'['", + "']'", + "'('", + "')'", + "identifier", + "string", + "number", + "':'", + "','", + "'='", + "EOF", + "ERROR" +}; + + + +Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, String &r_err_str) { + + while (true) { + + CharType cchar; + if (p_stream->saved) { + cchar=p_stream->saved; + p_stream->saved=0; + } else { + cchar=p_stream->get_char(); + if (p_stream->is_eof()) { + r_token.type=TK_EOF; + return OK; + } + } + + switch(cchar) { + + case '\n': { + + line++; + break; + }; + case 0: { + r_token.type=TK_EOF; + return OK; + } break; + case '{': { + + r_token.type=TK_CURLY_BRACKET_OPEN; + return OK; + }; + case '}': { + + r_token.type=TK_CURLY_BRACKET_CLOSE; + return OK; + }; + case '[': { + + r_token.type=TK_BRACKET_OPEN; + return OK; + }; + case ']': { + + r_token.type=TK_BRACKET_CLOSE; + return OK; + }; + case '(': { + + r_token.type=TK_PARENTHESIS_OPEN; + return OK; + }; + case ')': { + + r_token.type=TK_PARENTHESIS_CLOSE; + return OK; + }; + case ':': { + + r_token.type=TK_COLON; + return OK; + }; + case ',': { + + r_token.type=TK_COMMA; + return OK; + }; + case '=': { + + r_token.type=TK_EQUAL; + return OK; + }; + case '"': { + + + String str; + while(true) { + + CharType ch=p_stream->get_char(); + + if (ch==0) { + r_err_str="Unterminated String"; + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } else if (ch=='"') { + break; + } else if (ch=='\\') { + //escaped characters... + CharType next = p_stream->get_char(); + if (next==0) { + r_err_str="Unterminated String"; + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + CharType res=0; + + switch(next) { + + case 'b': res=8; break; + case 't': res=9; break; + case 'n': res=10; break; + case 'f': res=12; break; + case 'r': res=13; break; + case 'u': { + //hexnumbarh - oct is deprecated + + + for(int j=0;j<4;j++) { + CharType c = p_stream->get_char(); + if (c==0) { + r_err_str="Unterminated String"; + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) { + + r_err_str="Malformed hex constant in string"; + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + CharType v; + if (c>='0' && c<='9') { + v=c-'0'; + } else if (c>='a' && c<='f') { + v=c-'a'; + v+=10; + } else if (c>='A' && c<='F') { + v=c-'A'; + v+=10; + } else { + ERR_PRINT("BUG"); + v=0; + } + + res<<=4; + res|=v; + + + } + + + + } break; + //case '\"': res='\"'; break; + //case '\\': res='\\'; break; + //case '/': res='/'; break; + default: { + res = next; + //r_err_str="Invalid escape sequence"; + //return ERR_PARSE_ERROR; + } break; + } + + str+=res; + + } else { + if (ch=='\n') + line++; + str+=ch; + } + } + + if (p_stream->is_utf8()) { + str.parse_utf8( str.ascii(true).get_data() ); + } + r_token.type=TK_STRING; + r_token.value=str; + return OK; + + } break; + default: { + + if (cchar<=32) { + break; + } + + if (cchar=='-' || (cchar>='0' && cchar<='9')) { + //a number + + + String num; +#define READING_SIGN 0 +#define READING_INT 1 +#define READING_DEC 2 +#define READING_EXP 3 +#define READING_DONE 4 + int reading=READING_INT; + + if (cchar=='-') { + num+='-'; + cchar=p_stream->get_char(); + + } + + + + CharType c = cchar; + bool exp_sign=false; + bool exp_beg=false; + bool is_float=false; + + while(true) { + + switch(reading) { + case READING_INT: { + + if (c>='0' && c<='9') { + //pass + } else if (c=='.') { + reading=READING_DEC; + is_float=true; + } else if (c=='e') { + reading=READING_EXP; + } else { + reading=READING_DONE; + } + + } break; + case READING_DEC: { + + if (c>='0' && c<='9') { + + } else if (c=='e') { + reading=READING_EXP; + + } else { + reading=READING_DONE; + } + + } break; + case READING_EXP: { + + if (c>='0' && c<='9') { + exp_beg=true; + + } else if ((c=='-' || c=='+') && !exp_sign && !exp_beg) { + exp_sign=true; + + } else { + reading=READING_DONE; + } + } break; + } + + if (reading==READING_DONE) + break; + num+=String::chr(c); + c = p_stream->get_char(); + + + } + + p_stream->saved=c; + + + r_token.type=TK_NUMBER; + if (is_float) + r_token.value=num.to_double(); + else + r_token.value=num.to_int(); + return OK; + + } else if ((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_') { + + String id; + bool first=true; + + while((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_' || (!first && cchar>='0' && cchar<='9')) { + + id+=String::chr(cchar); + cchar=p_stream->get_char(); + first=false; + } + + p_stream->saved=cchar; + + r_token.type=TK_IDENTIFIER; + r_token.value=id; + return OK; + } else { + r_err_str="Unexpected character."; + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + } + } + } + + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; +} + +template<class T> +Error VariantParser::_parse_construct(Stream *p_stream,Vector<T>& r_construct,int &line,String &r_err_str) { + + + Token token; + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_OPEN) { + r_err_str="Expected '(' in constructor"; + return ERR_PARSE_ERROR; + } + + + bool first=true; + while(true) { + + if (!first) { + get_token(p_stream,token,line,r_err_str); + if (token.type==TK_COMMA) { + //do none + } else if (token.type==TK_PARENTHESIS_CLOSE) { + break; + } else { + r_err_str="Expected ',' or ')' in constructor"; + return ERR_PARSE_ERROR; + + } + } + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_NUMBER) { + r_err_str="Expected float in constructor"; + return ERR_PARSE_ERROR; + } + + + r_construct.push_back(token.value); + first=false; + } + + return OK; + +} + +Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,int &line,String &r_err_str,ResourceParser *p_res_parser) { + + + +/* { + Error err = get_token(p_stream,token,line,r_err_str); + if (err) + return err; + }*/ + + + if (token.type==TK_CURLY_BRACKET_OPEN) { + + Dictionary d; + Error err = _parse_dictionary(d,p_stream,line,r_err_str,p_res_parser); + if (err) + return err; + value=d; + return OK; + } else if (token.type==TK_BRACKET_OPEN) { + + Array a; + Error err = _parse_array(a,p_stream,line,r_err_str,p_res_parser); + if (err) + return err; + value=a; + return OK; + + } else if (token.type==TK_IDENTIFIER) { +/* + VECTOR2, // 5 + RECT2, + VECTOR3, + MATRIX32, + PLANE, + QUAT, // 10 + _AABB, //sorry naming convention fail :( not like it's used often + MATRIX3, + TRANSFORM, + + // misc types + COLOR, + IMAGE, // 15 + NODE_PATH, + _RID, + OBJECT, + INPUT_EVENT, + DICTIONARY, // 20 + ARRAY, + + // arrays + RAW_ARRAY, + INT_ARRAY, + REAL_ARRAY, + STRING_ARRAY, // 25 + VECTOR2_ARRAY, + VECTOR3_ARRAY, + COLOR_ARRAY, + + VARIANT_MAX + +*/ + String id = token.value; + if (id=="true") + value=true; + else if (id=="false") + value=false; + else if (id=="null") + value=Variant(); + else if (id=="Vector2"){ + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=2) { + r_err_str="Expected 2 arguments for constructor"; + } + + value=Vector2(args[0],args[1]); + return OK; + } else if (id=="Vector3"){ + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=3) { + r_err_str="Expected 3 arguments for constructor"; + } + + value=Vector3(args[0],args[1],args[2]); + return OK; + } else if (id=="Matrix32"){ + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=6) { + r_err_str="Expected 6 arguments for constructor"; + } + Matrix32 m; + m[0]=Vector2(args[0],args[1]); + m[1]=Vector2(args[2],args[3]); + m[2]=Vector2(args[4],args[5]); + value=m; + return OK; + } else if (id=="Plane") { + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=4) { + r_err_str="Expected 4 arguments for constructor"; + } + + value=Plane(args[0],args[1],args[2],args[3]); + return OK; + } else if (id=="Quat") { + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=4) { + r_err_str="Expected 4 arguments for constructor"; + } + + value=Quat(args[0],args[1],args[2],args[3]); + return OK; + + } else if (id=="AABB"){ + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=6) { + r_err_str="Expected 6 arguments for constructor"; + } + + value=AABB(Vector3(args[0],args[1],args[2]),Vector3(args[3],args[4],args[5])); + return OK; + + } else if (id=="Matrix3"){ + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=9) { + r_err_str="Expected 9 arguments for constructor"; + } + + value=Matrix3(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); + return OK; + } else if (id=="Transform"){ + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=12) { + r_err_str="Expected 12 arguments for constructor"; + } + + value=Transform(Matrix3(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]),Vector3(args[9],args[10],args[11])); + return OK; + + } else if (id=="Color") { + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + if (args.size()!=4) { + r_err_str="Expected 4 arguments for constructor"; + } + + value=Color(args[0],args[1],args[2],args[3]); + return OK; + + } else if (id=="Image") { + + //:| + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_OPEN) { + r_err_str="Expected '('"; + return ERR_PARSE_ERROR; + } + + + get_token(p_stream,token,line,r_err_str); + if (token.type==TK_PARENTHESIS_CLOSE) { + value=Image(); // just an Image() + return OK; + } else if (token.type!=TK_NUMBER) { + r_err_str="Expected number (width)"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + + int width=token.value; + if (token.type!=TK_COMMA) { + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_NUMBER) { + r_err_str="Expected number (height)"; + return ERR_PARSE_ERROR; + } + + int height=token.value; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_COMMA) { + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_NUMBER) { + r_err_str="Expected number (mipmaps)"; + return ERR_PARSE_ERROR; + } + + int mipmaps=token.value; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_COMMA) { + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } + + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_IDENTIFIER) { + r_err_str="Expected identifier (format)"; + return ERR_PARSE_ERROR; + } + + + String sformat=token.value; + + Image::Format format; + + if (sformat=="GRAYSCALE") format=Image::FORMAT_GRAYSCALE; + else if (sformat=="INTENSITY") format=Image::FORMAT_INTENSITY; + else if (sformat=="GRAYSCALE_ALPHA") format=Image::FORMAT_GRAYSCALE_ALPHA; + else if (sformat=="RGB") format=Image::FORMAT_RGB; + else if (sformat=="RGBA") format=Image::FORMAT_RGBA; + else if (sformat=="INDEXED") format=Image::FORMAT_INDEXED; + else if (sformat=="INDEXED_ALPHA") format=Image::FORMAT_INDEXED_ALPHA; + else if (sformat=="BC1") format=Image::FORMAT_BC1; + else if (sformat=="BC2") format=Image::FORMAT_BC2; + else if (sformat=="BC3") format=Image::FORMAT_BC3; + else if (sformat=="BC4") format=Image::FORMAT_BC4; + else if (sformat=="BC5") format=Image::FORMAT_BC5; + else if (sformat=="PVRTC2") format=Image::FORMAT_PVRTC2; + else if (sformat=="PVRTC2_ALPHA") format=Image::FORMAT_PVRTC2_ALPHA; + else if (sformat=="PVRTC4") format=Image::FORMAT_PVRTC4; + else if (sformat=="PVRTC4_ALPHA") format=Image::FORMAT_PVRTC4_ALPHA; + else if (sformat=="ATC") format=Image::FORMAT_ATC; + else if (sformat=="ATC_ALPHA_EXPLICIT") format=Image::FORMAT_ATC_ALPHA_EXPLICIT; + else if (sformat=="ATC_ALPHA_INTERPOLATED") format=Image::FORMAT_ATC_ALPHA_INTERPOLATED; + else if (sformat=="CUSTOM") format=Image::FORMAT_CUSTOM; + else { + r_err_str="Invalid image format: '"+sformat+"'"; + return ERR_PARSE_ERROR; + }; + + int len = Image::get_image_data_size(width,height,format,mipmaps); + + DVector<uint8_t> buffer; + buffer.resize(len); + + if (buffer.size()!=len) { + r_err_str="Couldn't allocate image buffer of size: "+itos(len); + } + + { + DVector<uint8_t>::Write w=buffer.write(); + + for(int i=0;i<len;i++) { + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_COMMA) { + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_NUMBER) { + r_err_str="Expected number"; + return ERR_PARSE_ERROR; + } + + w[i]=int(token.value); + + } + } + + + Image img(width,height,mipmaps,format,buffer); + + value=img; + + return OK; + + + } else if (id=="NodePath") { + + + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_OPEN) { + r_err_str="Expected '('"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_STRING) { + r_err_str="Expected string as argument for NodePath()"; + return ERR_PARSE_ERROR; + } + + value=NodePath(String(token.value)); + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + } else if (id=="RID") { + + + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_OPEN) { + r_err_str="Expected '('"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_NUMBER) { + r_err_str="Expected number as argument"; + return ERR_PARSE_ERROR; + } + + value=token.value; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + + return OK; + + } else if (id=="Resource" || id=="SubResource" || id=="ExtResource") { + + + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_OPEN) { + r_err_str="Expected '('"; + return ERR_PARSE_ERROR; + } + + + if (p_res_parser && id=="Resource" && p_res_parser->func){ + + RES res; + Error err = p_res_parser->func(p_res_parser->userdata,p_stream,res,line,r_err_str); + if (err) + return err; + + value=res; + + return OK; + } else if (p_res_parser && id=="ExtResource" && p_res_parser->ext_func){ + + RES res; + Error err = p_res_parser->ext_func(p_res_parser->userdata,p_stream,res,line,r_err_str); + if (err) + return err; + + value=res; + + return OK; + } else if (p_res_parser && id=="SubResource" && p_res_parser->sub_func){ + + RES res; + Error err = p_res_parser->sub_func(p_res_parser->userdata,p_stream,res,line,r_err_str); + if (err) + return err; + + value=res; + + return OK; + } else { + + get_token(p_stream,token,line,r_err_str); + if (token.type==TK_STRING) { + String path=token.value; + RES res = ResourceLoader::load(path); + if (res.is_null()) { + r_err_str="Can't load resource at path: '"+path+"'."; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + value=res; + return OK; + + } else { + r_err_str="Expected string as argument for Resource()."; + return ERR_PARSE_ERROR; + } + } + + return OK; + + + } else if (id=="InputEvent") { + + + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_OPEN) { + r_err_str="Expected '('"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + + if (token.type!=TK_IDENTIFIER) { + r_err_str="Expected identifier"; + return ERR_PARSE_ERROR; + } + + + String id = token.value; + + InputEvent ie; + + if (id=="KEY") { + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_COMMA) { + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } + + ie.type=InputEvent::KEY; + + + get_token(p_stream,token,line,r_err_str); + if (token.type==TK_IDENTIFIER) { + String name=token.value; + ie.key.scancode=find_keycode(name); + } else if (token.type==TK_NUMBER) { + + ie.key.scancode=token.value; + } else { + + r_err_str="Expected string or integer for keycode"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + + if (token.type==TK_COMMA) { + + get_token(p_stream,token,line,r_err_str); + + if (token.type!=TK_IDENTIFIER) { + r_err_str="Expected identifier with modifier flas"; + return ERR_PARSE_ERROR; + } + + String mods=token.value; + + if (mods.findn("C")!=-1) + ie.key.mod.control=true; + if (mods.findn("A")!=-1) + ie.key.mod.alt=true; + if (mods.findn("S")!=-1) + ie.key.mod.shift=true; + if (mods.findn("M")!=-1) + ie.key.mod.meta=true; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + } else if (token.type!=TK_PARENTHESIS_CLOSE) { + + r_err_str="Expected ')' or modifier flags."; + return ERR_PARSE_ERROR; + } + + + } else if (id=="MBUTTON") { + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_COMMA) { + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } + + ie.type=InputEvent::MOUSE_BUTTON; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_NUMBER) { + r_err_str="Expected button index"; + return ERR_PARSE_ERROR; + } + + ie.mouse_button.button_index = token.value; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + } else if (id=="JBUTTON") { + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_COMMA) { + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } + + ie.type=InputEvent::JOYSTICK_BUTTON; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_NUMBER) { + r_err_str="Expected button index"; + return ERR_PARSE_ERROR; + } + + ie.joy_button.button_index = token.value; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + } else if (id=="JAXIS") { + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_COMMA) { + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } + + ie.type=InputEvent::JOYSTICK_MOTION; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_NUMBER) { + r_err_str="Expected axis index"; + return ERR_PARSE_ERROR; + } + + ie.joy_motion.axis = token.value; + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + } else { + + r_err_str="Invalid input event type."; + return ERR_PARSE_ERROR; + } + + value=ie; + + return OK; + + } else if (id=="ByteArray") { + + Vector<uint8_t> args; + Error err = _parse_construct<uint8_t>(p_stream,args,line,r_err_str); + if (err) + return err; + + DVector<uint8_t> arr; + { + int len=args.size(); + arr.resize(len); + DVector<uint8_t>::Write w = arr.write(); + for(int i=0;i<len;i++) { + w[i]=args[i]; + } + } + + value=arr; + + return OK; + + } else if (id=="IntArray") { + + Vector<int32_t> args; + Error err = _parse_construct<int32_t>(p_stream,args,line,r_err_str); + if (err) + return err; + + DVector<int32_t> arr; + { + int len=args.size(); + arr.resize(len); + DVector<int32_t>::Write w = arr.write(); + for(int i=0;i<len;i++) { + w[i]=int(args[i]); + } + } + + value=arr; + + return OK; + + } else if (id=="FloatArray") { + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + DVector<float> arr; + { + int len=args.size(); + arr.resize(len); + DVector<float>::Write w = arr.write(); + for(int i=0;i<len;i++) { + w[i]=args[i]; + } + } + + value=arr; + + return OK; + } else if (id=="StringArray") { + + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_OPEN) { + r_err_str="Expected '('"; + return ERR_PARSE_ERROR; + } + + Vector<String> cs; + + bool first=true; + while(true) { + + if (!first) { + get_token(p_stream,token,line,r_err_str); + if (token.type==TK_COMMA) { + //do none + } else if (token.type!=TK_PARENTHESIS_CLOSE) { + break; + } else { + r_err_str="Expected ',' or ')'"; + return ERR_PARSE_ERROR; + + } + } + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_STRING) { + r_err_str="Expected string"; + return ERR_PARSE_ERROR; + } + + cs.push_back(token.value); + } + + + DVector<String> arr; + { + int len=cs.size(); + arr.resize(len); + DVector<String>::Write w = arr.write(); + for(int i=0;i<len;i++) { + w[i]=cs[i]; + } + } + + value=arr; + + return OK; + + + } else if (id=="Vector2Array") { + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + DVector<Vector2> arr; + { + int len=args.size()/2; + arr.resize(len); + DVector<Vector2>::Write w = arr.write(); + for(int i=0;i<len;i++) { + w[i]=Vector2(args[i*2+0],args[i*2+1]); + } + } + + value=arr; + + return OK; + + } else if (id=="Vector3Array") { + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + DVector<Vector3> arr; + { + int len=args.size()/3; + arr.resize(len); + DVector<Vector3>::Write w = arr.write(); + for(int i=0;i<len;i++) { + w[i]=Vector3(args[i*3+0],args[i*3+1],args[i*3+2]); + } + } + + value=arr; + + return OK; + + } else if (id=="ColorArray") { + + Vector<float> args; + Error err = _parse_construct<float>(p_stream,args,line,r_err_str); + if (err) + return err; + + DVector<Color> arr; + { + int len=args.size()/4; + arr.resize(len); + DVector<Color>::Write w = arr.write(); + for(int i=0;i<len;i++) { + w[i]=Color(args[i*3+0],args[i*3+1],args[i*3+2],args[i*3+3]); + } + } + + value=arr; + + return OK; + + } else { + r_err_str="Unexpected identifier: '"+id+"'."; + return ERR_PARSE_ERROR; + } + + + /* + VECTOR2, // 5 + RECT2, + VECTOR3, + MATRIX32, + PLANE, + QUAT, // 10 + _AABB, //sorry naming convention fail :( not like it's used often + MATRIX3, + TRANSFORM, + + // misc types + COLOR, + IMAGE, // 15 + NODE_PATH, + _RID, + OBJECT, + INPUT_EVENT, + DICTIONARY, // 20 + ARRAY, + + // arrays + RAW_ARRAY, + INT_ARRAY, + REAL_ARRAY, + STRING_ARRAY, // 25 + VECTOR2_ARRAY, + VECTOR3_ARRAY, + COLOR_ARRAY, + + VARIANT_MAX + + */ + + return OK; + + } else if (token.type==TK_NUMBER) { + + value=token.value; + return OK; + } else if (token.type==TK_STRING) { + + value=token.value; + return OK; + } else { + r_err_str="Expected value, got "+String(tk_name[token.type])+"."; + return ERR_PARSE_ERROR; + } + + return ERR_PARSE_ERROR; +} + + +Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { + + Token token; + bool need_comma=false; + + + while(true) { + + if (p_stream->is_eof()) { + r_err_str="Unexpected End of File while parsing array"; + return ERR_FILE_CORRUPT; + } + + Error err = get_token(p_stream,token,line,r_err_str); + if (err!=OK) + return err; + + if (token.type==TK_BRACKET_CLOSE) { + + return OK; + } + + if (need_comma) { + + if (token.type!=TK_COMMA) { + + r_err_str="Expected ','"; + return ERR_PARSE_ERROR; + } else { + need_comma=false; + continue; + } + } + + Variant v; + err = parse_value(token,v,p_stream,line,r_err_str,p_res_parser); + if (err) + return err; + + array.push_back(v); + need_comma=true; + + } + + return OK; + +} + +Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { + + bool at_key=true; + Variant key; + Token token; + bool need_comma=false; + + + while(true) { + + + if (p_stream->is_eof()) { + r_err_str="Unexpected End of File while parsing dictionary"; + return ERR_FILE_CORRUPT; + } + + if (at_key) { + + Error err = get_token(p_stream,token,line,r_err_str); + if (err!=OK) + return err; + + if (token.type==TK_CURLY_BRACKET_CLOSE) { + + return OK; + } + + if (need_comma) { + + if (token.type!=TK_COMMA) { + + r_err_str="Expected '}' or ','"; + return ERR_PARSE_ERROR; + } else { + need_comma=false; + continue; + } + } + + + + + err = parse_value(token,key,p_stream,line,r_err_str,p_res_parser); + + if (err) + return err; + + err = get_token(p_stream,token,line,r_err_str); + + if (err!=OK) + return err; + if (token.type!=TK_COLON) { + + r_err_str="Expected ':'"; + return ERR_PARSE_ERROR; + } + at_key=false; + } else { + + + Error err = get_token(p_stream,token,line,r_err_str); + if (err!=OK) + return err; + + Variant v; + err = parse_value(token,v,p_stream,line,r_err_str,p_res_parser); + if (err) + return err; + object[key]=v; + need_comma=true; + at_key=true; + } + } + + return OK; +} + + +Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, ResourceParser *p_res_parser) { + + r_tag.fields.clear(); + + if (token.type!=TK_BRACKET_OPEN) { + r_err_str="Expected '['"; + return ERR_PARSE_ERROR; + } + + + get_token(p_stream,token,line,r_err_str); + + + if (token.type!=TK_IDENTIFIER) { + r_err_str="Expected identifier (tag name)"; + return ERR_PARSE_ERROR; + } + + r_tag.name=token.value; + + while(true) { + + if (p_stream->is_eof()) { + r_err_str="Unexpected End of File while parsing tag: "+r_tag.name; + return ERR_FILE_CORRUPT; + } + + get_token(p_stream,token,line,r_err_str); + if (token.type==TK_BRACKET_CLOSE) + break; + + if (token.type!=TK_IDENTIFIER) { + r_err_str="Expected Identifier"; + return ERR_PARSE_ERROR; + } + + String id=token.value; + + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_EQUAL) { + r_err_str="Expected '='"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + Variant value; + Error err = parse_value(token,value,p_stream,line,r_err_str,p_res_parser); + if (err) + return err; + + r_tag.fields[id]=value; + + } + + + return OK; + +} + +Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, ResourceParser *p_res_parser) { + + Token token; + get_token(p_stream,token,line,r_err_str); + + if (token.type==TK_EOF) { + return ERR_FILE_EOF; + } + + if (token.type!=TK_BRACKET_OPEN) { + r_err_str="Expected '['"; + return ERR_PARSE_ERROR; + } + + return _parse_tag(token,p_stream,line,r_err_str,r_tag,p_res_parser); + +} + +Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser) { + + + //assign.. + String what; + + while(true) { + + + CharType c; + if (p_stream->saved) { + c=p_stream->saved; + p_stream->saved=0; + + } else { + c=p_stream->get_char(); + } + + if (p_stream->is_eof()) + return ERR_FILE_EOF; + + if (c=='[' && what.length()==0) { + //it's a tag! + p_stream->saved='['; //go back one + + Error err = parse_tag(p_stream,line,r_err_str,r_tag,p_res_parser); + + return err; + } + + if (c>32) { + if (c!='=') { + what+=String::chr(c); + } else { + r_assign=what; + Token token; + get_token(p_stream,token,line,r_err_str); + Error err = parse_value(token,r_value,p_stream,line,r_err_str,p_res_parser); + if (err) { + + } + return err; + } + } else if (c=='\n') { + line++; + } + } + + return OK; +} + +Error VariantParser::parse(Stream *p_stream, Variant& r_ret, String &r_err_str, int &r_err_line, ResourceParser *p_res_parser) { + + + Token token; + Error err = get_token(p_stream,token,r_err_line,r_err_str); + if (err) + return err; + + if (token.type==TK_EOF) { + return ERR_FILE_EOF; + } + + return parse_value(token,r_ret,p_stream,r_err_line,r_err_str,p_res_parser); + +} + + diff --git a/core/variant_parser.h b/core/variant_parser.h new file mode 100644 index 0000000000..e1d25f7512 --- /dev/null +++ b/core/variant_parser.h @@ -0,0 +1,103 @@ +#ifndef VARIANT_PARSER_H +#define VARIANT_PARSER_H + +#include "variant.h" +#include "os/file_access.h" +#include "resource.h" + +class VariantParser { +public: + + struct Stream { + + virtual CharType get_char()=0; + virtual bool is_utf8() const=0; + virtual bool is_eof() const=0; + + CharType saved; + + Stream() { saved=0; } + virtual ~Stream() {} + }; + + struct StreamFile : public Stream { + + FileAccess *f; + + virtual CharType get_char(); + virtual bool is_utf8() const; + virtual bool is_eof() const; + + StreamFile() { f=NULL; } + + }; + + typedef Error (*ParseResourceFunc)(void* p_self, Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str); + + struct ResourceParser { + + void *userdata; + ParseResourceFunc func; + ParseResourceFunc ext_func; + ParseResourceFunc sub_func; + + }; + + enum TokenType { + TK_CURLY_BRACKET_OPEN, + TK_CURLY_BRACKET_CLOSE, + TK_BRACKET_OPEN, + TK_BRACKET_CLOSE, + TK_PARENTHESIS_OPEN, + TK_PARENTHESIS_CLOSE, + TK_IDENTIFIER, + TK_STRING, + TK_NUMBER, + TK_COLON, + TK_COMMA, + TK_EQUAL, + TK_EOF, + TK_ERROR, + TK_MAX + }; + + enum Expecting { + + EXPECT_OBJECT, + EXPECT_OBJECT_KEY, + EXPECT_COLON, + EXPECT_OBJECT_VALUE, + }; + + struct Token { + + TokenType type; + Variant value; + }; + + struct Tag { + + String name; + Map<String,Variant> fields; + }; + +private: + static const char * tk_name[TK_MAX]; + + template<class T> + static Error _parse_construct(Stream *p_stream, Vector<T>& r_construct, int &line, String &r_err_str); + static Error _parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL); + static Error _parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL); + static Error _parse_tag(Token& token,Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,ResourceParser *p_res_parser=NULL); + +public: + + static Error parse_tag(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,ResourceParser *p_res_parser=NULL); + static Error parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, String &r_assign, Variant &r_value,ResourceParser *p_res_parser=NULL); + + static Error parse_value(Token& token,Variant &value, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL); + static Error get_token(Stream *p_stream,Token& r_token,int &line,String &r_err_str); + static Error parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line,ResourceParser *p_res_parser=NULL); +}; + +#endif // VARIANT_PARSER_H diff --git a/core/vector.h b/core/vector.h index d103400622..78dff5eadb 100644 --- a/core/vector.h +++ b/core/vector.h @@ -42,7 +42,7 @@ template<class T> class Vector { - mutable void* _ptr; + mutable T* _ptr; // internal helpers @@ -51,21 +51,21 @@ class Vector { if (!_ptr) return NULL; - return reinterpret_cast<SafeRefCount*>(_ptr); + return reinterpret_cast<SafeRefCount*>((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount)); } _FORCE_INLINE_ int* _get_size() const { if (!_ptr) return NULL; - return reinterpret_cast<int*>(((uint8_t*)(_ptr))+sizeof(SafeRefCount)); + return reinterpret_cast<int*>((uint8_t*)_ptr-sizeof(int)); } _FORCE_INLINE_ T* _get_data() const { if (!_ptr) return NULL; - return reinterpret_cast<T*>(((uint8_t*)(_ptr))+sizeof(SafeRefCount)+sizeof(int)); + return reinterpret_cast<T*>(_ptr); } @@ -88,11 +88,11 @@ public: _FORCE_INLINE_ void clear() { resize(0); } _FORCE_INLINE_ int size() const { - - if (!_ptr) - return 0; + int* size = _get_size(); + if (size) + return *size; else - return *reinterpret_cast<int*>(((uint8_t*)(_ptr))+sizeof(SafeRefCount)); + return 0; } _FORCE_INLINE_ bool empty() const { return _ptr == 0; } Error resize(int p_size); @@ -174,7 +174,7 @@ void Vector<T>::_unref(void *p_data) { if (!p_data) return; - SafeRefCount *src = reinterpret_cast<SafeRefCount*>(p_data); + SafeRefCount *src = reinterpret_cast<SafeRefCount*>((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount)); if (!src->unref()) return; // still in use @@ -189,7 +189,7 @@ void Vector<T>::_unref(void *p_data) { } // free mem - memfree(p_data); + memfree((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount)); } @@ -201,7 +201,8 @@ void Vector<T>::_copy_on_write() { if (_get_refcount()->get() > 1 ) { /* in use by more than me */ - SafeRefCount *src_new=(SafeRefCount *)memalloc(_get_alloc_size(*_get_size())); + void* mem_new = memalloc(_get_alloc_size(*_get_size())); + SafeRefCount *src_new=(SafeRefCount *)mem_new; src_new->init(); int * _size = (int*)(src_new+1); *_size=*_get_size(); @@ -215,7 +216,7 @@ void Vector<T>::_copy_on_write() { } _unref(_ptr); - _ptr=src_new; + _ptr=_data; } } @@ -260,16 +261,17 @@ Error Vector<T>::resize(int p_size) { if (size()==0) { // alloc from scratch - _ptr = (T*)memalloc(_get_alloc_size(p_size)); - ERR_FAIL_COND_V( !_ptr ,ERR_OUT_OF_MEMORY); + void* ptr=memalloc(_get_alloc_size(p_size)); + ERR_FAIL_COND_V( !ptr ,ERR_OUT_OF_MEMORY); + _ptr=(T*)((uint8_t*)ptr+sizeof(int)+sizeof(SafeRefCount)); _get_refcount()->init(); // init refcount *_get_size()=0; // init size (currently, none) } else { - void *_ptrnew = (T*)memrealloc(_ptr,_get_alloc_size(p_size)); + void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount),_get_alloc_size(p_size)); ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY); - _ptr=_ptrnew; + _ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount)); } // construct the newly created elements @@ -291,10 +293,10 @@ Error Vector<T>::resize(int p_size) { t->~T(); } - void *_ptrnew = (T*)memrealloc(_ptr,_get_alloc_size(p_size)); + void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount),_get_alloc_size(p_size)); ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY); - _ptr=_ptrnew; + _ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount)); *_get_size()=p_size; |