// ------------------------------------------------------------------ // Just a placeholder parent $root object $libraries var $root inited 1 var $root objname 'libraries // ------------------------------------------------------------------ // $string library parent $libraries object $string var $root inited 1 var $root objname 'string var $string alphabet "abcdefghijklmnopqrstuvwxyz" var $string numbers "1234567890" var $string non_alphanumeric "!@#$%^&*()_+-=~`'{}[]|/?\"\\,.<>;: " public trim arg string, [dir]; var reg, range; // trim whitespace from string, args can be 'left or 'right if (type(string) != 'string) throw(~invarg, "Argument must be a string."); dir = [@dir, 'right][1]; if (dir == 'left) { range = "[^ ] *$".match_regexp(string); if (!range) return string; range = [1, range[1][2]]; } else { range = "[^ ]".match_regexp(string); if (!range) return string; range = [range[1][1]]; } return .subrange(@range); . public alphabet return alphabet; . public numbers return numbers; . public non_alphanumeric return non_alphanumeric; . public is_numeric arg string; return toint(string) || string == "0"; . public a_or_an arg string; if (string[1].lowercase() in "aeiou") return "an"; return "a"; . public strip arg string, strip; var new_str, char; // strips all of "strip" characters from the string // if "strip" is -1 it will use .non_alphanumeric() if (type(string) != 'string || type(strip) != 'string && strip != -1) throw(~type, "First argument must be a string, second can be -1"); new_str = ""; if (strip == -1) new_str = non_alphanumeric; for char in [1 .. string.length()] { if (!(string[char] in strip)) new_str = new_str + string[char]; } return new_str; . public chop arg str, len, [end]; // chops string off end.length() characters before len and appends len end = [@end, "..."][1]; if (str.length() < len) return str; if (str.length() < end.length()) return str; return str.pad(len - end.length()) + end; . public explode_english_list arg line, [opts]; var x, output, tmp; // explodes an english list ("foo, bar and zoo"). line = line.explode(","); output = []; for x in (line) { x = .trim(x); if ((| x.subrange(1, 3) |) == "and") output = [@output, .trim(x.subrange(4))]; else output = [@output, x]; } // check the last element, if they didn't specify 'noand if (!('noand in opts)) { line = output[output.length()].explode(); tmp = ""; for x in [1 .. line.length()] { if (line[x] == "and") { output = output.delete(output.length()); if (tmp) output = [@output, tmp]; tmp = .to_string(line.subrange(x + 1)); if (tmp) output = [@output, tmp]; // only bother with the first "and" break; } tmp = tmp + (tmp ? " " | "") + line[x]; } } return output; . public wrap_lines arg string, length, [stuff]; var output, cutoff, firstline, prefix; // takes string and wraps it by words, compared to length, returns a list. prefix = [@stuff, ""][1]; firstline = [@stuff, 0, 0][2]; output = []; if (firstline) string = prefix + string; while (string.length() > length) { cutoff = .rindex(string.subrange(1, length), " "); output = [@output, string.subrange(1, cutoff - 1)]; string = prefix + string.subrange(cutoff + 1); } return [@output, string]; . public wrap_line arg string, length, [stuff]; var output, cutoff, firstline, prefix; // takes string and wraps it by words, compared to length, breaks with \n prefix = [@stuff, ""][1]; firstline = [@stuff, 0, 0][2]; output = ""; if (firstline) string = prefix + string; while (string.length() > length) { cutoff = .rindex(string.subrange(1, length), " "); output = output + "\\n" + string.subrange(1, cutoff - 1); string = prefix + string.subrange(cutoff + 1); } return output + "\\n" + string; . public rindex arg str, c; var i; i = strlen(str); while (i) { if (str[i] == c) return i; i = i - 1; } return 0; . public is_boolean arg str; if (.match_begin("yes", str) || .match_begin("true", str) || str == "1") return 1; else if (.match_begin("no", str) || .match_begin("false", str) || str == "0") return 0; else return -1; . public explode arg [args]; return (> explode(@args) <); . public match_template arg template, string; return (> match_template(template, string) <); . public match_pattern arg pattern, string; return (> match_pattern(pattern, string) <); . public match_regexp arg [args]; return (> match_regexp(@args) <); . public toliteral arg [args]; return (> toliteral(@args) <); . public last arg str; return str[str.length()]; . public explode_list arg str; if ("," in str) return str.explode_english_list(); else return str.explode(); . public explode_quoted arg str; var out, result; out = []; while (str) { result = .match_pattern("*\"*\"*", str); if (result) { out = [@out, @result[1].explode(), result[2].trim()]; str = result[3]; } else { out = [@out, @str.explode()]; str = ""; } } return out; . public regexp arg regexp, string; var match, m, complete, out; match = $string.match_regexp(regexp, string); if (!match) return 0; complete = match[1]; out = []; for m in (match.delete(1)) { if (!m[1]) break; out = out + [string.subrange(@m)]; } return out || string.subrange(@complete); . method pad arg [args]; return (> pad(@args) <); . method length arg str; return (> strlen(str) <); . method subrange arg [args]; return (> substr(@args) <); . method match_begin arg [args]; return (> match_begin(@args) <); . method crypt arg [args]; return (> crypt(@args) <); . method uppercase arg string; return (> uppercase(string) <); . method lowercase arg string; return (> lowercase(string) <); . method compare arg str1, str2; return (> strcmp(str1, str2) <); . method format arg format, [args]; return (> strfmt(format, args) <); . method to_symbol arg [args]; return (> tosym(@args) <); . method replace arg [args]; return (> strsub(@args) <); . // ------------------------------------------------------------------ // $list library parent $libraries object $list var $root inited 1 var $root objname 'list public to_string arg list, [sep]; var str, part; // uses $parse.unparse() rather than tostr() if (!list) return ""; sep = [@sep, " "][1]; str = tostr(list[1]); for part in (list.delete(1)) str = str + sep + tostr(part); return str; . public to_english arg list, [options]; var empty, and, sep; // uses $parse.unparse() rather than tostr() empty = [@options, "nothing"][1]; switch (list.length()) { case 0: return empty; case 1: return tostr(list[1]); } and = [@options, " and ", " and "][2]; sep = [@options, ", ", ", ", ", "][3]; return .to_string(list.delete(list.length()), sep) + and + tostr(list[list.length()]); . public map arg list, method, [args]; var out, x; // call 'method on each object, return results. out = []; for x in (list) out = [@out, x.(method)(@args)]; return out; . public reverse arg list; var elm, reversed; // .reverse(list) // -> list with its elements reversed reversed = []; for elm in (list) reversed = [elm, @reversed]; return reversed; . public compress arg list; var out, last, x; // [a,a,b,b,c,c,d,d] => [a,b,c,d] // removes duplicate entries in a list out = []; for x in (list) { if (!(x in out)) out = [@out, x]; } return out; . public last arg list; return list[list.length()]; . public slice arg big_list, element; var list, ret_list; // Return elementh' element of all lists in big_list // No type or length checking done for speed purposes. ret_list = []; for list in (big_list) ret_list = [@ret_list, list[element]]; return ret_list; . public max arg list; // return greatest element of list (no type checking performed) // if list is [], returns 0 while (list.length() > 1) { if (list[1] > list[2]) list = list.delete(2); else list = list.delete(1); } return [@list, 0][1]; . public min arg list; // return least element of list (no type checking performed) // if list is [], returns 0 while (list.length() > 1) { if (list[1] < list[2]) list = list.delete(2); else list = list.delete(1); } return [@list, 0][1]; . public lcolumnize arg list, [args]; var line, part, lines, max, cols, col, width, len, sep; len = [@args, (| sender().linelen() |) || 79][1]; sep = [@args, "", ""][2]; lines = []; line = ""; max = .element_maxlength(list) + sep.length(); cols = len > max ? len / max | 1; width = len / cols - sep.length(); col = cols; for part in (list) { col = col - 1; if (!col) { lines = lines + [line + part]; line = ""; col = cols; continue; } line = line + part.pad(width); } if (line) return lines + [line]; return lines; . public flatten arg list; var toret, elem; // [[[x], x], x] => [x, x, x] toret = []; for elem in (list) { if (type(elem) == 'list) toret = toret + .flatten(elem); else toret = toret + [elem]; } return toret; . public to_buffer arg [args]; return (> $buffer.from_strings(@args) <); . public delete arg [args]; return (> delete(@args) <); . public replace arg [args]; return (> replace(@args) <); . public graft arg l1, l2; var last, first; // Combines l1 and l2 by appending the first element of l2 to the last // of l1. if (type(l2) != 'list) l2 = [l2]; last = (| l1.last() |) || ""; first = (| l2[1] |) || ""; l1 = [@l1.chop(), last + first]; if (l2.length() > 1) l1 = l1 + l2.subrange(2); return l1; . public length arg l; return (> listlen(l) <); . public union arg [args]; return (> union(@args) <); . public setdifference arg [args]; var set, list, element; // Usage: diff(set 1, set 2, ..., set n) // Returns all elements of set 1 that are not in sets 2..n if (!args) return []; set = args[1]; for list in (args.delete(1)) { for element in (list) set = set.setremove(element); } return set; . public setcontains arg [args]; var super, list, element; // True if the first list given is a superset of all subsequent lists. // False otherwise. [] is a superset of [] and nothing else; anything is // a superset of []. If only one list is given, return true. super = args ? args[1] | []; for list in (args.delete(1)) { for element in (list) { if (!(element in super)) return 0; } } return 1; . public setequal arg set1, set2; var element; // True if the two lists given contain the same elements. // False otherwise. while (set1) { element = set1[1]; if (!element in set2) return 0; while (element in set2) set2 = set2.setremove(element); while (element in set1) set1 = set1.setremove(element); } return set2 == []; . public fold arg list, object, method, [args]; var i, out; // apply object.method to a current result and the next element, return the // result if (list == []) return 0; out = list[1]; for i in (list.subrange(2, list.length() - 1)) out = object.(method)(out, i, @args); return out; . public setadd arg [args]; return (> setadd(@args) <); . public intersection arg l1, l2; var i, out; // set intersection if the arguments out = []; for i in (l1) { if (i in l2) out = out.setadd(i); } return out; . public setremove arg [args]; return (> setremove(@args) <); . public insert arg [args]; return (> insert(@args) <); . public subrange arg [args]; return (> sublist(@args) <); . public msort arg list, [keys]; keys = keys ? keys[1] | list; if (listlen(list) != listlen(keys)) throw(~invarg, "Invalid key list - the list lengths must be the same."); if (!list) return []; return (._merge_sort(list, keys))[1]; // 9-25-95/21:26 Jenner ($jenner), moved from $jenner.msort . public _merge_sort arg list, keys; var i, j, l1, k1, l2, k2, n1, n2, n; n = listlen(list); if (n == 1) return [list, keys]; n1 = n / 2; n2 = n - n1; l1 = ._merge_sort(list.subrange(1, n1), keys.subrange(1, n1)); k1 = l1[2]; l1 = l1[1]; l2 = ._merge_sort(list.subrange(n1 + 1, n2), keys.subrange(n1 + 1, n2)); k2 = l2[2]; l2 = l2[1]; list = []; keys = []; i = 1; j = 1; if (n > 30) pause(); while (i <= n1 && j <= n2) { if (k1[i] <= k2[j]) { list = [@list, l1[i]]; keys = [@keys, k1[i]]; i = i + 1; } else { list = [@list, l2[j]]; keys = [@keys, k2[j]]; j = j + 1; } } return [[@list, @l1.subrange(i), @l2.subrange(j)], [@keys, @k1.subrange(i), @k2.subrange(j)]]; . public prefix arg list, prefix; var out, elem; out = []; for elem in (list) out = out + [prefix + elem]; return out; . public valid_objects arg list; var obj; for obj in (list) { if (!valid(obj)) list = list.setremove(obj); } return list; . // ------------------------------------------------------------------ // $parse library parent $libraries object $parse var $root inited 1 var $root objname 'parse public html_traceback arg status, t; var line, out, x; out = "<h2>" + t[1][2] + "</h2>"; out = [out, "<i><b>Thrown by " + ._html_traceback(@t[2]) + "</b></i>", "<p>"]; for x in [3 .. listlen(t)] { line = "<code><i>" + $parse.unparse(t[x][1]) + "</i>: "; out = out + [line + ._traceback(@t[x]) + "</code><br>"]; } return .response(status, [@out, "</p>"]); . public traceback arg t; var line, out, x; out = "=> " + t[1][2]; out = [out, "Thrown by " + ._traceback(@t[2])]; for x in [3 .. listlen(t)] { line = $parse.unparse(t[x][1]) + ": "; line = line + ._traceback(@t[x]); out = [@out, line]; } return out; . public _html_traceback arg type, what, [more]; var line; switch (type) { case 'function: return "function <tt>" + tostr(what) + "()</tt>"; case 'opcode: return "operator <tt>" + $parse.unparse(what) + "</tt>"; default: line = $parse.unparse(more[2]) + "." + tostr(what) + "()"; if (more[1] != more[2]) line = line + " (" + $parse.unparse(more[1]) + ") "; line = line + " line " + tostr(more[3]); return line; } . public _traceback arg type, what, [more]; var line; switch (type) { case 'function: return "function " + tostr(what) + "()"; case 'opcode: return "operator " + $parse.unparse(what); default: line = $parse.unparse(more[1]) + "." + tostr(what) + "()"; if (more[1] != more[2]) line = line + " (" + $parse.unparse(more[2]) + ") "; line = line + " line " + tostr(more[3]); return line; } . public get_name arg obj; var name; if (!valid(obj)) return "** Invalid " + toliteral(obj) + " **"; return obj.objname(); . public unparse arg data; var str, element, association, pos, method; switch (type(data)) { case 'integer, 'float: return tostr(data); case 'string, 'symbol, 'error, 'buffer: return toliteral(data); case 'dbref: return .get_name(data); case 'list: if (!data) return "[]"; str = "["; for element in (sublist(data, 1, listlen(data) - 1)) { str = str + .unparse(element); str = str + ", "; } str = str + .unparse(data[listlen(data)]); return str + "]"; case 'dictionary: if (!data) return "#[]"; str = "#["; for association in (data) { str = str + .unparse(association); str = str + ", "; } return substr(str, 1, strlen(str) - 2) + "]"; case 'frob: catch any { return data.unparse(); } with handler { return toliteral(data); } } . public filter_for_html arg text; var x, line; for x in [1 .. listlen(text)] { if (text[x]) { line = text[x].replace("&", "&").replace("<", "<").replace(">", ">"); text = text.replace(x, line); } } return text; . public getopt arg line, [defaults]; var out, newlist, part, v, opt, t, templates, keys, key, l, x; // submit: [["template", value], [...]]; // => if value is 1, it will take the next part of the string // receive: [["template", "flag", bool, value]], [...]]; line = line.explode_quoted(); out = []; newlist = []; defaults = (| defaults[1] |) || []; templates = defaults.slice(1); x = 1; l = line.length(); while (1) { if (x > l) break; if (line[x][1] in ["-", "+"]) { opt = 0; v = ""; part = line[x].subrange(2); for t in [1 .. templates.length()] { if ("=" in part) { part = part.explode("="); v = (| part[2] |) || ""; part = part[1]; } if ($string.match_template(templates[t], part)) { opt = [templates[t], part, line[x][1] == "+"]; if ((| defaults[t][2] |) && !v) { if (x + 1 <= l) { x = x + 1; if (line[x] == "=") { if (x + 1 <= l) x = x + 1; } v = line[x]; } } opt = opt + [v]; } } if (!opt) opt = [0, part, line[x][1] == "+", ""]; out = out + [opt]; } else { newlist = newlist + [line[x]]; } x = x + 1; } return [newlist, out]; . // ------------------------------------------------------------------ // $dictionary library parent $libraries object $dictionary var $root inited 1 var $root objname 'dictionary public to_list arg dict; var list, x, k; // merges into an associated list. k = dict.keys(); list = []; for x in (k) list = [@list, [x, dict[x]]]; return list; . method union arg dict1, dict2; var key; for key in (dict1) dict2 = dict2.add(key[1], key[2]); return dict2; . method values arg dict; var list, x, k; // returns values same as dict_keys() returns keys. k = dict.keys(); list = []; for x in (k) list = [@list, dict[x]]; return list; . method invert arg dict; var inverted, x; // Invert a dict (keys<->values) inverted = #[]; for x in (dict.keys()) inverted = inverted.add(dict[x], x); return inverted; . method add_elem arg dict, key, elem; var value; // same as old dict_add_elem value = (| dict[key] |); if (type(value) != 'list && type(value) != 'error) throw(~type, "Value for key " + $parse.unparse(key) + " (" + $parse.unparse(value) + ") is not a list."); if (value) value = [@value, elem]; else value = [elem]; return dict.add(key, value); . method del_elem arg dict, key, elem; var value; value = (| dict[key] |); if (type(value) != 'list && type(value) != 'error) throw(~type, "Value for key " + $parse.unparse(key) + " (" + $parse.unparse(value) + ") is not a list."); value = value.setremove(elem); if (!value) return dict.del(key); return dict.add(key, value); . method add arg [args]; return (> dict_add(@args) <); . method del arg [args]; return (> dict_del(@args) <); . method keys arg dict; return (> dict_keys(dict) <); . method add_elem_union arg dict, key, elem; var value; value = (| dict[key] |); if (value) value = value.union([elem]); else value = [elem]; return dict.add(key, value); . method contains arg [args]; return (> dict_contains(@args) <); . // ------------------------------------------------------------------ parent $libraries object $buffer var $root inited 1 var $root objname 'buffer method to_list arg buf; var idx, list; list = []; for idx in [1 .. buf.length()] list = list + [buf.retrieve(idx)]; return list; . method from_list arg list; var buf, x; buf = `[]; for x in [1 .. list.length()] buf = buf.add(list[x]); return buf; . method length arg buffer; return (> buffer_len(buffer) <); . method retrieve arg buffer, position; return (> buffer_retrieve(buffer, position) <); . method append arg buffer, buffer_2; return (> buffer_append(buffer, buffer_2) <); . method replace arg buffer, position, value; return (> buffer_replace(buffer, position, value) <); . method add arg buffer, value; return (> buffer_add(buffer, value) <); . method truncate arg buffer, position; return (> buffer_truncate(buffer, position) <); . method tail arg buffer, position; return (> buffer_tail(buffer, position) <); . method to_string arg buffer; return (> buffer_to_string(buffer) <); . method to_strings arg [args]; return (> buffer_to_strings(@args) <); . method from_string arg string; return (> buffer_from_string(string) <); . method from_strings arg strings, [seperator]; return (> buffer_from_strings(strings, @seperator) <); . // ------------------------------------------------------------------ // $time library parent $libraries object $time var $root inited 1 var $root objname 'time method format arg [args]; return (> strftime(@args) <); .