@@ -881,42 +881,69 @@ int fossil_media_json_validate(const char *json_text, fossil_media_json_error_t
881881// Path Access
882882// -----------------------------------------------------------------------------
883883
884- // Very simple dotted path: "foo.bar[2].baz"
885- fossil_media_json_value_t *
886- fossil_media_json_get_path (const fossil_media_json_value_t * root , const char * path ) {
884+ fossil_media_json_value_t * fossil_media_json_get_path (const fossil_media_json_value_t * root , const char * path ) {
887885 if (!root || !path ) return NULL ;
888886
889887 const fossil_media_json_value_t * cur = root ;
890- char * tokenized = fossil_media_strdup (path );
891- if (!tokenized ) return NULL ;
892-
893- char * tok = tokenized ;
894- while (tok && cur ) {
895- char * next_dot = strchr (tok , '.' );
896- if (next_dot ) {
897- * next_dot = '\0' ;
898- }
899- if (cur -> type == FOSSIL_MEDIA_JSON_OBJECT ) {
900- cur = fossil_media_json_object_get (cur , tok );
901- } else if (cur -> type == FOSSIL_MEDIA_JSON_ARRAY ) {
902- char * end ;
903- long idx = strtol (tok , & end , 10 );
904- if (* end == '\0' ) {
888+ size_t path_len = strlen (path );
889+ char * buf = fm_malloc (path_len + 1 );
890+ if (!buf ) return NULL ;
891+ strcpy (buf , path );
892+
893+ char * p = buf ;
894+ while (* p && cur ) {
895+ // Find next '.' or end
896+ char * dot = strchr (p , '.' );
897+ char * token_end = dot ? dot : p + strlen (p );
898+
899+ // Check for array index: look for '[' in token
900+ char * bracket = strchr (p , '[' );
901+ if (bracket && bracket < token_end ) {
902+ * bracket = '\0' ;
903+ // Object key before '['
904+ if (cur -> type != FOSSIL_MEDIA_JSON_OBJECT ) { fm_free (buf ); return NULL ; }
905+ cur = fossil_media_json_object_get (cur , p );
906+ if (!cur ) { fm_free (buf ); return NULL ; }
907+ // Array index (support multiple indices, e.g. arr[1][2])
908+ char * idx_ptr = bracket ;
909+ while (cur && idx_ptr && * idx_ptr == '[' && idx_ptr < token_end ) {
910+ char * idx_start = idx_ptr + 1 ;
911+ char * idx_end = strchr (idx_start , ']' );
912+ if (!idx_end || idx_end > token_end ) { fm_free (buf ); return NULL ; }
913+ * idx_end = '\0' ;
914+ long idx = strtol (idx_start , NULL , 10 );
915+ if (cur -> type != FOSSIL_MEDIA_JSON_ARRAY ) { fm_free (buf ); return NULL ; }
905916 cur = fossil_media_json_array_get (cur , (size_t )idx );
917+ if (!cur ) { fm_free (buf ); return NULL ; }
918+ idx_ptr = idx_end + 1 ;
919+ }
920+ p = token_end ;
921+ } else {
922+ // No array index, just object key or array index as token
923+ char save = * token_end ;
924+ * token_end = '\0' ;
925+ if (cur -> type == FOSSIL_MEDIA_JSON_OBJECT ) {
926+ cur = fossil_media_json_object_get (cur , p );
927+ } else if (cur -> type == FOSSIL_MEDIA_JSON_ARRAY ) {
928+ char * endptr ;
929+ long idx = strtol (p , & endptr , 10 );
930+ if (* endptr == '\0' ) {
931+ cur = fossil_media_json_array_get (cur , (size_t )idx );
932+ } else {
933+ fm_free (buf );
934+ return NULL ;
935+ }
906936 } else {
907- fm_free (tokenized );
937+ fm_free (buf );
908938 return NULL ;
909939 }
910- } else {
911- fm_free (tokenized );
912- return NULL ;
913- }
914- if (next_dot ) {
915- tok = next_dot + 1 ;
916- } else {
917- tok = NULL ;
940+ * token_end = save ;
941+ p = dot ? dot + 1 : token_end ;
918942 }
943+ // Skip '.' if present
944+ while (* p == '.' ) p ++ ;
919945 }
920- fm_free (tokenized );
921- return (fossil_media_json_value_t * )cur ;
946+ fm_free (buf );
947+ // Return a clone so caller can free safely
948+ return cur ? fossil_media_json_clone (cur ) : NULL ;
922949}
0 commit comments