pike.git / src / mapping.c

version» Context lines:

pike.git/src/mapping.c:1:   /*\   ||| This file a part of Pike, and is copyright by Fredrik Hubinette   ||| Pike is distributed as GPL (General Public License)   ||| See the files COPYING and DISCLAIMER for more information.   \*/   #include "global.h" - RCSID("$Id: mapping.c,v 1.12 1997/02/07 01:11:43 hubbe Exp $"); + RCSID("$Id: mapping.c,v 1.13 1997/02/17 20:47:13 hubbe Exp $");   #include "main.h"   #include "types.h"   #include "object.h"   #include "mapping.h"   #include "svalue.h"   #include "array.h"   #include "macros.h"   #include "language.h"   #include "error.h"   #include "memory.h"   #include "dynamic_buffer.h"   #include "interpret.h"   #include "las.h"   #include "gc.h"      #define AVG_LINK_LENGTH 4   #define MIN_LINK_LENGTH 1 - #define MAP_SLOTS(X) ((X)+((X)>>4)+8) + #define MAP_SLOTS(X) ((X)?((X)+((X)>>4)+8):0)   #define LOOP(m) for(e=0;e<m->hashsize;e++) for(k=m->hash[e];k;k=k->next)      struct keypair   {    struct keypair *next;    struct svalue ind, val;   };      struct mapping *first_mapping;   
pike.git/src/mapping.c:39: Inside #if defined(DEBUG)
   * It is used for debugging purposes only.    */   static void check_mapping_type_fields(struct mapping *m)   {    INT32 e;    struct keypair *k,**prev;    TYPE_FIELD ind_types, val_types;       ind_types=val_types=0;    -  for(e=0;e<m->hashsize;e++) +  LOOP(m)    { -  for(k=m->hash[e];k;k=k->next) -  { +     val_types |= 1 << k->val.type;    ind_types |= 1 << k->ind.type;    } -  } +        if(val_types & ~(m->val_types))    fatal("Mapping value types out of order!\n");       if(ind_types & ~(m->ind_types))    fatal("Mapping indices types out of order!\n");   }   #endif      
pike.git/src/mapping.c:70:    */   static void init_mapping(struct mapping *m, INT32 size)   {    char *tmp;    INT32 e;    INT32 hashsize,hashspace;      #ifdef DEBUG    if(size < 0) fatal("init_mapping with negative value.\n");   #endif -  if(size<3) size=3; -  +  if(size) +  {    hashsize=size / AVG_LINK_LENGTH + 1;    if(!(hashsize & 1)) hashsize++;    hashspace=hashsize+1;    e=sizeof(struct keypair)*size+ sizeof(struct keypair *)*hashspace;    tmp=(char *)xalloc(e);       m->hash=(struct keypair **) tmp;    m->hashsize=hashsize;       tmp+=sizeof(struct keypair *)*hashspace;       MEMSET((char *)m->hash, 0, sizeof(struct keypair *) * m->hashsize);       m->free_list=(struct keypair *) tmp;    for(e=1;e<size;e++)    m->free_list[e-1].next = m->free_list + e;    m->free_list[e-1].next=0; -  +  }else{ +  m->hashsize=0; +  m->hash=0; +  m->free_list=0; +  }    m->ind_types = 0;    m->val_types = 0;    m->size = 0;   }      /* This function allocates an empty mapping with room for 'size' values    */   struct mapping *allocate_mapping(int size)   {    struct mapping *m;
pike.git/src/mapping.c:142:    free_svalue(& k->ind);    }       if(m->prev)    m->prev->next = m->next;    else    first_mapping = m->next;       if(m->next) m->next->prev = m->prev;    +  if(m->hash)    free((char *)m->hash);    free((char *)m);       GC_FREE();   }      /* This function is used to rehash a mapping without loosing the internal    * order in each hash chain. This is to prevent mappings from becoming    * very inefficient just after being rehashed.    */
pike.git/src/mapping.c:188:    INT32 tmp=m->size;   #endif    INT32 e,hashsize;    struct keypair *k,**hash;       hashsize=m->hashsize;    hash=m->hash;       init_mapping(m, new_size);    +  if(hash) +  {    for(e=0;e<hashsize;e++)    mapping_rehash_backwards(m, hash[e]);    -  +  free((char *)hash); +  } +    #ifdef DEBUG    if(m->size != tmp)    fatal("Rehash failed, size not same any more.\n");   #endif    -  free((char *)hash); -  +    #ifdef DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif       return m;   }      /* This function brings the type fields in the mapping up to speed.    * I only use it when the type fields MUST be correct, which is not    * very often.    */   void mapping_fix_type_field(struct mapping *m)   {    INT32 e;    struct keypair *k;    TYPE_FIELD ind_types, val_types;       val_types = ind_types = 0;    -  for(e=0;e<m->hashsize;e++) +  LOOP(m)    { -  for(k=m->hash[e];k;k=k->next) -  { +     val_types |= 1 << k->val.type;    ind_types |= 1 << k->ind.type;    } -  } +       #ifdef DEBUG    if(val_types & ~(m->val_types))    fatal("Mapping value types out of order!\n");       if(ind_types & ~(m->ind_types))    fatal("Mapping indices types out of order!\n");   #endif    m->val_types = val_types;    m->ind_types = ind_types;   }      /* This function inserts key:val into the mapping m.    * Same as doing m[key]=val; in pike.    */   void mapping_insert(struct mapping *m,    struct svalue *key,    struct svalue *val)   { -  unsigned INT32 h; +  unsigned INT32 h,h2;    struct keypair *k, **prev;    -  h=hash_svalue(key) % m->hashsize; +  h2=hash_svalue(key); +  if(m->hashsize) +  { +  h=h2 % m->hashsize;      #ifdef DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif    if(m->ind_types & (1 << key->type))    {    for(prev= m->hash + h;k=*prev;prev=&k->next)    {    if(is_eq(& k->ind, key))    {
pike.git/src/mapping.c:272:    m->val_types |= 1 << val->type;    assign_svalue(& k->val, val);      #ifdef DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif    return;    }    }    } +  }else{ +  h=0; +  }       if(!(k=m->free_list))    { -  rehash(m, m->size * 2 + 1); -  h=hash_svalue(key) % m->hashsize; +  rehash(m, m->size * 2 + 2); +  h=h2 % m->hashsize;    k=m->free_list;    }       m->free_list=k->next;    k->next=m->hash[h];    m->hash[h]=k;    m->ind_types |= 1 << key->type;    m->val_types |= 1 << val->type;    assign_svalue_no_free(& k->ind, key);    assign_svalue_no_free(& k->val, val);
pike.git/src/mapping.c:298: Inside #if defined(DEBUG)
     #ifdef DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif   }      union anything *mapping_get_item_ptr(struct mapping *m,    struct svalue *key,    TYPE_T t)   { -  unsigned INT32 h; +  unsigned INT32 h, h2;    struct keypair *k, **prev;    -  h=hash_svalue(key) % m->hashsize; +  h2=hash_svalue(key);    -  +  if(m->hashsize) +  { +  h=h2 % m->hashsize; +    #ifdef DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif       for(prev= m->hash + h;k=*prev;prev=&k->next)    {    if(is_eq(& k->ind, key))    {    *prev=k->next;    k->next=m->hash[h];
