Back to index

radiance  4R0+20100331
modobject.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: modobject.c,v 2.12 2004/07/14 02:37:23 greg Exp $";
00003 #endif
00004 /*
00005  *  Routines for tracking object modifiers
00006  *
00007  *  External symbols declared in object.h
00008  */
00009 
00010 #include "copyright.h"
00011 
00012 #include  "standard.h"
00013 
00014 #include  "object.h"
00015 
00016 #include  "otypes.h"
00017 
00018 
00019 static struct ohtab {
00020        int  hsiz;                  /* current table size */
00021        OBJECT  *htab;                     /* table, if allocated */
00022 }  modtab = {100, NULL}, objtab = {1000, NULL};  /* modifiers and objects */
00023 
00024 static int  otndx(char *, struct ohtab *);
00025 
00026 
00027 OBJECT
00028 objndx(op)                  /* get object number from pointer */
00029 register OBJREC  *op;
00030 {
00031        register int  i, j;
00032 
00033        for (i = nobjects>>OBJBLKSHFT; i >= 0; i--) {
00034               j = op - objblock[i];
00035               if ((j >= 0) & (j < OBJBLKSIZ))
00036                      return((i<<OBJBLKSHFT) + j);
00037        }
00038        return(OVOID);
00039 }
00040 
00041 
00042 OBJECT
00043 lastmod(obj, mname)         /* find modifier definition before obj */
00044 OBJECT  obj;
00045 char  *mname;
00046 {
00047        register OBJREC  *op;
00048        register int  i;
00049 
00050        i = modifier(mname);        /* try hash table first */
00051        if ((obj == OVOID) | (i < obj))
00052               return(i);
00053        for (i = obj; i-- > 0; ) {  /* need to search */
00054               op = objptr(i);
00055               if (ismodifier(op->otype) && !strcmp(op->oname, mname))
00056                      return(i);
00057        }
00058        return(OVOID);
00059 }
00060 
00061 
00062 OBJECT
00063 modifier(mname)                    /* get a modifier number from its name */
00064 char  *mname;
00065 {
00066        register int  ndx;
00067 
00068        ndx = otndx(mname, &modtab);
00069        return(modtab.htab[ndx]);
00070 }
00071 
00072 
00073 #ifdef  GETOBJ
00074 OBJECT
00075 object(oname)               /* get an object number from its name */
00076 char  *oname;
00077 {
00078        register int  ndx;
00079 
00080        ndx = otndx(oname, &objtab);
00081        return(objtab.htab[ndx]);
00082 }
00083 #endif
00084 
00085 
00086 void
00087 insertobject(obj)           /* insert new object into our list */
00088 register OBJECT  obj;
00089 {
00090        register int  i;
00091 
00092        if (ismodifier(objptr(obj)->otype)) {
00093               i = otndx(objptr(obj)->oname, &modtab);
00094               modtab.htab[i] = obj;
00095        }
00096 #ifdef  GETOBJ
00097        else {
00098               i = otndx(objptr(obj)->oname, &objtab);
00099               objtab.htab[i] = obj;
00100        }
00101 #endif
00102        for (i = 0; addobjnotify[i] != NULL; i++)
00103               (*addobjnotify[i])(obj);
00104 }
00105 
00106 
00107 void
00108 clearobjndx()               /* clear object hash tables */
00109 {
00110        if (modtab.htab != NULL) {
00111               free((void *)modtab.htab);
00112               modtab.htab = NULL;
00113               modtab.hsiz = 100;
00114        }
00115        if (objtab.htab != NULL) {
00116               free((void *)objtab.htab);
00117               objtab.htab = NULL;
00118               objtab.hsiz = 100;
00119        }
00120 }
00121 
00122 
00123 static int
00124 nexthsiz(oldsiz)            /* return next hash table size */
00125 int  oldsiz;
00126 {
00127        static int  hsiztab[] = {
00128               251, 509, 1021, 2039, 4093, 8191, 16381, 0
00129        };
00130        register int  *hsp;
00131 
00132        for (hsp = hsiztab; *hsp; hsp++)
00133               if (*hsp > oldsiz)
00134                      return(*hsp);
00135        return(oldsiz*2 + 1);              /* not always prime */
00136 }
00137 
00138 
00139 static int
00140 otndx(name, tab)            /* get object table index for name */
00141 char  *name;
00142 register struct ohtab  *tab;
00143 {
00144        OBJECT  *oldhtab;
00145        int  hval, i;
00146        register int  ndx;
00147 
00148        if (tab->htab == NULL) {           /* new table */
00149               tab->hsiz = nexthsiz(tab->hsiz);
00150               tab->htab = (OBJECT *)malloc(tab->hsiz*sizeof(OBJECT));
00151               if (tab->htab == NULL)
00152                      error(SYSTEM, "out of memory in otndx");
00153               ndx = tab->hsiz;
00154               while (ndx--)               /* empty it */
00155                      tab->htab[ndx] = OVOID;
00156        }
00157                                    /* look up object */
00158        hval = shash(name);
00159 tryagain:
00160        for (i = 0; i < tab->hsiz; i++) {
00161               ndx = (hval + (unsigned long)i*i) % tab->hsiz;
00162               if (tab->htab[ndx] == OVOID ||
00163                             !strcmp(objptr(tab->htab[ndx])->oname, name))
00164                      return(ndx);
00165        }
00166                                    /* table is full, reallocate */
00167        oldhtab = tab->htab;
00168        ndx = tab->hsiz;
00169        tab->htab = NULL;
00170        while (ndx--)
00171               if (oldhtab[ndx] != OVOID) {
00172                      i = otndx(objptr(oldhtab[ndx])->oname, tab);
00173                      tab->htab[i] = oldhtab[ndx];
00174               }
00175        free((void *)oldhtab);
00176        goto tryagain;                     /* should happen only once! */
00177 }