jblanked 1 год назад
Родитель
Сommit
63ad590c68
3 измененных файлов с 239 добавлено и 2 удалено
  1. BIN
      .DS_Store
  2. 2 0
      .gitignore
  3. 237 2
      jsmn.h

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+
+.DS_Store

+ 237 - 2
jsmn.h

@@ -527,6 +527,8 @@ extern "C"
 
 #endif /* JSMN_H */
 
+#ifndef JB_JSMN_EDIT
+#define JB_JSMN_EDIT
 /* Added in by JBlanked on 2024-10-16 for use in Flipper Zero SDK*/
 
 #include <string.h>
@@ -547,7 +549,6 @@ int jsoneq(const char *json, jsmntok_t *tok, const char *s)
 }
 
 // return the value of the key in the JSON data
-// works for the first level of the JSON data
 char *get_json_value(char *key, char *json_data, uint32_t max_tokens)
 {
   // Parse the JSON feed
@@ -612,4 +613,238 @@ char *get_json_value(char *key, char *json_data, uint32_t max_tokens)
   }
   FURI_LOG_E("JSMM.H", "Failed to find the key in the JSON.");
   return NULL; // Return NULL if something goes wrong
-}
+}
+
+// Revised get_json_array_value function
+char *get_json_array_value(char *key, uint32_t index, char *json_data, uint32_t max_tokens)
+{
+  // Retrieve the array string for the given key
+  char *array_str = get_json_value(key, json_data, max_tokens);
+  if (array_str == NULL)
+  {
+    FURI_LOG_E("JSMM.H", "Failed to get array for key: %s", key);
+    return NULL;
+  }
+
+  // Initialize the JSON parser
+  jsmn_parser parser;
+  jsmn_init(&parser);
+
+  // Allocate memory for JSON tokens
+  jsmntok_t *tokens = malloc(sizeof(jsmntok_t) * max_tokens);
+  if (tokens == NULL)
+  {
+    FURI_LOG_E("JSMM.H", "Failed to allocate memory for JSON tokens.");
+    free(array_str);
+    return NULL;
+  }
+
+  // Parse the JSON array
+  int ret = jsmn_parse(&parser, array_str, strlen(array_str), tokens, max_tokens);
+  if (ret < 0)
+  {
+    FURI_LOG_E("JSMM.H", "Failed to parse JSON array: %d", ret);
+    free(tokens);
+    free(array_str);
+    return NULL;
+  }
+
+  // Ensure the root element is an array
+  if (ret < 1 || tokens[0].type != JSMN_ARRAY)
+  {
+    FURI_LOG_E("JSMM.H", "Value for key '%s' is not an array.", key);
+    free(tokens);
+    free(array_str);
+    return NULL;
+  }
+
+  // Check if the index is within bounds
+  if (index >= (uint32_t)tokens[0].size)
+  {
+    FURI_LOG_E("JSMM.H", "Index %lu out of bounds for array with size %d.", (unsigned long)index, tokens[0].size);
+    free(tokens);
+    free(array_str);
+    return NULL;
+  }
+
+  // Locate the token corresponding to the desired array element
+  int current_token = 1; // Start after the array token
+  for (uint32_t i = 0; i < index; i++)
+  {
+    if (tokens[current_token].type == JSMN_OBJECT)
+    {
+      // For objects, skip all key-value pairs
+      current_token += 1 + 2 * tokens[current_token].size;
+    }
+    else if (tokens[current_token].type == JSMN_ARRAY)
+    {
+      // For nested arrays, skip all elements
+      current_token += 1 + tokens[current_token].size;
+    }
+    else
+    {
+      // For primitive types, simply move to the next token
+      current_token += 1;
+    }
+
+    // Safety check to prevent out-of-bounds
+    if (current_token >= ret)
+    {
+      FURI_LOG_E("JSMM.H", "Unexpected end of tokens while traversing array.");
+      free(tokens);
+      free(array_str);
+      return NULL;
+    }
+  }
+
+  // Extract the array element
+  jsmntok_t element = tokens[current_token];
+  int length = element.end - element.start;
+  char *value = malloc(length + 1);
+  if (value == NULL)
+  {
+    FURI_LOG_E("JSMM.H", "Failed to allocate memory for array element.");
+    free(tokens);
+    free(array_str);
+    return NULL;
+  }
+
+  // Copy the element value to a new string
+  strncpy(value, array_str + element.start, length);
+  value[length] = '\0'; // Null-terminate the string
+
+  // Clean up
+  free(tokens);
+  free(array_str);
+
+  return value;
+}
+
+// Revised get_json_array_values function with correct token skipping
+char **get_json_array_values(char *key, char *json_data, uint32_t max_tokens, int *num_values)
+{
+  // Retrieve the array string for the given key
+  char *array_str = get_json_value(key, json_data, max_tokens);
+  if (array_str == NULL)
+  {
+    FURI_LOG_E("JSMM.H", "Failed to get array for key: %s", key);
+    return NULL;
+  }
+
+  // Initialize the JSON parser
+  jsmn_parser parser;
+  jsmn_init(&parser);
+
+  // Allocate memory for JSON tokens
+  jsmntok_t *tokens = malloc(sizeof(jsmntok_t) * max_tokens); // Allocate on the heap
+  if (tokens == NULL)
+  {
+    FURI_LOG_E("JSMM.H", "Failed to allocate memory for JSON tokens.");
+    free(array_str);
+    return NULL;
+  }
+
+  // Parse the JSON array
+  int ret = jsmn_parse(&parser, array_str, strlen(array_str), tokens, max_tokens);
+  if (ret < 0)
+  {
+    FURI_LOG_E("JSMM.H", "Failed to parse JSON array: %d", ret);
+    free(tokens);
+    free(array_str);
+    return NULL;
+  }
+
+  // Ensure the root element is an array
+  if (tokens[0].type != JSMN_ARRAY)
+  {
+    FURI_LOG_E("JSMM.H", "Value for key '%s' is not an array.", key);
+    free(tokens);
+    free(array_str);
+    return NULL;
+  }
+
+  // Allocate memory for the array of values (maximum possible)
+  int array_size = tokens[0].size;
+  char **values = malloc(array_size * sizeof(char *));
+  if (values == NULL)
+  {
+    FURI_LOG_E("JSMM.H", "Failed to allocate memory for array of values.");
+    free(tokens);
+    free(array_str);
+    return NULL;
+  }
+
+  int actual_num_values = 0;
+
+  // Traverse the array and extract all object values
+  int current_token = 1; // Start after the array token
+  for (int i = 0; i < array_size; i++)
+  {
+    if (current_token >= ret)
+    {
+      FURI_LOG_E("JSMM.H", "Unexpected end of tokens while traversing array.");
+      break;
+    }
+
+    jsmntok_t element = tokens[current_token];
+
+    if (element.type != JSMN_OBJECT)
+    {
+      FURI_LOG_E("JSMM.H", "Array element %d is not an object, skipping.", i);
+      // Skip this element
+      current_token += 1;
+      continue;
+    }
+
+    int length = element.end - element.start;
+
+    // Allocate a new string for the value and copy the data
+    char *value = malloc(length + 1);
+    if (value == NULL)
+    {
+      FURI_LOG_E("JSMM.H", "Failed to allocate memory for array element.");
+      for (int j = 0; j < actual_num_values; j++)
+      {
+        free(values[j]);
+      }
+      free(values);
+      free(tokens);
+      free(array_str);
+      return NULL;
+    }
+
+    strncpy(value, array_str + element.start, length);
+    value[length] = '\0'; // Null-terminate the string
+
+    values[actual_num_values] = value;
+    actual_num_values++;
+
+    // Skip all tokens related to this object to avoid misparsing
+    current_token += 1 + (2 * element.size); // Each key-value pair consumes two tokens
+  }
+
+  *num_values = actual_num_values;
+
+  // Reallocate the values array to actual_num_values if necessary
+  if (actual_num_values < array_size)
+  {
+    char **reduced_values = realloc(values, actual_num_values * sizeof(char *));
+    if (reduced_values != NULL)
+    {
+      values = reduced_values;
+    }
+
+    // Free the remaining values
+    for (int i = actual_num_values; i < array_size; i++)
+    {
+      free(values[i]);
+    }
+  }
+
+  // Clean up
+  free(tokens);
+  free(array_str);
+  return values;
+}
+
+#endif /* JB_JSMN_EDIT */