Back to index

radiance  4R0+20100331
savestr.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: savestr.c,v 2.10 2004/03/04 16:34:34 greg Exp $";
00003 #endif
00004 /*
00005  *  savestr.c - routines for efficient string storage.
00006  *
00007  *     Savestr(s) stores a shared read-only string.
00008  *  Freestr(s) indicates a client is finished with a string.
00009  *     All strings must be null-terminated.  There is
00010  *  no imposed length limit.
00011  *     Strings stored with savestr(s) can be equated
00012  *  reliably using their pointer values.
00013  *     Calls to savestr(s) and freestr(s) should be
00014  *  balanced (obviously).  The last call to freestr(s)
00015  *  frees memory associated with the string; it should
00016  *  never be referenced again.
00017  *
00018  *  External symbols declared in standard.h
00019  */
00020 
00021 #include "copyright.h"
00022 
00023 #include <string.h>
00024 #include <stdlib.h>
00025 
00026 #include "rtmisc.h"
00027 #include "rterror.h"
00028 #include "rtio.h"
00029 
00030 #ifndef  NHASH
00031 #define  NHASH              2039          /* hash table size (prime!) */
00032 #endif
00033 
00034 typedef struct s_head {
00035        struct s_head  *next;              /* next in hash list */
00036        int  nl;                    /* links count */
00037 }  S_HEAD;                         /* followed by the string itself */
00038 
00039 static S_HEAD  *stab[NHASH];
00040 
00041 #define  hash(s)     (shash(s)%NHASH)
00042 
00043 #define  string(sp)  ((char *)((sp)+1))
00044 
00045 #define  salloc(str) (S_HEAD *)malloc(sizeof(S_HEAD)+1+strlen(str))
00046 
00047 #define  sfree(sp)   free((void *)(sp))
00048 
00049 
00050 char *
00051 savestr(char *str)                        /* save a string */
00052 {
00053        register int  hval;
00054        register S_HEAD  *sp;
00055 
00056        if (str == NULL)
00057               return(NULL);
00058        hval = hash(str);
00059        for (sp = stab[hval]; sp != NULL; sp = sp->next)
00060               if (!strcmp(str, string(sp))) {
00061                      sp->nl++;
00062                      return(string(sp));
00063               }
00064        if ((sp = salloc(str)) == NULL) {
00065               eputs("Out of memory in savestr\n");
00066               quit(1);
00067        }
00068        strcpy(string(sp), str);
00069        sp->nl = 1;
00070        sp->next = stab[hval];
00071        stab[hval] = sp;
00072        return(string(sp));
00073 }
00074 
00075 
00076 void
00077 freestr(char *s)                          /* free a string */
00078 {
00079        int  hval;
00080        register S_HEAD  *spl, *sp;
00081 
00082        if (s == NULL)
00083               return;
00084        hval = hash(s);
00085        for (spl = NULL, sp = stab[hval]; sp != NULL; spl = sp, sp = sp->next)
00086               if (s == string(sp)) {
00087                      if (--sp->nl > 0)
00088                             return;
00089                      if (spl != NULL)
00090                             spl->next = sp->next;
00091                      else
00092                             stab[hval] = sp->next;
00093                      sfree(sp);
00094                      return;
00095               }
00096 }
00097 
00098 
00099 int
00100 shash(register char  *s)
00101 {
00102        register int  h = 0;
00103 
00104        while (*s)
00105               h = (h<<1 & 0x7fff) ^ (*s++ & 0xff);
00106        return(h);
00107 }