[PD-cvs] externals/zexy/src index.c,1.3,1.4

IOhannes m zmölnig zmoelnig at users.sourceforge.net
Mon May 30 16:34:46 CEST 2005


Update of /cvsroot/pure-data/externals/zexy/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21097

Modified Files:
	index.c 
Log Message:
improved performance (i think)
added a lot of new functionality


Index: index.c
===================================================================
RCS file: /cvsroot/pure-data/externals/zexy/src/index.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** index.c	19 May 2005 09:42:55 -0000	1.3
--- index.c	30 May 2005 14:34:44 -0000	1.4
***************
*** 20,31 ****
     "index" simulates an associative index :: that is : convert a symbol to an index
  
! */
  
! #include "zexy.h"
  
! #include <string.h>
! #include <stdio.h>
  
! #define MAXKEYLEN 16
  
  /* ----------------------- index --------------------- */
--- 20,38 ----
     "index" simulates an associative index :: that is : convert a symbol to an index
  
!    CAVEATS: starts to count at "1"
  
!    TODO: use "symbol" instead of "char*" : FIXED
!    TODO: "dump" the contents (so we can share between [index]es, ...) FIXED
!    TODO: "compact": move all entries to the beginning of the array FIXED
!    TODO: "sort" FIXED
!    TODO: "add" at a specific position (like "add 10 hallo" of "add hallo 10") (??) FIXED
!    TODO: "delete" from a specific position (like "delete 4" deletes the 4th element) FIXED
!    TODO: get the number of stored entries ("bang") FIXED
!    
!    TODO: resize the array if it gets to small
  
! */
  
! #include "zexy.h"
  
  /* ----------------------- index --------------------- */
***************
*** 39,47 ****
    int entries, maxentries;
    int auto_mode; /* 1--add if key doesn't already exist; 0--do not add; */
  
!   char **names;
  } t_index;
  
! static int find_last(char **names, int maxentries)
  {  /* returns the index of the last entry (0..(maxentries-1)) */
    while (maxentries--) if (names[maxentries]) return maxentries;
--- 46,63 ----
    int entries, maxentries;
    int auto_mode; /* 1--add if key doesn't already exist; 0--do not add; */
+   int auto_resize; /* 1--resize the array if we are running out of slots; 0--don't */
  
!   t_symbol **names;
  } t_index;
  
! /************************************
!  * helpers
!  */
! 
! 
! /* find the last non-NULL entry in the array *
!  * LATER: shouldn't this return "-1" on failure ?
!  */
! static int find_last(t_symbol **names, int maxentries)
  {  /* returns the index of the last entry (0..(maxentries-1)) */
    while (maxentries--) if (names[maxentries]) return maxentries;
***************
*** 49,53 ****
  }
  
! static int find_item(const char *key, char **names, int maxentries)
  {  /* returns index (0..[maxentries-1?]) on success; -1 if the item could not be found */
    int i=-1;
--- 65,72 ----
  }
  
! /* search the array for "key" 
!  * if it is not there, return "-1" 
!  */
! static int find_item(const t_symbol *key, t_symbol **names, int maxentries)
  {  /* returns index (0..[maxentries-1?]) on success; -1 if the item could not be found */
    int i=-1;
***************
*** 55,65 ****
    
    while (++i<=max)
!     if (names[i])
!       if (!strcmp(key, names[i])) return i;
    
    return -1;
  }
  
! static int find_free(char **names, int maxentries)
  {
    int i=0;
--- 74,86 ----
    
    while (++i<=max)
!     if (names[i] && key==names[i]) return i;
    
    return -1;
  }
  
! /* find the first NULL entry in the array
!  * return "-1" if none can be found 
!  */
! static int find_free(t_symbol **names, int maxentries)
  {
    int i=0;
***************
*** 72,75 ****
--- 93,113 ----
  }
  
+ /************************************
+  * methods
+  */
+ static void index_add(t_index *x, t_symbol *s, t_float f);
+ 
+ /* look up a symbol in the map */
+ static void index_symbol(t_index *x, t_symbol *s)
+ {
+   int element;
+   if ( (element = find_item(s, x->names, x->maxentries)+1) )
+     outlet_float(x->x_obj.ob_outlet, (t_float)element);
+   else if (x->auto_mode) // not yet stored: add automatically
+     index_add(x, s, 0);
+   else outlet_float(x->x_obj.ob_outlet, 0.f); // not yet stored but do not add
+ }
+ 
+ /* output the entry at a given index */
  static void index_float(t_index *x, t_float findex)
  {
***************
*** 78,133 ****
    {
        /* TB: output symbol to outlet */
!       t_symbol * s = gensym (x->names[iindex-1]);
!       outlet_symbol (x->x_obj.ob_outlet,s);
!       //      post("iindex[%d] = %s", iindex, x->names[iindex-1]);
    }
  }
  
