14 if (properties == NULL) {
18 if (!json_is_array(properties)) {
26 size_t property_count = json_array_size(properties);
39 json_t*
property = NULL;
41 json_array_foreach(properties, idx, property) {
42 int unpk = json_unpack_ex(property,
45 "{s:s, s?s, s?s, s:o}",
51 &ret[idx].propertytype,
56 logmsg(
TMJ_LOG_ERR,
"Unable to unpack properties, %s at line %d column %d", error.text, error.line, error.column);
64 if (ret[idx].type == NULL || strcmp(ret[idx].type,
"string") == 0) {
65 unpk = json_unpack_ex(value, &error, 0,
"s", &ret[idx].value_string);
68 logmsg(
TMJ_LOG_ERR,
"Unable to unpack string value from property, %s at line %d column %d", error.text, error.line, error.column);
76 if (strcmp(ret[idx].type,
"int") == 0) {
77 unpk = json_unpack_ex(value, &error, 0,
"i", &ret[idx].value_int);
80 logmsg(
TMJ_LOG_ERR,
"Unable to unpack integer value from property, %s at line %d column %d", error.text, error.line, error.column);
88 if (strcmp(ret[idx].type,
"float") == 0) {
89 unpk = json_unpack_ex(value, &error, 0,
"i", &ret[idx].value_float);
92 logmsg(
TMJ_LOG_ERR,
"Unable to unpack float value from property, %s at line %d column %d", error.text, error.line, error.column);
100 if (strcmp(ret[idx].type,
"bool") == 0) {
101 unpk = json_unpack_ex(value, &error, 0,
"b", &ret[idx].value_bool);
104 logmsg(
TMJ_LOG_ERR,
"Unable to unpack bool value from property, %s at line %d column %d", error.text, error.line, error.column);
112 if (strcmp(ret[idx].type,
"color") == 0) {
113 unpk = json_unpack_ex(value, &error, 0,
"s", &ret[idx].value_color);
116 logmsg(
TMJ_LOG_ERR,
"Unable to unpack color value from property, %s at line %d column %d", error.text, error.line, error.column);
124 if (strcmp(ret[idx].type,
"file") == 0) {
125 unpk = json_unpack_ex(value, &error, 0,
"s", &ret[idx].value_file);
128 logmsg(
TMJ_LOG_ERR,
"Unable to unpack file value from property, %s at line %d column %d", error.text, error.line, error.column);
136 if (strcmp(ret[idx].type,
"object") == 0) {
137 unpk = json_unpack_ex(value, &error, 0,
"i", &ret[idx].value_object);
140 logmsg(
TMJ_LOG_ERR,
"Unable to unpack object value from property, %s at line %d column %d", error.text, error.line, error.column);
156 if (points == NULL) {
160 if (!json_is_array(points)) {
168 size_t point_count = json_array_size(points);
170 Point* ret = calloc(point_count,
sizeof(
Point));
181 json_array_foreach(points, idx, point) {
182 int unpk = json_unpack_ex(point, &error, 0,
"{s:F, s:F}",
"x", &ret[idx].x,
"y", &ret[idx].y);
185 logmsg(
TMJ_LOG_ERR,
"Unable to unpack points, %s at line %d column %d", error.text, error.line, error.column);
206 Text* ret = calloc(1,
sizeof(
Text));
214 int unpk = json_unpack_ex(text,
218 "s?b, s?b, s?b, s?b, s?b, s?b,"
219 "s?s, s?s?, s?s, s:s, s?s,"
247 logmsg(
TMJ_LOG_ERR,
"Unable to unpack text, %s at line %d column %d", error.text, error.line, error.column);
258 if (objects == NULL) {
262 if (!json_is_array(objects)) {
268 size_t object_count = json_array_size(objects);
279 json_t*
object = NULL;
281 json_array_foreach(objects, idx,
object) {
282 json_t* properties = NULL;
284 json_t* polygon = NULL;
285 json_t* polyline = NULL;
288 int unpk = json_unpack_ex(
object,
295 "s:F, s:F, s:F, s:F, s:F,"
334 logmsg(
TMJ_LOG_ERR,
"Unable to unpack object, %s at line %d column %d", error.text, error.line, error.column);
340 if (properties != NULL) {
341 if (!json_is_array(properties)) {
344 goto fail_properties;
349 if (ret[idx].properties == NULL) {
352 goto fail_properties;
362 if (ret[idx].text == NULL) {
370 if (ret[idx].ellipse || ret[idx].point || ret[idx].gid != 0 || ret[idx].text != NULL) {
375 if (polygon != NULL) {
378 if (ret[idx].polygon == NULL) {
389 if (polyline != NULL) {
392 if (ret[idx].polyline == NULL) {
404 for (
size_t i = 0; i < object_count; i++) {
409 for (
size_t i = 0; i < object_count; i++) {
410 free(ret[i].properties);
424 for (
size_t i = 0; i < object_count; i++) {
426 free(objects[i].polygon);
427 free(objects[i].text);
428 free(objects[i].properties);
435 if (chunks == NULL) {
439 if (!json_is_array(chunks)) {
447 size_t chunk_count = json_array_size(chunks);
449 Chunk* ret = calloc(chunk_count,
sizeof(
Chunk));
460 json_array_foreach(chunks, idx, chunk) {
463 int unpk = json_unpack_ex(chunk,
467 "s:i, s:i, s:i, s:i,"
482 logmsg(
TMJ_LOG_ERR,
"Unable to unpack chunk, %s at line %d column %d", error.text, error.line, error.column);
487 if (json_is_string(data)) {
488 unpk = json_unpack_ex(data, &error, 0,
"s", &ret[idx].data_str);
491 logmsg(
TMJ_LOG_ERR,
"Unable to unpack chunk data, %s at line %d column %d", error.text, error.line, error.column);
497 }
else if (json_is_array(data)) {
498 size_t datum_count = json_array_size(data);
500 ret[idx].
data_uint = calloc(datum_count,
sizeof(
unsigned int));
502 if (ret[idx].data_uint == NULL) {
511 json_array_foreach(data, idx2, datum) {
512 unpk = json_unpack_ex(datum, &error, 0,
"i", &ret[idx].data_uint[idx2]);
515 logmsg(
TMJ_LOG_ERR,
"Unable to unpack chunk datum, %s at line %d column %d", error.text, error.line, error.column);
521 logmsg(
TMJ_LOG_ERR,
"Unable to unpack chunk, chunk data must be a string or an array of uint");
530 for (
size_t i = 0; i < chunk_count; i++) {
531 if (!ret[i].data_is_str) {
532 free(ret[i].data_uint);
544 for (
size_t i = 0; i < chunk_count; i++) {
545 if (!chunks[i].data_is_str) {
546 free(chunks[i].data_uint);
557 if (!json_is_array(layers)) {
563 size_t layer_count = json_array_size(layers);
565 if (layer_count < 1) {
566 logmsg(
TMJ_LOG_ERR,
"Unable to load layers, 'layers' array must have at least one element");
571 Layer* ret = calloc(layer_count,
sizeof(
Layer));
583 json_array_foreach(layers, idx, layer) {
585 int unpk = json_unpack_ex(layer, &error, 0,
"{s:i}",
"id", &ret[idx].
id);
588 logmsg(
TMJ_LOG_ERR,
"Could not unpack layer ID, %s at line %d column %d", error.text, error.line, error.column);
594 unpk = json_unpack_ex(layer, &error, 0,
"{s:s}",
"type", &ret[idx].type);
597 logmsg(
TMJ_LOG_ERR,
"Could not unpack layer[%d], %s at line %d column %d", ret[idx].
id, error.text, error.line, error.column);
603 unpk = json_unpack_ex(layer,
609 "s?i, s?i, s:i, s:i,"
610 "s?F, s?F, s:F, s?F, s?F"
639 &ret[idx].parallaxy);
642 logmsg(
TMJ_LOG_ERR,
"Could not unpack layer[%d], %s at line %d column %d", ret[idx].
id, error.text, error.line, error.column);
648 if (strcmp(ret[idx].type,
"imagelayer") == 0) {
649 unpk = json_unpack_ex(layer,
663 &ret[idx].transparentcolor);
666 logmsg(
TMJ_LOG_ERR,
"Could not unpack layer[%d], %s at line %d column %d", ret[idx].
id, error.text, error.line, error.column);
670 }
else if (strcmp(ret[idx].type,
"tilelayer") == 0) {
671 unpk = json_unpack_ex(layer,
679 &ret[idx].compression,
688 logmsg(
TMJ_LOG_ERR,
"Could not unpack layer[%d], %s at line %d column %d", ret[idx].
id, error.text, error.line, error.column);
692 }
else if (strcmp(ret[idx].type,
"objectgroup") == 0) {
693 unpk = json_unpack_ex(layer, &error, 0,
"{s?s}",
"draworder", &ret[idx].draworder);
696 logmsg(
TMJ_LOG_ERR,
"Could not unpack layer[%d], %s at line %d column %d", ret[idx].
id, error.text, error.line, error.column);
703 if (strcmp(ret[idx].type,
"tilelayer") == 0) {
706 unpk = json_unpack_ex(layer, &error, 0,
"{s:o}",
"data", &data);
709 logmsg(
TMJ_LOG_ERR,
"Could not unpack layer[%d], %s at line %d column %d", ret[idx].
id, error.text, error.line, error.column);
714 if (json_is_string(data)) {
717 unpk = json_unpack_ex(layer, &error, 0,
"{s:s}",
"data", &ret[idx].data_str);
720 logmsg(
TMJ_LOG_ERR,
"Could not unpack layer[%d], %s at line %d column %d", ret[idx].
id, error.text, error.line, error.column);
724 }
else if (json_is_array(data)) {
729 ret[idx].
data_uint = calloc(ret[idx].data_count,
sizeof(
unsigned int));
731 if (ret[idx].data_uint == NULL) {
732 logmsg(
TMJ_LOG_ERR,
"Unable to unpack layer[%d]->data, the system is out of memory", ret[idx].
id);
741 json_array_foreach(data, idx2, datum) {
742 unpk = json_unpack_ex(datum, &error, 0,
"i", &ret[idx].data_uint[idx2]);
749 logmsg(
TMJ_LOG_ERR,
"Unable to unpack layer[%d]->data, data must be a string or an array", ret[idx].
id);
756 json_t* properties = NULL;
758 unpk = json_unpack_ex(layer, &error, 0,
"{s?o}",
"properties", &properties);
764 if (properties != NULL) {
767 if (ret[idx].properties == NULL) {
775 if (strcmp(ret[idx].type,
"tilelayer") == 0) {
776 json_t* chunks = NULL;
778 unpk = json_unpack_ex(layer, &error, 0,
"{s?o}",
"chunks", &chunks);
781 goto fail_properties;
784 if (chunks != NULL) {
787 if (ret[idx].chunks == NULL) {
790 goto fail_properties;
796 if (strcmp(ret[idx].type,
"objectgroup") == 0) {
797 json_t* objects = NULL;
799 unpk = json_unpack_ex(layer, &error, 0,
"{s:o}",
"objects", &objects);
805 if (objects != NULL) {
808 if (ret[idx].objects == NULL) {
819 if (strcmp(ret[idx].type,
"group") == 0) {
820 json_t* nested_layers = NULL;
822 unpk = json_unpack_ex(layer, &error, 0,
"{s:o}",
"layers", &nested_layers);
828 if (json_is_array(nested_layers) && json_array_size(nested_layers) > 0) {
831 if (ret[idx].layers == NULL) {
843 for (
size_t i = 0; i < layer_count; i++) {
847 for (
size_t i = 0; i < layer_count; i++) {
852 for (
size_t i = 0; i < layer_count; i++) {
853 free(ret[i].properties);
857 for (
size_t i = 0; i < layer_count; i++) {
858 if (!ret[i].data_is_str) {
859 free(ret[i].data_uint);
875 for (
size_t i = 0; i < layer_count; i++) {
876 free_objects(layers[i].objects, layers[i].object_count);
877 free_chunks(layers[i].chunks, layers[i].chunk_count);
878 free(layers[i].properties);
879 free(layers[i].data_uint);
881 layers_free(layers[i].layers, layers[i].layer_count);
890 Map* map = calloc(1,
sizeof(
Map));
893 logmsg(
TMJ_LOG_ERR,
"Could not load map '%s', the system is out of memory", path);
901 int unpk = json_unpack_ex(root, &error, 0,
"{s:s}",
"type", &map->
type);
904 logmsg(
TMJ_LOG_ERR,
"Unable to unpack map[%s]->type, %s at line %d, column %d", path, error.text, error.line, error.column);
909 if (strcmp(map->
type,
"map") != 0) {
915 json_t* tilesets = NULL;
916 json_t* layers = NULL;
917 json_t* properties = NULL;
920 unpk = json_unpack_ex(root,
925 "s?s, s?s, s:s, s:s, s:s, s:s,"
926 "s:i, s:i, s:i, s:i, s:i, s:i, s:i,"
970 logmsg(
TMJ_LOG_ERR,
"Could not unpack map[%s], %s at line %d, column %d", path, error.text, error.line, error.column);
977 unpk = json_unpack_ex(root, &error, 0,
"{s:s, s:s}",
"staggeraxis", &map->
staggeraxis,
"staggerindex", &map->
staggerindex);
980 logmsg(
TMJ_LOG_ERR,
"Could not unpack map[%s], %s at line %d, column %d", path, error.text, error.line, error.column);
987 unpk = json_unpack_ex(root, &error, 0,
"{s:i}",
"hexsidelength", &map->
hexsidelength);
990 logmsg(
TMJ_LOG_ERR,
"Unable to unpack map[%s], %s at line %d, column %d", path, error.text, error.line, error.column);
997 if (properties != NULL) {
1010 if (map->
layers == NULL) {
1013 goto fail_properties;
1019 if (!json_is_array(tilesets)) {
1020 logmsg(
TMJ_LOG_ERR,
"Unable to unpack map[%s]->tilesets, tilesets must be an array of Tilesets", path);
1025 size_t tileset_count = json_array_size(tilesets);
1030 logmsg(
TMJ_LOG_ERR,
"Unable to unpack map[%s]->tilesets, the system is out of memory", path);
1036 json_t* tileset = NULL;
1038 json_array_foreach(tilesets, idx, tileset) {
1039 char* source = NULL;
1042 unpk = json_unpack_ex(tileset, &error, 0,
"{s?s, s?i}",
"source", &source,
"firstgid", &firstgid);
1045 logmsg(
TMJ_LOG_ERR,
"Unable to unpack map[%s]->tilesets, %s at line %d column %d", path, error.text, error.line, error.column);
1060 logmsg(
TMJ_LOG_ERR,
"Unable to unpack map[%s]->tilesets, could not unpack embedded tileset", path);
1089 char* ext = strrchr(path,
'.');
1091 if (check_extension) {
1098 if (strcmp(ext,
".tmj") != 0 && strcmp(ext,
".json") != 0) {
1099 logmsg(
TMJ_LOG_ERR,
"Map filename '%s' has unknown extension, '%s'", path, ext);
1100 logmsg(
TMJ_LOG_ERR,
"Map filename '%s' must have '.tmj' or '.json' extension to be loaded", path);
1109 json_t* root = json_load_file(path, JSON_REJECT_DUPLICATES, &error);
1112 logmsg(
TMJ_LOG_ERR,
"Could not load map %s, %s at line %d column %d", path, error.text, error.line, error.column);
1123 json_t* root = json_loads(map, JSON_REJECT_DUPLICATES, &error);
1126 logmsg(
TMJ_LOG_ERR,
"Could not load map %s, %s at line %d column %d", name, error.text, error.line, error.column);
1143 json_decref(map->
root);
void logmsg(tmj_log_priority priority, char *msg,...)
Processes log messages and passes them to the active logging callback, if there is one.
Map * tmj_map_load(const char *map, const char *name)
Loads the Tiled map from the given JSON object string.
Map * tmj_map_loadf(const char *path, bool check_extension)
Loads the Tiled map from the file at the given path.
void tmj_map_free(Map *map)
Frees the memory associated with the given map.
Chunk * unpack_chunks(json_t *chunks)
Object * unpack_objects(json_t *objects)
Point * unpack_points(json_t *points)
Unpacks an array of points.
Map * map_load_json(json_t *root, const char *path)
Property * unpack_properties(json_t *properties)
void free_chunks(Chunk *chunks, size_t chunk_count)
Text * unpack_text(json_t *text)
Unpacks a text object.
void free_objects(Object *objects, size_t object_count)
Helper function to free Objects.
Layer * unpack_layers(json_t *layers)
Loads map layers recursively.
void layers_free(Layer *layers, size_t layer_count)
Helper function for freeing layer tree associated with a map.
https://doc.mapeditor.org/en/stable/reference/json-map-format/#chunk
https://doc.mapeditor.org/en/stable/reference/json-map-format/#layer
https://doc.mapeditor.org/en/stable/reference/json-map-format/#json-map-format
json_t * root
The root object returned by jansson after parsing.
https://doc.mapeditor.org/en/stable/reference/json-map-format/#object
size_t polygon_point_count
size_t polyline_point_count
https://doc.mapeditor.org/en/stable/reference/json-map-format/#point
https://doc.mapeditor.org/en/stable/reference/json-map-format/#property
https://doc.mapeditor.org/en/stable/reference/json-map-format/#text
https://doc.mapeditor.org/en/stable/reference/json-map-format/#tileset
int unpack_tileset(json_t *tileset, Tileset *ret)
void tilesets_free(Tileset *tilesets, size_t tileset_count)
Helper function for freeing tilesets embedded in maps.