sortkey()
authorAri Johnson <ari@cobramush.org>
Wed, 21 Feb 2007 04:44:05 +0000 (04:44 +0000)
committerAri Johnson <ari@cobramush.org>
Wed, 21 Feb 2007 04:44:05 +0000 (04:44 +0000)
game/txt/hlp/cobra_func.hlp
hdrs/externs.h
src/flags.c
src/function.c
src/funlist.c
win32/funs.h

index 3a9d8e7b5c10f07d65d1d3b4da33dcb09ce12d6d..28974cecc2b2555410d0d576e65b7277f6913d8e 100644 (file)
@@ -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([<obj>/]<attrib>,<list>[,<sort type>[,<delimiter>[,<osep>]]])
+
+  This function creates a list of keys by passing every element of <list>
+  into the u-function given in <attrib>. The list is then sorted according
+  to the sorting method in <sort type>, or is automatically guessed.
+  (As per 'help sorting')
+
+  This is equivalent to:
+    > &munge_sort me=sort(%0,<sort type>)
+    > munge(munge_sort,map(<attrib>,<list>),<list>)
+
+    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(<word>)
index 27bea3878875c162a2fd3a7883c5d7e91ae6c4b6..b0f15dfcd7ddbbbd5e7c6aa91aa2e5a42c3f6cdc 100644 (file)
@@ -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 */
index a4b28b3f6788c4351445e2ea4d501747cb130e2f..3958cbb2aa7f38b12c0019865434e05b5aef3d56 100644 (file)
@@ -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) {
index 8184a30217ac4de5b537ebb02b2c38463c4c583f..5814f28f5f485d171590c7728a0bcdb215477fe3 100644 (file)
@@ -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++) {
index d653c77cb50d6b989717c3a4307d03a68806ece3..d3e3c60576efe6eb35255977958ce10a2d30c492 100644 (file)
@@ -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;
index b90c957fb6b6acbb120ed484b32c4311bb903f88..46cdd0c5d41f108ddadd0f0eadda9222bf6f5df8 100644 (file)
@@ -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);