pike.git/src/mapping.c:324:       if(k->val.type == t) return & ( k->val.u );      #ifdef DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif       return 0;    }    } +  }else{ +  h=0; +  }       if(!(k=m->free_list))    { -  rehash(m, m->size * 2 + 1); -  h=hash_svalue(key) % m->hashsize; +  rehash(m, m->size * 2 + 2); +  h=h2 % m->hashsize;    k=m->free_list;    }       m->free_list=k->next;    k->next=m->hash[h];    m->hash[h]=k;    assign_svalue_no_free(& k->ind, key);    k->val.type=T_INT;    k->val.subtype=NUMBER_NUMBER;    k->val.u.integer=0;
pike.git/src/mapping.c:358:       return & ( k->val.u );   }      void map_delete(struct mapping *m,    struct svalue *key)   {    unsigned INT32 h;    struct keypair *k, **prev;    +  if(!m->size) return; +     h=hash_svalue(key) % m->hashsize;       for(prev= m->hash + h;k=*prev;prev=&k->next)    {    if(is_eq(& k->ind, key))    {    *prev=k->next;    free_svalue(& k->ind);    free_svalue(& k->val);    k->next=m->free_list;
pike.git/src/mapping.c:392:   void check_mapping_for_destruct(struct mapping *m)   {    INT32 e;    struct keypair *k, **prev;    TYPE_FIELD ind_types, val_types;      #ifdef DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif    +  if(!m->size) return; +     if((m->ind_types | m->val_types) & (BIT_OBJECT | BIT_FUNCTION))    {    val_types = ind_types = 0;    m->val_types |= BIT_INT;    for(e=0;e<m->hashsize;e++)    {    for(prev= m->hash + e;k=*prev;)    {    check_destructed(& k->val);   
pike.git/src/mapping.c:438:      struct svalue *low_mapping_lookup(struct mapping *m,    struct svalue *key)   {    unsigned INT32 h;    struct keypair *k, **prev;      #ifdef DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif +  if(!m->size) return 0;       if((1 << key->type) & m->ind_types)    {    h=hash_svalue(key) % m->hashsize;       for(prev= m->hash + h;k=*prev;prev=&k->next)    {    if(is_eq(& k->ind, key))    {    *prev=k->next;
pike.git/src/mapping.c:825:         void mapping_search_no_free(struct svalue *to,    struct mapping *m,    struct svalue *look_for,    struct svalue *start)   {    unsigned INT32 h;    struct keypair *k;    +  if(m->size) +  {    h=0;    k=m->hash[h];    if(start)    {    h=hash_svalue(start) % m->hashsize;    for(k=m->hash[h];k;k=k->next)    if(is_eq(&k->ind, start))    break;       if(!k)
pike.git/src/mapping.c:857:    {    if(is_eq(look_for, &k->val))    {    assign_svalue_no_free(to,&k->ind);    return;    }    k=k->next;    }    k=m->hash[++h];    } +  }       to->type=T_INT;    to->subtype=NUMBER_UNDEFINED;    to->u.integer=0;   }         #ifdef DEBUG      void check_mapping(struct mapping *m)
pike.git/src/mapping.c:898: Inside #if defined(DEBUG)
      if(m->size > (m->hashsize + 3) * AVG_LINK_LENGTH)    fatal("Pretty mean hashtable there buster!.\n");       if(m->size < (m->hashsize - 3) * MIN_LINK_LENGTH)    fatal("Hashsize is too small for mapping.\n");       if(m->size > 0 && (!m->ind_types || !m->val_types))    fatal("Mapping type fields are... wrong.\n");    -  if(!m->hash) +  if(!m->hash && m->size)    fatal("Hey! where did my hashtable go??\n");      }      void check_all_mappings()   {    struct mapping *m;    for(m=first_mapping;m;m=m->next)    check_mapping(m);   }