diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-01-08 02:04:53 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2017-01-08 02:04:53 -0300 |
commit | 8b912d11152410302f45eaa117c19b7016d781f5 (patch) | |
tree | 58e7e9ab9ee7e22c5f7e70c4342219a5918fd55e | |
parent | 2ab83e1abbf5ee6d00e16056a9e9394114026f28 (diff) |
-Fix bugs related to PoolVector crashes
-Added ability to request nodes using $Name in GDScript :)
-rw-r--r-- | core/dvector.h | 38 | ||||
-rw-r--r-- | modules/gdscript/gd_parser.cpp | 86 | ||||
-rw-r--r-- | modules/gdscript/gd_parser.h | 1 | ||||
-rw-r--r-- | modules/gdscript/gd_tokenizer.cpp | 3 | ||||
-rw-r--r-- | modules/gdscript/gd_tokenizer.h | 1 |
5 files changed, 124 insertions, 5 deletions
diff --git a/core/dvector.h b/core/dvector.h index f109f842a2..cac9e8ef85 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;i<cur_elements;i++) { + memnew_placement(&dst[i],T(src[i])); + } + } + + + if (old_alloc->refcount.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;i<cur_elements;i++) { + elems[i].~T(); + } + + } if (MemoryPool::memory_pool) { //resize memory pool @@ -151,6 +177,7 @@ class PoolVector { //if some resize } else { + memfree( old_alloc->mem ); 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<cur_elements;i++) { w[i].~T(); @@ -585,7 +613,7 @@ Error PoolVector<T>::resize(int p_size) { } else { { - Write w; + Write w = write(); for (int i=p_size;i<cur_elements;i++) { w[i].~T(); diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index bc9d3fa4f4..029e227cdd 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -265,6 +265,92 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ tokenizer->advance(); 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<OperatorNode>(); + op->op=OperatorNode::OP_CALL; + + op->arguments.push_back(alloc_node<SelfNode>()); + + IdentifierNode *funcname = alloc_node<IdentifierNode>(); + funcname->name="get_node"; + + op->arguments.push_back(funcname); + + ConstantNode *nodepath = alloc_node<ConstantNode>(); + 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 1b4a37f67e..e8f5f0f981 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 427b0cbf04..865c07f3b2 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 38b677ca7a..18e5547d36 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, |