/* * NAME: badarg() * DESCRIPTION: cause a bad argument error */ private void badarg(string func, int arg) { error("Bad argument " + arg + " to function " + func); } /* * NAME: capitalize() * DESCRIPTION: capitalize a string */ static string capitalize(string str) { ARGCHECK(str, capitalize, 1); if (str[0] >= 'a' && str[0] <= 'z') { str[0] -= 'a' - 'A'; } return str; } /* * NAME: lower_case() * DESCRIPTION: convert a string to lower case */ static string lower_case(string str) { int i, len, c; ARGCHECK(str, lower_case, 1); for (i = 0, len = strlen(str); i < len; i++) { c = str[i]; if (c >= 'A' && c <= 'Z') { str[i] += 'a' - 'A'; } } return str; } /* * NAME: set_bit() * DESCRIPTION: set a bit in a bit string */ static string set_bit(string str, int bit) { int ind, len, c; ARGCHECK(str, set_bit, 1); if (bit > MAX_BITS) { error("Too big bit number " + bit); } ind = bit / 6; len = strlen(str); if (ind >= len) { do { str += " "; len += 20; } while (ind >= len); str = str[0 .. ind]; } c = str[ind]; if (c < ' ') { error("Illegal bit pattern in character " + ind); } str[ind] = (c - ' ' | 1 << bit % 6) + ' '; return str; } /* * NAME: clear_bit() * DESCRIPTION: clear a bit in a bit string */ static string clear_bit(string str, int bit) { int ind, c; ARGCHECK(str, clear_bit, 1); if (bit > MAX_BITS) { error("Too big bit number " + bit); } ind = bit / 6; if (ind >= strlen(str)) { return str; } c = str[ind]; if (c < ' ') { error("Illegal bit pattern in character " + ind); } str[ind] = (c - ' ' & ~(1 << bit % 6)) + ' '; return str; } /* * NAME: test_bit() * DESCRIPTION: test a bit in a bit string */ static int test_bit(string str, int bit) { int ind; ARGCHECK(str, test_bit, 1); ind = bit / 6; if (ind >= strlen(str)) { return 0; } return (str[ind] - ' ' & 1 << bit % 6) != 0; } /* * NAME: member_array() * DESCRIPTION: return the index of the element in the array, or -1 */ static int member_array(mixed elt, mixed *arr) { int i, sz; ARGCHECK(arr, member_array, 1); for (i = 0, sz = sizeof(arr); i < sz; i++) { if (arr[i] == elt) { return i; } } return -1; } /* * NAME: filter_array * DESCRIPTION: filter the elements of an array */ static varargs mixed * filter_array(mixed *arr, string func, mixed obj, mixed arg) { mixed *copy, elt; int i, j, sz; ARGCHECK(arr, filter_array, 1); ARGCHECK(func && function_object(func, this_object()) != AUTO, filter_array, 2); if (stringp(obj)) { call_other(obj = ::find_object(DRIVER)->path_object(obj), "???"); obj = find_object(obj); } ARGCHECK(objectp(obj) && sscanf(object_name(obj), "/dgd/%*s") == 0, filter_array, 3); copy = allocate(sz = sizeof(arr)); for (i = 0, j = -1; i < sz; i++) { if (call_other(obj, func, elt = arr[i], arg)) { copy[++j] = elt; } } return copy[0 .. j]; } /* * NAME: map_array * DESCRIPTION: map the elements of an array */ static varargs mixed *map_array(mixed *arr, string func, mixed obj, mixed arg) { mixed *copy; int i, sz; ARGCHECK(arr, map_array, 1); ARGCHECK(func && function_object(func, this_object()) != AUTO, map_array, 2); if (stringp(obj)) { call_other(obj = ::find_object(DRIVER)->path_object(obj), "???"); obj = find_object(obj); } ARGCHECK(objectp(obj) && sscanf(object_name(obj), "/dgd/%*s") == 0, map_array, 3); copy = allocate(sz = sizeof(arr)); for (i = 0; i < sz; i++) { copy[i] = call_other(obj, func, arr[i], arg); } return copy; } /* * NAME: extract() * DESCRIPTION: extract a substring */ static varargs string extract(string str, int first, int last) { ARGCHECK(str, extract, 1); /* will mistake extract(str, 0) for extract(str, 0, 0) */ if (first != 0 && last == 0) { last = strlen(str) - 1; } else if (first >= strlen(str) || last < first) { return ""; } return str[first .. last]; } /* * NAME: slice_array() * DESCRIPTION: return part on an array */ static mixed *slice_array(mixed *arr, int first, int last) { ARGCHECK(arr, slice_array, 1); if (first >= sizeof(arr) || last < first) { return ({ }); } return arr[first .. last]; } /* * NAME: sort_array() * DESCRIPTION: sort an array */ static varargs mixed *sort_array(mixed *source, string func, mixed obj) { int step, halfstep, size; int i, j, i1, i2, end1, end2; mixed *dest, *temp; ARGCHECK(source, sort_array, 1); ARGCHECK(func && function_object(func, this_object()) != AUTO, sort_array, 2); if (obj == 0) { obj = this_object(); } else if (stringp(obj)) { call_other(obj = ::find_object(DRIVER)->path_object(obj), "???"); obj = find_object(obj); } ARGCHECK(objectp(obj) && sscanf(object_name(obj), "/dgd/%*s") == 0, sort_array, 3); size = sizeof(source = source[..]); if (size < 2) { return source; } dest = allocate(size); step = 2; halfstep = 1; while (halfstep < size) { for (i = j = 0; i < size; i += step) { i1 = i; i2 = i + halfstep; end1 = i2; if (end1 > size) { end1 = size; } end2 = i + step; if (end2 > size) { end2 = size; } while (i1 < end1 && i2 < end2) { if (call_other(obj, func, source[i1], source[i2]) > 0) { dest[j++] = source[i2++]; } else { dest[j++] = source[i1++]; } } if (i1 == end1) { while (i2 < end2) { dest[j++] = source[i2++]; } } else { while (i1 < end1) { dest[j++] = source[i1++]; } } } halfstep = step; step += step; temp = source; source = dest; dest = temp; } return source; } /* * NAME: unique_array() * DESCRIPTION: subdevide an array of objects into arrays with objects where * obj->func() returned identical descriptions */ static varargs mixed *unique_array(mixed *arr, string func, mixed exclude) { mapping map; int i, sz; mixed val, elt; object *list; ARGCHECK(arr, unique_array, 1); ARGCHECK(func && function_object(func, this_object()) != AUTO, unique_array, 2); map = ([ ]); for (i = 0, sz = sizeof(arr); i < sz; i++) { elt = arr[i]; if (objectp(elt) && sscanf(object_name(elt), "/dgd/%*s") == 0 && (val=call_other(elt, func)) != exclude) { list = map[val]; if (list == 0) { list = ({ elt }); } else { list = ({ elt }) + list; } map[val] = list; } } return map_values(map); }