- static void index_auto(t_index *x, t_float automod)
- {
-   x->auto_mode = !(!automod);
- }
- 
  
! static void index_add(t_index *x, t_symbol *s)
  {
!   int newentry;
    int ok = 0;
  
-   if (! (find_item(s->s_name, x->names, x->maxentries)+1) ) {
      if ( x->entries < x->maxentries ) {
!       newentry=find_free(x->names, x->maxentries);
        if (newentry + 1) {
- 	char *buf = (char *)getbytes(sizeof(char) * MAXKEYLEN);
  	x->entries++;
! 	strcpy(buf, s->s_name);
! 	x->names[newentry]=buf;
! 
! 	ok=1;
  
  	outlet_float(x->x_obj.ob_outlet, (t_float)newentry+1);
  
!       } else post("index :: couldn't find any place for new entry");
!     } else post("index :: max number of elements (%d) reached !", x->maxentries);
    } else post("index :: element already exists");
  
!   if (!ok) outlet_float(x->x_obj.ob_outlet, -1.f);
  }
! 
! static void index_delete(t_index *x, t_symbol *s)
  {
!   int element;
!   t_float r = -1.f;
  
!   if ( (element = find_item(s->s_name,x->names, x->maxentries))+1 ) {
!     freebytes(x->names[element], sizeof(char) * MAXKEYLEN);
!     x->names[element]=0;
!     r = 0.f;
      x->entries--;
!   } else post("index :: couldn't find element");
! 
!   outlet_float(x->x_obj.ob_outlet, r);
  }
  
  static void index_reset(t_index *x)
  {
--- 116,201 ----
    {
        /* TB: output symbol to outlet */
!       outlet_symbol (x->x_obj.ob_outlet,x->names[iindex-1]);
    }
  }
  
  
! /* add a symbol to the map (if possible) */
! static void index_add(t_index *x, t_symbol *s, t_float f)
  {
!   int newentry=(int)f;
    int ok = 0;
+   
+   if (! (find_item(s, x->names, x->maxentries)+1) ) {
+     if (x->auto_resize && x->entries==x->maxentries){
+       /* do some resizing */
+       int maxentries=x->maxentries*2;
+       int i;
+       t_symbol**buf=(t_symbol **)getbytes(sizeof(t_symbol *) * maxentries);
+       if(buf!=0){
+         memcpy(buf, x->names, sizeof(t_symbol *) * x->maxentries);
+         for(i=x->maxentries; i<maxentries; i++)buf[i]=0;
+ 
+         freebytes(x->names, sizeof(t_symbol *) * x->maxentries);
+ 
+         x->names=buf;
+         x->maxentries=maxentries;
+       }
+     }
  
      if ( x->entries < x->maxentries ) {
!       if(newentry>0){
!         newentry--;
!         if(x->names[newentry]){ /* it is already taken! */
!           error("index :: couldn't add element at position %d (already taken)", newentry+1);
!           outlet_float(x->x_obj.ob_outlet, -1.f);
!           return;
!         }
!       } else
!         newentry=find_free(x->names, x->maxentries);
! 
        if (newentry + 1) {
  	x->entries++;
! 	x->names[newentry]=s;
  
  	outlet_float(x->x_obj.ob_outlet, (t_float)newentry+1);
+         return;
  
!       } else error("index :: couldn't find any place for new entry");
!     } else error("index :: max number of elements (%d) reached !", x->maxentries);
    } else post("index :: element already exists");
  
!   /* couldn't add the symbol to our index table */
!   outlet_float(x->x_obj.ob_outlet, -1.f);
  }
! /* delete a symbol from the map (if it is in there) */
! static void index_delete(t_index *x, t_symbol *s, int argc, t_atom*argv)
  {
!   int index=-1;
!   if(argc!=1){
!     error("index :: delete what ?");
!     return;
!   } else {
!     if(argv->a_type==A_FLOAT){
!       index=atom_getint(argv)-1;
!     } else if (argv->a_type==A_SYMBOL){
!       index=find_item(atom_getsymbol(argv),x->names, x->maxentries);
!     } else {
!       error("index :: delete what ?");
!       return;    
!     }
!   }
  
!   if ( index >= 0 && index < x->maxentries) {
!     x->names[index]=0;
      x->entries--;
!     outlet_float(x->x_obj.ob_outlet, 0.0);
!   } else {
!     post("index :: couldn't find element");
!     outlet_float(x->x_obj.ob_outlet, -1.0);
!   }
  }
  
