From 8b912d11152410302f45eaa117c19b7016d781f5 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 8 Jan 2017 02:04:53 -0300 Subject: [PATCH] -Fix bugs related to PoolVector crashes -Added ability to request nodes using $Name in GDScript :) --- core/dvector.h | 38 ++++++++++++-- modules/gdscript/gd_parser.cpp | 86 +++++++++++++++++++++++++++++++ modules/gdscript/gd_parser.h | 1 + modules/gdscript/gd_tokenizer.cpp | 3 ++ modules/gdscript/gd_tokenizer.h | 1 + 5 files changed, 124 insertions(+), 5 deletions(-) diff --git a/core/dvector.h b/core/dvector.h index f109f842a20..cac9e8ef850 100644 --- a/core/dvector.h +++ b/core/dvector.h @@ -127,15 +127,30 @@ class PoolVector { MemoryPool::alloc_mutex->unlock(); + if (MemoryPool::memory_pool) { } else { alloc->mem = memalloc( alloc->size ); - copymem( alloc->mem, old_alloc->mem, alloc->size ); } - if (old_alloc->refcount.unref()) { + { + Write w; + w._ref(alloc); + Read r; + r._ref(old_alloc); + + int cur_elements = alloc->size/sizeof(T); + T*dst = (T*)w.ptr(); + const T*src = (const T*)r.ptr(); + for(int i=0;irefcount.unref()==true) { //this should never happen but.. #ifdef DEBUG_ENABLED @@ -144,6 +159,17 @@ class PoolVector { MemoryPool::alloc_mutex->unlock(); #endif + { + Write w; + w._ref(old_alloc); + + int cur_elements = old_alloc->size/sizeof(T); + T*elems = (T*)w.ptr(); + for(int i=0;imem ); old_alloc->mem=NULL; old_alloc->size=0; @@ -190,7 +217,7 @@ class PoolVector { if (!alloc) return; - if (!alloc->refcount.unref()) { + if (alloc->refcount.unref()==false) { alloc=NULL; return; } @@ -199,7 +226,8 @@ class PoolVector { { int cur_elements = alloc->size/sizeof(T); - Write w; + Write w = write(); + for (int i=0;i::resize(int p_size) { } else { { - Write w; + Write w = write(); for (int i=p_size;iadvance(); expr=subexpr; + } else if (tokenizer->get_token()==GDTokenizer::TK_DOLLAR) { + tokenizer->advance(); + + String path; + + bool need_identifier=true; + bool done=false; + + while(!done) { + + switch(tokenizer->get_token()) { + case GDTokenizer::TK_CURSOR: { + completion_cursor=StringName(); + completion_type=COMPLETION_GET_NODE; + completion_class=current_class; + completion_function=current_function; + completion_line=tokenizer->get_token_line(); + completion_cursor=path; + completion_argument=0; + completion_block=current_block; + completion_found=true; + tokenizer->advance(); + } break; + case GDTokenizer::TK_CONSTANT: { + + if (!need_identifier) + break; + + if (tokenizer->get_token_constant().get_type()!=Variant::STRING) { + _set_error("Expected string constant or identifier after '$' or '/'."); + return NULL; + } + + path+=String(tokenizer->get_token_constant()); + tokenizer->advance(); + + } break; + case GDTokenizer::TK_IDENTIFIER: { + + if (!need_identifier) + break; + + path+=String(tokenizer->get_token_identifier()); + tokenizer->advance(); + need_identifier=false; + + } break; + case GDTokenizer::TK_OP_DIV: { + + if (need_identifier) + break; + + path+="/"; + tokenizer->advance(); + need_identifier=true; + + } break; + default: { + done=true; + break; + } + } + } + + if (path=="") { + _set_error("Path expected after $."); + return NULL; + + } + + OperatorNode *op = alloc_node(); + op->op=OperatorNode::OP_CALL; + + op->arguments.push_back(alloc_node()); + + IdentifierNode *funcname = alloc_node(); + funcname->name="get_node"; + + op->arguments.push_back(funcname); + + ConstantNode *nodepath = alloc_node(); + nodepath->value = NodePath(StringName(path)); + op->arguments.push_back(nodepath); + + expr=op; + } else if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) { tokenizer->advance(); continue; //no point in cursor in the middle of expression diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 1b4a37f67e8..e8f5f0f9815 100644 --- a/modules/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -376,6 +376,7 @@ public: enum CompletionType { COMPLETION_NONE, COMPLETION_BUILT_IN_TYPE_CONSTANT, + COMPLETION_GET_NODE, COMPLETION_FUNCTION, COMPLETION_IDENTIFIER, COMPLETION_PARENT_FUNCTION, diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index 427b0cbf043..865c07f3b2f 100644 --- a/modules/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -460,6 +460,9 @@ void GDTokenizerText::_advance() { case ':': _make_token(TK_COLON); //for methods maybe but now useless. break; + case '$': + _make_token(TK_DOLLAR); //for the get_node() shortener + break; case '^': { if (GETCHAR(1)=='=') { _make_token(TK_OP_ASSIGN_BIT_XOR); diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h index 38b677ca7af..18e5547d36c 100644 --- a/modules/gdscript/gd_tokenizer.h +++ b/modules/gdscript/gd_tokenizer.h @@ -123,6 +123,7 @@ public: TK_PERIOD, TK_QUESTION_MARK, TK_COLON, + TK_DOLLAR, TK_NEWLINE, TK_CONST_PI, TK_ERROR,