Each file now has a separate Parser allocated for it which holds all the

parsed objects from the file in their intermediary state. These will be
consumed by the caller into their actual in-game representations
dev
Shariq Shah 8 years ago
parent 83255ae281
commit 114d44371e
  1. 98
      src/common/parser.c
  2. 23
      src/common/parser.h
  3. 18
      src/libsymmetry/game.c

@ -1,20 +1,18 @@
#include "parser.h" #include "parser.h"
#include "hashmap.h" #include "hashmap.h"
#include "array.h"
#include "log.h" #include "log.h"
#include "string_utils.h"
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#define MAX_LINE_LEN 512 #define MAX_LINE_LEN 512
#define MAX_VALUE_LEN 512 #define MAX_VALUE_LEN 512
struct Parser_Object static int parser_object_type_from_str(const char* str);
{
int type;
char* key;
char* value;
char* object_data;
};
bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line) bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line)
{ {
@ -37,6 +35,7 @@ bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_fun
char line_buffer[MAX_LINE_LEN]; char line_buffer[MAX_LINE_LEN];
memset(key_str, '\0', HASH_MAX_KEY_LEN); memset(key_str, '\0', HASH_MAX_KEY_LEN);
memset(line_buffer, '\0', MAX_LINE_LEN); memset(line_buffer, '\0', MAX_LINE_LEN);
memset(format_str, '\0', 64);
snprintf(format_str, 64, " %%%d[^: ] : %%%d[^\n]", HASH_MAX_KEY_LEN, MAX_VALUE_LEN); snprintf(format_str, 64, " %%%d[^: ] : %%%d[^\n]", HASH_MAX_KEY_LEN, MAX_VALUE_LEN);
while(fgets(line_buffer, MAX_LINE_LEN - 1, file)) while(fgets(line_buffer, MAX_LINE_LEN - 1, file))
@ -67,7 +66,7 @@ bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_fun
return true; return true;
} }
bool parser_load_objects(FILE* file, const char* filename) struct Parser* parser_load_objects(FILE* file, const char* filename)
{ {
/* Note, this is isn't really a proper parser and might have lurking bugs, it just has to be /* Note, this is isn't really a proper parser and might have lurking bugs, it just has to be
good enough for my needs. For example, multiple opening and closing braces on them good enough for my needs. For example, multiple opening and closing braces on them
@ -82,6 +81,16 @@ bool parser_load_objects(FILE* file, const char* filename)
return false; return false;
} }
struct Parser* parser = malloc(sizeof(*parser));
if(!parser)
{
log_error("parser:load_objects", "Out of memeory");
return parser;
}
parser->filename = str_new(filename);
parser->objects = array_new(struct Parser_Object);
int current_line = 0; int current_line = 0;
char line_buffer[MAX_LINE_LEN]; char line_buffer[MAX_LINE_LEN];
char type_str[HASH_MAX_KEY_LEN]; char type_str[HASH_MAX_KEY_LEN];
@ -136,7 +145,7 @@ bool parser_load_objects(FILE* file, const char* filename)
if(c == '{') if(c == '{')
{ {
obj_beginning = ftell(file) - 1; obj_beginning = ftell(file);
c = ' '; c = ' ';
while(!feof(file)) while(!feof(file))
{ {
@ -158,7 +167,7 @@ bool parser_load_objects(FILE* file, const char* filename)
if(c == '}') if(c == '}')
{ {
obj_ending = ftell(file); obj_ending = ftell(file) - 1;
break; break;
} }
} }
@ -185,8 +194,73 @@ bool parser_load_objects(FILE* file, const char* filename)
memset(line_buffer, '\0', MAX_LINE_LEN); memset(line_buffer, '\0', MAX_LINE_LEN);
fseek(file, obj_beginning, SEEK_SET); fseek(file, obj_beginning, SEEK_SET);
fread(obj_str, obj_ending - obj_beginning, 1, file); fread(obj_str, obj_ending - obj_beginning, 1, file);
log_to_stdout("Object found\nType: %s\n%s\n\n", type_str, obj_str); fseek(file, obj_ending + 1, SEEK_SET); // Position cursor after closing brace '}'
// Read into intermediate parser object and add it to the objects list
struct Parser_Object* object = array_grow(parser->objects, struct Parser_Object);
object->type = parser_object_type_from_str(type_str);
object->data = hashmap_new();
char format_str[64];
char key_str[HASH_MAX_KEY_LEN];
char value_str[MAX_VALUE_LEN];
memset(format_str, '\0', 64);
snprintf(format_str, 64, " %%%d[^: ] : %%%d[^\n]", HASH_MAX_KEY_LEN, MAX_VALUE_LEN);
char* line = strtok(obj_str, "\n");
do
{
memset(key_str, '\0', HASH_MAX_KEY_LEN);
memset(value_str, '\0', MAX_VALUE_LEN);
if(strlen(line) == 0)
{
continue;
} }
return true; if(line[0] == '#')
continue;
if(sscanf(line, format_str, key_str, value_str) != 2)
{
log_warning("Malformed value in config file %s, line %d", filename, current_line);
continue;
}
hashmap_str_set(object->data, key_str, value_str);
}
while((line = strtok(NULL, "\n")) != NULL);
//log_to_stdout("Object found\nType: %s\n%s\n\n", type_str, obj_str);
}
return parser;
}
int parser_object_type_from_str(const char* str)
{
int object_type = PO_UNKNOWN;
if(strncmp(str, "Entity", HASH_MAX_KEY_LEN) == 0) object_type = PO_ENTITY;
else if(strncmp(str, "Model", HASH_MAX_KEY_LEN) == 0) object_type = PO_MODEL;
else if(strncmp(str, "Material", HASH_MAX_KEY_LEN) == 0) object_type = PO_MATERIAL;
return object_type;
}
void parser_free(struct Parser *parser)
{
assert(parser);
if(parser->filename)
{
free(parser->filename);
parser->filename = NULL;
}
for(int i = 0; i < array_len(parser->objects); i++)
{
struct Parser_Object* object = &parser->objects[i];
hashmap_free(object->data);
object->data = NULL;
object->type = PO_UNKNOWN;
}
} }

@ -3,11 +3,30 @@
#include "common.h" #include "common.h"
struct Hashmap; enum Parser_Object_Type
{
PO_ENTITY,
PO_MATERIAL,
PO_MODEL,
PO_UNKNOWN
};
struct Parser_Object
{
int type;
struct Hashmap* data;
};
struct Parser
{
char* filename;
struct Parser_Object* objects;
};
typedef void (*Parser_Assign_Func)(const char* key, const char* value, const char* filename, int current_line); typedef void (*Parser_Assign_Func)(const char* key, const char* value, const char* filename, int current_line);
bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line); bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line);
bool parser_load_objects(FILE* file, const char* filename); struct Parser* parser_load_objects(FILE* file, const char* filename);
void parser_free(struct Parser* parser);
#endif #endif

@ -217,10 +217,24 @@ void scene_setup(void)
game_state->player_node = player->id; game_state->player_node = player->id;
} }
FILE* obj_file = platform->file.open(DIRT_INSTALL, "test_scene.symtres", "rb"); FILE* obj_file = platform->file.open(DIRT_INSTALL, "obj_test.symtres", "rb");
if(obj_file) if(obj_file)
{ {
parser_load_objects(obj_file, "obj_test.symtres"); struct Parser* parsed_file = parser_load_objects(obj_file, "obj_test.symtres");
log_message("%d objects read from %s", array_len(parsed_file->objects), "obj_test.symtres");
for(int i = 0; i < array_len(parsed_file->objects); i++)
{
struct Parser_Object* object = &parsed_file->objects[i];
if(object->type == PO_UNKNOWN)
log_message("Type : Unknown");
else if(object->type == PO_ENTITY)
log_message("Type : Entity");
else if(object->type == PO_MATERIAL)
log_message("Type : Material");
else if(object->type == PO_MODEL)
log_message("Type : Model");
hashmap_debug_print(object->data);
}
fclose(obj_file); fclose(obj_file);
} }
else else

Loading…
Cancel
Save