timesynk/data.c

309 lines
10 KiB
C

/****** data.c
This file contains the functions for loading Data, be they Tiles or otherwise, from text data into TileData/TileSetData/Data structures. Additionally are defined functions for populating TileData into *Tile structures (as would be used from map generation or spawning operations).
******/
#include <stdlib.h>
#include <string.h>
#include <limits.h> // for ULONG_MAX
#include "data.h"
/**** loadDataFromMemory
Loads given data from memory into a Data struct, also populating TileSetData and TileData structs.
****/
struct Data *loadDataFromMemory(char *memory, int size) {
struct Data *data = malloc(sizeof(struct Data));
data->size = SET_SIZE;
data->id = malloc(sizeof(int)*SET_SIZE);
data->set = malloc(sizeof(struct TileSetData*)*SET_SIZE);
memset(data->set, 0, sizeof(struct TileSetData*)*SET_SIZE);
int offset = 0;
int depth = 0; // used to manage position!
data->set_count = 0;
while (offset <= size) {
if (memory[offset] == '{') {
depth++;
offset++; // skip that bracket
if (depth == 1) {
// now we get our tileset's id
char temp_string[31];
int temp_offset = offset-1;
int temp_offset_2 = 0;
while (memory[temp_offset] != '\n' && temp_offset > 0) {
temp_offset--;
}
while (memory[temp_offset] != '{') {
temp_string[temp_offset_2++] = memory[temp_offset++];
}
temp_string[temp_offset_2] = '\0';
int tileset_id = atoi(temp_string);
// resize Data if tileset's id is greater than our size
if (tileset_id > data->size) {
data->size += tileset_id-data->size;
void *ret;
ret = realloc(data->id, sizeof(int)*data->size);
ret = realloc(data->set, sizeof(struct TileSetData*)*data->size);
}
data->set[tileset_id] = loadTileSetData(tileset_id, memory, &offset, &depth);
data->set_count++;
}
} else if (memory[offset] == '}') {
depth--;
}
offset++;
}
return data;
}
struct TileData *getTileDataByKey(struct Data *data, char *key) {
int data_set = 0;
while (data_set < data->size) {
if (data->set[data_set] != NULL) {
int *tid = getTablePairValue(data->set[data_set]->keys, key);
if (tid != NULL) {
return data->set[data_set]->tile[*tid];
}
}
data_set++;
}
return NULL;
}
struct TileData *getTileDataById(struct Data *data, int tileset_id, int tile_id) {
if (data->set[tileset_id] != NULL) {
if (data->set[tileset_id]->tile[tile_id] != NULL) {
return data->set[tileset_id]->tile[tile_id];
}
}
return NULL;
}
struct TileSetData *loadTileSetData(int tileset_id, char *memory, int *offset, int *depth) {
struct TileSetData *set_data = malloc(sizeof(struct TileSetData));
set_data->tid = tileset_id;
set_data->tile_count = 0;
set_data->size = SET_SIZE; // default of 32
set_data->keys = newTable(set_data->size);
set_data->tile = malloc(sizeof(struct TileData*)*SET_SIZE);
/* populate Tiles! */
while (*depth != 0) {
if (memory[*offset] == '{') {
*offset = *offset + 1; //skip the bracket
*depth = *depth + 1;
if (*depth == 2) {
// now we get our tileset's id
char temp_string[31];
int temp_offset = *offset-1;
int temp_offset_2 = 0;
while (memory[temp_offset] != '\n' && temp_offset > 0) {
temp_offset--;
}
while (memory[temp_offset] != '{') {
temp_string[temp_offset_2++] = memory[temp_offset++];
}
temp_string[temp_offset_2] = '\0';
int tile_id = atoi(temp_string);
// resize Data if tileset's id is greater than our size
if (tile_id > set_data->size) {
set_data->size += tile_id-set_data->size;
void *ret;
ret = realloc(set_data->tile, sizeof(struct TileData*)*set_data->size);
}
// if tile entry already exists, free old one and load in new one
if (set_data->tile[tile_id] != NULL) {
// FIXME: must free data for overwrite
//freeTileData(set_data->tile[tile_id]);
} else {
set_data->tile_count++;
}
set_data->tile[tile_id] = loadTileData(tile_id, memory, offset, depth);
set_data->tile[tile_id]->tid = tileset_id; // store the tileset id in tile as well
// now let's
//printf("--> key->id: (%s)%d=>%d\n", getTablePairValue(set_data->tile[tile_id]->table, "name"), getTableIndex(set_data->keys, getTablePairValue(set_data->tile[tile_id]->table, "name")), tile_id);
addTablePair(set_data->keys, getTablePairValue(set_data->tile[tile_id]->table, "name"), &tile_id, sizeof(int), T_INT);
//printf("<-- key->id: (%s)%d=>%d\n", getTablePairValue(set_data->tile[tile_id]->table, "name"), getTableIndex(set_data->keys, getTablePairValue(set_data->tile[tile_id]->table, "name")), *(int*)getTablePairValue(set_data->keys, getTablePairValue(set_data->tile[tile_id]->table, "name")));
}
} else if (memory[*offset] == '}') {
*depth = *depth - 1;
}
*offset = *offset + 1;
}
return set_data;
}
/**** loadTileData
This function is the third step in the linear processing of a data file - it takes an offset and begins processing at that memory until the depth is less than or equal to 1. What it actually does is convert all lines into key=>value pairs (using a Table and TablePairs), with the key delimited from the value by the first occurance of a space character after a non-space character has occurred. ex: " name my name" = name=>"my name"
From that point forward, properties can be retrieved from the TileData's Table by using the various getTable* functions.
****/
struct TileData *loadTileData(int id, char *memory, int *offset, int *depth) {
struct TileData *tile_data = malloc(sizeof(struct TileData));
tile_data->id = id;
tile_data->count = 0;
tile_data->size = 8;
tile_data->table = newTable(8);
char var_name[32]; // max 32 chars for var name
char var_value[256]; // max 256 chars for value
int i = 0;
short mode = 0;
while(*depth > 1) {
switch (memory[*offset]) {
case '{':
*depth = *depth + 1;
break;
case '}':
*depth = *depth - 1;
break;
case ' ':
if (mode == 1) {
var_name[i] = '\0';
i = 0;
mode = 2;
} else if (mode == 2) {
var_value[i++] = memory[*offset];
}
break;
case '\n':
var_value[i] = '\0';
if (mode == 2) {
if (*depth == 2) {
addTablePair(tile_data->table, var_name, var_value, strlen(var_value)+1, T_STRING);
printf("%s(%d)=>%s\n", var_name, getTableIndex(tile_data->table, var_name), (char*)getTablePair(tile_data->table, var_name)->value);
}
}
i = 0;
mode = 0;
break;
default:
if (mode == 1) {
var_name[i++] = memory[*offset];
} else if (mode == 2) {
var_value[i++] = memory[*offset];
} else if (mode == 0) {
mode = 1;
var_name[i++] = memory[*offset];
}
break;
}
if (*depth <= 1)
break;
*offset = *offset + 1;
}
return tile_data;
}
void freeTileData(struct TileData *tile_data) {
freeTable(tile_data->table);
free(tile_data);
}
struct Table *newTable(int size) {
struct Table *table = malloc(sizeof(struct Table));
table->size = size;
table->pair = malloc(sizeof(struct TablePair*)*size);
return table;
}
void freeTable(struct Table *table) {
int i = 0;
while (i < table->size) {
freeTablePair(table->pair[i++]);
}
free(table->pair);
free(table);
}
int getTableIndex(struct Table *table, char *key) {
if (key == NULL)
return NULL;
int i = 0;
int index = 0;
int key_length = strlen(key);
while (index < INT_MAX && i < key_length) {
index += key[i++];
}
return index % table->size;
}
struct TablePair *getTablePair(struct Table *table, char *key) {
struct TablePair *pair = table->pair[getTableIndex(table, key)];
while (pair != NULL) {
if (strcmp(key, pair->key) == 0) {
return pair;
}
pair = pair->next;
}
return NULL;
}
/**** getTablePairValue
Attempts to return the TablePair value of given key. If the TablePair's type is of T_INT, T_FLOAT, or other such values, the
****/
void *getTablePairValue(struct Table *table, char *key) {
struct TablePair *pair = getTablePair(table, key);
if (pair != NULL) {
return pair->value;
}
return NULL;
}
int addTablePair(struct Table *table, char *key, void *value, int value_size, int type) {
if (key == NULL || value == NULL)
return -10;
int index = getTableIndex(table, key);
if (table->pair[index] == NULL) {
struct TablePair *table_pair = malloc(sizeof(struct TablePair));
if (table_pair == NULL)
return -1;
setTablePair(table_pair, key, value, value_size, type);
table->pair[index] = table_pair;
} else {
struct TablePair *current_pair = table->pair[index];
while (1) {
if (strcmp(key, current_pair->key) == 0) {
current_pair->value = value;
break;
} else {
if (current_pair->next == NULL) {
struct TablePair *table_pair = malloc(sizeof(struct TablePair));
if (table_pair == NULL)
return -2;
setTablePair(table_pair, key, value, value_size, type);
current_pair->next = table_pair;
break;
} else {
current_pair = current_pair->next;
}
}
}
}
return 0;
}
void setTablePair(struct TablePair *table_pair, char *key, void *value, int value_size, int type) {
int key_size = strlen(key)+1;
table_pair->key = malloc(key_size);
memcpy(table_pair->key, key, key_size);
table_pair->value = malloc(value_size);
memcpy(table_pair->value, value, value_size);
table_pair->type = type;
table_pair->next = NULL;
}
void freeTablePair(struct TablePair *table_pair) {
struct TablePair *pair = table_pair;
while (pair != NULL) {
struct TablePair *sub_pair = pair->next;
free(pair->key);
free(pair->value);
free(pair);
pair = sub_pair;
}
}