Properly deinit everything

dev
Louis Pearson 2022-08-03 12:40:25 -06:00
parent ec04460077
commit f2d59bbcd7
2 changed files with 140 additions and 81 deletions

View File

@ -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 };
}

View File

@ -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);