1137 lines
38 KiB
C
1137 lines
38 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). Finally, and more tertiary, this file also defines functions for loading files into memory.
|
|
******/
|
|
#include <stdio.h> // for file reading
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <limits.h> // for ULONG_MAX
|
|
#include <ctype.h> // for isdigit
|
|
#include "data.h"
|
|
#include "c_extra.h"
|
|
|
|
/*
|
|
================================================================
|
|
Table
|
|
|
|
These functions provide access, manipulation, and deletion to Tables. Table(s) are a key=>value storage struct that act similar to associative arrays.
|
|
================================================================
|
|
*/
|
|
struct Table *newTable(int size) {
|
|
struct Table *table = malloc(sizeof(struct Table));
|
|
table->size = size;
|
|
table->count = 0;
|
|
table->pair = malloc(sizeof(struct TablePair*)*size);
|
|
int i = 0;
|
|
while (i != size) {
|
|
table->pair[i++] = NULL;
|
|
}
|
|
//memset(table->pair, sizeof(struct TablePair*)*size, NULL);
|
|
return table;
|
|
}
|
|
|
|
struct Table *duplicateTable(struct Table *table) {
|
|
struct Table *new_table = malloc(table->size);
|
|
if (new_table == NULL) {
|
|
printf("ERR: duplicateTable failed!\n");
|
|
return NULL;
|
|
}
|
|
memcpy(new_table, table, sizeof(struct Table));
|
|
|
|
int i = 0;
|
|
while (i < table->size) {
|
|
if (table->pair[i] != NULL) {
|
|
new_table->pair[i] = duplicateTablePair(table->pair[i]);
|
|
}
|
|
i++;
|
|
}
|
|
return new_table;
|
|
}
|
|
|
|
void freeTable(struct Table *table) {
|
|
int i = 0;
|
|
while (i < table->size) {
|
|
if (table->pair[i] != NULL) {
|
|
freeTablePair(table->pair[i]);
|
|
}
|
|
i++;
|
|
}
|
|
free(table->pair);
|
|
free(table);
|
|
}
|
|
|
|
int getTableIndex(struct Table *table, const char *key) {
|
|
if (key == NULL)
|
|
return -1;
|
|
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;
|
|
}
|
|
|
|
/*
|
|
================================================================
|
|
TablePair
|
|
|
|
These functions provide access, manipulation, and deletion of TablePair structs. TablePair structs are the key=>value container held by Table(s). When a value is added to a TablePair, memory equal to the size of the value (providing it is given) is allocated and pointed to by the TablePair's value property. The value passed is then memcpy'd into that location.
|
|
|
|
Each TablePair also contains the TablePair pointer, /next/, which is used for linked list behavior if a TablePair already exists at a given index in a Table and the TablePair at that index is not the same as the TablePair.
|
|
|
|
Datatype-specific storing wrapper functions (e.g., addTablePairInt) to addTablePair are provided to allow for easier implementation (no direct usage of value pointers). Retrieval functions are also provided to ensure unspecified behavior does not occur. If the user accesses a TablePair->value with the wrong data type than intended, a value of zero or "blank" is returned(int,float=0, char,string = '\0'), providing the appropriate getTablePair function is called.
|
|
================================================================
|
|
*/
|
|
int addTablePair(struct Table *table, const char *key, void *value, int value_size, int type) {
|
|
if (key == NULL) return 1;
|
|
int index = getTableIndex(table, key);
|
|
struct TablePair *table_pair = table->pair[index];
|
|
if (table_pair == NULL) { // doesn't exist, let's create
|
|
table_pair = malloc(sizeof(struct TablePair));
|
|
if (table_pair == NULL)
|
|
return 2;
|
|
setTablePair(table_pair, key, value, value_size, type);
|
|
table->pair[index] = table_pair;
|
|
table->count++;
|
|
} else { // pair exists at index
|
|
while(table_pair != NULL) {
|
|
// key already exists, set its value to passed value
|
|
if (strcmp(key, table_pair->key) == 0) {
|
|
free(table_pair->key);
|
|
free(table_pair->value);
|
|
setTablePair(table_pair, key, value, value_size, type);
|
|
break; // let's get out of here!
|
|
}
|
|
if (table_pair->next == NULL) {
|
|
// pair's next is null, so let's _assume the position_
|
|
table_pair->next = malloc(sizeof(struct TablePair));
|
|
if (table_pair->next == NULL)
|
|
return 2;
|
|
setTablePair(table_pair->next, key, value, value_size, type);
|
|
table->count++;
|
|
break; // bustin out
|
|
}
|
|
table_pair = table_pair->next; // continue down the line
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int addTablePairAtIndex(struct Table *table, int index, void *value, int value_size, int type) {
|
|
struct TablePair *table_pair = table->pair[index];
|
|
if (table_pair == NULL) { // doesn't exist, let's create
|
|
table_pair = malloc(sizeof(struct TablePair));
|
|
if (table_pair == NULL)
|
|
return 2;
|
|
setTablePairAtIndex(table_pair, index, value, value_size, type);
|
|
table->pair[index] = table_pair;
|
|
table->count++;
|
|
} else { // pair exists at index
|
|
while(table_pair != NULL) {
|
|
// key already exists, set its value to passed value
|
|
char key[6]; // FIXME
|
|
itoa(index, (char *)key, 10);
|
|
if (strcmp(key, table_pair->key) == 0) {
|
|
free(table_pair->key);
|
|
free(table_pair->value);
|
|
setTablePairAtIndex(table_pair, index, value, value_size, type);
|
|
break; // let's get out of here!
|
|
}
|
|
if (table_pair->next == NULL) {
|
|
// pair's next is null, so let's _assume the position_
|
|
table_pair->next = malloc(sizeof(struct TablePair));
|
|
if (table_pair->next == NULL)
|
|
return 2;
|
|
setTablePairAtIndex(table_pair->next, index, value, value_size, type);
|
|
table->count++;
|
|
break; // bustin out
|
|
}
|
|
table_pair = table_pair->next; // continue down the line
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
int addTablePairPointer(struct Table *table, const char *key, void *value, 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;
|
|
setTablePairPointer(table_pair, key, value, type);
|
|
table->pair[index] = table_pair;
|
|
table->count++;
|
|
} 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;
|
|
setTablePairPointer(table_pair, key, value, type);
|
|
current_pair->next = table_pair;
|
|
table->count++;
|
|
break;
|
|
} else {
|
|
current_pair = current_pair->next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int addTablePairInt(struct Table *table, const char *key, int value) {
|
|
return (addTablePair(table, key, &value, sizeof(int), T_INT));
|
|
}
|
|
|
|
int addTablePairFloat(struct Table *table, const char *key, float value) {
|
|
return (addTablePair(table, key, &value, sizeof(float), T_FLOAT));
|
|
}
|
|
|
|
int addTablePairChar(struct Table *table, const char *key, char value) {
|
|
return (addTablePair(table, key, &value, sizeof(char), T_CHAR));
|
|
}
|
|
|
|
int addTablePairString(struct Table *table, const char *key, char *value) {
|
|
return (addTablePair(table, key, &value, sizeof(char*), T_STRING));
|
|
}
|
|
|
|
void setTablePair(struct TablePair *table_pair, const 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->value_size = value_size;
|
|
|
|
table_pair->type = type;
|
|
table_pair->next = NULL;
|
|
}
|
|
|
|
// TODO: this is named stupid to match it to addTablePairIndex
|
|
void setTablePairAtIndex(struct TablePair *table_pair, int index, void *value, int value_size, int type) {
|
|
// FIXME: we are limited index size to 6 digits long
|
|
char key[6];
|
|
itoa(index, (char *)key, 10);
|
|
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->value_size = value_size;
|
|
|
|
table_pair->type = type;
|
|
table_pair->next = NULL;
|
|
}
|
|
|
|
void setTablePairPointer(struct TablePair *table_pair, const char *key, void *value, int type) {
|
|
int key_size = strlen(key)+1;
|
|
table_pair->key = malloc(key_size);
|
|
memcpy(table_pair->key, key, key_size);
|
|
|
|
table_pair->value = value;
|
|
table_pair->value_size = sizeof(void *);
|
|
|
|
table_pair->type = type;
|
|
table_pair->next = NULL;
|
|
}
|
|
|
|
struct TablePair *getTablePair(struct Table *table, const char *key) {
|
|
if (table == NULL)
|
|
return NULL;
|
|
struct TablePair *pair = table->pair[getTableIndex(table, key)];
|
|
while (pair != NULL) {
|
|
if (strcmp(key, pair->key) == 0) {
|
|
return pair;
|
|
}
|
|
pair = pair->next;
|
|
}
|
|
//printf("could not find %s\n", key);
|
|
return NULL;
|
|
}
|
|
|
|
void *getTablePairValue(struct Table *table, const char *key) {
|
|
struct TablePair *pair = getTablePair(table, key);
|
|
if (pair != NULL) {
|
|
return pair->value;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int getTablePairValueInt(struct Table *table, const char *key) {
|
|
struct TablePair *pair = getTablePair(table, key);
|
|
if (pair != NULL) {
|
|
if (pair->type != T_INT) {
|
|
return 0;
|
|
} else {
|
|
return *(int*)pair->value;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
float getTablePairValueFloat(struct Table *table, const char *key) {
|
|
struct TablePair *pair = getTablePair(table, key);
|
|
if (pair != NULL) {
|
|
if (pair->type != T_FLOAT) {
|
|
return 0.0f;
|
|
} else {
|
|
return *(float*)pair->value;
|
|
}
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
char getTablePairValueChar(struct Table *table, const char *key) {
|
|
struct TablePair *pair = getTablePair(table, key);
|
|
if (pair != NULL) {
|
|
if (pair->type != T_CHAR) {
|
|
return 0;
|
|
} else {
|
|
return *(char*)pair->value;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char *getTablePairValueString(struct Table *table, const char *key) {
|
|
struct TablePair *pair = getTablePair(table, key);
|
|
if (pair != NULL) {
|
|
if (pair->type != T_STRING) {
|
|
return '\0';
|
|
} else {
|
|
return (char*)pair->value;
|
|
}
|
|
}
|
|
return '\0';
|
|
}
|
|
|
|
struct Table* getTablePairValueTable(struct Table *table, const char *key) {
|
|
struct TablePair *pair = getTablePair(table, key);
|
|
if (pair != NULL) {
|
|
if (pair->type != T_TABLE) {
|
|
return 0;
|
|
} else {
|
|
return (struct Table*)pair->value;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int dumpTable(struct Table *table, int depth) {
|
|
int i = 0;
|
|
char i_depth[31]; // just cap it for now
|
|
i_depth[0] = '\0';
|
|
while(i<depth) {
|
|
i_depth[i] = '\t';
|
|
i_depth[i+1] = '\0';
|
|
i++;
|
|
}
|
|
i = 0;
|
|
while (i < table->size) {
|
|
struct TablePair *entry = table->pair[i];
|
|
// use a loop here, as multiple TablePairs can occupy the same index
|
|
while (entry != NULL) {
|
|
switch(entry->type) {
|
|
case T_INT:
|
|
printf("%s%s=>%d(int)\n", i_depth, entry->key, *(int*)entry->value);
|
|
break;
|
|
case T_FLOAT:
|
|
printf("%s%s=>%f(float)\n", i_depth, entry->key, *(float*)entry->value);
|
|
break;
|
|
case T_CHAR:
|
|
printf("%s%s=>%c(char)\n", i_depth, entry->key, *(char *)entry->value);
|
|
break;
|
|
case T_STRING:
|
|
printf("%s%s=>%s(string)\n", i_depth, entry->key, (char *)entry->value);
|
|
break;
|
|
case T_TABLE:
|
|
printf("%s%s=>\n", i_depth, entry->key);
|
|
dumpTable(entry->value, depth+1);
|
|
break;
|
|
}
|
|
entry = entry->next;
|
|
}
|
|
i++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int deleteTablePair(struct Table *table, char *key) {
|
|
if (key == NULL)
|
|
return -10;
|
|
int index = getTableIndex(table, key);
|
|
if (table->pair[index] == NULL) {
|
|
// does not exist
|
|
return -1;
|
|
} else {
|
|
struct TablePair *current_pair = table->pair[index];
|
|
struct TablePair *last_pair = NULL;
|
|
while (1) {
|
|
if (strcmp(key, current_pair->key) == 0) {
|
|
// we have a match, so let's repair the chain if needed
|
|
if (current_pair->next != NULL) {
|
|
last_pair->next = current_pair->next;
|
|
}
|
|
freeTablePair(current_pair);
|
|
table->count--;
|
|
break;
|
|
} else {
|
|
if (current_pair->next == NULL) {
|
|
// does not exist
|
|
return -1;
|
|
} else {
|
|
last_pair = current_pair;
|
|
current_pair = current_pair->next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct TablePair *duplicateTablePair(struct TablePair *from) {
|
|
struct TablePair *new_pair = malloc(sizeof(struct TablePair));
|
|
if (new_pair == NULL) {
|
|
printf("ERR: duplicateTablePair failed\n");
|
|
return NULL;
|
|
}
|
|
memcpy(new_pair, from, sizeof(struct TablePair));
|
|
|
|
// copy key
|
|
int key_size = strlen(from->key)+1;
|
|
new_pair->key = malloc(key_size);
|
|
if (new_pair->key == NULL) {
|
|
printf("ERR: duplicateTablePair key failed\n");
|
|
free(new_pair);
|
|
return NULL;
|
|
}
|
|
memcpy(new_pair->key, from->key, key_size);
|
|
// copy value
|
|
new_pair->value = malloc(from->value_size);
|
|
if (new_pair->value == NULL) {
|
|
printf("ERR: duplicateTablePair value failed\n");
|
|
free(new_pair->key);
|
|
free(new_pair);
|
|
return NULL;
|
|
}
|
|
memcpy(new_pair->value, from->value, from->value_size);
|
|
// TODO: ugh, we need to copy InventoryData too.
|
|
|
|
if (from->next != NULL) {
|
|
new_pair->next = duplicateTablePair(from->next);
|
|
}
|
|
return new_pair;
|
|
}
|
|
|
|
void freeTablePair(struct TablePair *table_pair) {
|
|
struct TablePair *pair = table_pair;
|
|
while (pair != NULL) {
|
|
struct TablePair *sub_pair = pair->next;
|
|
free(pair->key);
|
|
switch (pair->type) {
|
|
case T_POINTER:
|
|
// we do nothing with pointers - remember to free yoself!
|
|
break;
|
|
case T_PROTO_INVENTORY:
|
|
freeInventoryData(pair->value);
|
|
break;
|
|
default:
|
|
free(pair->value);
|
|
break;
|
|
}
|
|
free(pair);
|
|
pair = sub_pair;
|
|
}
|
|
}
|
|
/*
|
|
================================================================
|
|
Data
|
|
|
|
These functions are related to the loading of TSD files into a Data struct. This Data struct also contains TileSetData, which then contains TileData.
|
|
================================================================
|
|
*/
|
|
/*
|
|
================================
|
|
struct Data *loadDataFromMemory(char *memory, int size)
|
|
|
|
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-1) { // err, size-1? FIXME
|
|
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;
|
|
data->id = realloc(data->id, sizeof(int)*data->size);
|
|
data->set = 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;
|
|
}
|
|
|
|
int saveDataToFile(struct Data* data, const char *filename) {
|
|
FILE *output = fopen(filename, "w");
|
|
if (output == NULL) {
|
|
return -1;
|
|
}
|
|
int chars = 0;
|
|
int count = 0;
|
|
while (count < data->size) {
|
|
int count_2 = 0;
|
|
if (data->set[count]) {
|
|
chars += fprintf(output, "%d {\n", count);
|
|
while (count_2 < data->set[count]->size) {
|
|
if (data->set[count]->tile[count_2]) {
|
|
chars += fprintf(output, "%d {\n", count_2);
|
|
struct Table *table = data->set[count]->tile[count_2]->table;
|
|
int i = 0;
|
|
while (i < table->size) {
|
|
struct TablePair *table_pair = table->pair[i];
|
|
while (table_pair != NULL) {
|
|
if (table_pair->type == T_STRING) {
|
|
chars += fprintf(output, "%s %s\n", table_pair->key, (char*)table_pair->value);
|
|
} else if (table_pair->type == T_INT) {
|
|
chars += fprintf(output, "%s %d\n", table_pair->key, *(int*)table_pair->value);
|
|
} else if (table_pair->type == T_FLOAT) {
|
|
chars += fprintf(output, "%s %f\n", table_pair->key, *(float*)table_pair->value);
|
|
} else if (table_pair->type == T_PROTO_INVENTORY) {
|
|
chars += fprintf(output, "%s {\n", table_pair->key);
|
|
struct InventoryData* inv = table_pair->value;
|
|
while (inv != NULL) {
|
|
chars += fprintf(output, "%s, %d-%d, %f\n", inv->name, inv->count.min, inv->count.max, inv->chance);
|
|
inv = inv->next;
|
|
}
|
|
chars += fprintf(output, "}\n");
|
|
}
|
|
table_pair = table_pair->next;
|
|
}
|
|
i++;
|
|
}
|
|
chars += fprintf(output, "}\n");
|
|
}
|
|
count_2++;
|
|
}
|
|
chars += fprintf(output, "}\n");
|
|
}
|
|
count++;
|
|
}
|
|
fclose(output);
|
|
return chars;
|
|
}
|
|
|
|
void freeData(struct Data *data) {
|
|
// MAJOR TODO: actually free the Data
|
|
free(data->id);
|
|
free(data->set);
|
|
free(data);
|
|
}
|
|
|
|
/*
|
|
================================================================
|
|
TileSetData
|
|
|
|
These functions pertain to the TileSetData struct that contains a collection of TileData(s). Provided here is the loading mechanism that takes over from the earlier defined loadData. Also provided is a function to load a particular TileSetData by its TID from a Data struct.
|
|
================================================================
|
|
*/
|
|
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);
|
|
// just so we're not working with undeclared vars
|
|
int i = 0;
|
|
while (i < SET_SIZE) {
|
|
set_data->tile[i++] = NULL;
|
|
}
|
|
/* 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;
|
|
set_data->tile = 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;
|
|
}
|
|
|
|
struct TileSetData *getTileSetData(struct Data *data, int tileset_id) {
|
|
if (tileset_id > data->size) {
|
|
return NULL;
|
|
}
|
|
if (data->set[tileset_id] != NULL) {
|
|
return data->set[tileset_id];
|
|
}
|
|
return NULL;
|
|
}
|
|
/*
|
|
================================================================
|
|
TileData
|
|
|
|
These functions cover the allocation, accessing, and freeing of TileData structs from a larger Data struct. TileData structs will generally be referred to by their /id/, and contain a Table for their properties.
|
|
================================================================
|
|
*/
|
|
struct TileData *newTileData(int size) {
|
|
struct TileData *tile_data = malloc(sizeof(struct TileData));
|
|
tile_data->id = 0;
|
|
tile_data->count = 0;
|
|
tile_data->size = size;
|
|
tile_data->table = newTable(size);
|
|
return tile_data;
|
|
}
|
|
|
|
/*
|
|
================================
|
|
struct TileData *loadTileData(int id, char *memory, int *offset, int *depth)
|
|
|
|
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 = newTileData(8);
|
|
tile_data->id = id;
|
|
|
|
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;
|
|
short value_mode = 0;
|
|
while(*depth > 1) {
|
|
switch (memory[*offset]) {
|
|
case '{':
|
|
*depth = *depth + 1;
|
|
if (*depth == 3) {
|
|
*offset = *offset + 2; // skip that bracket and newline
|
|
// let's get the name for the inventory
|
|
char temp_string[31];
|
|
int temp_offset = *offset-2;
|
|
int temp_offset_2 = 0;
|
|
while (memory[temp_offset] != '\n' && temp_offset > 0) {
|
|
temp_offset--;
|
|
}
|
|
temp_offset++;
|
|
while (memory[temp_offset] != ' ') {
|
|
temp_string[temp_offset_2++] = memory[temp_offset++];
|
|
}
|
|
temp_string[temp_offset_2] = '\0';
|
|
struct InventoryData *inv = loadInventoryData(memory, offset, depth);
|
|
addTablePairPointer(tile_data->table, temp_string, inv, T_PROTO_INVENTORY);
|
|
mode = 0;
|
|
}
|
|
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) {
|
|
if (value_mode == T_CHAR) {
|
|
addTablePair(tile_data->table, var_name, var_value, strlen(var_value)+1, T_STRING);
|
|
printf("%s(%d)=>%s(string)\n", var_name, getTableIndex(tile_data->table, var_name), (char*)getTablePair(tile_data->table, var_name)->value);
|
|
} else if (value_mode == T_FLOAT) {
|
|
float val = atof(var_value);
|
|
addTablePair(tile_data->table, var_name, &val, sizeof(float*), T_FLOAT);
|
|
printf("%s(%d)=>%f(float)\n", var_name, getTableIndex(tile_data->table, var_name), *(float*)getTablePair(tile_data->table, var_name)->value);
|
|
} else {
|
|
int val = atoi(var_value);
|
|
addTablePair(tile_data->table, var_name, &val, sizeof(int*), T_INT);
|
|
printf("%s(%d)=>%d(int)\n", var_name, getTableIndex(tile_data->table, var_name), *(int*)getTablePair(tile_data->table, var_name)->value);
|
|
}
|
|
}
|
|
}
|
|
i = 0;
|
|
mode = 0;
|
|
value_mode = 0;
|
|
break;
|
|
default:
|
|
if (mode == 1) {
|
|
var_name[i++] = memory[*offset];
|
|
} else if (mode == 2) {
|
|
var_value[i++] = memory[*offset];
|
|
if (isdigit(memory[*offset]) == 0) {
|
|
// not exactly fail safe
|
|
if (memory[*offset] == '.' && value_mode != T_CHAR) {
|
|
value_mode = T_FLOAT;
|
|
} else {
|
|
value_mode = T_CHAR;
|
|
}
|
|
}
|
|
} else if (mode == 0) {
|
|
mode = 1;
|
|
var_name[i++] = memory[*offset];
|
|
}
|
|
break;
|
|
}
|
|
if (*depth <= 1)
|
|
break;
|
|
*offset = *offset + 1;
|
|
}
|
|
return tile_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 (tile_id >= data->size) {
|
|
return NULL;
|
|
}
|
|
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 TileData *duplicateTileData(struct TileData *data) {
|
|
struct TileData *new_data = malloc(sizeof(struct TileData));
|
|
if (new_data == NULL) {
|
|
printf("ERR: duplicateTileData failed!\n");
|
|
return NULL;
|
|
}
|
|
memcpy(new_data, data, sizeof(struct TileData));
|
|
new_data->table = duplicateTable(data->table);
|
|
return new_data;
|
|
}
|
|
|
|
void freeTileData(struct TileData *tile_data) {
|
|
freeTable(tile_data->table);
|
|
free(tile_data);
|
|
}
|
|
|
|
/*
|
|
================================================================
|
|
InventoryData
|
|
|
|
These functions cover the loading(from memory), allocation, setting, and freeing of InventoryData structs. InventoryData structs contain a TID, ID, count range, chance, and name for a target Tile, as well as the InventoryData pointer, /next/, used for InventoryData(s)' linked list behavior.
|
|
================================================================
|
|
*/
|
|
struct InventoryData *newInventoryData() {
|
|
struct InventoryData *inventory_data = malloc(sizeof(struct InventoryData));
|
|
inventory_data->tid = 0;
|
|
inventory_data->id = 0;
|
|
inventory_data->count.min = 1;
|
|
inventory_data->count.max = 1;
|
|
inventory_data->chance = 100.0f;
|
|
inventory_data->name = malloc(6);
|
|
memcpy(inventory_data->name, "undef", 6);
|
|
inventory_data->next = NULL;
|
|
return inventory_data;
|
|
}
|
|
|
|
struct InventoryData *loadInventoryData(char *memory, int *offset, int *depth) {
|
|
struct InventoryData *inventory_data = newInventoryData();
|
|
struct InventoryData *first_data = inventory_data;
|
|
struct InventoryData *last_data = NULL;
|
|
// mode, 0 = name, 1 = count, 2 = chance
|
|
char temp_string[64];
|
|
int temp_i = 0;
|
|
int mode = 0;
|
|
while (*depth > 2) {
|
|
switch(memory[*offset]) {
|
|
case '{':
|
|
*depth = *depth +1;
|
|
break;
|
|
case '}':
|
|
*depth = *depth - 1;
|
|
break;
|
|
case ' ':
|
|
if (mode == 0)
|
|
temp_string[temp_i++] = memory[*offset];
|
|
break;
|
|
case '\n':
|
|
temp_string[temp_i] = '\0';
|
|
if (mode == 0) {
|
|
inventory_data->name = realloc(inventory_data->name, temp_i+1);
|
|
memcpy(inventory_data->name, temp_string, temp_i+1);
|
|
} else if (mode == 1) {
|
|
char chance_buffer[64];
|
|
int ch_buffer_i = 0;
|
|
int temp_offset = 0;
|
|
int c_mode = 0;
|
|
while (temp_offset != temp_i) {
|
|
switch(temp_string[temp_offset]) {
|
|
case '-':
|
|
chance_buffer[ch_buffer_i] = '\0';
|
|
inventory_data->count.min = atoi(chance_buffer);
|
|
c_mode = 1;
|
|
ch_buffer_i = 0;
|
|
break;
|
|
default:
|
|
chance_buffer[ch_buffer_i++] = temp_string[temp_offset];
|
|
break;
|
|
}
|
|
temp_offset++;
|
|
}
|
|
chance_buffer[ch_buffer_i] = '\0';
|
|
if (c_mode == 0)
|
|
inventory_data->count.min = atoi(chance_buffer);
|
|
inventory_data->count.max = atoi(chance_buffer);
|
|
} else if (mode == 2) {
|
|
inventory_data->chance = atof(temp_string);
|
|
}
|
|
temp_i = 0;
|
|
mode = 0;
|
|
if (last_data != NULL)
|
|
last_data->next = inventory_data;
|
|
last_data = inventory_data;
|
|
inventory_data = newInventoryData();
|
|
break;
|
|
case ',':
|
|
temp_string[temp_i] = '\0';
|
|
if (mode == 0) {
|
|
inventory_data->name = realloc(inventory_data->name, temp_i+1);
|
|
memcpy(inventory_data->name, temp_string, temp_i+1);
|
|
} else if (mode == 1) {
|
|
char chance_buffer[64];
|
|
int ch_buffer_i = 0;
|
|
int temp_offset = 0;
|
|
int c_mode = 0;
|
|
while (temp_offset != temp_i) {
|
|
switch(temp_string[temp_offset]) {
|
|
case '-':
|
|
chance_buffer[ch_buffer_i] = '\0';
|
|
inventory_data->count.min = atoi(chance_buffer);
|
|
c_mode = 1;
|
|
ch_buffer_i = 0;
|
|
break;
|
|
default:
|
|
chance_buffer[ch_buffer_i++] = temp_string[temp_offset];
|
|
break;
|
|
}
|
|
temp_offset++;
|
|
}
|
|
chance_buffer[ch_buffer_i] = '\0';
|
|
if (c_mode == 0)
|
|
inventory_data->count.min = atoi(chance_buffer);
|
|
inventory_data->count.max = atoi(chance_buffer);
|
|
} else if (mode == 2) {
|
|
inventory_data->chance = atof(temp_string);
|
|
}
|
|
temp_i = 0;
|
|
mode++;
|
|
break;
|
|
default:
|
|
temp_string[temp_i++] = memory[*offset];
|
|
break;
|
|
}
|
|
*offset = *offset + 1;
|
|
}
|
|
return first_data;
|
|
}
|
|
|
|
void setInventoryDataName(struct InventoryData *inventory, const char *name) {
|
|
int length = strlen(name)+1;
|
|
inventory->name = realloc(inventory->name, length);
|
|
memcpy(inventory->name, name, length);
|
|
}
|
|
|
|
void freeInventoryData(struct InventoryData *inventory_data) {
|
|
struct InventoryData *current_data = inventory_data;
|
|
while (current_data != NULL) {
|
|
struct InventoryData *next_data = current_data->next;
|
|
free(current_data->name);
|
|
free(current_data);
|
|
current_data = next_data;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================================================================
|
|
etc
|
|
================================================================
|
|
*/
|
|
/*
|
|
================================
|
|
int loadConfig_r(struct Table *table, char *memory, int size, int *offset)
|
|
|
|
This function takes a Table ptr(*table), a ptr to a buffer(*memory), the memory's byte size(size), and an int ptr(*offset) for the current offset within the buffer. The *offset ptr is used for recursion, however the model may be changed so that loadConfig_r takes a normal int as start offset and returns the new offset.
|
|
|
|
What the function actually does is take a tsCS-formatted "string"(memory) and populates the passed Table with TablePair representations of tcCS.
|
|
================================
|
|
*/
|
|
int loadConfig_r(struct Table *table, char *memory, int size, int *offset) {
|
|
char var_name[63]; // max var_name of 64 inc. terminating char
|
|
int var_name_i = 0; // var name offset
|
|
char var_value[255]; // max var_value of 256 bytes inc. term ch
|
|
int var_value_i = 0; // var value offset
|
|
/*
|
|
0 = search for varname start
|
|
1 = search for varname end
|
|
2 = search for var start
|
|
3 = search for var end as digit
|
|
4 = search for var end as float
|
|
5 = search for var end as string
|
|
6 = search for var end as Table
|
|
10 = eat line mode (for comments)
|
|
*/
|
|
int mode = 0;
|
|
while(*offset < size) {
|
|
switch(mode) {
|
|
case 0: // search for varname start
|
|
switch(memory[*offset]) {
|
|
case ';': // it's a comment, switch to mode 10
|
|
mode = 10;
|
|
break;
|
|
case ' ': // skip spaces, tabs, and newlines
|
|
case '\t':
|
|
case '\n':
|
|
break;
|
|
case '}': // if we run into this, that should mean we are recursively called
|
|
// TODO: clean up and return
|
|
return -1;
|
|
break;
|
|
default: // if alpha, set var_name to char and mode to 1
|
|
var_name[var_name_i++] = memory[*offset];
|
|
mode = 1;
|
|
break;
|
|
}
|
|
break;
|
|
case 1: // var name populating and end
|
|
switch(memory[*offset]) {
|
|
case '\n': // reset if newline
|
|
var_name_i = 0;
|
|
var_name[0] = '\0';
|
|
var_value_i = 0;
|
|
var_value[0] = '\0';
|
|
mode = 0;
|
|
break;
|
|
case ' ':
|
|
case '\t': // space, meaning end of var name
|
|
var_name[var_name_i] = '\0';
|
|
mode = 2;
|
|
break;
|
|
default:
|
|
var_name[var_name_i++] = memory[*offset];
|
|
break;
|
|
}
|
|
break;
|
|
case 2: // var find data begin
|
|
switch(memory[*offset]) {
|
|
case '\n': // reset on newline
|
|
var_value_i = 0;
|
|
var_value[0] = '\0';
|
|
var_name_i = 0;
|
|
var_name[0] = '\0';
|
|
mode = 0;
|
|
break;
|
|
case ' ':
|
|
case '\t': // eat spaces and tabs
|
|
break;
|
|
case '{': // Data section, begin recursion
|
|
mode = 6;
|
|
break;
|
|
default:
|
|
if (isdigit(memory[*offset])) {
|
|
var_value[var_value_i++] = memory[*offset];
|
|
mode = 3; // switch to digit processing
|
|
} else {
|
|
var_value[var_value_i++] = memory[*offset];
|
|
mode = 5; // switch to string processing
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 3: // digit var type
|
|
if (memory[*offset] == '\n') {
|
|
var_value[var_value_i] = '\0';
|
|
int integer = atoi(var_value);
|
|
addTablePair(table, var_name, &integer, sizeof(int*), T_INT);
|
|
//printf("%s=>%s(int)\n", var_name, var_value);
|
|
var_name_i = 0;
|
|
var_name[0] = '\0';
|
|
var_value_i = 0;
|
|
var_value[0] = '\0';
|
|
mode = 0;
|
|
} else {
|
|
if (!isdigit(memory[*offset])) {
|
|
if (memory[*offset] == '.') { // it may be a float
|
|
mode = 4;
|
|
} else {
|
|
mode = 5; // it's actually a string, switch!
|
|
}
|
|
}
|
|
var_value[var_value_i++] = memory[*offset];
|
|
}
|
|
break;
|
|
case 4: // float var type
|
|
if (memory[*offset] == '\n') {
|
|
var_value[var_value_i] = '\0';
|
|
float val = atof(var_value);
|
|
addTablePair(table, var_name, &val, sizeof(float*), T_FLOAT);
|
|
var_name_i = 0;
|
|
var_name[0] = '\0';
|
|
var_value_i = 0;
|
|
var_value[0] = '\0';
|
|
mode = 0;
|
|
} else {
|
|
if (!isdigit(memory[*offset])) {
|
|
mode = 5; // it's actually a string
|
|
}
|
|
var_value[var_value_i++] = memory[*offset];
|
|
}
|
|
break;
|
|
case 5: // string var type
|
|
// FIXME: I want to use var_name as index if it is a digit. Just doing this hack only on string for now, should fix.
|
|
{} // FIXME: figure out this label ish...
|
|
int index = -1;
|
|
if (isdigit(var_name[0])) {
|
|
index = atoi(var_name);
|
|
}
|
|
if (memory[*offset] == '\n') {
|
|
var_value[var_value_i] = '\0';
|
|
if (var_value_i == 1) { // single char
|
|
if (index != -1) {
|
|
addTablePairAtIndex(table, index, var_value, var_value_i, T_CHAR);
|
|
} else {
|
|
addTablePair(table, var_name, var_value, var_value_i, T_CHAR);
|
|
}
|
|
} else { // string
|
|
if (index != -1) {
|
|
addTablePairAtIndex(table, index, var_value, var_value_i+1, T_STRING);
|
|
} else {
|
|
addTablePair(table, var_name, var_value, var_value_i+1, T_STRING);
|
|
}
|
|
}
|
|
//printf("%s=>%s(string)\n", var_name, var_value);
|
|
var_name_i = 0;
|
|
var_name[0] = '\0';
|
|
var_value_i = 0;
|
|
var_value[0] = '\0';
|
|
mode = 0;
|
|
} else {
|
|
var_value[var_value_i++] = memory[*offset];
|
|
}
|
|
break;
|
|
case 6: // data section var type
|
|
{ // what the heck, label can only be part of a statement?
|
|
struct Table *new_table = newTable(32);
|
|
loadConfig_r(new_table, memory, size, offset);
|
|
addTablePairPointer(table, var_name, new_table, T_TABLE);
|
|
var_name_i = 0;
|
|
var_name[0] = '\0';
|
|
var_value_i = 0;
|
|
var_value[0] = '\0';
|
|
mode = 0;
|
|
}
|
|
// call self recursively
|
|
break;
|
|
case 10: // comment / eat line mode
|
|
// switch back to initial mode on newline
|
|
if (memory[*offset] == '\n')
|
|
mode = 0;
|
|
break;
|
|
}
|
|
*offset += 1;
|
|
}
|
|
return *offset;
|
|
}
|