From bdff1204ece0c324996ef0b80d28476b0d8273a0 Mon Sep 17 00:00:00 2001
From: Sander Mertens <sander.mertens8@gmail.com>
Date: Tue, 28 Dec 2021 20:59:23 -0800
Subject: [PATCH] #124 fix issue with linking component id symbols, appending
 long strbuf strings

---
 flecs.c                       | 45 +++++++++++++++++++++++++++--------
 flecs.h                       | 10 ++++++--
 include/flecs/addons/meta_c.h | 10 ++++++--
 src/datastructures/strbuf.c   |  3 ++-
 4 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/flecs.c b/flecs.c
index 31fff373df..bf06618900 100644
--- a/flecs.c
+++ b/flecs.c
@@ -11337,7 +11337,8 @@ bool appendstr(
             /* Update to number of characters copied to new buffer */
             b->current->pos += n;
         } else {
-            char *remainder = ecs_os_strdup(str);
+            /* String doesn't fit in a single element, strdup */
+            char *remainder = ecs_os_strdup(str + memLeftInElement);
             ecs_strbuf_grow_str(b, remainder, remainder, n);
         }
     } else {
@@ -37049,17 +37050,41 @@ void rematch_table(
             resolve_cascade_subject(world, query, match, table, table->type);
 
         /* If query has optional columns, it is possible that a column that
-         * previously had data no longer has data, or vice versa. Do a full
+         * previously had data no longer has data, or vice versa. Do a
          * rematch to make sure data is consistent. */
         } else if (query->flags & EcsQueryHasOptional) {
-            unmatch_table(query, table);
-            if (!(query->flags & EcsQueryIsSubquery)) {
-                flecs_table_notify(world, table, &(ecs_table_event_t){
-                    .kind = EcsTableQueryUnmatch,
-                    .query = query
-                }); 
+            /* Check if optional terms that weren't matched before are matched
+             * now & vice versa */
+            ecs_query_table_match_t *qt = match->first;
+
+            bool rematch = false;
+            int32_t i, count = query->filter.term_count_actual;
+            for (i = 0; i < count; i ++) {
+                ecs_term_t *term = &query->filter.terms[i];
+
+                if (term->oper == EcsOptional) {
+                    int32_t t = term->index;
+                    int32_t column = 0;
+                    flecs_term_match_table(world, term, table,
+                        table->type, 0, &column, 0, 0, true);
+                    if (column && (qt->columns[t] == 0)) {
+                        rematch = true;
+                    } else if (!column && (qt->columns[t] != 0)) {
+                        rematch = true;
+                    }
+                }
+            }
+
+            if (rematch) {
+                unmatch_table(query, table);
+                if (!(query->flags & EcsQueryIsSubquery)) {
+                    flecs_table_notify(world, table, &(ecs_table_event_t){
+                        .kind = EcsTableQueryUnmatch,
+                        .query = query
+                    }); 
+                }
+                add_table(world, query, table);
             }
-            add_table(world, query, table);
         }
     } else {
         /* Table no longer matches, remove */
@@ -37120,7 +37145,7 @@ void rematch_tables(
     ecs_world_t *world,
     ecs_query_t *query,
     ecs_query_t *parent_query)
-{
+{    
     if (parent_query) {
         ecs_query_table_t *tables = ecs_vector_first(
             parent_query->cache.tables, ecs_query_table_t);
diff --git a/flecs.h b/flecs.h
index 176908e6f0..b391be2f8f 100644
--- a/flecs.h
+++ b/flecs.h
@@ -9201,12 +9201,14 @@ int ecs_meta_from_desc(
 #define ECS_STRUCT_ECS_META_IMPL ECS_STRUCT_IMPL
 
 #define ECS_STRUCT_IMPL(name, type_desc)\
+    ECS_STRUCT_EXTERN(name, type_desc);\
     static const char *FLECS__##name##_desc = type_desc;\
     static ecs_type_kind_t FLECS__##name##_kind = EcsStructType;\
-    FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
+    FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name) = 0
 
 #define ECS_STRUCT_DECLARE(name, type_desc)\
-    FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
+    ECS_STRUCT_EXTERN(name, type_desc);\
+    FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name) = 0
 
 #define ECS_STRUCT_EXTERN(name, type_desc)\
     FLECS_META_C_IMPORT extern ECS_COMPONENT_DECLARE(name)
@@ -9219,11 +9221,13 @@ int ecs_meta_from_desc(
 #define ECS_ENUM_ECS_META_IMPL ECS_ENUM_IMPL
 
 #define ECS_ENUM_IMPL(name, type_desc)\
+    ECS_ENUM_EXTERN(name, type_desc);\
     static const char *FLECS__##name##_desc = type_desc;\
     static ecs_type_kind_t FLECS__##name##_kind = EcsEnumType;\
     FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
 
 #define ECS_ENUM_DECLARE(name, type_desc)\
+    ECS_ENUM_EXTERN(name, type_desc);\
     FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
 
 #define ECS_ENUM_EXTERN(name, type_desc)\
@@ -9237,11 +9241,13 @@ int ecs_meta_from_desc(
 #define ECS_BITMASK_ECS_META_IMPL ECS_BITMASK_IMPL
 
 #define ECS_BITMASK_IMPL(name, type_desc)\
+    ECS_BITMASK_EXTERN(name, type_desc);\
     static const char *FLECS__##name##_desc = type_desc;\
     static ecs_type_kind_t FLECS__##name##_kind = EcsBitmaskType;\
     FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
 
 #define ECS_BITMASK_DECLARE(name, type_desc)\
+    ECS_BITMASK_EXTERN(name, type_desc);\
     FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
 
 #define ECS_BITMASK_EXTERN(name, type_desc)\
diff --git a/include/flecs/addons/meta_c.h b/include/flecs/addons/meta_c.h
index 4eb10e9943..5b1cf40014 100644
--- a/include/flecs/addons/meta_c.h
+++ b/include/flecs/addons/meta_c.h
@@ -87,12 +87,14 @@ int ecs_meta_from_desc(
 #define ECS_STRUCT_ECS_META_IMPL ECS_STRUCT_IMPL
 
 #define ECS_STRUCT_IMPL(name, type_desc)\
+    FLECS_META_C_EXPORT extern ECS_COMPONENT_DECLARE(name);\
     static const char *FLECS__##name##_desc = type_desc;\
     static ecs_type_kind_t FLECS__##name##_kind = EcsStructType;\
-    FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
+    FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name) = 0
 
 #define ECS_STRUCT_DECLARE(name, type_desc)\
-    FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
+    FLECS_META_C_EXPORT extern ECS_COMPONENT_DECLARE(name);\
+    FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name) = 0
 
 #define ECS_STRUCT_EXTERN(name, type_desc)\
     FLECS_META_C_IMPORT extern ECS_COMPONENT_DECLARE(name)
@@ -105,11 +107,13 @@ int ecs_meta_from_desc(
 #define ECS_ENUM_ECS_META_IMPL ECS_ENUM_IMPL
 
 #define ECS_ENUM_IMPL(name, type_desc)\
+    FLECS_META_C_EXPORT extern ECS_COMPONENT_DECLARE(name);\
     static const char *FLECS__##name##_desc = type_desc;\
     static ecs_type_kind_t FLECS__##name##_kind = EcsEnumType;\
     FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
 
 #define ECS_ENUM_DECLARE(name, type_desc)\
+    FLECS_META_C_EXPORT extern ECS_COMPONENT_DECLARE(name);\
     FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
 
 #define ECS_ENUM_EXTERN(name, type_desc)\
@@ -123,11 +127,13 @@ int ecs_meta_from_desc(
 #define ECS_BITMASK_ECS_META_IMPL ECS_BITMASK_IMPL
 
 #define ECS_BITMASK_IMPL(name, type_desc)\
+    FLECS_META_C_EXPORT extern ECS_COMPONENT_DECLARE(name);\
     static const char *FLECS__##name##_desc = type_desc;\
     static ecs_type_kind_t FLECS__##name##_kind = EcsBitmaskType;\
     FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
 
 #define ECS_BITMASK_DECLARE(name, type_desc)\
+    FLECS_META_C_EXPORT extern ECS_COMPONENT_DECLARE(name);\
     FLECS_META_C_EXPORT ECS_COMPONENT_DECLARE(name)
 
 #define ECS_BITMASK_EXTERN(name, type_desc)\
diff --git a/src/datastructures/strbuf.c b/src/datastructures/strbuf.c
index 152a6ccb89..6ef78cec3b 100644
--- a/src/datastructures/strbuf.c
+++ b/src/datastructures/strbuf.c
@@ -307,7 +307,8 @@ bool appendstr(
             /* Update to number of characters copied to new buffer */
             b->current->pos += n;
         } else {
-            char *remainder = ecs_os_strdup(str);
+            /* String doesn't fit in a single element, strdup */
+            char *remainder = ecs_os_strdup(str + memLeftInElement);
             ecs_strbuf_grow_str(b, remainder, remainder, n);
         }
     } else {