z_mirror/hare-fmm
git clone https://git.raiguard.me/z_mirror/hare-fmm
74b341b
trunk
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};