+ /* delete all symbols from the map */
  static void index_reset(t_index *x)
  {
***************
*** 136,140 ****
    while (i--)
      if (x->names[i]) {
-       freebytes(x->names[i], sizeof(char) * MAXKEYLEN);
        x->names[i]=0;
      }
--- 204,207 ----
***************
*** 145,162 ****
  }
  
! static void index_symbol(t_index *x, t_symbol *s)
  {
!   int element;
!   if ( (element = find_item(s->s_name, x->names, x->maxentries)+1) )
!     outlet_float(x->x_obj.ob_outlet, (t_float)element);
!   else if (x->auto_mode)
!     index_add(x, s);
!   else outlet_float(x->x_obj.ob_outlet, 0.f);
  }
  
  static void *index_new(t_symbol *s, int argc, t_atom *argv)
  {
    t_index *x = (t_index *)pd_new(index_class);
!   char** buf;
  
    int maxentries = 0, automod=0;
--- 212,295 ----
  }
  
! /* output the number of entries stored in the array */
! static void index_bang(t_index *x)
  {
!   outlet_float(x->x_obj.ob_outlet, (t_float)x->entries);
! }
! /* dump each entry in the format: "list <symbol> <index>" */
! static void index_dump(t_index *x)
! {
!   t_atom ap[2];
!   int i=0;
!   
!   for(i=0; i<x->maxentries; i++){
!     if(x->names[i]){
!       SETSYMBOL(ap, x->names[i]);
!       SETFLOAT(ap+1, i+1);
!       outlet_list(x->x_obj.ob_outlet, 0, 2, ap);
!     }
!   }
! }
! 
! /* compact all entries, removing all holes in the map */
! static void index_compact(t_index *x){
!   int i,j;
!   for(i=0; i<x->entries; i++){
!     if(!x->names[i]){
!       for(j=i+1; j<x->maxentries; j++){
!         if(x->names[j]){
!           x->names[i]=x->names[j];
!           x->names[j]=0;
!           break;
!         }
!       }
!     }
!   }
! }
! /* sort the map alphabetically */
! static void index_sort(t_index *x){
!   int entries=x->entries;
!   int step=entries;
!   int loops=1, n;
!   t_symbol**buf=x->names;
!   index_compact(x); /* couldn't we do it more "in-place", e.g. don't touch empty slots ? */
! 
!   while(step>1){
!     //step = (step % 2)?(step+1)/2:step/2;
!     step+=step%2;
!     step>>=1;
!     int i = loops;
!     loops+=2;
! 
!     while(i--) { /* there might be some optimization in here */
!       for (n=0; n<(x->entries-step); n++) {
!         int comp=strcmp(buf[n]->s_name,buf[n+step]->s_name);
! 	if (comp>0) { // compare STRINGS not SYMBOLS
! 	  t_symbol*s_tmp = buf[n];
! 	  buf[n]        = buf[n+step];
! 	  buf[n+step]   = s_tmp;
! 	}
!       }
!     }
!   }
  }
  
