summaryrefslogtreecommitdiff
path: root/utl
diff options
context:
space:
mode:
Diffstat (limited to 'utl')
-rw-r--r--utl/json2map/common.c21
-rw-r--r--utl/json2map/common.h4
-rw-r--r--utl/json2map/main.c266
3 files changed, 226 insertions, 65 deletions
diff --git a/utl/json2map/common.c b/utl/json2map/common.c
index c401fc1..8c2c4c2 100644
--- a/utl/json2map/common.c
+++ b/utl/json2map/common.c
@@ -1,7 +1,28 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "common.h"
+struct blob blob_new(void) {
+ return (struct blob) {.data = NULL, .size = 0};
+}
+
+void blob_append(struct blob *const blob, void const *const data, size_t const size) {
+ char *new = realloc(blob->data, blob->size + size);
+ if (new == NULL) {
+ abort();
+ }
+ memcpy(new + blob->size, data, size);
+ blob->data = new;
+ blob->size += size;
+}
+
+void blob_free(struct blob *const blob) {
+ free(blob->data);
+ blob->data = NULL;
+ blob->size = 0;
+}
+
struct blob load_file(char const *const name) {
const size_t START_SIZE = 8192;
FILE *file = fopen(name, "rb");
diff --git a/utl/json2map/common.h b/utl/json2map/common.h
index 73e3240..e5a7590 100644
--- a/utl/json2map/common.h
+++ b/utl/json2map/common.h
@@ -5,4 +5,8 @@ struct blob {
size_t size;
};
+struct blob blob_new(void);
+void blob_append(struct blob *const blob, void const *const data, size_t const size);
+void blob_free(struct blob *const blob);
+
struct blob load_file(char const *const name);
diff --git a/utl/json2map/main.c b/utl/json2map/main.c
index 684e0ed..9ffa9b9 100644
--- a/utl/json2map/main.c
+++ b/utl/json2map/main.c
@@ -21,7 +21,7 @@ struct PACKED sets {
};
struct PACKED map {
- struct {
+ struct color {
uint8_t r, g, b, a;
} backdrop;
uint32_t width;
@@ -91,6 +91,56 @@ size_t safe_write(void const *restrict buf, size_t size, FILE *restrict stream)
return fwrite(buf, 1, size, stream);
}
+int string_to_color(struct color *const restrict color, char const *const restrict string) {
+ if (string[0] != '#') {
+ fprintf(stderr, "color %s: missing a hash\n", string);
+ return 1;
+ }
+ char *end = NULL;
+ unsigned const value = strtoul(string + 1, &end, 16);
+ size_t const len = strlen(string);
+ if (end != string + len) {
+ fprintf(stderr, "color %s: not a color string\n", string);
+ return 1;
+ }
+ switch (len) {
+ case 9:
+ color->a = value >> 24;
+ break;
+ case 7:
+ color->a = 0xff;
+ break;
+ default:
+ fprintf(stderr, "color %s: not a color string\n", string);
+ return 1;
+ }
+ color->r = value >> 16;
+ color->g = value >> 8;
+ color->b = value >> 0;
+ return 0;
+}
+
+// will turn, say, example/file.name into just file
+// or another/example/file.with.multiple.dots into file.with.multiple
+struct blob strip_filename(char *str) {
+ size_t length = strlen(str);
+ char *temp, *start = str;
+ while ((temp = memchr(start, '/', length))) {
+ temp++;
+ length -= temp - start;
+ start = temp;
+ }
+ char *data = start;
+ char *end = data + length;
+ while ((temp = memchr(data, '.', length))) {
+ end = temp;
+ temp++;
+ length -= temp - data;
+ data = temp;
+ }
+ return (struct blob) {.data = start, .size = end - start};
+}
+
int main(int argc, char **argv) {
if (argc != 2 && argc != 3) {
return EXIT_FAILURE;
@@ -124,8 +174,7 @@ int main(int argc, char **argv) {
char *wang_tileset = NULL;
uint32_t wang_height;
- char *tilesets_data = NULL;
- size_t tilesets_size = 0;
+ struct blob tilesets_blob = blob_new();
struct sets counts = {MAGIC, 0, 0};
cJSON_ArrayForEach(tileset, tilesets) {
@@ -163,28 +212,13 @@ int main(int argc, char **argv) {
}
cJSON const *image = cJSON_GetObjectItemCaseSensitive(tileset, "image");
{
- char const *const str = image->valuestring;
- size_t start = 0, length = strlen(str);
- for (size_t i = 0; i < length; i++) {
- if (str[i] == '/') {
- start = i + 1;
- }
- }
- length -= start;
- for (size_t i = length; i > 0; i--) {
- if (str[start + i] == '.') {
- length = i;
- break;
- }
- }
+ struct blob fragment = strip_filename(image->valuestring);
//printf("%.*s\n", (int) length, str + start);
uint32_t height = cJSON_GetObjectItemCaseSensitive(tileset, "imageheight")->valueint;
- tilesets_data = realloc(tilesets_data, tilesets_size + length + sizeof (uint32_t) + 1);
- memcpy(tilesets_data + tilesets_size, &height, sizeof (uint32_t));
- memcpy(tilesets_data + tilesets_size + sizeof (uint32_t), str + start, length);
- tilesets_data[tilesets_size + sizeof (uint32_t) + length] = 0;
+ blob_append(&tilesets_blob, &height, sizeof (uint32_t));
+ blob_append(&tilesets_blob, fragment.data, fragment.size);
+ blob_append(&tilesets_blob, &(char) {0}, 1);
//puts(tilesets_data + tilesets_size + sizeof (uint32_t));
- tilesets_size += length + sizeof (uint32_t) + 1;
counts.tilesets_count++;
}
//puts(image->valuestring);
@@ -196,24 +230,11 @@ int main(int argc, char **argv) {
wang_continue:;
}
if (counts.wang_count == 1) {
- char const *const str = wang_tileset;
- size_t start = 0, length = strlen(str);
- for (size_t i = 0; i < length; i++) {
- if (str[i] == '/') {
- start = i + 1;
- }
- }
- length -= start;
- for (size_t i = length; i > 0; i--) {
- if (str[start + i] == '.') {
- length = i;
- break;
- }
- }
+ struct blob fragment = strip_filename(wang_tileset);
//printf("%.*s\n", (int) length, str + start);
- wang_tileset = malloc(length + 1);
- memcpy(wang_tileset, str + start, length);
- wang_tileset[length] = 0;
+ wang_tileset = malloc(fragment.size + 1);
+ memcpy(wang_tileset, fragment.data, fragment.size);
+ wang_tileset[fragment.size] = 0;
//puts(wang_tileset);
}
@@ -235,29 +256,14 @@ int main(int argc, char **argv) {
cJSON const *backdrop = cJSON_GetObjectItemCaseSensitive(json, "backgroundcolor");
if (cJSON_IsString(backdrop)) {
- switch (strlen(backdrop->valuestring)) {
- unsigned value;
- case 9:
- value = strtoul(backdrop->valuestring + 1, NULL, 16);
- map.backdrop.r = value >> 16;
- map.backdrop.g = value >> 8;
- map.backdrop.b = value >> 0;
- map.backdrop.a = value >> 24;
- break;
- case 7:
- value = strtoul(backdrop->valuestring + 1, NULL, 16);
- map.backdrop.r = value >> 16;
- map.backdrop.g = value >> 8;
- map.backdrop.b = value >> 0;
- map.backdrop.a = 0xff;
- break;
- default:
- fputs("incorrect backdrop color format\n", stderr);
- return 1;
+ if (string_to_color(&map.backdrop, backdrop->valuestring)) {
+ return 1;
}
}
//printf("sky: # %02x %02x %02x %02x\n", map.backdrop.r, map.backdrop.g, map.backdrop.b, map.backdrop.a);
+ struct blob entities = blob_new();
+
cJSON const *layers = cJSON_GetObjectItemCaseSensitive(json, "layers");
cJSON const *layer = NULL;
cJSON_ArrayForEach (layer, layers) {
@@ -365,6 +371,127 @@ int main(int argc, char **argv) {
puts(str);
free(str);
#endif
+ } else if (strcmp(type, "object")) {
+ // object layer
+ cJSON const *object = NULL;
+ cJSON_ArrayForEach(object, cJSON_GetObjectItemCaseSensitive(layer, "objects")) {
+ struct blob entity = blob_new();
+
+ cJSON const *property = cJSON_GetObjectItemCaseSensitive(object, "type");
+ blob_append(&entity, property->valuestring, strlen(property->valuestring) + 1);
+ //printf("%s:", property->valuestring);
+
+ char const *const *default_props = (char const *const[]) {"x", "y", "width", "height", NULL};
+ if (cJSON_IsTrue(cJSON_GetObjectItemCaseSensitive(object, "point"))) {
+ default_props = (char const *const[]) {"x", "y", NULL};
+ }
+ for (int i = 0; default_props[i] != NULL; i++) {
+ property = cJSON_GetObjectItemCaseSensitive(object, default_props[i]);
+ if (property == NULL) {
+ continue;
+ }
+
+ blob_append(&entity, default_props[i], strlen(default_props[i]) + 1);
+ if (cJSON_IsNumber(property)) {
+ char buf[32];
+ sprintf(buf, "%i", property->valueint);
+ blob_append(&entity, buf, strlen(buf) + 1);
+ //printf(" %s=%i", default_props[i], property->valueint);
+ } else if (cJSON_IsString(property)) {
+ blob_append(&entity, property->valuestring, strlen(property->valuestring) + 1);
+ //printf(" %s=%s", default_props[i], property->valuestring);
+ } else {
+ char *str = cJSON_Print(property);
+ puts(str);
+ free(str);
+ return 1;
+ }
+ }
+ cJSON_ArrayForEach(property, cJSON_GetObjectItemCaseSensitive(object, "properties")) {
+ char const *const name = cJSON_GetObjectItemCaseSensitive(property, "name")->valuestring;
+ char const *const type = cJSON_GetObjectItemCaseSensitive(property, "type")->valuestring;
+ cJSON const *value_obj = cJSON_GetObjectItemCaseSensitive(property, "value");
+
+ blob_append(&entity, name, strlen(name) + 1);
+ if (strcmp(type, "string") == 0) {
+ if (!cJSON_IsString(value_obj)) {
+ fprintf(stderr, "%s: not actually a %s\n", name, type);
+ return 1;
+ }
+ char const *const value = value_obj->valuestring;
+ blob_append(&entity, value, strlen(value) + 1);
+ //printf(" %s='%s'", name, value);
+ } else if (strcmp(type, "file") == 0) {
+ if (!cJSON_IsString(value_obj)) {
+ fprintf(stderr, "%s: not actually a %s\n", name, type);
+ return 1;
+ }
+ struct blob const fragment = strip_filename(value_obj->valuestring);
+ blob_append(&entity, fragment.data, fragment.size);
+ blob_append(&entity, &(char) {0}, 1);
+ //printf(" %s='%.*s'", name, fragment.size, fragment.data);
+ } else if (strcmp(type, "bool") == 0) {
+ if (!cJSON_IsBool(value_obj)) {
+ fprintf(stderr, "%s: not actually a %s\n", name, type);
+ return 1;
+ }
+ if (cJSON_IsTrue(value_obj)) {
+ blob_append(&entity, "true", sizeof ("true"));
+ //printf(" %s=true", name);
+ } else {
+ blob_append(&entity, "false", sizeof ("false"));
+ //printf(" %s=false", name);
+ }
+ } else if (strcmp(type, "color") == 0) {
+ if (!cJSON_IsString(value_obj)) {
+ fprintf(stderr, "%s: not actually a %s\n", name, type);
+ return 1;
+ }
+ struct color color;
+ char const *const value = value_obj->valuestring;
+ string_to_color(&color, value);
+ char buf[10];
+ sprintf(buf, "#%02x%02x%02x%02x", color.r, color.g, color.b, color.a);
+ blob_append(&entity, buf, strlen(buf) + 1);
+ //printf(" %s='%s'", name, buf);
+ } else if (strcmp(type, "int") == 0) {
+ if (!cJSON_IsNumber(value_obj)) {
+ fprintf(stderr, "%s: not actually a %s\n", name, type);
+ return 1;
+ }
+
+ char buf[32];
+ sprintf(buf, "%i", value_obj->valueint);
+ blob_append(&entity, buf, strlen(buf) + 1);
+ //printf(" %s=%s", name, buf);
+ } else if (strcmp(type, "float") == 0) {
+ if (!cJSON_IsNumber(value_obj)) {
+ fprintf(stderr, "%s: not actually a %s\n", name, type);
+ return 1;
+ }
+
+ char buf[32];
+ sprintf(buf, "%a", value_obj->valuedouble);
+ blob_append(&entity, buf, strlen(buf) + 1);
+ //printf(" %s=%s", name, buf);
+ } else if (strcmp(type, "object") == 0) {
+ fputs("object properties are not supported\n", stderr);
+ return 1;
+ } else {
+ fprintf(stderr, "%s: dont know what '%s' is\n", name, type);
+ return 1;
+ }
+ }
+ blob_append(&entity, &(char) {0}, 1);
+ //putchar('\n');
+ #if 0
+ char *str = cJSON_Print(property);
+ puts(str);
+ free(str);
+ #endif
+ blob_append(&entities, entity.data, entity.size);
+ blob_free(&entity);
+ }
} else {
// ??? layer
}
@@ -384,17 +511,26 @@ int main(int argc, char **argv) {
}
}
- fwrite(&counts, 1, sizeof (counts), outfile);
- fwrite(tilesets_data, 1, tilesets_size, outfile);
+ safe_write(&counts, sizeof (counts), outfile);
+ safe_write(tilesets_blob.data, tilesets_blob.size, outfile);
+ blob_free(&tilesets_blob);
+
if (wang_tileset != NULL) {
- fwrite(&wang_height, 1, sizeof (uint32_t), outfile);
- fwrite(wang_tileset, 1, strlen(wang_tileset) + 1, outfile);
+ safe_write(&wang_height, sizeof (uint32_t), outfile);
+ safe_write(wang_tileset, strlen(wang_tileset) + 1, outfile);
+ free(wang_tileset);
}
- fwrite(&map, 1, sizeof (map), outfile);
- fwrite(tile_data, 1, map.width * map.height * map.layers, outfile);
- fwrite(parallaxes, 1, sizeof (float) * 2 * map.layers, outfile);
+ safe_write(&map, sizeof (map), outfile);
+ safe_write(tile_data, map.width * map.height * map.layers, outfile);
free(tile_data);
+
+ safe_write(parallaxes, sizeof (float) * 2 * map.layers, outfile);
+ free(parallaxes);
+
+ safe_write(entities.data, entities.size, outfile);
+ blob_free(&entities);
+
end:
if (outfile != NULL) {
fclose(outfile);