summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2017-01-08 02:04:53 -0300
committerJuan Linietsky <reduzio@gmail.com>2017-01-08 02:04:53 -0300
commit8b912d11152410302f45eaa117c19b7016d781f5 (patch)
tree58e7e9ab9ee7e22c5f7e70c4342219a5918fd55e
parent2ab83e1abbf5ee6d00e16056a9e9394114026f28 (diff)
-Fix bugs related to PoolVector crashes
-Added ability to request nodes using $Name in GDScript :)
-rw-r--r--core/dvector.h38
-rw-r--r--modules/gdscript/gd_parser.cpp86
-rw-r--r--modules/gdscript/gd_parser.h1
-rw-r--r--modules/gdscript/gd_tokenizer.cpp3
-rw-r--r--modules/gdscript/gd_tokenizer.h1
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,