From f57d785c334e7b12d2049eb00a2888b3776b21f9 Mon Sep 17 00:00:00 2001 From: Ari Johnson Date: Wed, 21 Feb 2007 04:44:05 +0000 Subject: [PATCH] sortkey() --- game/txt/hlp/cobra_func.hlp | 21 ++++++++ hdrs/externs.h | 3 +- src/flags.c | 2 +- src/function.c | 3 +- src/funlist.c | 98 ++++++++++++++++++++++++++++++++----- win32/funs.h | 1 + 6 files changed, 114 insertions(+), 14 deletions(-) diff --git a/game/txt/hlp/cobra_func.hlp b/game/txt/hlp/cobra_func.hlp index 3a9d8e7..28974ce 100644 --- a/game/txt/hlp/cobra_func.hlp +++ b/game/txt/hlp/cobra_func.hlp @@ -3272,6 +3272,27 @@ for an object named "Test", preferring a thing over other types. this limit is exceeded, the function will fail _silently_. List and function sizes should be kept reasonable. + See also: anonymous attributes +& SORTKEY() + sortkey([/],[,[,[,]]]) + + This function creates a list of keys by passing every element of + into the u-function given in . The list is then sorted according + to the sorting method in , or is automatically guessed. + (As per 'help sorting') + + This is equivalent to: + > &munge_sort me=sort(%0,) + > munge(munge_sort,map(,),) + + Only there is no risk with delimiters ocurring within the list. + + A simple example, which sorts players by their names: + > @@ #1 is "God", #2 is "Amby", "#3" is "Bob" + > &KEY_NAME me=name(%0) + > say sortkey(key_name,#1 #2 #3) + You say, "#2 #3 #1" + See also: anonymous attributes & SOUNDEX() soundex() diff --git a/hdrs/externs.h b/hdrs/externs.h index 27bea38..b0f15df 100644 --- a/hdrs/externs.h +++ b/hdrs/externs.h @@ -682,7 +682,8 @@ extern int safe_ansi_string2(ansi_string *as, size_t start, size_t len, char *bu void local_flags(void); /* funlist.c */ - void do_gensort(dbref player, char *s[], int n, char *sort_type); + void do_gensort(dbref player, char *keys[], char *strs[], int n, + char *sort_type); /* sig.c */ /** Type definition for signal handlers */ diff --git a/src/flags.c b/src/flags.c index a4b28b3..3958cbb 100644 --- a/src/flags.c +++ b/src/flags.c @@ -2513,7 +2513,7 @@ list_all_flags(const char *ns, const char *name, dbref privs, int which) ptrs[numptrs++] = (char *) f->name; } } - do_gensort(privs, ptrs, numptrs, ALPHANUM_LIST); + do_gensort(privs, ptrs, NULL, numptrs, ALPHANUM_LIST); bp = buf; for (i = 0; i < numptrs; i++) { switch (which) { diff --git a/src/function.c b/src/function.c index 8184a30..5814f28 100644 --- a/src/function.c +++ b/src/function.c @@ -602,6 +602,7 @@ FUNTAB flist[] = { {"SIGNAL", fun_signal, 2, 3, FN_REG}, {"SORT", fun_sort, 1, 4, FN_REG}, {"SORTBY", fun_sortby, 2, 4, FN_REG}, + {"SORTKEY", fun_sortkey, 2, 5, FN_REG}, {"SOUNDEX", fun_soundex, 1, 1, FN_REG}, {"SOUNDSLIKE", fun_soundlike, 2, 2, FN_REG}, {"SPACE", fun_space, 1, 1, FN_REG}, @@ -766,7 +767,7 @@ list_functions(void) } /* do_gensort needs a dbref now, but only for sort types that aren't * used here anyway */ - do_gensort((dbref) 0, (char **) ptrs, nptrs, 0); + do_gensort((dbref) 0, (char **) ptrs, NULL, nptrs, 0); bp = buff; safe_str(ptrs[0], buff, &bp); for (i = 1; i < nptrs; i++) { diff --git a/src/funlist.c b/src/funlist.c index d653c77..d3e3c60 100644 --- a/src/funlist.c +++ b/src/funlist.c @@ -760,6 +760,7 @@ typedef void (*makerecord) (s_rec *, dbref player, char *sortflags); * its 'key' to sort by. Sort of a hardcode munge. */ struct sort_record { + char *ptr; /**< NULL except for sortkey */ char *val; /**< The string this is */ dbref db; /**< dbref (default 0, bad is -1) */ char *str; /**< string comparisons */ @@ -1111,7 +1112,7 @@ gencomp(dbref player, char *a, char *b, char *sort_type) */ void -do_gensort(dbref player, char *s[], int n, char *sort_type) +do_gensort(dbref player, char *keys[], char *strs[], int n, char *sort_type) { char *ptr; static char stype[BUFFER_LEN]; @@ -1137,12 +1138,17 @@ do_gensort(dbref player, char *s[], int n, char *sort_type) } sp = (s_rec *) mush_malloc(n * sizeof(s_rec), "do_gensort"); for (i = 0; i < n; i++) { - sp[i].val = s[i]; + sp[i].val = keys[i]; sp[i].freestr = 0; sp[i].db = 0; + if (strs) { + sp[i].ptr = strs[i]; + } else { + sp[i].ptr = NULL; + } sp[i].str = NULL; if (ltypelist[sorti].isdbs) { - sp[i].db = parse_objid(s[i]); + sp[i].db = parse_objid(keys[i]); if (!RealGoodObject(sp[i].db)) sp[i].db = NOTHING; } @@ -1151,7 +1157,10 @@ do_gensort(dbref player, char *s[], int n, char *sort_type) qsort((void *) sp, n, sizeof(s_rec), ltypelist[sorti].sorter); for (i = 0; i < n; i++) { - s[i] = sp[i].val; + keys[i] = sp[i].val; + if (strs) { + strs[i] = sp[i].ptr; + } if (sp[i].freestr) mush_free(sp[i].str, "genrecord"); } @@ -1181,7 +1190,7 @@ FUNCTION(fun_sort) nptrs = list2arr(ptrs, MAX_SORTSIZE, args[0], sep); sort_type = get_list_type(args, nargs, 2, ptrs, nptrs); - do_gensort(executor, ptrs, nptrs, sort_type); + do_gensort(executor, ptrs, NULL, nptrs, sort_type); arr2list(ptrs, nptrs, buff, bp, outsep); } @@ -1249,6 +1258,73 @@ loop: } } +/* ARGSUSED */ +FUNCTION(fun_sortkey) +{ + char *ptrs[MAX_SORTSIZE]; + char *keys[MAX_SORTSIZE]; + int nptrs; + char *sort_type; + char sep; + char outsep[BUFFER_LEN]; + int i; + char tbuff[BUFFER_LEN]; + char *tp; + char const *cp; + char result[BUFFER_LEN]; + char *rp; + ATTR *attrib; + dbref thing; + + /* sortkey(attr,list,sort_type,delim,osep) */ + + if (!nargs || !*args[0] || !*args[1]) + return; + + if (!delim_check(buff, bp, nargs, args, 4, &sep)) + return; + + if (nargs < 5) { + outsep[0] = sep; + outsep[1] = '\0'; + } else + strcpy(outsep, args[4]); + + /* Find object and attribute to get sortby function from. */ + parse_anon_attrib(executor, args[0], &thing, &attrib); + if (!GoodObject(thing) || !attrib || !Can_Read_Attr(executor, thing, attrib)) { + free_anon_attrib(attrib); + return; + } + if (!CanEvalAttr(executor, thing, attrib)) { + free_anon_attrib(attrib); + return; + } + tp = tbuff; + safe_str(atr_value(attrib), tbuff, &tp); + *tp = '\0'; + + nptrs = list2arr(ptrs, MAX_SORTSIZE, args[1], sep); + + /* Now we make a list of keys */ + for (i = 0; i < nptrs; i++) { + global_eval_context.wenv[0] = (char *) ptrs[i]; + rp = result; + cp = tbuff; + process_expression(result, &rp, &cp, + thing, executor, enactor, + PE_DEFAULT, PT_DEFAULT, pe_info); + *rp = '\0'; + keys[i] = mush_strdup(result, "sortkey"); + } + + sort_type = get_list_type(args, nargs, 3, keys, nptrs); + do_gensort(executor, keys, ptrs, nptrs, sort_type); + arr2list(ptrs, nptrs, buff, bp, outsep); + for (i = 0; i < nptrs; i++) { + mush_free(keys[i], "sortkey"); + } +} /* ARGSUSED */ FUNCTION(fun_sortby) @@ -1354,8 +1430,8 @@ FUNCTION(fun_setinter) osepl = arglens[4]; } /* sort each array */ - do_gensort(executor, a1, n1, sort_type); - do_gensort(executor, a2, n2, sort_type); + do_gensort(executor, a1, NULL, n1, sort_type); + do_gensort(executor, a2, NULL, n2, sort_type); /* get the first value for the intersection, removing duplicates */ x1 = x2 = 0; @@ -1470,8 +1546,8 @@ FUNCTION(fun_setunion) } /* sort each array */ - do_gensort(executor, a1, n1, sort_type); - do_gensort(executor, a2, n2, sort_type); + do_gensort(executor, a1, NULL, n1, sort_type); + do_gensort(executor, a2, NULL, n2, sort_type); /* get the first value for the difference, removing duplicates */ x1 = x2 = 0; @@ -1582,8 +1658,8 @@ FUNCTION(fun_setdiff) } /* sort each array */ - do_gensort(executor, a1, n1, sort_type); - do_gensort(executor, a2, n2, sort_type); + do_gensort(executor, a1, NULL, n1, sort_type); + do_gensort(executor, a2, NULL, n2, sort_type); /* get the first value for the difference, removing duplicates */ x1 = x2 = 0; diff --git a/win32/funs.h b/win32/funs.h index b90c957..46cdd0c 100644 --- a/win32/funs.h +++ b/win32/funs.h @@ -299,6 +299,7 @@ FUNCTION_PROTO(fun_signal); FUNCTION_PROTO(fun_sin); FUNCTION_PROTO(fun_sort); FUNCTION_PROTO(fun_sortby); +FUNCTION_PROTO(fun_sortkey); FUNCTION_PROTO(fun_soundex); FUNCTION_PROTO(fun_soundlike); FUNCTION_PROTO(fun_space); -- 2.30.2