+ /* turn on/off auto-adding of elements that are not yet in the map */
+ static void index_auto(t_index *x, t_float automod)
+ {
+   x->auto_mode = !(!automod);
+ }
+ /* turn on/off auto-resizing of the map if it gets to small */
+ static void index_resize(t_index *x, t_float automod)
+ {
+   x->auto_resize = !(!automod);
+ }
+ 
+ 
+ 
  static void *index_new(t_symbol *s, int argc, t_atom *argv)
  {
    t_index *x = (t_index *)pd_new(index_class);
!   t_symbol** buf;
  
    int maxentries = 0, automod=0;
***************
*** 170,177 ****
    if (!maxentries) maxentries=128;
  
!   buf = (char **)getbytes(sizeof(char *) * maxentries);
  
-   i = maxentries;
-   while (i--) buf[i]=0;
  
    x->entries = 0;
--- 303,308 ----
    if (!maxentries) maxentries=128;
  
!   buf = (t_symbol **)getbytes(sizeof(t_symbol *) * maxentries);
  
  
    x->entries = 0;
***************
*** 179,182 ****
--- 310,316 ----
    x->names = buf;
    x->auto_mode = !(!automod);
+   x->auto_resize = 1;
+ 
+   while (maxentries--) buf[maxentries]=0;
  
    outlet_new(&x->x_obj, &s_float);
***************
*** 187,192 ****
  static void index_free(t_index *x)
  {
!   index_reset(x);
!   freebytes(x->names, sizeof(char *) * x->maxentries);
  }
  
--- 321,325 ----
  static void index_free(t_index *x)
  {
!   freebytes(x->names, sizeof(t_symbol *) * x->maxentries);
  }
  
***************
*** 195,205 ****
  {
    post("\n%c index :: index symbols to indices", HEARTSYMBOL);
!   post("<symbol>\t : look up the <symbol> in the index and return it's index\n"
!        "'add <symbol>'\t: add a new symbol to the index\n"
!        "'delete <symbol>' : delete a symbol from the index\n"
!        "'reset'\t\t : delete the whole index\n"
!        "'auto <1/0>\t : if auto is 1 and a yet unknown symbol is looked up it is\n\t\t\t automatically added to the index\n"
!        "'help'\t\t : view this"
!        "\noutlet : <n>\t : index of the <symbol>");
    post("\ncreation:\"index [<maxelements> [<auto>]]\": creates a <maxelements> sized index");
  }
--- 328,347 ----
  {
    post("\n%c index :: index symbols to indices", HEARTSYMBOL);
!   post("<symbol>             : look up the <symbol> in the index and return it's index\n"
!        "\n<int>                : look up the element at index <int> in the index"
!        "\n'add <symbol>'       : add a new symbol to the index-map"
!        "\n'add <symbol> <int>' : add a new symbol at the index <int>"
!        "\n'delete <symbol>'    : delete a symbol from the index-map"
!        "\n'delete <int>'       : delete the entry at index <int> from the index-map"
!        "\n'reset'              : delete the whole index-map"
!        "\n'bang'               : return the number of entries in the index-map"
!        "\n'dump'               : dump each entry in the format \"list <symbol> <index>\""
!        "\n'compact'            : remove holes in the index-map"
!        "\n'sort'               : alphabetically sort the entries"
!        "\n'auto <1/0>          : if auto is 1 and a yet unknown symbol is looked up it is\n\t\t\t automatically added to the index-map"
!        "\n'resize <1/0>        : if resize is 1 (default), the index-map is resized\n\t\t\t automatically if needed"
!        "\n'help'               : view this"
!        "\noutlet : <n>         : index of the <symbol>"
!        "\n         <symbol>    : entry at <index>");
    post("\ncreation:\"index [<maxelements> [<auto>]]\": creates a <maxelements> sized index");
  }
***************
*** 214,223 ****
  
    class_addmethod(index_class, (t_method)index_reset,  gensym("reset"), 0);
!   class_addmethod(index_class, (t_method)index_delete, gensym("delete"), A_SYMBOL, 0);
!   class_addmethod(index_class, (t_method)index_add,	 gensym("add"), A_SYMBOL, 0);
  
    class_addmethod(index_class, (t_method)index_auto,	 gensym("auto"), A_FLOAT, 0);
  
!   class_addfloat(index_class, (t_method)index_float);
  
    class_addmethod(index_class, (t_method)helper, gensym("help"), 0);
--- 356,371 ----
  
    class_addmethod(index_class, (t_method)index_reset,  gensym("reset"), 0);
!   class_addmethod(index_class, (t_method)index_delete, gensym("delete"), A_GIMME, 0);
!   //  class_addmethod(index_class, (t_method)index_add,	 gensym("add"), A_SYMBOL, 0);
!   class_addmethod(index_class, (t_method)index_add,	 gensym("add"), A_SYMBOL, A_DEFFLOAT, 0);
  
    class_addmethod(index_class, (t_method)index_auto,	 gensym("auto"), A_FLOAT, 0);
+   class_addmethod(index_class, (t_method)index_resize,	 gensym("resize"), A_FLOAT, 0);
  
!   class_addfloat(index_class,  (t_method)index_float);
!   class_addbang(index_class,   (t_method)index_bang);
!   class_addmethod(index_class, (t_method)index_sort,  gensym("sort"), 0);
!   class_addmethod(index_class, (t_method)index_compact,  gensym("compact"), 0);
!   class_addmethod(index_class, (t_method)index_dump,  gensym("dump"), 0);
  
    class_addmethod(index_class, (t_method)helper, gensym("help"), 0);





More information about the Pd-cvs mailing list