diff --git a/src/heap.c b/src/heap.c new file mode 100644 index 0000000..a2203b6 --- /dev/null +++ b/src/heap.c @@ -0,0 +1,152 @@ +#include +#include + +#include "game.h" +#include "sprite.h" +#include "heap.h" +#include "registry.h" + +actor HEAP_ACTOR[MAX_HEAP_ACTOR]; +sprite HEAP_SPRITE[MAX_HEAP_SPRITE]; +spritesheet HEAP_SPRITESHEET[MAX_HEAP_SPRITESHEET]; +character HEAP_CHARACTER[MAX_HEAP_CHARACTER]; +string HEAP_STRING[MAX_HEAP_STRING]; + +void heap_init() +{ + int i = 0; + for ( i = 0; i < MAX_HEAP_ACTOR; i++) { + memset(&HEAP_ACTOR[i], 0x00, sizeof(actor)); + } + for ( i = 0; i < MAX_HEAP_SPRITE; i++) { + memset(&HEAP_SPRITE[i], 0x00, sizeof(sprite)); + } + for ( i = 0; i < MAX_HEAP_SPRITESHEET; i++) { + memset(&HEAP_SPRITESHEET[i], 0x00, sizeof(spritesheet)); + } + for ( i = 0; i < MAX_HEAP_CHARACTER; i++) { + memset(&HEAP_CHARACTER[i], 0x00, sizeof(character)); + } + for ( i = 0; i < MAX_HEAP_STRING; i++) { + memset(&HEAP_STRING[i], 0x00, sizeof(string)); + } +} + +actor *heap_next_actor() +{ + for (int i = 0; i < MAX_HEAP_ACTOR; i++ ) { + if ( HEAP_ACTOR[i].refcount != 0 ) { + continue; + } + return &HEAP_ACTOR[i]; + } + THROW(EXC_HEAPERROR, "Unable to find unused actor on the heap"); +} + +sprite *heap_next_sprite() +{ + for (int i = 0; i < MAX_HEAP_SPRITE; i++ ) { + if ( HEAP_SPRITE[i].refcount != 0 ) { + continue; + } + return &HEAP_SPRITE[i]; + } + THROW(EXC_HEAPERROR, "Unable to find unused sprite on the heap"); +} + +spritesheet *heap_next_spritesheet() +{ + for (int i = 0; i < MAX_HEAP_SPRITESHEET; i++ ) { + if ( HEAP_SPRITESHEET[i].refcount != 0 ) { + continue; + } + return &HEAP_SPRITESHEET[i]; + } + THROW(EXC_HEAPERROR, "Unable to find unused spritesheet on the heap"); +} + +character *heap_next_character() +{ + for (int i = 0; i < MAX_HEAP_CHARACTER; i++ ) { + if ( HEAP_CHARACTER[i].refcount != 0 ) { + continue; + } + return &HEAP_CHARACTER[i]; + } + THROW(EXC_HEAPERROR, "Unable to find unused character on the heap"); +} + +string *heap_next_string() +{ + for (int i = 0; i < MAX_HEAP_STRING; i++ ) { + if ( HEAP_STRING[i].refcount != 0 ) { + continue; + } + return &HEAP_STRING[i]; + } + THROW(EXC_HEAPERROR, "Unable to find unused string on the heap"); +} + +void heap_release_actor(actor *ptr) +{ + THROW_ZERO(ptr, EXC_NULLPOINTER, "NULL character reference"); + if ( ptr->refcount > 0 ) { + ptr->refcount -= 1; + } + if ( ptr->refcount == 0 ) { + heap_release_character(ptr->basechar); + SDL_ClearProperty(REGISTRY_ACTOR, (char *)&ptr->name); + } +} + +void heap_release_character(character *basechar) +{ + iterator opflags; + THROW_ZERO(basechar, EXC_NULLPOINTER, "NULL character reference"); + BITMASK_CLEAR(opflags.flags); + BITMASK_ADD(opflags.flags, ITERATOR_OP_RELEASE); + + if ( basechar->refcount > 0 ) { + basechar->refcount -= 1; + } + if ( basechar->refcount == 0 ) { + SDL_EnumerateProperties(basechar->state_sprites, &character_state_sprites_iterate, (void *)&opflags); + SDL_ClearProperty(REGISTRY_CHARACTER, (char *)&basechar->name); + } +} + +void heap_release_sprite(sprite *ptr) +{ + THROW_ZERO(ptr, EXC_NULLPOINTER, "Received NULL sprite reference"); + if ( ptr->refcount > 0 ) { + ptr->refcount -= 1; + } + if ( ptr->refcount == 0 ) { + heap_release_spritesheet(ptr->sheet); + SDL_ClearProperty(REGISTRY_SPRITE, (char *)&ptr->name); + } +} + +void heap_release_spritesheet(spritesheet *ptr) +{ + THROW_ZERO(ptr, EXC_NULLPOINTER, "Received NULL spritesheet reference"); + if ( ptr->refcount > 0 ) { + ptr->refcount -= 1; + } + if ( ptr->refcount == 0 ) { + // TODO : If we go threaded, make sure this is only happening on the main thread + SDL_DestroyTexture(ptr->texture); + SDL_ClearProperty(REGISTRY_CHARACTER, (char *)&ptr->name); + } +} + +void heap_release_string(string *ptr) +{ + THROW_ZERO(ptr, EXC_NULLPOINTER, "Received NULL spritesheet reference"); + if ( ptr->refcount > 0 ) { + ptr->refcount -= 1; + } + if ( ptr->refcount == 0 ) { + memset(ptr->data, 0x00, MAX_STRING_LENGTH); + } +} diff --git a/src/heap.h b/src/heap.h new file mode 100644 index 0000000..0f6700e --- /dev/null +++ b/src/heap.h @@ -0,0 +1,31 @@ +#ifndef _HEAP_H_ +#define _HEAP_H_ + +#include "sprite.h" +#include "string.h" + +#define MAX_HEAP_ACTOR 64 +#define MAX_HEAP_SPRITE (MAX_HEAP_ACTOR * 16) +#define MAX_HEAP_SPRITESHEET MAX_HEAP_SPRITE +#define MAX_HEAP_CHARACTER 256 +#define MAX_HEAP_STRING 256 + +extern actor HEAP_ACTOR[MAX_HEAP_ACTOR]; +extern sprite HEAP_SPRITE[MAX_HEAP_SPRITE]; +extern spritesheet HEAP_SPRITESHEET[MAX_HEAP_SPRITESHEET]; +extern character HEAP_CHARACTER[MAX_HEAP_CHARACTER]; +extern string HEAP_STRING[MAX_HEAP_STRING]; + +void heap_init(); +actor *heap_next_actor(); +sprite *heap_next_sprite(); +spritesheet *heap_next_spritesheet(); +character *heap_next_character(); +string *heap_next_string(); +void heap_release_actor(actor *ptr); +void heap_release_sprite(sprite *ptr); +void heap_release_spritesheet(spritesheet *ptr); +void heap_release_character(character *ptr); +void heap_release_string(string *ptr); + +#endif //_HEAP_H_ diff --git a/src/json_helpers.c b/src/json_helpers.c index 91356e3..84a1d4c 100644 --- a/src/json_helpers.c +++ b/src/json_helpers.c @@ -1,6 +1,8 @@ #include #include "json_helpers.h" #include "game.h" +#include "string.h" +#include "heap.h" json_t *get_json_object_value(json_t *obj, char *key) { @@ -41,13 +43,13 @@ float get_json_number_value(json_t *obj, char *key) return f; } -const char *get_json_string_value(json_t *obj, char *key) +string *get_json_string_value(json_t *obj, char *key) { - const char *s; + string *s = heap_next_string(); json_t *value = json_object_get(obj, key); THROW_ZERO(value, EXC_KEYERROR, key); THROW_ZERO(json_is_string(value), EXC_ATTRIBUTEERROR, key); - s = json_string_value(value); + strncpy(s->data, (char *)json_string_value(value), MAX_STRING_LENGTH); json_decref(value); return s; } diff --git a/src/json_helpers.h b/src/json_helpers.h index 401ac7a..8c1daf0 100644 --- a/src/json_helpers.h +++ b/src/json_helpers.h @@ -2,12 +2,13 @@ #define _JSON_HELPERS_H_ #include +#include "string.h" json_t *get_json_object_value(json_t *obj, char *key); bool get_json_boolean_value(json_t *obj, char *key); int get_json_integer_value(json_t *obj, char *key); float get_json_number_value(json_t *obj, char *key); -const char *get_json_string_value(json_t *obj, char *key); +string *get_json_string_value(json_t *obj, char *key); json_t *get_json_array_value(json_t *obj, char *key); json_t *get_json_array_index_object(json_t *array, int index); int get_json_array_index_integer(json_t *array, int index); diff --git a/src/registry.c b/src/registry.c new file mode 100644 index 0000000..5b16104 --- /dev/null +++ b/src/registry.c @@ -0,0 +1,32 @@ +#include +#include "sprite.h" +#include "registry.h" + +SDL_PropertiesID REGISTRY_ACTOR; +SDL_PropertiesID REGISTRY_SPRITE; +SDL_PropertiesID REGISTRY_SPRITESHEET; +SDL_PropertiesID REGISTRY_CHARACTER; + +void registry_init_actor() +{ + REGISTRY_ACTOR = SDL_CreateProperties(); + THROW_ZERO(REGISTRY_ACTOR, EXC_NULLPOINTER, "Error initializing actor registry"); +} + +void registry_init_sprite() +{ + REGISTRY_SPRITE = SDL_CreateProperties(); + THROW_ZERO(REGISTRY_SPRITE, EXC_NULLPOINTER, "Error initializing sprite registry"); +} + +void registry_init_spritesheet() +{ + REGISTRY_SPRITESHEET = SDL_CreateProperties(); + THROW_ZERO(REGISTRY_SPRITESHEET, EXC_NULLPOINTER, "Error initializing spritesheet registry"); +} + +void registry_init_character() +{ + REGISTRY_CHARACTER = SDL_CreateProperties(); + THROW_ZERO(REGISTRY_CHARACTER, EXC_NULLPOINTER, "Error initializing character registry"); +} diff --git a/src/registry.h b/src/registry.h new file mode 100644 index 0000000..ec8f1e7 --- /dev/null +++ b/src/registry.h @@ -0,0 +1,16 @@ +#ifndef _REGISTRY_H_ +#define _REGISTRY_H_ + +extern SDL_PropertiesID REGISTRY_ACTOR; +extern SDL_PropertiesID REGISTRY_SPRITE; +extern SDL_PropertiesID REGISTRY_SPRITESHEET; +extern SDL_PropertiesID REGISTRY_CHARACTER; + +void registry_init_actor(); +void registry_iterate_actor(void *userdata, SDL_PropertiesID registry, const char *name); +void registry_init_sprite(); +void registry_init_spritesheet(); +void registry_init_character(); + + +#endif //_REGISTRY_H_ diff --git a/src/sdl3-gametest.c b/src/sdl3-gametest.c index 2eb4b0d..6daa827 100644 --- a/src/sdl3-gametest.c +++ b/src/sdl3-gametest.c @@ -13,6 +13,8 @@ #include "draw.h" #include "assets.h" #include "sprite.h" +#include "heap.h" +#include "registry.h" SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { @@ -81,18 +83,6 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) return SDL_APP_FAILURE; } ETRY; - /*TRY { - actorptr = heap_next_actor(); - actor_initialize(actorptr, "npc"); - actorptr->basechar = characterptr; - actorptr->x = 0; - actorptr->y = 0; - actorptr->state = (ACTOR_STATE_ALIVE | ACTOR_STATE_FACE_LEFT | ACTOR_STATE_MOVING_LEFT); - } CATCH(EXC_NULLPOINTER) { - SDL_Log("Attempting to setup npc: %s (%s)", EXCLIB_EXCEPTION->description, SDL_GetError()); - return SDL_APP_FAILURE; - } ETRY;*/ - /* TRY { //load_start_bgm("../assets/nutcracker.mid"); diff --git a/src/sprite.c b/src/sprite.c index e914410..1caf85e 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -5,105 +5,12 @@ #include #include #include - +#include "string.h" #include "game.h" #include "sprite.h" #include "json_helpers.h" - -SDL_PropertiesID REGISTRY_ACTOR; -SDL_PropertiesID REGISTRY_SPRITE; -SDL_PropertiesID REGISTRY_SPRITESHEET; -SDL_PropertiesID REGISTRY_CHARACTER; - -actor HEAP_ACTOR[MAX_HEAP_ACTOR]; -sprite HEAP_SPRITE[MAX_HEAP_SPRITE]; -spritesheet HEAP_SPRITESHEET[MAX_HEAP_SPRITESHEET]; -character HEAP_CHARACTER[MAX_HEAP_CHARACTER]; - -void heap_init() -{ - int i = 0; - for ( i = 0; i < MAX_HEAP_ACTOR; i++) { - memset(&HEAP_ACTOR[i], 0x00, sizeof(actor)); - } - for ( i = 0; i < MAX_HEAP_SPRITE; i++) { - memset(&HEAP_SPRITE[i], 0x00, sizeof(sprite)); - } - for ( i = 0; i < MAX_HEAP_SPRITESHEET; i++) { - memset(&HEAP_SPRITESHEET[i], 0x00, sizeof(spritesheet)); - } - for ( i = 0; i < MAX_HEAP_CHARACTER; i++) { - memset(&HEAP_CHARACTER[i], 0x00, sizeof(character)); - } -} - -actor *heap_next_actor() -{ - for (int i = 0; i < MAX_HEAP_ACTOR; i++ ) { - if ( HEAP_ACTOR[i].refcount != 0 ) { - continue; - } - return &HEAP_ACTOR[i]; - } - THROW(EXC_HEAPERROR, "Unable to find unused actor on the heap"); -} - -sprite *heap_next_sprite() -{ - for (int i = 0; i < MAX_HEAP_SPRITE; i++ ) { - if ( HEAP_SPRITE[i].refcount != 0 ) { - continue; - } - return &HEAP_SPRITE[i]; - } - THROW(EXC_HEAPERROR, "Unable to find unused sprite on the heap"); -} - -spritesheet *heap_next_spritesheet() -{ - for (int i = 0; i < MAX_HEAP_SPRITESHEET; i++ ) { - if ( HEAP_SPRITESHEET[i].refcount != 0 ) { - continue; - } - return &HEAP_SPRITESHEET[i]; - } - THROW(EXC_HEAPERROR, "Unable to find unused spritesheet on the heap"); -} - -character *heap_next_character() -{ - for (int i = 0; i < MAX_HEAP_CHARACTER; i++ ) { - if ( HEAP_CHARACTER[i].refcount != 0 ) { - continue; - } - return &HEAP_CHARACTER[i]; - } - THROW(EXC_HEAPERROR, "Unable to find unused character on the heap"); -} - -void registry_init_actor() -{ - REGISTRY_ACTOR = SDL_CreateProperties(); - THROW_ZERO(REGISTRY_ACTOR, EXC_NULLPOINTER, "Error initializing actor registry"); -} - -void registry_init_sprite() -{ - REGISTRY_SPRITE = SDL_CreateProperties(); - THROW_ZERO(REGISTRY_SPRITE, EXC_NULLPOINTER, "Error initializing sprite registry"); -} - -void registry_init_spritesheet() -{ - REGISTRY_SPRITESHEET = SDL_CreateProperties(); - THROW_ZERO(REGISTRY_SPRITESHEET, EXC_NULLPOINTER, "Error initializing spritesheet registry"); -} - -void registry_init_character() -{ - REGISTRY_CHARACTER = SDL_CreateProperties(); - THROW_ZERO(REGISTRY_CHARACTER, EXC_NULLPOINTER, "Error initializing character registry"); -} +#include "heap.h" +#include "registry.h" void actor_initialize(actor *obj, char *name) { @@ -236,6 +143,7 @@ void character_load_json(char *filename) json_t *mappings; json_t *curmapping; json_error_t error; + string *s; sprite *spriteptr = NULL; char *asset_path = NULL; character *obj = NULL; @@ -253,23 +161,22 @@ void character_load_json(char *filename) } FINALLY { SDL_free(asset_path); } ETRY; - - character_initialize(obj, (char *)get_json_string_value(json, "name")); + TRY { + s = get_json_string_value(json, "name"); + character_initialize(obj, s->data); + heap_release_string(s); mappings = get_json_array_value(json, "sprite_mappings"); TRY { for ( i = 0; i < json_array_size(mappings) ; i++ ) { curmapping = get_json_array_index_object(mappings, i); + s = get_json_string_value(curmapping, "sprite"); spriteptr = SDL_GetPointerProperty( REGISTRY_SPRITE, - get_json_string_value(curmapping, "sprite"), + s->data, NULL ); - SDL_Log("Character %s for state %d references sprite %s", - (char *)get_json_string_value(json, "name"), - get_json_integer_value(curmapping, "state"), - (char *)get_json_string_value(curmapping, "sprite") - ); + heap_release_string(s); THROW_ZERO(spriteptr, EXC_NULLPOINTER, "Character references sprite that does not exist"); character_sprite_add( obj, @@ -292,6 +199,7 @@ void sprite_load_json(char *filename) json_t *spritesheet_json; json_t *frames; json_error_t error; + string *s; spritesheet *sheet = NULL; char *asset_path = NULL; sprite *obj = NULL; @@ -313,9 +221,10 @@ void sprite_load_json(char *filename) TRY { spritesheet_json = get_json_object_value(json, "spritesheet"); + s = get_json_string_value(spritesheet_json, "filename"); sheet = SDL_GetPointerProperty( REGISTRY_SPRITESHEET, - get_json_string_value(spritesheet_json, "filename"), + s->data, NULL ); TRY { @@ -325,13 +234,16 @@ void sprite_load_json(char *filename) sheet, get_json_integer_value(spritesheet_json, "frame_width"), get_json_integer_value(spritesheet_json, "frame_height"), - (char *)get_json_string_value(spritesheet_json, "filename") + s->data ); } + heap_release_string(s); + s = get_json_string_value(json, "name"); sprite_initialize( obj, - (char *)get_json_string_value(json, "name"), + s->data, sheet); + heap_release_string(s); } FINALLY { json_decref(spritesheet_json); } ETRY; @@ -459,48 +371,4 @@ void character_state_sprites_iterate(void *userdata, SDL_PropertiesID registry, } } -void heap_release_actor(actor *ptr) -{ - THROW_ZERO(ptr, EXC_NULLPOINTER, "NULL character reference"); - ptr->refcount -= 1; - if ( ptr->refcount == 0 ) { - heap_release_character(ptr->basechar); - SDL_ClearProperty(REGISTRY_ACTOR, (char *)&ptr->name); - } -} - -void heap_release_character(character *basechar) -{ - iterator opflags; - THROW_ZERO(basechar, EXC_NULLPOINTER, "NULL character reference"); - BITMASK_CLEAR(opflags.flags); - BITMASK_ADD(opflags.flags, ITERATOR_OP_RELEASE); - - basechar->refcount -= 1; - if ( basechar->refcount == 0 ) { - SDL_EnumerateProperties(basechar->state_sprites, &character_state_sprites_iterate, (void *)&opflags); - SDL_ClearProperty(REGISTRY_CHARACTER, (char *)&basechar->name); - } -} - -void heap_release_sprite(sprite *ptr) -{ - THROW_ZERO(ptr, EXC_NULLPOINTER, "Received NULL sprite reference"); - ptr->refcount -= 1; - if ( ptr->refcount == 0 ) { - heap_release_spritesheet(ptr->sheet); - SDL_ClearProperty(REGISTRY_SPRITE, (char *)&ptr->name); - } -} - -void heap_release_spritesheet(spritesheet *ptr) -{ - THROW_ZERO(ptr, EXC_NULLPOINTER, "Received NULL spritesheet reference"); - ptr->refcount -= 1; - if ( ptr->refcount == 0 ) { - // TODO : If we go threaded, make sure this is only happening on the main thread - SDL_DestroyTexture(ptr->texture); - SDL_ClearProperty(REGISTRY_CHARACTER, (char *)&ptr->name); - } -} diff --git a/src/sprite.h b/src/sprite.h index 701b601..27f28c7 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -3,6 +3,7 @@ #include #include +#include #define ACTOR_STATE_FACE_DOWN 1 // 1 #define ACTOR_STATE_FACE_LEFT 1 << 1 // 2 @@ -44,11 +45,6 @@ #define SPRITE_MAX_ACTOR_NAME_LENGTH 128 #define SPRITE_MAX_CHARACTER_NAME_LENGTH 128 -#define MAX_HEAP_ACTOR 64 -#define MAX_HEAP_SPRITE (MAX_HEAP_ACTOR * 16) -#define MAX_HEAP_SPRITESHEET MAX_HEAP_SPRITE -#define MAX_HEAP_CHARACTER 256 - typedef struct { int refcount; SDL_Texture *texture; @@ -93,16 +89,6 @@ typedef struct { int y; } actor; -extern SDL_PropertiesID REGISTRY_ACTOR; -extern SDL_PropertiesID REGISTRY_SPRITE; -extern SDL_PropertiesID REGISTRY_SPRITESHEET; -extern SDL_PropertiesID REGISTRY_CHARACTER; - -extern actor HEAP_ACTOR[MAX_HEAP_ACTOR]; -extern sprite HEAP_SPRITE[MAX_HEAP_SPRITE]; -extern spritesheet HEAP_SPRITESHEET[MAX_HEAP_SPRITESHEET]; -extern character HEAP_CHARACTER[MAX_HEAP_CHARACTER]; - void actor_initialize(actor *obj, char *name); void actor_set_character(actor *obj, char *basecharname); void actor_render(actor *obj, SDL_Renderer *renderer); @@ -120,20 +106,4 @@ void sprite_initialize(sprite *spr, char *name, spritesheet *sheet); void spritesheet_initialize(spritesheet *sheet, short sprite_w, short sprite_h, char *filename); void sprite_load_json(char *filename); -void registry_init_actor(); -void registry_iterate_actor(void *userdata, SDL_PropertiesID registry, const char *name); -void registry_init_sprite(); -void registry_init_spritesheet(); -void registry_init_character(); - -void heap_init(); -actor *heap_next_actor(); -sprite *heap_next_sprite(); -spritesheet *heap_next_spritesheet(); -character *heap_next_character(); -void heap_release_actor(actor *ptr); -void heap_release_sprite(sprite *ptr); -void heap_release_spritesheet(spritesheet *ptr); -void heap_release_character(character *ptr); - #endif //_SPRITE_H_ diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..fc58450 --- /dev/null +++ b/src/string.c @@ -0,0 +1,12 @@ +#include "string.h" +#include + +void string_initialize(string *obj, char *init) +{ + THROW_ZERO(obj, EXC_NULLPOINTER, "Attempted to initialize NULL string reference"); + if ( init != NULL ) { + strncpy(obj->data, init, MAX_STRING_LENGTH); + } else { + memset(obj->data, 0x00, sizeof(string)); + } +} diff --git a/src/string.h b/src/string.h new file mode 100644 index 0000000..7f2b696 --- /dev/null +++ b/src/string.h @@ -0,0 +1,14 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#define MAX_STRING_LENGTH 256 + +typedef struct string +{ + int refcount; + char data[MAX_STRING_LENGTH]; +} string; + +void string_initialize(string *obj, char *init); + +#endif //_STRING_H_ diff --git a/src/tilemap.c b/src/tilemap.c index 7c2eb47..410cbc0 100644 --- a/src/tilemap.c +++ b/src/tilemap.c @@ -5,6 +5,9 @@ #include "tilemap.h" #include "game.h" #include "sprite.h" +#include "heap.h" +#include "registry.h" +#include "string.h" #include #include #include "json_helpers.h" @@ -13,6 +16,7 @@ static json_t *get_json_tilemap_property(json_t *obj, char *key, char *type) { json_t *properties; json_t *property; + string *s; int i = 0; // This is not a generic JSON helper. It assumes we are receiving an object with a 'properties' key // inside of it. That key is an array of objects, and each object has a name, type, and value. @@ -22,28 +26,34 @@ static json_t *get_json_tilemap_property(json_t *obj, char *key, char *type) TRY { for (i = 0; i < json_array_size(properties); i++) { property = get_json_array_index_object(properties, i); - if ( strcmp(get_json_string_value(property, "name"), key) != 0 ) { + s = get_json_string_value(property, "name"); + if ( strcmp(s->data, key) != 0 ) { + heap_release_string(s); continue; } - if ( strcmp(get_json_string_value(property, "type"), type) != 0 ) { + heap_release_string(s); + s = get_json_string_value(property, "type"); + if ( strcmp(s->data, type) != 0 ) { THROW(EXC_ATTRIBUTEERROR, "Character property is present but is incorrect type"); } + heap_release_string(s); json_decref(properties); return property; } } FINALLY { + heap_release_string(s); json_decref(properties); } ETRY; THROW(EXC_KEYERROR, "Property not found in properties map"); } -static const char *get_json_properties_string(json_t *obj, char *key) +static string *get_json_properties_string(json_t *obj, char *key) { json_t *property = get_json_tilemap_property(obj, key, "string"); - const char *t = get_json_string_value(property, "value"); + string *s = get_json_string_value(property, "value");; json_decref(property); - return t; + return s; } static int get_json_properties_integer(json_t *obj, char *key) @@ -60,6 +70,7 @@ static void tilemap_load_tilesets(tilemap *dest, json_t *root) THROW_ZERO(dest, EXC_NULLPOINTER, "Received NULL tilemap pointer"); THROW_ZERO(root, EXC_NULLPOINTER, "Received NULL json object pointer"); char *asset_path; + string *s; json_t *tilesets = get_json_array_value(root, "tilesets"); json_t *tileset; int i; @@ -81,18 +92,22 @@ static void tilemap_load_tilesets(tilemap *dest, json_t *root) dest->tilesets[i].tilecount = get_json_integer_value(tileset, "tilecount"); dest->tilesets[i].tileheight = get_json_integer_value(tileset, "tileheight"); dest->tilesets[i].tilewidth = get_json_integer_value(tileset, "tilewidth"); - + + s = get_json_string_value(tileset, "name"); strncpy((char *)&dest->tilesets[i].name, - get_json_string_value(tileset, "name"), + s->data, TILEMAP_MAX_TILESET_NAME_SIZE ); + heap_release_string(s); + s = get_json_string_value(tileset, "image"); snprintf((char *)&dest->tilesets[i].imagefilename, TILEMAP_MAX_TILESET_FILENAME_SIZE, "%s%s", SDL_GetBasePath(), - get_json_string_value(tileset, "image") + s->data ); + heap_release_string(s); dest->tilesets[i].texture = IMG_LoadTexture(renderer, (char *)&dest->tilesets[i].imagefilename); THROW_ZERO(dest->tilesets[i].texture, EXC_NULLPOINTER, "Failed loading tileset image"); @@ -153,6 +168,8 @@ static void tilemap_load_layer_objects(tilemap *dest, json_t *root, int layerid) int j; int len; actor *actorobj; + string *s; + string *sc; tilemap_layer *curlayer; tilemap_object *curobj; const char *charptr; @@ -167,11 +184,14 @@ static void tilemap_load_layer_objects(tilemap *dest, json_t *root, int layerid) for ( j = 0; j < len; j++ ) { layerdatavalue = get_json_array_index_object(layerdata, j); curobj = &curlayer->objects[j]; - strncpy(curobj->name, get_json_string_value(layerdatavalue, "name"), SPRITE_MAX_ACTOR_NAME_LENGTH); + s = get_json_string_value(layerdatavalue, "name"); + strncpy(curobj->name, s->data, SPRITE_MAX_ACTOR_NAME_LENGTH); + heap_release_string(s); curobj->x = (int) get_json_number_value(layerdatavalue, "x"); curobj->y = (int) get_json_number_value(layerdatavalue, "y"); curobj->visible = get_json_boolean_value(layerdatavalue, "visible"); - if ( strcmp((char *)get_json_string_value(layerdatavalue, "type"), "actor") == 0 ) { + s = get_json_string_value(layerdatavalue, "type"); + if ( strcmp(s->data, "actor") == 0 ) { curobj->type = TILEMAP_OBJECT_TYPE_ACTOR; if ( strlen((char *)&curobj->name) == 0 ) { THROW(EXC_KEYERROR, "Actor in tile object layer cannot have empty name"); @@ -179,8 +199,10 @@ static void tilemap_load_layer_objects(tilemap *dest, json_t *root, int layerid) actorobj = SDL_GetPointerProperty(REGISTRY_ACTOR, (char *)&curobj->name, NULL); if ( actorobj == NULL ) { actorobj = heap_next_actor(); + sc = get_json_properties_string(layerdatavalue, "character"); actor_initialize(actorobj, (char *)&curobj->name); - actor_set_character(actorobj, (char *)get_json_properties_string(layerdatavalue, "character")); + actor_set_character(actorobj, sc->data); + heap_release_string(sc); } else { actorobj->refcount += 1; } @@ -194,6 +216,7 @@ static void tilemap_load_layer_objects(tilemap *dest, json_t *root, int layerid) json_decref(layerdatavalue); } } FINALLY { + heap_release_string(s); if ( layerdatavalue != NULL ) { json_decref(layerdatavalue); } @@ -245,6 +268,7 @@ static void tilemap_load_layers(tilemap *dest, json_t *root) THROW_ZERO(root, EXC_NULLPOINTER, "tilemap_load_layers received NULL json object pointer"); json_t *layers = get_json_array_value(root, "layers"); json_t *layer; + string *s; const char *layertype = NULL; int i; @@ -268,15 +292,16 @@ static void tilemap_load_layers(tilemap *dest, json_t *root) dest->layers[i].y = get_json_integer_value(layer, "y"); TRY { - layertype = get_json_string_value(layer, "type"); - if ( strncmp(layertype, "objectgroup", strlen(layertype)) == 0 ) { + s = get_json_string_value(layer, "type"); + if ( strncmp(s->data, "objectgroup", strlen(s->data)) == 0 ) { dest->layers[i].type = TILEMAP_LAYER_TYPE_OBJECTS; tilemap_load_layer_objects(dest, layer, i); - } else if ( strncmp(layertype, "tilelayer", strlen(layertype)) == 0 ) { + } else if ( strncmp(s->data, "tilelayer", strlen(s->data)) == 0 ) { dest->layers[i].type = TILEMAP_LAYER_TYPE_TILES; tilemap_load_layer_tile(dest, layer, i); - } + } } FINALLY { + heap_release_string(s); json_decref(layer); } ETRY; }