186 lines
5.1 KiB
Zig
186 lines
5.1 KiB
Zig
const std = @import("std");
|
|
|
|
const Allocator = std.mem.Allocator;
|
|
const AutoHashMap = std.AutoHashMap;
|
|
const ArrayList = std.ArrayList;
|
|
|
|
/// This file introduces the main structures used by guid once running.
|
|
/// Tests show how to use them.
|
|
/// Type.create do no allocate memory for the structure, only to its attributes.
|
|
/// Type.deinit works in cascade (deinit its children).
|
|
|
|
const PropertyHashMap = AutoHashMap([] const u8, PropertyValue);
|
|
const NodeList = ArrayList(Node);
|
|
const DefinitionHashMap = AutoHashMap([] const u8, Node);
|
|
|
|
pub const Node = struct {
|
|
id: ?[] const u8,
|
|
type_name: [] const u8,
|
|
properties: PropertyHashMap,
|
|
children: NodeList,
|
|
|
|
gpa: *Allocator,
|
|
|
|
pub fn deinit(self: *Node) void {
|
|
self.properties.deinit();
|
|
for (self.children.items) |*value| {
|
|
value.deinit();
|
|
}
|
|
self.children.deinit();
|
|
}
|
|
|
|
pub fn create(allocator: *Allocator, type_name: []const u8, id: ?[]const u8) !Node {
|
|
return Node{
|
|
.id = id,
|
|
.type_name = type_name,
|
|
.properties = PropertyHashMap.init(allocator),
|
|
.children = NodeList.init(allocator),
|
|
.gpa = allocator,
|
|
};
|
|
}
|
|
};
|
|
|
|
const PropertyValueTags = enum {
|
|
string,
|
|
integer,
|
|
float,
|
|
reference,
|
|
};
|
|
|
|
pub const PropertyValue = union(PropertyValueTags) {
|
|
// nil: null,
|
|
string: [] const u8, // String.
|
|
integer: u64, // Num (integer).
|
|
float: f64, // Num (float).
|
|
reference: [] const u8, // Reference to another property (property binding).
|
|
};
|
|
|
|
pub const Tree = struct {
|
|
definitions: DefinitionHashMap,
|
|
children: NodeList,
|
|
|
|
gpa: *Allocator,
|
|
|
|
pub fn deinit(self: *Tree) void {
|
|
self.definitions.deinit();
|
|
for (self.children.items) |*value| {
|
|
value.deinit();
|
|
}
|
|
self.children.deinit();
|
|
}
|
|
|
|
pub fn create(allocator: *Allocator) !Tree {
|
|
return Tree{
|
|
.definitions = DefinitionHashMap.init(allocator),
|
|
.children = NodeList.init(allocator),
|
|
.gpa = allocator,
|
|
};
|
|
}
|
|
|
|
};
|
|
|
|
// TESTS and private util functions.
|
|
|
|
fn say(tosay: []const u8) void {
|
|
std.debug.print("{}", .{tosay});
|
|
}
|
|
|
|
fn print_properties(properties: PropertyHashMap) void {
|
|
var it = properties.iterator();
|
|
while(it.next()) |kv| {
|
|
std.debug.print("\t{} => {}\n", .{kv.key, properties.get(kv.key)});
|
|
}
|
|
}
|
|
|
|
fn print_node(node: Node) void {
|
|
std.debug.print("Node type {} (id: {})\n", .{node.type_name, node.id});
|
|
print_properties(node.properties);
|
|
}
|
|
|
|
pub fn print_tree(tree: Tree) void {
|
|
say("\ntree.definitions:\n");
|
|
var it = tree.definitions.iterator();
|
|
while(it.next()) |kv| {
|
|
std.debug.print("{} => ", .{kv.key});
|
|
const node = tree.definitions.get(kv.key);
|
|
if(node) |n| { print_node(n); }
|
|
}
|
|
|
|
say("tree.children:\n");
|
|
for(tree.children.items) |v, k| {
|
|
std.debug.print("{} => ", .{k});
|
|
print_node(v);
|
|
}
|
|
}
|
|
|
|
test "simple test about structures" {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{.safety = true}){};
|
|
const allocator = &gpa.allocator;
|
|
|
|
var value = PropertyValue { .integer = 10 };
|
|
var properties = PropertyHashMap.init(allocator);
|
|
try properties.put("hello", value);
|
|
|
|
// Displaying the content.
|
|
// say("\n");
|
|
// print_properties(properties);
|
|
|
|
// Freeing the properties.
|
|
properties.deinit();
|
|
|
|
// Testing memory leaks at the end of the test.
|
|
const leaks = gpa.deinit();
|
|
if (leaks) {
|
|
say("\nthere were leaks, oh no\n");
|
|
}
|
|
else {
|
|
say("\nno leaks, yay!\n");
|
|
}
|
|
std.testing.expect(! leaks);
|
|
}
|
|
|
|
fn init_stuff(allocator: *Allocator) !Tree {
|
|
var tree = try Tree.create(allocator);
|
|
|
|
// Creating a definition and a few children.
|
|
try tree.definitions.put("MyObject", try Node.create(allocator, "my-type-name", "my-id"));
|
|
var new_node = try Node.create(allocator, "Object", "some-id-for-this-object");
|
|
var value = PropertyValue { .integer = 10 };
|
|
try new_node.properties.put("integer-val", value);
|
|
value = PropertyValue { .string = "some value" };
|
|
try new_node.properties.put("string-val", value);
|
|
|
|
try tree.children.append(new_node);
|
|
try tree.children.append(try Node.create(allocator, "Object", "my-id"));
|
|
try tree.children.append(try Node.create(allocator, "OtherObject", null));
|
|
try tree.children.append(try Node.create(allocator, "Text", "my-id-for-text-object"));
|
|
|
|
return tree;
|
|
}
|
|
|
|
test "init a Tree structure" {
|
|
// Allocator with safety on: checking for memory leaks.
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{.safety = true}){};
|
|
const allocator = &gpa.allocator;
|
|
|
|
// Creating a tree.
|
|
var tree = try init_stuff(allocator);
|
|
|
|
// Display the content of the tree.
|
|
// print_tree(tree);
|
|
|
|
// Freeing the tree.
|
|
tree.deinit();
|
|
|
|
// Testing memory leaks at the end of the test.
|
|
const leaks = gpa.deinit();
|
|
if (leaks) {
|
|
say("\nthere were leaks, oh no\n");
|
|
}
|
|
else {
|
|
say("\nno leaks, yay!\n");
|
|
}
|
|
std.testing.expect(! leaks);
|
|
}
|
|
|