@@ -55737,6 +55737,7 @@ int ecs_meta_from_desc(
5573755737 * @brief API for reading and assigning values of runtime types with reflection.
5573855738 */
5573955739
55740+ #include <ctype.h>
5574055741#include <inttypes.h>
5574155742
5574255743#ifdef FLECS_META
@@ -56159,7 +56160,7 @@ const char* flecs_meta_parse_member(
5615956160 const char *ptr;
5616056161 char ch;
5616156162 for (ptr = start; (ch = *ptr); ptr ++) {
56162- if (ch == '.') {
56163+ if (ch == '.' || ch == '[' ) {
5616356164 break;
5616456165 }
5616556166 }
@@ -56171,11 +56172,47 @@ const char* flecs_meta_parse_member(
5617156172
5617256173 ecs_os_memcpy(token_out, start, len);
5617356174 token_out[len] = '\0';
56174- if (ch == '.') {
56175+
56176+ return ptr;
56177+ }
56178+
56179+ static
56180+ const char* flecs_meta_parse_elem(
56181+ const char *start,
56182+ int32_t *elem_out)
56183+ {
56184+ if (start[0] != '[') {
56185+ ecs_err("expected '[' in member expression");
56186+ return NULL;
56187+ }
56188+
56189+ start ++;
56190+ if (!isdigit((unsigned char)start[0])) {
56191+ ecs_err("expected array index in member expression");
56192+ return NULL;
56193+ }
56194+
56195+ int32_t elem = 0;
56196+ const char *ptr = start;
56197+ char ch;
56198+ while ((ch = ptr[0]) && ch != ']') {
56199+ if (!isdigit((unsigned char)ch)) {
56200+ ecs_err("invalid array index in member expression");
56201+ return NULL;
56202+ }
56203+
56204+ elem *= 10;
56205+ elem += ch - '0';
5617556206 ptr ++;
5617656207 }
5617756208
56178- return ptr;
56209+ if (ptr[0] != ']') {
56210+ ecs_err("missing ']' in member expression");
56211+ return NULL;
56212+ }
56213+
56214+ elem_out[0] = elem;
56215+ return ptr + 1;
5617956216}
5618056217
5618156218static
@@ -56188,33 +56225,68 @@ int flecs_meta_dotmember(
5618856225 flecs_cursor_restore_scope(cursor, cur_scope);
5618956226
5619056227 int16_t prev_depth = cursor->depth;
56191- int dotcount = 0 ;
56228+ bool moved = false ;
5619256229
5619356230 char token[ECS_MAX_TOKEN_SIZE];
5619456231 const char *ptr = name;
56195- while ((ptr = flecs_meta_parse_member(ptr, token))) {
56196- if (dotcount) {
56197- ecs_meta_push(cursor);
56232+ while (ptr[0]) {
56233+ if (ptr[0] != '[') {
56234+ ptr = flecs_meta_parse_member(ptr, token);
56235+ if (!ptr) {
56236+ goto error;
56237+ }
56238+
56239+ if (moved) {
56240+ if (ecs_meta_push(cursor) != 0) {
56241+ goto error;
56242+ }
56243+ }
56244+
56245+ if (flecs_meta_member(cursor, token, try)) {
56246+ goto error;
56247+ }
56248+
56249+ moved = true;
5619856250 }
5619956251
56200- if (flecs_meta_member(cursor, token, try)) {
56201- goto error;
56252+ while (ptr[0] == '[') {
56253+ int32_t elem;
56254+
56255+ if (ecs_meta_push(cursor) != 0) {
56256+ goto error;
56257+ }
56258+
56259+ ptr = flecs_meta_parse_elem(ptr, &elem);
56260+ if (!ptr) {
56261+ goto error;
56262+ }
56263+
56264+ if (ecs_meta_elem(cursor, elem) != 0) {
56265+ goto error;
56266+ }
56267+
56268+ moved = true;
5620256269 }
5620356270
56204- if (!ptr[0]) {
56205- break;
56271+ if (ptr[0] == '.') {
56272+ ptr ++;
56273+ continue;
5620656274 }
5620756275
56208- dotcount ++;
56276+ if (ptr[0] != '\0') {
56277+ ecs_err("invalid token '%c' in member expression", ptr[0]);
56278+ goto error;
56279+ }
5620956280 }
5621056281
5621156282 cur_scope = flecs_cursor_get_scope(cursor);
56212- if (dotcount ) {
56283+ if (moved && (cursor->depth != prev_depth) ) {
5621356284 cur_scope->prev_depth = prev_depth;
5621456285 }
5621556286
5621656287 return 0;
5621756288error:
56289+ cursor->depth = prev_depth;
5621856290 return -1;
5621956291}
5622056292
@@ -56426,6 +56498,19 @@ bool ecs_meta_is_collection(
5642656498 const ecs_meta_cursor_t *cursor)
5642756499{
5642856500 ecs_meta_scope_t *scope = flecs_cursor_get_scope(cursor);
56501+
56502+ /* If the scope was reached through dotmember with array indexing, the
56503+ * current scope can still be the collection that contains the selected
56504+ * element. In that case, report whether the selected element is a
56505+ * collection, not whether its parent container is. */
56506+ if (scope->prev_depth && scope->is_collection) {
56507+ ecs_meta_op_t *op = flecs_cursor_get_op(scope);
56508+ return op->kind == EcsOpPushArray ||
56509+ op->kind == EcsOpPushVector ||
56510+ op->kind == EcsOpOpaqueArray ||
56511+ op->kind == EcsOpOpaqueVector;
56512+ }
56513+
5642956514 return scope->is_collection;
5643056515}
5643156516
0 commit comments