Add the json parser
This commit is contained in:
		
							
								
								
									
										211
									
								
								haversine_02/src/json/dstring.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								haversine_02/src/json/dstring.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,211 @@
 | 
			
		||||
#include "json/dstring.h"
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
// Use this scalar to allocate extra memory in order to avoid having to
 | 
			
		||||
// constantly reallocate
 | 
			
		||||
#define CAPACITY_SCALAR 8
 | 
			
		||||
 | 
			
		||||
struct dstring {
 | 
			
		||||
  u64 capacity;
 | 
			
		||||
  u64 size;
 | 
			
		||||
  char buf[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
dstr_t *dstr_with_capacity(u64 capacity) {
 | 
			
		||||
  dstr_t *out = (dstr_t *)malloc(sizeof(dstr_t) + capacity + 1);
 | 
			
		||||
 | 
			
		||||
  if (!out) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  out->capacity = capacity;
 | 
			
		||||
  out->size = 0;
 | 
			
		||||
  memset(out->buf, 0, capacity + 1);
 | 
			
		||||
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dstr_t *dstr_from_string(const char *str) {
 | 
			
		||||
  u64 length = strlen(str);
 | 
			
		||||
 | 
			
		||||
  u64 capacity = length * CAPACITY_SCALAR;
 | 
			
		||||
 | 
			
		||||
  dstr_t *out = dstr_with_capacity(capacity);
 | 
			
		||||
 | 
			
		||||
  if (!out) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  out->size = length;
 | 
			
		||||
  strncpy(out->buf, str, length);
 | 
			
		||||
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dstr_update(dstr_t **dst, const char *src) {
 | 
			
		||||
  if (!(*dst)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 length = strlen(src);
 | 
			
		||||
 | 
			
		||||
  dstr_t *str = *dst;
 | 
			
		||||
 | 
			
		||||
  if (length <= str->capacity) {
 | 
			
		||||
    memset(str->buf, 0, str->capacity);
 | 
			
		||||
 | 
			
		||||
    str->size = length;
 | 
			
		||||
 | 
			
		||||
    strncpy(str->buf, src, length);
 | 
			
		||||
  } else {
 | 
			
		||||
    u64 capacity = length * CAPACITY_SCALAR;
 | 
			
		||||
 | 
			
		||||
    dstr_t *tmp = (dstr_t *)realloc(*dst, sizeof(dstr_t) + capacity + 1);
 | 
			
		||||
 | 
			
		||||
    if (!tmp) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tmp->capacity = capacity;
 | 
			
		||||
    tmp->size = length;
 | 
			
		||||
    strncpy(tmp->buf, src, length);
 | 
			
		||||
 | 
			
		||||
    *dst = tmp;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dstr_free(dstr_t **str) {
 | 
			
		||||
  if (!(*str)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  free(*str);
 | 
			
		||||
  *str = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dstr_concat(dstr_t **dst, const char *src) {
 | 
			
		||||
  if (!(*dst)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 src_length = strlen(src);
 | 
			
		||||
 | 
			
		||||
  if (src_length == 0) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 new_length = (*dst)->size + src_length;
 | 
			
		||||
 | 
			
		||||
  char str[new_length + 1];
 | 
			
		||||
  memset(str, 0, new_length + 1);
 | 
			
		||||
 | 
			
		||||
  strncpy(str, (*dst)->buf, (*dst)->size);
 | 
			
		||||
  strncat(str, src, src_length);
 | 
			
		||||
 | 
			
		||||
  dstr_update(dst, str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dstr_append(dstr_t **dst, char c) {
 | 
			
		||||
  if (!(*dst)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 new_length = (*dst)->size + 1;
 | 
			
		||||
 | 
			
		||||
  char str[new_length + 1];
 | 
			
		||||
  memset(str, 0, new_length + 1);
 | 
			
		||||
 | 
			
		||||
  strncpy(str, (*dst)->buf, (*dst)->size);
 | 
			
		||||
  str[(*dst)->size] = c;
 | 
			
		||||
 | 
			
		||||
  dstr_update(dst, str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dstr_resize(dstr_t **str) {
 | 
			
		||||
  u64 capacity = (*str)->size;
 | 
			
		||||
 | 
			
		||||
  dstr_t *tmp = (dstr_t *)realloc(*str, sizeof(dstr_t) + capacity + 1);
 | 
			
		||||
 | 
			
		||||
  if (!tmp) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  tmp->capacity = capacity;
 | 
			
		||||
 | 
			
		||||
  *str = tmp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dstr_clear(dstr_t *str) {
 | 
			
		||||
  if (!str || str->size == 0) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  memset(str->buf, 0, str->capacity);
 | 
			
		||||
  str->size = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dstr_print(const dstr_t *str) {
 | 
			
		||||
  if (!str) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  printf("%s\n", str->buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
i64 dstr_find(const dstr_t *str, const char *substr) {
 | 
			
		||||
  if (!str || !substr) {
 | 
			
		||||
    return -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 substr_length = strlen(substr);
 | 
			
		||||
 | 
			
		||||
  if (substr_length == 0 || substr_length > str->size) {
 | 
			
		||||
    return -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char buf[substr_length + 1];
 | 
			
		||||
  memset(buf, 0, substr_length + 1);
 | 
			
		||||
 | 
			
		||||
  for (u64 i = 0; i < str->size; ++i) {
 | 
			
		||||
    if (i + substr_length >= str->size) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (u64 j = 0; j < substr_length; ++j) {
 | 
			
		||||
      buf[j] = str->buf[i + j];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (strcmp(buf, substr) == 0) {
 | 
			
		||||
      return i;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 dstr_length(const dstr_t *str) {
 | 
			
		||||
  if (!str) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return str->size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 dstr_capacity(const dstr_t *str) {
 | 
			
		||||
  if (!str) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return str->capacity;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dstr_to_cstr(const dstr_t *str) {
 | 
			
		||||
  if (!str) {
 | 
			
		||||
    return "";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return str->buf;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										194
									
								
								haversine_02/src/json/json_entities.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								haversine_02/src/json/json_entities.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
			
		||||
#include "json/json_entities.h"
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "json/dstring.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
void print_json(const jentity_t *entity, u32 indent) {
 | 
			
		||||
  PERSISTENT i32 indentation = 0;
 | 
			
		||||
 | 
			
		||||
  dstr_t *key = NULL;
 | 
			
		||||
  const jval_t *value = NULL;
 | 
			
		||||
 | 
			
		||||
  if (entity->type == JENTITY_SINGLE) {
 | 
			
		||||
    value = &(entity->value);
 | 
			
		||||
  } else {
 | 
			
		||||
    key = entity->pair.key;
 | 
			
		||||
    value = &(entity->pair.value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (key) {
 | 
			
		||||
    printf("%*s\"%s\": ", indentation * indent, "", dstr_to_cstr(key));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (value->type) {
 | 
			
		||||
  case JVAL_COLLECTION: {
 | 
			
		||||
    const char *open = "";
 | 
			
		||||
    const char *close = "";
 | 
			
		||||
 | 
			
		||||
    if (value->collection->type == JCOLL_OBJECT) {
 | 
			
		||||
      open = "{";
 | 
			
		||||
      close = "}";
 | 
			
		||||
    } else {
 | 
			
		||||
      open = "[";
 | 
			
		||||
      close = "]";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (key) {
 | 
			
		||||
      printf("%s\n", open);
 | 
			
		||||
    } else {
 | 
			
		||||
      printf("%*s%s\n", indentation * indent, "", open);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ++indentation;
 | 
			
		||||
 | 
			
		||||
    if (value->collection->begin) {
 | 
			
		||||
      print_json(value->collection->begin, indent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    --indentation;
 | 
			
		||||
 | 
			
		||||
    printf("\n%*s%s", indentation * indent, "", close);
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  case JVAL_STRING:
 | 
			
		||||
    if (key) {
 | 
			
		||||
      printf("\"%s\"", dstr_to_cstr(value->string));
 | 
			
		||||
    } else {
 | 
			
		||||
      printf("%*s\"%s\"", indentation * indent, "",
 | 
			
		||||
             dstr_to_cstr(value->string));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  case JVAL_INTEGER:
 | 
			
		||||
    if (key) {
 | 
			
		||||
      printf("%llu", (unsigned long long)value->num_int);
 | 
			
		||||
    } else {
 | 
			
		||||
      printf("%*s%llu", indentation * indent, "",
 | 
			
		||||
             (unsigned long long)value->num_int);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  case JVAL_DOUBLE:
 | 
			
		||||
    if (key) {
 | 
			
		||||
      printf("%f", value->num_dbl);
 | 
			
		||||
    } else {
 | 
			
		||||
      printf("%*s%f", indentation * indent, "", value->num_dbl);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  case JVAL_BOOLEAN:
 | 
			
		||||
    if (key) {
 | 
			
		||||
      printf("%s", value->boolean ? "true" : "false");
 | 
			
		||||
    } else {
 | 
			
		||||
      printf("%*s%s", indentation * indent, "",
 | 
			
		||||
             value->boolean ? "true" : "false");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  case JVAL_NULL:
 | 
			
		||||
    if (key) {
 | 
			
		||||
      printf("%s", "null");
 | 
			
		||||
    } else {
 | 
			
		||||
      printf("%*s%s", indentation * indent, "", "null");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  case JVAL_EMPTY:
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (entity->next) {
 | 
			
		||||
    printf(",\n");
 | 
			
		||||
    print_json(entity->next, indent);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Add newline after printing the entire json tree
 | 
			
		||||
  if (indentation == 0 && entity->parent == NULL && entity->next == NULL) {
 | 
			
		||||
    printf("\n");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void free_json(jentity_t **entity) {
 | 
			
		||||
  if (!(*entity)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  jentity_t *entt_ptr = *entity;
 | 
			
		||||
 | 
			
		||||
  dstr_t *key = NULL;
 | 
			
		||||
  const jval_t *value = NULL;
 | 
			
		||||
 | 
			
		||||
  if (entt_ptr->type == JENTITY_SINGLE) {
 | 
			
		||||
    value = &(entt_ptr->value);
 | 
			
		||||
  } else {
 | 
			
		||||
    key = entt_ptr->pair.key;
 | 
			
		||||
    value = &(entt_ptr->pair.value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (key) {
 | 
			
		||||
    dstr_free(&(entt_ptr->pair.key));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (value->type) {
 | 
			
		||||
  case JVAL_COLLECTION:
 | 
			
		||||
    if (value->collection->begin) {
 | 
			
		||||
      free_json(&(value->collection->begin));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    free(value->collection);
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  case JVAL_STRING:
 | 
			
		||||
    dstr_free(&(entt_ptr->pair.value.string));
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (entt_ptr->next) {
 | 
			
		||||
    free_json(&(entt_ptr->next));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  free(*entity);
 | 
			
		||||
  *entity = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
jcoll_t *get_collection_from_entity(const jentity_t *entity) {
 | 
			
		||||
  return entity->type == JENTITY_SINGLE ? entity->value.collection
 | 
			
		||||
                                        : entity->pair.value.collection;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
jentity_t *create_new_single_entity(const jval_t value, jentity_t *parent) {
 | 
			
		||||
  jentity_t *entity = (jentity_t *)malloc(sizeof(jentity_t));
 | 
			
		||||
 | 
			
		||||
  if (!entity) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  entity->type = JENTITY_SINGLE;
 | 
			
		||||
  entity->value = value;
 | 
			
		||||
  entity->parent = parent;
 | 
			
		||||
  entity->next = NULL;
 | 
			
		||||
 | 
			
		||||
  return entity;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
jentity_t *create_new_pair_entity(dstr_t *key, const jval_t value,
 | 
			
		||||
                                  jentity_t *parent) {
 | 
			
		||||
  jentity_t *entity = (jentity_t *)malloc(sizeof(jentity_t));
 | 
			
		||||
 | 
			
		||||
  if (!entity) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  entity->type = JENTITY_PAIR;
 | 
			
		||||
  entity->pair.key = key;
 | 
			
		||||
  entity->pair.value = value;
 | 
			
		||||
  entity->parent = parent;
 | 
			
		||||
  entity->next = NULL;
 | 
			
		||||
 | 
			
		||||
  return entity;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1067
									
								
								haversine_02/src/json/lexer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1067
									
								
								haversine_02/src/json/lexer.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										256
									
								
								haversine_02/src/json/parser.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								haversine_02/src/json/parser.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,256 @@
 | 
			
		||||
#include "json/parser.h"
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "json/dstring.h"
 | 
			
		||||
#include "json/json_entities.h"
 | 
			
		||||
#include "json/lexer.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
struct parser_s {
 | 
			
		||||
  jentity_t *root;
 | 
			
		||||
  jentity_t *current;
 | 
			
		||||
  jval_t value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
INTERNAL void parser_free(parser_t **parser);
 | 
			
		||||
INTERNAL void parser_init(parser_t **parser);
 | 
			
		||||
INTERNAL void parse_token(parser_t *parser, token_t token);
 | 
			
		||||
INTERNAL void add_key(parser_t *parser, dstr_t *key);
 | 
			
		||||
INTERNAL jentity_t *add_value(parser_t *parser);
 | 
			
		||||
INTERNAL void add_collection(parser_t *parser);
 | 
			
		||||
 | 
			
		||||
jentity_t *load_json(const char *filepath) {
 | 
			
		||||
  FILE *fp = fopen(filepath, "r");
 | 
			
		||||
 | 
			
		||||
  if (!fp) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fseek(fp, 0, SEEK_END);
 | 
			
		||||
 | 
			
		||||
  u64 length = ftell(fp);
 | 
			
		||||
 | 
			
		||||
  fseek(fp, 0, SEEK_SET);
 | 
			
		||||
 | 
			
		||||
  char json[length + 1];
 | 
			
		||||
  memset(json, 0, length + 1);
 | 
			
		||||
 | 
			
		||||
  fread(json, sizeof(char), length, fp);
 | 
			
		||||
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
 | 
			
		||||
  lexer_t *lexer = NULL;
 | 
			
		||||
  parser_t *parser = NULL;
 | 
			
		||||
 | 
			
		||||
  lexer_init(&lexer);
 | 
			
		||||
  if (!lexer) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  parser_init(&parser);
 | 
			
		||||
  if (!parser) {
 | 
			
		||||
    lexer_free(&lexer);
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  lex_result_t result = get_next_token(lexer, json);
 | 
			
		||||
 | 
			
		||||
  if (result.error.errno) {
 | 
			
		||||
    printf("%s\n", result.error.msg);
 | 
			
		||||
  } else {
 | 
			
		||||
    while (result.token.type != TK_NO_TOKEN) {
 | 
			
		||||
      parse_token(parser, result.token);
 | 
			
		||||
 | 
			
		||||
      result = get_next_token(lexer, NULL);
 | 
			
		||||
 | 
			
		||||
      if (result.error.errno) {
 | 
			
		||||
        printf("%s\n", result.error.msg);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  jentity_t *root = parser->root;
 | 
			
		||||
 | 
			
		||||
  parser_free(&parser);
 | 
			
		||||
  lexer_free(&lexer);
 | 
			
		||||
 | 
			
		||||
  return root;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void parser_init(parser_t **parser) {
 | 
			
		||||
  if (*parser) {
 | 
			
		||||
    parser_free(parser);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *parser = (parser_t *)malloc(sizeof(parser_t));
 | 
			
		||||
 | 
			
		||||
  if (!(*parser)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  (*parser)->root = NULL;
 | 
			
		||||
  (*parser)->current = NULL;
 | 
			
		||||
  (*parser)->value = (jval_t){};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void parser_free(parser_t **parser) {
 | 
			
		||||
  if (!(*parser)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  (*parser)->root = NULL;
 | 
			
		||||
  (*parser)->current = NULL;
 | 
			
		||||
 | 
			
		||||
  free(*parser);
 | 
			
		||||
  *parser = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void parse_token(parser_t *parser, token_t token) {
 | 
			
		||||
  switch (token.type) {
 | 
			
		||||
  case TK_L_BRACE:
 | 
			
		||||
  case TK_L_BRACKET: {
 | 
			
		||||
    parser->value = (jval_t){
 | 
			
		||||
        .type = JVAL_COLLECTION,
 | 
			
		||||
        .collection = (jcoll_t *)malloc(sizeof(jcoll_t)),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (token.type == TK_L_BRACE) {
 | 
			
		||||
      parser->value.collection->type = JCOLL_OBJECT;
 | 
			
		||||
    } else {
 | 
			
		||||
      parser->value.collection->type = JCOLL_ARRAY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    parser->value.collection->size = 0;
 | 
			
		||||
    parser->value.collection->begin = NULL;
 | 
			
		||||
    parser->value.collection->end = NULL;
 | 
			
		||||
 | 
			
		||||
    add_collection(parser);
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  case TK_R_BRACE:
 | 
			
		||||
  case TK_R_BRACKET:
 | 
			
		||||
    if (parser->current->parent) {
 | 
			
		||||
      parser->current = parser->current->parent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  case TK_STR_KEY: {
 | 
			
		||||
    parser->value = (jval_t){.type = JVAL_EMPTY, .null_val = NULL};
 | 
			
		||||
 | 
			
		||||
    add_key(parser, dstr_from_string(token.value.string));
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  case TK_NULL: {
 | 
			
		||||
    parser->value = (jval_t){.type = JVAL_NULL, .null_val = NULL};
 | 
			
		||||
 | 
			
		||||
    add_value(parser);
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  case TK_BOOL: {
 | 
			
		||||
    parser->value =
 | 
			
		||||
        (jval_t){.type = JVAL_BOOLEAN, .boolean = token.value.boolean};
 | 
			
		||||
 | 
			
		||||
    add_value(parser);
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  case TK_STR_VAL: {
 | 
			
		||||
    parser->value = (jval_t){.type = JVAL_STRING,
 | 
			
		||||
                             .string = dstr_from_string(token.value.string)};
 | 
			
		||||
 | 
			
		||||
    add_value(parser);
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  case TK_INTEGER: {
 | 
			
		||||
    parser->value =
 | 
			
		||||
        (jval_t){.type = JVAL_INTEGER, .num_int = token.value.num_int};
 | 
			
		||||
 | 
			
		||||
    add_value(parser);
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  case TK_DOUBLE: {
 | 
			
		||||
    parser->value =
 | 
			
		||||
        (jval_t){.type = JVAL_DOUBLE, .num_dbl = token.value.num_frac};
 | 
			
		||||
 | 
			
		||||
    add_value(parser);
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  case TK_NO_TOKEN:
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void add_key(parser_t *parser, dstr_t *key) {
 | 
			
		||||
  jcoll_t *collection = get_collection_from_entity(parser->current);
 | 
			
		||||
 | 
			
		||||
  if (!collection) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!(collection->end)) {
 | 
			
		||||
    collection->begin = collection->end =
 | 
			
		||||
        create_new_pair_entity(key, parser->value, parser->current);
 | 
			
		||||
 | 
			
		||||
    collection->size = 1;
 | 
			
		||||
  } else {
 | 
			
		||||
    jentity_t *new_entity =
 | 
			
		||||
        create_new_pair_entity(key, parser->value, parser->current);
 | 
			
		||||
 | 
			
		||||
    collection->end->next = new_entity;
 | 
			
		||||
 | 
			
		||||
    collection->end = new_entity;
 | 
			
		||||
 | 
			
		||||
    ++(collection->size);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
jentity_t *add_value(parser_t *parser) {
 | 
			
		||||
  jcoll_t *collection = get_collection_from_entity(parser->current);
 | 
			
		||||
 | 
			
		||||
  if (!collection) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!(collection->end)) {
 | 
			
		||||
    collection->begin = collection->end =
 | 
			
		||||
        create_new_single_entity(parser->value, parser->current);
 | 
			
		||||
 | 
			
		||||
    collection->size = 1;
 | 
			
		||||
  } else {
 | 
			
		||||
    if (collection->end->type == JENTITY_PAIR &&
 | 
			
		||||
        collection->end->pair.value.type == JVAL_EMPTY) {
 | 
			
		||||
      collection->end->pair.value = parser->value;
 | 
			
		||||
    } else {
 | 
			
		||||
      jentity_t *new_entity =
 | 
			
		||||
          create_new_single_entity(parser->value, parser->current);
 | 
			
		||||
 | 
			
		||||
      collection->end->next = new_entity;
 | 
			
		||||
 | 
			
		||||
      collection->end = new_entity;
 | 
			
		||||
 | 
			
		||||
      ++(collection->size);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return collection->end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void add_collection(parser_t *parser) {
 | 
			
		||||
  if (!(parser->root)) {
 | 
			
		||||
    parser->root = parser->current =
 | 
			
		||||
        create_new_single_entity(parser->value, NULL);
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  parser->current = add_value(parser);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user