z_mirror/hare-fmm

git clone https://git.raiguard.me/z_mirror/hare-fmm

Caleb HeuerConvert to for-each loops and fix some potential memory issues74b341b

trunk
2.0 KiB76 linesraw
1use fmt;
2use strings;
3
4// A representation of a mod, with a name and optional version.
5type modident = (str, (version | void));
6
7// Frees resources related to a [[modident]].
8fn modident_free(mod: *modident) void = {
9	free(mod.0);
10};
11
12// Frees resources related to a slice of [[modident]].
13fn modident_free_all(list: []modident) void = {
14	for (let ident &.. list) {
15		modident_free(ident);
16	};
17	free(list);
18};
19
20// Parses an input string into a [[modident]]. The input string will not be
21// interpreted as a mod set. The return value must be freed with
22// [[modident_free]].
23fn modident_parse(input: str) modident = {
24	const input = strings::trimsuffix(input, ".zip");
25	const parts = strings::split(input, "_")!;
26	defer free(parts);
27	if (len(parts) == 1)
28		return (strings::dup(input)!, void);
29
30	const name = strings::concat(parts[..len(parts) - 1]...)!;
31	match (version_parse(parts[len(parts) - 1])) {
32	case let ver: version =>
33		return (name, ver);
34	case =>
35		return (name, void);
36	};
37};
38
39// Parses a slice of input strings into a slice of [[modident]]. If the input is
40// a mod set name, it will be expanded. The return value must be freed with
41// [[modident_free_all]].
42fn modident_parseall(input: *[]str, config: *config) []modident = {
43	let mods: []modident = [];
44	for (let input &.. input) {
45		// Mod set
46		if (strings::hasprefix(*input, '!')) {
47			const set_name = strings::sub(*input, 1, strings::end);
48			match (config_find_set(config, set_name)) {
49			case let set: *modset =>
50				append(mods, set.1...)!;
51			case =>
52				fmt::errorfln(
53					"Mod set '{}' does not exist",
54					set_name
55				)!;
56			};
57			continue;
58		};
59		// Standard mod
60		append(mods, modident_parse(*input))!;
61	};
62	return mods;
63};
64
65// Converts a [[modident]] into a user-friendly string. The return value must
66// be freed by the caller.
67fn modident_str(mod: *modident) str = {
68	match (mod.1) {
69	case let ver: version =>
70		const verstr = version_str(ver, false);
71		defer free(verstr);
72		return fmt::asprint(mod.0, verstr)!;
73	case =>
74		return fmt::asprint(mod.0)!;
75	};
76};