Plaster
New
List
Login
clike
default
gingerale
2017.06.09 17:29:19
#include <SDL.h> #include <SDL_image.h> #include <pcre.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "util.h" #ifndef NULL #define NULL ((void *)(0)) #endif // NULL #define ASSETNAME_MAX ((Uint32)1024) #define READLINE_BUFFER_SIZE (2048) const Sint32 SCR_W = 640; const Sint32 SCR_H = 480; typedef struct _AssetContainer { char name[ASSETNAME_MAX]; Uint32 name_length; SDL_Surface *data; } ACont; typedef struct _GContainer { SDL_Window *window; SDL_Surface *surf; Map *assets; Uint32 last_tick; Uint32 current_tick; SDL_bool running; } GCont; static int read_line(char [], int, FILE *); static void add_asset(GCont *, const char *, const char *); static SDL_bool init(GCont *); static SDL_bool load(GCont *, const char *); static void loop(GCont *); static void close(GCont *); // Private int read_line(char buffer[], int size, FILE *file) { int pos = 0; int ch = 0; do { ch = fgetc(file); if (ch != EOF && ch != '\r' && ch != '\n') buffer[pos++] = (char)ch; if (ferror(file) != 0) return (size << 1); } while (ch != EOF && ch != '\n' && pos < size); buffer[pos] = '\0'; return (ch == EOF ? EOF : pos); } void add_asset(GCont *gc, const char *name, const char *filename) { Uint32 i = 0; ACont *asset = NULL; SDL_Surface *data = IMG_Load(filename); if (!data) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to read '%s': %s\n", filename, SDL_GetError()); return; } asset = (ACont *)calloc(1, sizeof(ACont)); for (i = 0; i < ASSETNAME_MAX; i++) asset->name[i] = '\0'; asset->data = data; asset->name_length = min(ASSETNAME_MAX, strlen(name)); memcpy(asset->name, name, asset->name_length); gc->assets = map_put(gc->assets, asset->name, asset); } SDL_bool init(GCont *gc) { static const Uint32 SDL_FLAGS = (SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS); static const Uint32 IMG_FLAGS = (IMG_INIT_PNG | IMG_INIT_JPG); if (SDL_Init(SDL_FLAGS) != 0) { printf("SDL could not initialize: %s\n", SDL_GetError()); return SDL_FALSE; } if ((IMG_Init(IMG_FLAGS) & IMG_FLAGS) != IMG_FLAGS) { printf("SDL image manager could not initialize: %s\n", SDL_GetError()); SDL_Quit(); return SDL_FALSE; } gc->running = SDL_FALSE; gc->assets = NULL; gc->surf = NULL; gc->window = SDL_CreateWindow("SDL experiment", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCR_W, SCR_H, SDL_WINDOW_SHOWN); if (!gc->window) { printf("SDL window could not be created: %s\n", SDL_GetError()); SDL_Quit(); IMG_Quit(); return SDL_FALSE; } gc->surf = SDL_GetWindowSurface(gc->window); return SDL_TRUE; } SDL_bool load(GCont *gc, const char *path) { const char *error = NULL; const char *error_extra = NULL; int err_offset = 0; pcre *regex = NULL; pcre_extra *regex_extra = NULL; int len = 0; int res_vector[8] = {0}; char buffer[READLINE_BUFFER_SIZE] = {0}; FILE *file = NULL; SDL_bool retval = SDL_FALSE; regex = pcre_compile("^\\s*\"([^\"]+)\"\\s*:\\s*\"([^\"]+)\"\\s*$", (PCRE_EXTENDED | PCRE_UTF8), &error, &err_offset, NULL); if (!regex) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to compile regex: %s\n", error); return SDL_FALSE; } regex_extra = pcre_study(regex, 0, &error_extra); if (error_extra) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to study regex: %s\n", error_extra); goto load_cleanup; } if (!(file = fopen(path, "r"))) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to open file '%s'.\n", path); goto load_cleanup; } do { int regex_ret = 0; len = read_line(buffer, READLINE_BUFFER_SIZE, file); if (READLINE_BUFFER_SIZE < len) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to read file '%s'.\n", path); goto load_cleanup; } else if (len == EOF) { break; } else if (len == 0) { continue; } regex_ret = pcre_exec(regex, regex_extra, buffer, len, 0, 0, res_vector, 32); if (regex_ret < 0) { switch (regex_ret) { case PCRE_ERROR_NOMATCH: break; case PCRE_ERROR_NULL: SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Null error while parsing '%.*s'!\n", len, buffer); goto load_cleanup; case PCRE_ERROR_BADOPTION: SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Bad option while parsing '%.*s'!\n", len, buffer); goto load_cleanup; case PCRE_ERROR_BADMAGIC: SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Corrupt regex while parsing '%.*s'!\n", len, buffer); goto load_cleanup; case PCRE_ERROR_UNKNOWN_NODE: SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Bad regex while parsing '%.*s'!\n", len, buffer); goto load_cleanup; case PCRE_ERROR_NOMEMORY: SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Out of memory while parsing '%.*s'!\n", len, buffer); goto load_cleanup; default: break; } } if (regex_ret != 0 && regex_ret != 3) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Invalid number of results (%d) while parsing '%.*s'!\n", regex_ret, len, buffer); goto load_cleanup; } else if (regex_ret == 3) // [ "<whole line>", "<name>", "<path>" ] { const char *name = NULL; const char *path = NULL; int name_len = pcre_get_substring(buffer, res_vector, regex_ret, 1, &(name)); int path_len = pcre_get_substring(buffer, res_vector, regex_ret, 2, &(path)); if (0 < name_len && 0 < path_len) { SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Loading asset '%.*s' from path '%.*s'\n", name_len, name, path_len, path); add_asset(gc, name, path); } else { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Invalid line '%.*s' where\n name = '%.*s'\n path = '%.*s'\n", len, buffer, name_len, (0 < name_len ? name : "(null)"), path_len, (0 < path_len ? path : "(null)")); } if (0 < name_len) pcre_free_substring(name); if (0 < path_len) pcre_free_substring(path); } } while (0 < len); retval = SDL_TRUE; load_cleanup: if (regex) pcre_free(regex); if (regex_extra) #ifdef PCRE_CONFIG_JIT pcre_free_study(regex_extra); #else pcre_free(regex_extra); #endif // PCRE_CONFIG_JIT if (file) fclose(file); return retval; } void loop(GCont *gc) { SDL_Event ev = {0}; gc->running = SDL_TRUE; SDL_FillRect(gc->surf, NULL, SDL_MapRGB(gc->surf->format, 0xff, 0xff, 0xff)); SDL_UpdateWindowSurface(gc->window); gc->last_tick = 0; gc->current_tick = 0; while (gc->running) { while (SDL_PollEvent(&ev)) { if (ev.type == SDL_QUIT) gc->running = SDL_FALSE; } if (gc->running) { gc->last_tick = gc->current_tick; gc->current_tick = SDL_GetTicks(); // update(gc); // draw(gc); } SDL_UpdateWindowSurface(gc->window); } } void close(GCont *gc) { if (gc->assets) { Uint32 i = 0; Map *assets = gc->assets; gc->assets = NULL; for (i = 0; i < assets->size; i++) { ACont *asset = (ACont *)assets->nodes[i].value; assets->nodes[i].value = NULL; if (asset) { SDL_FreeSurface(asset->data); asset->data = NULL; free(asset); } } free(assets); } SDL_DestroyWindow(gc->window); IMG_Quit(); SDL_Quit(); gc->window = NULL; gc->surf = NULL; } int main(int argc, char *argv[]) { GCont gc = {0}; if (argc != 2) { fprintf(stderr, "Usage: ./sandbox <template-file>\n"); return EXIT_FAILURE; } if (!init(&gc)) return EXIT_FAILURE; if (!load(&gc,argv[1])) { fprintf(stderr, "Failed to load file: %s\n", argv[1]); close(&gc); return EXIT_FAILURE; } loop(&gc); close(&gc); return EXIT_SUCCESS; }
Raw
Annotate
Repaste
Annotations
clike
default
gingerale
2017.06.09 17:58:26
#ifndef _UTIL_H_ #define _UTIL_H_ #include <stdio.h> #include <stdlib.h> #ifndef min #define min(x,y) (((x) < (y)) ? (x) : (y)) #endif // min #ifndef max #define max(x,y) (((x) < (y)) ? (y) : (x)) #endif // max #ifdef _HASHMAP_NODEKEY_MAXLEN #define NODEKEY_MAXLEN (_HASHMAP_NODEKEY_MAXLEN) #else #define NODEKEY_MAXLEN ((unsigned int)1024) #endif // _HASHMAP_NODEKEY_MAXLEN typedef struct _Node { char key[NODEKEY_MAXLEN]; unsigned int key_length; unsigned long hash; void *value; } MapNode; typedef struct _Map { unsigned int size; unsigned int count; MapNode *nodes; } Map; unsigned long map_hash(const char *); void * map_get(Map *, const char *); Map * map_put(Map *, const char *, void *); void * map_remove(Map *, const char *); #endif // _UTIL_H_
Raw
Repaste
clike
default
gingerale
2017.06.09 18:05:27
#include "util.h" #include <string.h> #include <math.h> #ifndef NULL #define NULL ((void *)(0)) #endif // NULL // -- HashMap -- static unsigned int map_index(MapNode *,unsigned int,unsigned long, const char *); // Private unsigned int map_index(MapNode *nodes, unsigned int size, unsigned long hash, const char *key) { unsigned int offset = hash % size; unsigned int i = offset; unsigned int roundtrip = 0xffffffff; while (nodes[i].value && nodes[i].hash != hash && strcmp(nodes[i].key,key) != 0) { if (1 < offset) offset = (offset >> 1); // divide by 2 else if (roundtrip == 0xffffffff) roundtrip = i; i = ((i + offset) % size); if (i == roundtrip) return 0xffffffff; } return i; } // Public unsigned long map_hash(const char *str) { // djb2 unsigned long hash = 5381l; // x_0 /* 5381 is 709th prime, 709 is 127th prime, 127 is 31st prime, etc. */ int ch; while ((ch = (int)(*str++))) hash = ((hash << 5) + hash) + ch; // x_i where 0 < i /* above is equivelant of (hash * 33 + ch) why 33? nobody knows exactly but it's likely due to (2^4)+1 being good for hashing */ return hash; } void * map_get(Map *map, const char *key) { unsigned int idx; unsigned long hash = map_hash(key); idx = map_index(map->nodes, map->size, hash, key); if (idx == 0xffffffff) return NULL; return map->nodes[idx].value; } Map * map_put(Map *map, const char *key, void *value) { static const unsigned int START_SIZE = ((unsigned int)0x0000000f); static const unsigned int MAX_SIZE = ((unsigned int)0xf0000000); unsigned long hash; unsigned int i, idx; unsigned int key_length = (unsigned int)(strlen(key) * sizeof(char)); if (NODEKEY_MAXLEN < key_length) return (Map *)NULL; if (!map) { map = (Map *)calloc(1,sizeof(Map)); map->size = START_SIZE; map->count = 0; map->nodes = (MapNode *)calloc(map->size,sizeof(MapNode)); for (i = 0; i < map->size; i++) map->nodes[i].value = NULL; } else if (map->count == map->size) { unsigned int new_size; MapNode *old_map, *new_map; new_size = (unsigned int)((((unsigned long)map->size) << 1) & 0xffffffff); if (!new_size) new_size = MAX_SIZE; if (new_size == map->size) return (Map *)NULL; new_map = (MapNode *)calloc(new_size, sizeof(MapNode)); for (i = 0; i < new_size; i++) new_map[i].value = NULL; for (i = 0; i < map->size; i++) { if (map->nodes[i].value) { unsigned int index = map_index(new_map, new_size, map->nodes[i].hash, map->nodes[i].key); if (index == 0xffffffff) { free(new_map); return (Map *)NULL; } memcpy(new_map[index].key, map->nodes[i].key, NODEKEY_MAXLEN); new_map[index].key_length = map->nodes[i].key_length; new_map[index].hash = map->nodes[i].hash; new_map[index].value = map->nodes[i].value; } } old_map = map->nodes; for (i = 0; i < map->size; i++) old_map[i].value = NULL; map->nodes = new_map; map->size += map->size; free(old_map); } map->count += 1; hash = map_hash(key); idx = map_index(map->nodes, map->size, hash, key); if (idx == 0xffffffff) return (Map *)NULL; for (i = 0; i < NODEKEY_MAXLEN; i++) map->nodes[idx].key[i] = '\0'; map->nodes[idx].hash = hash; map->nodes[idx].value = value; map->nodes[idx].key_length = key_length; memcpy(map->nodes[idx].key, key, map->nodes[idx].key_length); return map; } void * map_remove(Map *map, const char *key) { void *value; unsigned long hash = map_hash(key); unsigned int idx = map_index(map->nodes, map->size, hash, key); if (idx == 0xffffffff) return NULL; value = map->nodes[idx].value; if (value) map->nodes[idx].value = NULL; return value; }
Raw
Repaste
shell
default
gingerale
2017.06.09 18:06:20
## Sandbox make file. Run with "make clean build run" after M-x compile ## IDIR = include CC = gcc CXX = g++ CFLAGS = -Wall -IC:/msys64/mingw64/include -D_REENTRANT -Dmain=SDL_main -IC:/msys64/mingw64/include/SDL2 -I$(IDIR) ODIR = obj LDIR = lib LIBS = -LC:/msys64/mingw64/lib -lpcre -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lmingw32 -lSDL2main -lSDL2 _DEPS = DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) _OBJ = main.o util.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) BIN = sandbox $(ODIR)/%.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) build: $(OBJ) $(CC) -o $(BIN) $^ $(CFLAGS) -L$(LDIR) $(LIBS) .PHONY: clean clean: rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ ./$(BIN) run: ./$(BIN)
Raw
Repaste
text
default
gingerale
2017.06.09 18:13:40
"foo" : "assets/asset.png"
Raw
Repaste