Properly deinit everything
parent
ec04460077
commit
f2d59bbcd7
220
src/LDtk.zig
220
src/LDtk.zig
|
@ -10,87 +10,6 @@ pub fn parse(alloc: std.mem.Allocator, ldtk_file: []const u8) !Root {
|
||||||
return Root.fromJSON(alloc, value_tree.root);
|
return Root.fromJSON(alloc, value_tree.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility functions
|
|
||||||
pub fn object(value_opt: ?std.json.Value) ?std.json.ObjectMap {
|
|
||||||
const value = value_opt orelse return null;
|
|
||||||
return switch (value) {
|
|
||||||
.Object => |obj| obj,
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn array(value_opt: ?std.json.Value) ?std.json.Array {
|
|
||||||
const value = value_opt orelse return null;
|
|
||||||
return switch (value) {
|
|
||||||
.Array => |arr| arr,
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string(value_opt: ?std.json.Value) ?[]const u8 {
|
|
||||||
const value = value_opt orelse return null;
|
|
||||||
return switch (value) {
|
|
||||||
.String => |str| str,
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string_list(alloc: std.mem.Allocator, array_opt: ?std.json.Value) ![][]const u8 {
|
|
||||||
const arr = array(array_opt) orelse return &[_][]const u8{};
|
|
||||||
var list = try std.ArrayList([]const u8).initCapacity(alloc, arr.items.len);
|
|
||||||
defer list.deinit();
|
|
||||||
for (arr.items) |value| {
|
|
||||||
list.appendAssumeCapacity(string(value) orelse return error.InvalidString);
|
|
||||||
}
|
|
||||||
return list.toOwnedSlice();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn boolean(value_opt: ?std.json.Value) ?bool {
|
|
||||||
const value = value_opt orelse return null;
|
|
||||||
return switch (value) {
|
|
||||||
.Bool => |b| b,
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn integer(value_opt: ?std.json.Value) ?i64 {
|
|
||||||
const value = value_opt orelse return null;
|
|
||||||
return switch (value) {
|
|
||||||
.Integer => |int| int,
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn float(value_opt: ?std.json.Value) ?f64 {
|
|
||||||
const value = value_opt orelse return null;
|
|
||||||
return switch (value) {
|
|
||||||
.Float => |float| float,
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn enum_from_value(comptime T: type, value_opt: ?std.json.Value) ?T {
|
|
||||||
const value = value_opt orelse return null;
|
|
||||||
return switch (value) {
|
|
||||||
.String => |str| std.meta.stringToEnum(T, str),
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pos_from_value(value_opt: ?std.json.Value) ?[2]i64 {
|
|
||||||
const value = array(value_opt) orelse return null;
|
|
||||||
const x = integer(value.items[0]) orelse return null;
|
|
||||||
const y = integer(value.items[1]) orelse return null;
|
|
||||||
return [2]i64{ x, y };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn posf_from_value(value_opt: ?std.json.Value) ?[2]f64 {
|
|
||||||
const value = array(value_opt) orelse return null;
|
|
||||||
const x = float(value.items[0]) orelse return null;
|
|
||||||
const y = float(value.items[1]) orelse return null;
|
|
||||||
return [2]f64{ x, y };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 1. LDtk Json root
|
/// 1. LDtk Json root
|
||||||
pub const Root = struct {
|
pub const Root = struct {
|
||||||
bgColor: []const u8,
|
bgColor: []const u8,
|
||||||
|
@ -121,6 +40,16 @@ pub const Root = struct {
|
||||||
}
|
}
|
||||||
return ldtk_root;
|
return ldtk_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(root: Root, alloc: std.mem.Allocator) void {
|
||||||
|
if (root.defs) |defs| defs.deinit(alloc);
|
||||||
|
if (root.worlds) |worlds| {
|
||||||
|
for (worlds) |world| world.deinit(alloc);
|
||||||
|
alloc.free(worlds);
|
||||||
|
}
|
||||||
|
for (root.levels) |level| level.deinit(alloc);
|
||||||
|
alloc.free(root.levels);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 1.1. World
|
/// 1.1. World
|
||||||
|
@ -153,6 +82,11 @@ pub const World = struct {
|
||||||
}
|
}
|
||||||
return ldtk_worlds.toOwnedSlice();
|
return ldtk_worlds.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(world: World, alloc: std.mem.Allocator) void {
|
||||||
|
for (world.levels) |level| level.deinit(alloc);
|
||||||
|
alloc.free(world.levels);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const WorldLayout = enum {
|
pub const WorldLayout = enum {
|
||||||
|
@ -219,6 +153,15 @@ pub const Level = struct {
|
||||||
}
|
}
|
||||||
return ldtk_levels.toOwnedSlice();
|
return ldtk_levels.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(level: Level, alloc: std.mem.Allocator) void {
|
||||||
|
alloc.free(level.__neighbours);
|
||||||
|
alloc.free(level.fieldInstances);
|
||||||
|
if (level.layerInstances) |layerInstances| {
|
||||||
|
for (layerInstances) |layerInstance| layerInstance.deinit(alloc);
|
||||||
|
alloc.free(layerInstances);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Neighbour = struct {
|
pub const Neighbour = struct {
|
||||||
|
@ -318,6 +261,15 @@ pub const LayerInstance = struct {
|
||||||
}
|
}
|
||||||
return ldtk_layers.toOwnedSlice();
|
return ldtk_layers.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(layerInstance: LayerInstance, alloc: std.mem.Allocator) void {
|
||||||
|
alloc.free(layerInstance.autoLayerTiles);
|
||||||
|
alloc.free(layerInstance.gridTiles);
|
||||||
|
for (layerInstance.entityInstances) |entityInstance| {
|
||||||
|
entityInstance.deinit(alloc);
|
||||||
|
}
|
||||||
|
alloc.free(layerInstance.entityInstances);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const LayerType = enum {
|
const LayerType = enum {
|
||||||
|
@ -427,6 +379,11 @@ const EntityInstance = struct {
|
||||||
}
|
}
|
||||||
return ldtk_entities.toOwnedSlice();
|
return ldtk_entities.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(entityInstance: EntityInstance, alloc: std.mem.Allocator) void {
|
||||||
|
alloc.free(entityInstance.fieldInstances);
|
||||||
|
alloc.free(entityInstance.__tags);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 2.4. Field Instance
|
/// 2.4. Field Instance
|
||||||
|
@ -503,6 +460,12 @@ const Definitions = struct {
|
||||||
levelFields: []FieldDefinition,
|
levelFields: []FieldDefinition,
|
||||||
/// All tilesets
|
/// All tilesets
|
||||||
tilesets: []TilesetDefinition,
|
tilesets: []TilesetDefinition,
|
||||||
|
|
||||||
|
pub fn deinit(defs: Definitions, alloc: std.mem.Allocator) void {
|
||||||
|
_ = defs;
|
||||||
|
_ = alloc;
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 3.1. Layer definition
|
/// 3.1. Layer definition
|
||||||
|
@ -620,3 +583,98 @@ const EnumValueDefinition = struct {
|
||||||
id: []const u8,
|
id: []const u8,
|
||||||
tileId: ?i64,
|
tileId: ?i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
/// Takes std.json.Value and returns std.json.ObjectMap or null
|
||||||
|
pub fn object(value_opt: ?std.json.Value) ?std.json.ObjectMap {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Object => |obj| obj,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes std.json.Value and returns std.json.Array or null
|
||||||
|
pub fn array(value_opt: ?std.json.Value) ?std.json.Array {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Array => |arr| arr,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes std.json.Value and returns []const u8 or null
|
||||||
|
pub fn string(value_opt: ?std.json.Value) ?[]const u8 {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.String => |str| str,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes std.json.Value and returns an error, [][]const u8, or null
|
||||||
|
pub fn string_list(alloc: std.mem.Allocator, array_opt: ?std.json.Value) ![][]const u8 {
|
||||||
|
const arr = array(array_opt) orelse return &[_][]const u8{};
|
||||||
|
var list = try std.ArrayList([]const u8).initCapacity(alloc, arr.items.len);
|
||||||
|
defer list.deinit();
|
||||||
|
for (arr.items) |value| {
|
||||||
|
list.appendAssumeCapacity(string(value) orelse return error.InvalidString);
|
||||||
|
}
|
||||||
|
return list.toOwnedSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes std.json.Value and returns bool or null
|
||||||
|
pub fn boolean(value_opt: ?std.json.Value) ?bool {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Bool => |b| b,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes std.json.Value and returns i64 or null
|
||||||
|
pub fn integer(value_opt: ?std.json.Value) ?i64 {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Integer => |int| int,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes std.json.Value and returns f64 or null
|
||||||
|
fn float(value_opt: ?std.json.Value) ?f64 {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Float => |float| float,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes an enum and std.json.Value.
|
||||||
|
/// Return values:
|
||||||
|
/// - If the Value is a String it will attempt to convert it into an enum
|
||||||
|
/// - If the String is not in the enum, null is returned
|
||||||
|
/// - If the Value is not a String, null is returned
|
||||||
|
pub fn enum_from_value(comptime T: type, value_opt: ?std.json.Value) ?T {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.String => |str| std.meta.stringToEnum(T, str),
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes std.json.Value and returns [2]i64 or null
|
||||||
|
pub fn pos_from_value(value_opt: ?std.json.Value) ?[2]i64 {
|
||||||
|
const value = array(value_opt) orelse return null;
|
||||||
|
const x = integer(value.items[0]) orelse return null;
|
||||||
|
const y = integer(value.items[1]) orelse return null;
|
||||||
|
return [2]i64{ x, y };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes std.json.Value and returns [2]f64 or null
|
||||||
|
pub fn posf_from_value(value_opt: ?std.json.Value) ?[2]f64 {
|
||||||
|
const value = array(value_opt) orelse return null;
|
||||||
|
const x = float(value.items[0]) orelse return null;
|
||||||
|
const y = float(value.items[1]) orelse return null;
|
||||||
|
return [2]f64{ x, y };
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ test "load default/empty ldtk file" {
|
||||||
const empty_ldtk = @embedFile("test.ldtk");
|
const empty_ldtk = @embedFile("test.ldtk");
|
||||||
|
|
||||||
const ldtk_root = try LDtk.parse(testing.allocator, empty_ldtk);
|
const ldtk_root = try LDtk.parse(testing.allocator, empty_ldtk);
|
||||||
|
defer ldtk_root.deinit(testing.allocator);
|
||||||
|
|
||||||
try testing.expectEqualStrings("1.1.3", ldtk_root.jsonVersion);
|
try testing.expectEqualStrings("1.1.3", ldtk_root.jsonVersion);
|
||||||
try testing.expectEqualStrings("#40465B", ldtk_root.bgColor);
|
try testing.expectEqualStrings("#40465B", ldtk_root.bgColor);
|
||||||
|
|
Loading…
Reference in New Issue