e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
aedfb12002-10-09Martin Nilsson 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
515b6c1996-06-09Fredrik Hübinette (Hubbe) #include "main.h" #include "object.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "mapping.h" #include "svalue.h" #include "array.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
8696e62008-07-16Henrik Grubbström (Grubba) #include "pike_types.h"
2d10fb2016-12-29Arne Goedeke #include "buffer.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "interpret.h"
515b6c1996-06-09Fredrik Hübinette (Hubbe) #include "las.h"
c94c371996-03-28Fredrik Hübinette (Hubbe) #include "gc.h"
5588271998-01-13Henrik Grubbström (Grubba) #include "stralloc.h"
d476592013-06-12Arne Goedeke #include "block_allocator.h"
f76b4c2000-05-11Henrik Grubbström (Grubba) #include "opcodes.h"
447e9b2001-09-06Fredrik Hübinette (Hubbe) #include "stuff.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e65af12016-10-24Henrik Grubbström (Grubba) /* Average number of keypairs per slot when allocating. */
06983f1996-09-22Fredrik Hübinette (Hubbe) #define AVG_LINK_LENGTH 4
e65af12016-10-24Henrik Grubbström (Grubba)  /* Minimum number of elements in a hashtable is half of the slots. */ #define MIN_LINK_LENGTH_NUMERATOR 1 #define MIN_LINK_LENGTH_DENOMINATOR 2 /* Number of keypairs to allocate for a given size. */
9076fa1997-02-17Fredrik Hübinette (Hubbe) #define MAP_SLOTS(X) ((X)?((X)+((X)>>4)+8):0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *first_mapping;
e2d9e62000-06-10Martin Stjernholm struct mapping *gc_internal_mapping = 0; static struct mapping *gc_mark_mapping_pos = 0;
1f342f2000-02-04Fredrik Hübinette (Hubbe) #define unlink_mapping_data(M) do{ \ struct mapping_data *md_=(M); \ if(md_->hardlinks) { md_->hardlinks--; md_->valrefs--; } \ free_mapping_data(M); \ }while(0)
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #define MAPPING_DATA_SIZE(HSIZE, KEYPAIRS) \
d2361e2003-06-30Martin Stjernholm  PTR_TO_INT(MD_KEYPAIRS(0, HSIZE) + KEYPAIRS)
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
d476592013-06-12Arne Goedeke static struct block_allocator mapping_allocator = BA_INIT_PAGES(sizeof(struct mapping), 2); void count_memory_in_mappings(size_t * num, size_t * size) { struct mapping *m; double datasize = 0.0; ba_count_all(&mapping_allocator, num, size); for(m=first_mapping;m;m=m->next) { datasize+=MAPPING_DATA_SIZE(m->data->hashsize, m->data->num_keypairs) / (double) m->data->refs; } *size += (size_t) datasize; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
d476592013-06-12Arne Goedeke void really_free_mapping(struct mapping * m) { #ifdef PIKE_DEBUG if (m->refs) { # ifdef DEBUG_MALLOC describe_something(m, T_MAPPING, 0,2,0, NULL); # endif Pike_fatal("really free mapping on mapping with %d refs.\n", m->refs); } #endif unlink_mapping_data(m->data); DOUBLEUNLINK(first_mapping, m); GC_FREE(m); ba_free(&mapping_allocator, m); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
d476592013-06-12Arne Goedeke ATTRIBUTE((malloc))
3b54e52014-08-21Martin Nilsson static struct mapping * alloc_mapping(void) {
d476592013-06-12Arne Goedeke  return ba_alloc(&mapping_allocator); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
3b54e52014-08-21Martin Nilsson void free_all_mapping_blocks(void) {
d476592013-06-12Arne Goedeke  ba_destroy(&mapping_allocator); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
d4741b2007-10-04Henrik Grubbström (Grubba) #define IF_ELSE_KEYPAIR_LOOP(X, Y) Y
df9b622001-05-27Henrik Grubbström (Grubba) #define FREE_KEYPAIR(md, k) do { \ k->next = md->free_list; \ md->free_list = k; \ } while(0) #else /* PIKE_MAPPING_KEYPAIR_LOOP */
d4741b2007-10-04Henrik Grubbström (Grubba) #define IF_ELSE_KEYPAIR_LOOP(X, Y) X
df9b622001-05-27Henrik Grubbström (Grubba) #define FREE_KEYPAIR(md, k) do { \ md->free_list--; \ if (k != md->free_list) { \ struct keypair **prev_; \ unsigned INT32 h_; \
d4741b2007-10-04Henrik Grubbström (Grubba)  INT32 e; \
df9b622001-05-27Henrik Grubbström (Grubba)  /* Move the last keypair to the new hole. */ \ *k = *(md->free_list); \
9031422011-04-05Arne Goedeke  h_ = k->hval & ( md->hashsize - 1); \
df9b622001-05-27Henrik Grubbström (Grubba)  prev_ = md->hash + h_; \ DO_IF_DEBUG( \ if (!*prev_) { \
f49b922007-10-03Henrik Grubbström (Grubba)  Pike_fatal("Node to move not found!\n"); \
df9b622001-05-27Henrik Grubbström (Grubba)  } \ ); \ while (*prev_ != md->free_list) { \ prev_ = &((*prev_)->next); \ DO_IF_DEBUG( \ if (!*prev_) { \
f49b922007-10-03Henrik Grubbström (Grubba)  Pike_fatal("Node to move not found!\n"); \
df9b622001-05-27Henrik Grubbström (Grubba)  } \ ); \ } \ *prev_ = k; \ } \ } while(0) #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
06983f1996-09-22Fredrik Hübinette (Hubbe) 
a4682e2012-09-26Henrik Grubbström (Grubba) void mapping_free_keypair(struct mapping_data *md, struct keypair *k) { FREE_KEYPAIR(md, k); }
01b9212016-01-12Per Hedbor static inline int check_type_contains(TYPE_FIELD types, const struct svalue * s) {
3b2cd42012-11-04Arne Goedeke  return (TYPEOF(*s) == PIKE_T_OBJECT || types & (BIT_OBJECT|(1 << TYPEOF(*s)))); }
01b9212016-01-12Per Hedbor static inline int check_type_overlaps(TYPE_FIELD t1, TYPE_FIELD t2) {
3c54432012-12-30Jonas Walldén  return (!t1 && !t2) || t1 & t2 || (t1|t2) & BIT_OBJECT;
a2bcc72012-11-15Arne Goedeke }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2dff752005-09-10Marek Habersack  /** This function checks that the type field isn't lacking any bits.
06983f1996-09-22Fredrik Hübinette (Hubbe)  * It is used for debugging purposes only.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
466b662008-01-05Martin Nilsson static void check_mapping_type_fields(const struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
06983f1996-09-22Fredrik Hübinette (Hubbe)  INT32 e;
466b662008-01-05Martin Nilsson  const struct keypair *k=0; const struct mapping_data *md;
06983f1996-09-22Fredrik Hübinette (Hubbe)  TYPE_FIELD ind_types, val_types; ind_types=val_types=0;
fa666b2004-04-15Martin Nilsson  md = m->data; NEW_MAPPING_LOOP(md)
06983f1996-09-22Fredrik Hübinette (Hubbe)  {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(k->val) > MAX_TYPE)
8696e62008-07-16Henrik Grubbström (Grubba)  Pike_fatal("Invalid mapping keypair value type: %s\n",
017b572011-10-28Henrik Grubbström (Grubba)  get_name_of_type(TYPEOF(k->val))); val_types |= 1 << TYPEOF(k->val); if (TYPEOF(k->ind) > MAX_TYPE)
8696e62008-07-16Henrik Grubbström (Grubba)  Pike_fatal("Invalid maping keypair index type: %s\n",
017b572011-10-28Henrik Grubbström (Grubba)  get_name_of_type(TYPEOF(k->ind))); ind_types |= 1 << TYPEOF(k->ind);
06983f1996-09-22Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(val_types & ~(m->data->val_types))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping value types out of order!\n");
06983f1996-09-22Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(ind_types & ~(m->data->ind_types))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping indices types out of order!\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f4d7572001-04-15Martin Stjernholm static struct mapping_data empty_data =
9386322011-07-21Henrik Grubbström (Grubba)  { PIKE_CONSTANT_MEMOBJ_INIT(1, T_MAPPING_DATA), 1, 0,0,0,0,0,0, 0,
d4741b2007-10-04Henrik Grubbström (Grubba)  IF_ELSE_KEYPAIR_LOOP((struct keypair *)&empty_data.hash, 0), {0}};
0b5d2b2001-06-05Martin Stjernholm static struct mapping_data weak_ind_empty_data =
9386322011-07-21Henrik Grubbström (Grubba)  { PIKE_CONSTANT_MEMOBJ_INIT(1, T_MAPPING_DATA), 1, 0,0,0,0,0,0, MAPPING_WEAK_INDICES,
d4741b2007-10-04Henrik Grubbström (Grubba)  IF_ELSE_KEYPAIR_LOOP((struct keypair *)&weak_ind_empty_data.hash, 0), {0}};
0b5d2b2001-06-05Martin Stjernholm static struct mapping_data weak_val_empty_data =
9386322011-07-21Henrik Grubbström (Grubba)  { PIKE_CONSTANT_MEMOBJ_INIT(1, T_MAPPING_DATA), 1, 0,0,0,0,0,0, MAPPING_WEAK_VALUES,
d4741b2007-10-04Henrik Grubbström (Grubba)  IF_ELSE_KEYPAIR_LOOP((struct keypair *)&weak_val_empty_data.hash, 0), {0}};
0b5d2b2001-06-05Martin Stjernholm static struct mapping_data weak_both_empty_data =
9386322011-07-21Henrik Grubbström (Grubba)  { PIKE_CONSTANT_MEMOBJ_INIT(1, T_MAPPING_DATA), 1, 0,0,0,0,0,0, MAPPING_WEAK,
d4741b2007-10-04Henrik Grubbström (Grubba)  IF_ELSE_KEYPAIR_LOOP((struct keypair *)&weak_both_empty_data.hash, 0), {0}};
06983f1996-09-22Fredrik Hübinette (Hubbe) 
2dff752005-09-10Marek Habersack /** This function allocates the hash table and svalue space for a mapping
06983f1996-09-22Fredrik Hübinette (Hubbe)  * struct. The size is the max number of indices that can fit in the * allocated space.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
c0e91b2001-01-25Fredrik Hübinette (Hubbe) static void init_mapping(struct mapping *m,
4fe8a52016-10-25Henrik Grubbström (Grubba)  INT32 hashsize,
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  INT16 flags)
515b6c1996-06-09Fredrik Hübinette (Hubbe) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
f5757f2000-08-11Henrik Grubbström (Grubba)  ptrdiff_t e;
4fe8a52016-10-25Henrik Grubbström (Grubba)  INT32 size;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5eca4d2000-09-04Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_ZAP_WEAK)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Can't allocate a new mapping_data inside gc.\n");
4fe8a52016-10-25Henrik Grubbström (Grubba)  if(hashsize < 0) Pike_fatal("init_mapping with negative value.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
4fe8a52016-10-25Henrik Grubbström (Grubba)  if(hashsize)
9076fa1997-02-17Fredrik Hübinette (Hubbe)  {
4fe8a52016-10-25Henrik Grubbström (Grubba)  if (hashsize & (hashsize - 1)) { hashsize = find_next_power(hashsize); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
4fe8a52016-10-25Henrik Grubbström (Grubba)  size = hashsize * AVG_LINK_LENGTH;
2da2982014-08-08Henrik Grubbström (Grubba) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  e=MAPPING_DATA_SIZE(hashsize, size);
e5cee12014-04-27Martin Nilsson  md=xcalloc(1,e);
7bf6232000-04-23Martin Stjernholm 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data=md; md->hashsize=hashsize;
e5cee12014-04-27Martin Nilsson 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->free_list=MD_KEYPAIRS(md, hashsize);
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
9076fa1997-02-17Fredrik Hübinette (Hubbe)  for(e=1;e<size;e++)
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  { md->free_list[e-1].next = md->free_list + e;
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&md->free_list[e-1].ind); mark_free_svalue (&md->free_list[e-1].val);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  }
e5cee12014-04-27Martin Nilsson  /* md->free_list[e-1].next=0; */
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&md->free_list[e-1].ind); mark_free_svalue (&md->free_list[e-1].val);
df9b622001-05-27Henrik Grubbström (Grubba) #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
e5cee12014-04-27Martin Nilsson  /* md->ind_types = 0; */ /* md->val_types = 0; */
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  md->flags = flags;
e5cee12014-04-27Martin Nilsson  /* md->size = 0; */ /* md->refs=0; */ /* md->valrefs=0; */ /* md->hardlinks=0; */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->num_keypairs=size;
9076fa1997-02-17Fredrik Hübinette (Hubbe)  }else{
0b5d2b2001-06-05Martin Stjernholm  switch (flags & MAPPING_WEAK) { case 0: md = &empty_data; break; case MAPPING_WEAK_INDICES: md = &weak_ind_empty_data; break; case MAPPING_WEAK_VALUES: md = &weak_val_empty_data; break; default: md = &weak_both_empty_data; break;
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  }
9076fa1997-02-17Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  add_ref(md); m->data=md;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
20b19f2000-02-09Fredrik Hübinette (Hubbe)  m->debug_size = md->size;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
54c9eb2016-08-16Arne Goedeke static struct mapping *allocate_mapping_no_init(void)
79ea9b2016-07-25Martin Nilsson { struct mapping *m=alloc_mapping(); GC_ALLOC(m); m->refs = 0; add_ref(m); /* For DMALLOC... */ DOUBLELINK(first_mapping, m); return m; }
2dff752005-09-10Marek Habersack /** This function allocates an empty mapping with initial room
7964ef2002-10-27Martin Nilsson  * for 'size' values.
2dff752005-09-10Marek Habersack  * * @param size initial number of values * @return the newly allocated mapping * @see do_free_mapping * @see free_mapping
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *debug_allocate_mapping(int size)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
54c9eb2016-08-16Arne Goedeke  struct mapping *m = allocate_mapping_no_init();
4fe8a52016-10-25Henrik Grubbström (Grubba)  init_mapping(m, (size + AVG_LINK_LENGTH - 1) / AVG_LINK_LENGTH, 0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return m; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void really_free_mapping_data(struct mapping_data *md)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_malloc_touch(md);
7dd0d72000-09-14Martin Stjernholm 
765de02000-01-28Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (md->refs) {
5aad932002-08-15Marcus Comstedt  Pike_fatal("really_free_mapping_data(): md has non-zero refs: %d\n",
445db52014-11-11Henrik Grubbström (Grubba)  md->refs); } if (!md->size) { /* Paranoia and keep gcc happy. */ if (md == &empty_data) { Pike_fatal("really_free_mapping_data(): md is empty_data!\n"); } if (md == &weak_ind_empty_data) { Pike_fatal("really_free_mapping_data(): md is weak_ind_empty_data!\n"); } if (md == &weak_val_empty_data) { Pike_fatal("really_free_mapping_data(): md is weak_val_empty_data!\n"); } if (md == &weak_both_empty_data) { Pike_fatal("really_free_mapping_data(): md is weak_both_empty_data!\n"); }
765de02000-01-28Henrik Grubbström (Grubba)  } #endif /* PIKE_DEBUG */
7dd0d72000-09-14Martin Stjernholm 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  NEW_MAPPING_LOOP(md)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { free_svalue(& k->val); free_svalue(& k->ind); }
0ec7522014-04-27Martin Nilsson  free(md);
553d232000-09-14Martin Stjernholm  GC_FREE_BLOCK(md);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void do_free_mapping(struct mapping *m)
65b6732000-07-07Martin Stjernholm { if (m)
63040d2008-01-05Martin Nilsson  inl_free_mapping(m);
65b6732000-07-07Martin Stjernholm }
5e83442008-05-11Martin Stjernholm /* This function is used to rehash a mapping without losing the internal
06983f1996-09-22Fredrik Hübinette (Hubbe)  * order in each hash chain. This is to prevent mappings from becoming
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  * inefficient just after being rehashed.
06983f1996-09-22Fredrik Hübinette (Hubbe)  */
bd6e562013-01-01Henrik Grubbström (Grubba) /* Evil: Steal the svalues from the old md. */
54beb22000-02-01Fredrik Hübinette (Hubbe) static void mapping_rehash_backwards_evil(struct mapping_data *md, struct keypair *from)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  unsigned INT32 h;
9e7ce52006-01-19Henrik Grubbström (Grubba)  struct keypair *k, *prev = NULL, *next; if(!(k = from)) return; /* Reverse the hash chain. */ while ((next = k->next)) { k->next = prev; prev = k; k = next; } k->next = prev;
54beb22000-02-01Fredrik Hübinette (Hubbe) 
ebe2692013-01-01Henrik Grubbström (Grubba)  prev = k;
54beb22000-02-01Fredrik Hübinette (Hubbe) 
9e7ce52006-01-19Henrik Grubbström (Grubba)  /* Rehash and reverse the hash chain. */
ebe2692013-01-01Henrik Grubbström (Grubba)  while ((from = prev)) { /* Reverse */ prev = from->next; from->next = next; next = from;
bd6e562013-01-01Henrik Grubbström (Grubba)  if (md->flags & MAPPING_WEAK) { switch(md->flags & MAPPING_WEAK) { default: Pike_fatal("Instable mapping data flags.\n");
a22fe12015-04-23Henrik Grubbström (Grubba)  break;
bd6e562013-01-01Henrik Grubbström (Grubba)  case MAPPING_WEAK_INDICES:
e99c432013-08-03Arne Goedeke  if (!REFCOUNTED_TYPE(TYPEOF(from->ind)) ||
bd6e562013-01-01Henrik Grubbström (Grubba)  (*from->ind.u.refs > 1)) { goto keep_keypair; } break; case MAPPING_WEAK_VALUES:
e99c432013-08-03Arne Goedeke  if (!REFCOUNTED_TYPE(TYPEOF(from->val)) ||
bd6e562013-01-01Henrik Grubbström (Grubba)  (*from->val.u.refs > 1)) { goto keep_keypair; } break; case MAPPING_WEAK:
f10f3e2013-01-01Henrik Grubbström (Grubba)  /* NB: Compat: Unreference counted values are counted * as multi-referenced here. */
4a93e82013-06-11Henrik Grubbström (Grubba)  if ((!REFCOUNTED_TYPE(TYPEOF(from->ind)) ||
f10f3e2013-01-01Henrik Grubbström (Grubba)  (*from->ind.u.refs > 1)) &&
4a93e82013-06-11Henrik Grubbström (Grubba)  (!REFCOUNTED_TYPE(TYPEOF(from->val)) ||
f10f3e2013-01-01Henrik Grubbström (Grubba)  (*from->val.u.refs > 1))) {
bd6e562013-01-01Henrik Grubbström (Grubba)  goto keep_keypair; } break; } /* Free. * Note that we don't need to free or unlink the keypair, * since that will be done by the caller anyway. */ free_svalue(&from->ind); free_svalue(&from->val); continue; } keep_keypair:
9e7ce52006-01-19Henrik Grubbström (Grubba)  /* unlink */ k=md->free_list;
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
54beb22000-02-01Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
9e7ce52006-01-19Henrik Grubbström (Grubba)  if(!k) Pike_fatal("Error in rehash: not enough keypairs.\n");
54beb22000-02-01Fredrik Hübinette (Hubbe) #endif
9e7ce52006-01-19Henrik Grubbström (Grubba)  md->free_list=k->next;
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */
9e7ce52006-01-19Henrik Grubbström (Grubba)  md->free_list++;
df9b622001-05-27Henrik Grubbström (Grubba) #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
54beb22000-02-01Fredrik Hübinette (Hubbe) 
9e7ce52006-01-19Henrik Grubbström (Grubba)  /* initialize */ *k=*from; /* link */ h=k->hval;
9031422011-04-05Arne Goedeke  h&=md->hashsize - 1;
9e7ce52006-01-19Henrik Grubbström (Grubba)  k->next=md->hash[h]; md->hash[h]=k; /* update */
017b572011-10-28Henrik Grubbström (Grubba)  md->ind_types |= 1<< (TYPEOF(k->ind)); md->val_types |= 1<< (TYPEOF(k->val));
9e7ce52006-01-19Henrik Grubbström (Grubba)  md->size++; }
54beb22000-02-01Fredrik Hübinette (Hubbe) }
bd6e562013-01-01Henrik Grubbström (Grubba) /* Good: Copy the svalues from the old md. */
54beb22000-02-01Fredrik Hübinette (Hubbe) static void mapping_rehash_backwards_good(struct mapping_data *md, struct keypair *from) { unsigned INT32 h;
9e7ce52006-01-19Henrik Grubbström (Grubba)  struct keypair *k, *prev = NULL, *next; if(!(k = from)) return;
54beb22000-02-01Fredrik Hübinette (Hubbe) 
9e7ce52006-01-19Henrik Grubbström (Grubba)  /* Reverse the hash chain. */ while ((next = k->next)) { k->next = prev; prev = k; k = next; } k->next = prev;
ebe2692013-01-01Henrik Grubbström (Grubba)  prev = k;
54beb22000-02-01Fredrik Hübinette (Hubbe) 
9e7ce52006-01-19Henrik Grubbström (Grubba)  /* Rehash and reverse the hash chain. */
ebe2692013-01-01Henrik Grubbström (Grubba)  while ((from = prev)) { /* Reverse */ prev = from->next; from->next = next; next = from;
bd6e562013-01-01Henrik Grubbström (Grubba)  if (md->flags & MAPPING_WEAK) { switch(md->flags & MAPPING_WEAK) { default: Pike_fatal("Instable mapping data flags.\n");
a22fe12015-04-23Henrik Grubbström (Grubba)  break;
bd6e562013-01-01Henrik Grubbström (Grubba)  case MAPPING_WEAK_INDICES:
4a93e82013-06-11Henrik Grubbström (Grubba)  if (REFCOUNTED_TYPE(TYPEOF(from->ind)) &&
bd6e562013-01-01Henrik Grubbström (Grubba)  (*from->ind.u.refs > 1)) { goto keep_keypair; } break; case MAPPING_WEAK_VALUES:
4a93e82013-06-11Henrik Grubbström (Grubba)  if (REFCOUNTED_TYPE(TYPEOF(from->val)) &&
bd6e562013-01-01Henrik Grubbström (Grubba)  (*from->val.u.refs > 1)) { goto keep_keypair; } break; case MAPPING_WEAK:
f10f3e2013-01-01Henrik Grubbström (Grubba)  /* NB: Compat: Unreference counted values are counted * as multi-referenced here. */
4a93e82013-06-11Henrik Grubbström (Grubba)  if ((!REFCOUNTED_TYPE(TYPEOF(from->ind)) ||
f10f3e2013-01-01Henrik Grubbström (Grubba)  (*from->ind.u.refs > 1)) &&
4a93e82013-06-11Henrik Grubbström (Grubba)  (!REFCOUNTED_TYPE(TYPEOF(from->val)) ||
f10f3e2013-01-01Henrik Grubbström (Grubba)  (*from->val.u.refs > 1))) {
bd6e562013-01-01Henrik Grubbström (Grubba)  goto keep_keypair; } break; } /* Skip copying of this keypair. * * NB: We can't mess with the original md here, * since it might be in use by an iterator * or similar. */ continue; } keep_keypair:
9e7ce52006-01-19Henrik Grubbström (Grubba)  /* unlink */ k=md->free_list;
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
54beb22000-02-01Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
9e7ce52006-01-19Henrik Grubbström (Grubba)  if(!k) Pike_fatal("Error in rehash: not enough keypairs.\n");
54beb22000-02-01Fredrik Hübinette (Hubbe) #endif
9e7ce52006-01-19Henrik Grubbström (Grubba)  md->free_list=k->next;
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */
9e7ce52006-01-19Henrik Grubbström (Grubba)  md->free_list++;
df9b622001-05-27Henrik Grubbström (Grubba) #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
9e7ce52006-01-19Henrik Grubbström (Grubba)  /* initialize */ k->hval=from->hval; assign_svalue_no_free(&k->ind, &from->ind); assign_svalue_no_free(&k->val, &from->val); /* link */ h=k->hval;
9031422011-04-05Arne Goedeke  h&=md->hashsize - 1;
9e7ce52006-01-19Henrik Grubbström (Grubba)  k->next=md->hash[h]; md->hash[h]=k; /* update */
017b572011-10-28Henrik Grubbström (Grubba)  md->ind_types |= 1<< (TYPEOF(k->ind)); md->val_types |= 1<< (TYPEOF(k->val));
9e7ce52006-01-19Henrik Grubbström (Grubba)  md->size++; }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
2dff752005-09-10Marek Habersack /** This function re-allocates a mapping. It adjusts the max no. of
06983f1996-09-22Fredrik Hübinette (Hubbe)  * values can be fitted into the mapping. It takes a bit of time to * run, but is used seldom enough not to degrade preformance significantly.
2dff752005-09-10Marek Habersack  * * @param m the mapping to be rehashed
4fe8a52016-10-25Henrik Grubbström (Grubba)  * @param hashsize new mappingsize
2dff752005-09-10Marek Habersack  * @return the rehashed mapping
06983f1996-09-22Fredrik Hübinette (Hubbe)  */
4fe8a52016-10-25Henrik Grubbström (Grubba) static struct mapping *rehash(struct mapping *m, int hashsize)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
54beb22000-02-01Fredrik Hübinette (Hubbe)  struct mapping_data *md, *new_md;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  INT32 tmp=m->data->size;
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  INT32 e;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
59e53e2000-01-31Fredrik Hübinette (Hubbe)  md=m->data;
27bec92000-02-15Henrik Grubbström (Grubba)  debug_malloc_touch(md);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
59e53e2000-01-31Fredrik Hübinette (Hubbe)  if(md->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
e65af12016-10-24Henrik Grubbström (Grubba)  /* NB: Code duplication from init_mapping(). */
4fe8a52016-10-25Henrik Grubbström (Grubba)  if (hashsize & (hashsize - 1)) hashsize = find_next_power(hashsize);
e65af12016-10-24Henrik Grubbström (Grubba)  if ((md->hashsize == hashsize) && (md->refs == 1)) return m;
9406512008-06-26Henrik Grubbström (Grubba) 
4fe8a52016-10-25Henrik Grubbström (Grubba)  init_mapping(m, hashsize, md->flags);
616b622000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
54beb22000-02-01Fredrik Hübinette (Hubbe)  new_md=m->data;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
54beb22000-02-01Fredrik Hübinette (Hubbe)  /* This operation is now 100% atomic - no locking required */ if(md->refs>1) { /* good */
bd6e562013-01-01Henrik Grubbström (Grubba)  /* More than one reference to the md ==> We need to * keep it afterwards. */
54beb22000-02-01Fredrik Hübinette (Hubbe)  for(e=0;e<md->hashsize;e++) mapping_rehash_backwards_good(new_md, md->hash[e]);
59e53e2000-01-31Fredrik Hübinette (Hubbe) 
1f342f2000-02-04Fredrik Hübinette (Hubbe)  unlink_mapping_data(md);
54beb22000-02-01Fredrik Hübinette (Hubbe)  }else{ /* evil */
bd6e562013-01-01Henrik Grubbström (Grubba)  /* We have the only reference to the md, * so we can just copy the svalues without * bothering about type checking. */
54beb22000-02-01Fredrik Hübinette (Hubbe)  for(e=0;e<md->hashsize;e++) mapping_rehash_backwards_evil(new_md, md->hash[e]);
59e53e2000-01-31Fredrik Hübinette (Hubbe) 
0ec7522014-04-27Martin Nilsson  free(md);
553d232000-09-14Martin Stjernholm  GC_FREE_BLOCK(md);
54beb22000-02-01Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG
ece55d2013-01-29Henrik Grubbström (Grubba)  if((m->data->size != tmp) && ((m->data->size > tmp) || !(m->data->flags & MAPPING_WEAK))) Pike_fatal("Rehash failed, size not same any more (%ld != %ld).\n", (long)m->data->size, (long)tmp);
5eca4d2000-09-04Martin Stjernholm #endif #ifdef MAPPING_SIZE_DEBUG
20b19f2000-02-09Fredrik Hübinette (Hubbe)  m->debug_size = m->data->size;
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  return m; }
2868742016-02-29Henrik Grubbström (Grubba) ptrdiff_t do_gc_weak_mapping(struct mapping *m) { struct mapping_data *md = m->data; ptrdiff_t initial_size = md->size; INT32 e; if (!(md->flags & MAPPING_WEAK) || (md->refs != 1)) { // Nothing to do. return 0; } for (e = 0; e < md->hashsize; e++) { struct keypair **kp = md->hash + e; struct keypair *k; while ((k = *kp)) { switch(md->flags & MAPPING_WEAK) { default: Pike_fatal("Unstable mapping data flags.\n"); break; case MAPPING_WEAK_INDICES: if (REFCOUNTED_TYPE(TYPEOF(k->ind)) && (*k->ind.u.refs > 1)) { kp = &k->next; continue; } break; case MAPPING_WEAK_VALUES: if (REFCOUNTED_TYPE(TYPEOF(k->val)) && (*k->val.u.refs > 1)) { kp = &k->next; continue; } break; case MAPPING_WEAK: /* NB: Compat: Unreferenced counted values are counted * as multi-referenced here. */ if ((!REFCOUNTED_TYPE(TYPEOF(k->ind)) || (*k->ind.u.refs > 1)) && (!REFCOUNTED_TYPE(TYPEOF(k->val)) || (*k->val.u.refs > 1))) { kp = &k->next; continue; } break; } /* Unlink. */ *kp = k->next; /* Free. */ free_svalue(&k->ind); free_svalue(&k->val); k->next = md->free_list; md->free_list = k; md->size--; /* Note: Do not advance kp here, as it has been done by the unlink. */ } } return initial_size - md->size; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) /* * No need for super efficiency, should not be called very often * -Hubbe */ #define LOW_RELOC(X) X= (void *) ((char *)(X) + off); #define RELOC(X) if(X) LOW_RELOC(X) struct mapping_data *copy_mapping_data(struct mapping_data *md) {
f5757f2000-08-11Henrik Grubbström (Grubba)  long e; ptrdiff_t size, off;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *nmd; struct keypair *keypairs;
5eca4d2000-09-04Martin Stjernholm #ifdef PIKE_DEBUG if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_ZAP_WEAK)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Can't allocate a new mapping_data inside gc.\n");
5eca4d2000-09-04Martin Stjernholm #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_malloc_touch(md); size=MAPPING_DATA_SIZE(md->hashsize, md->num_keypairs); nmd=(struct mapping_data *)xalloc(size);
59fc9e2014-09-03Martin Nilsson  memcpy(nmd, md, size);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  off=((char *)nmd) - ((char *)md); RELOC(nmd->free_list); for(e=0;e<nmd->hashsize;e++) RELOC(nmd->hash[e]); keypairs=MD_KEYPAIRS(nmd, nmd->hashsize);
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  for(e=0;e<nmd->num_keypairs;e++) { RELOC(keypairs[e].next); add_ref_svalue(& keypairs[e].ind); add_ref_svalue(& keypairs[e].val); }
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ for(e=0;e<nmd->size;e++) { RELOC(keypairs[e].next); add_ref_svalue(& keypairs[e].ind); add_ref_svalue(& keypairs[e].val); } #endif /* PIKE_MAPPING_KEYPAIR_LOOP */
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
50ea682003-03-14Henrik Grubbström (Grubba)  nmd->refs=0; add_ref(nmd); /* For DMALLOC... */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  nmd->valrefs=0; nmd->hardlinks=0;
353ba12016-10-25Henrik Grubbström (Grubba)  nmd->ind_types = md->ind_types; nmd->val_types = md->val_types;
aa95de2008-06-24Henrik Grubbström (Grubba)  /* FIXME: What about nmd->flags? */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->hardlinks) { #ifdef PIKE_DEBUG if(md->refs <= 0 || md->valrefs<=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Hardlink without refs/valrefs!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif md->hardlinks--; md->valrefs--; }
50ea682003-03-14Henrik Grubbström (Grubba)  sub_ref(md);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  return nmd; }
5eca4d2000-09-04Martin Stjernholm #define MAPPING_DATA_IN_USE(MD) ((MD)->refs != (MD)->hardlinks + 1)
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #define LOW_FIND(FUN, KEY, FOUND, NOT_FOUND) do { \ md=m->data; \ add_ref(md); \ if(md->hashsize) \ { \
9031422011-04-05Arne Goedeke  h=h2 & (md->hashsize - 1); \
9e398c2000-02-08Fredrik Hübinette (Hubbe)  DO_IF_DEBUG( if(d_flag > 1) check_mapping_type_fields(m); ) \
3b2cd42012-11-04Arne Goedeke  if(check_type_contains(md->ind_types, key)) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  { \ for(prev= md->hash + h;(k=*prev);prev=&k->next) \ { \
54beb22000-02-01Fredrik Hübinette (Hubbe)  if(h2 == k->hval && FUN(& k->ind, KEY)) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  { \ FOUND; \ } \ } \ } \ } \ NOT_FOUND; \ }while(0) #define LOW_FIND2(FUN, KEY, FOUND, NOT_FOUND) do { \ struct keypair *k2; \ md=m->data; \ add_ref(md); \ if(md->hashsize) \ { \
9031422011-04-05Arne Goedeke  h=h2 & (md->hashsize-1); \
9e398c2000-02-08Fredrik Hübinette (Hubbe)  DO_IF_DEBUG( if(d_flag > 1) check_mapping_type_fields(m); ) \
3b2cd42012-11-04Arne Goedeke  if(check_type_contains(md->ind_types, key)) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  { \
9031422011-04-05Arne Goedeke  k2=omd->hash[h2 & (omd->hashsize - 1)]; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  prev= md->hash + h; \ for(;(k=*prev) && k2;(prev=&k->next),(k2=k2->next)) \
54beb22000-02-01Fredrik Hübinette (Hubbe)  if(!(h2 == k->hval && is_identical(&k2->ind, &k->ind))) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  break; \ for(;(k=*prev);prev=&k->next) \ { \ if(FUN(& k->ind, KEY)) \ { \ FOUND; \ } \ } \ } \ } \ NOT_FOUND; \ }while(0) #define SAME_DATA(SAME,NOT_SAME) \ if(m->data == md) \ { \ SAME; \ }else{ \ NOT_SAME; \ } /* FIXME: the 'no action' might need to be fixed.... */ #define FIND() do{ \ LOW_FIND(is_eq, key, \ omd=md; \ SAME_DATA( break, \ struct svalue *tmp=&k->ind; \ LOW_FIND(is_identical, tmp, break, ;); \ free_mapping_data(omd)), \ break); \ free_mapping_data(md); \ }while(0)
13670c2015-05-25Martin Nilsson 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) /* Assumes md is *NOT* locked */ #define COPYMAP2() do { \
aa45cf2000-08-07Henrik Grubbström (Grubba)  ptrdiff_t off; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data=copy_mapping_data(m->data); \ debug_malloc_touch(m->data); \
d3018a2000-01-30Fredrik Hübinette (Hubbe)  DO_IF_DEBUG( if(d_flag>1) check_mapping(m); ) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  off=((char *)m->data)-((char *)md); \ LOW_RELOC(k); \ LOW_RELOC(prev); \ md=m->data; \ }while(0) #define PREPARE_FOR_DATA_CHANGE2() \ if(md->valrefs) COPYMAP2() #define PREPARE_FOR_INDEX_CHANGE2() \ if(md->refs>1) COPYMAP2() #define PROPAGATE() do { \ if(md->refs==1) \ { \
9031422011-04-05Arne Goedeke  h=h2 & (md->hashsize - 1); \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  *prev=k->next; \ k->next=md->hash[h]; \ md->hash[h]=k; \ } \ }while(0) /* Assumes md is locked */ #define COPYMAP() do { \
d1f2712000-08-07Henrik Grubbström (Grubba)  ptrdiff_t off; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data=copy_mapping_data(m->data); \ debug_malloc_touch(m->data); \ off=((char *)m->data)-((char *)md); \ LOW_RELOC(k); \ free_mapping_data(md); \ md=m->data; \
50ea682003-03-14Henrik Grubbström (Grubba)  add_ref(md); \
57a4ab2000-01-27Fredrik Hübinette (Hubbe) }while(0) #define PREPARE_FOR_DATA_CHANGE() \ if(md->valrefs) COPYMAP() #define PREPARE_FOR_INDEX_CHANGE() \ if(md->refs>1) COPYMAP()
2dff752005-09-10Marek Habersack /** This function brings the type fields in the mapping up to speed. * It should be used only when the type fields MUST be correct, which is not
06983f1996-09-22Fredrik Hübinette (Hubbe)  * very often. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_fix_type_field(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k; TYPE_FIELD ind_types, val_types; val_types = ind_types = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  NEW_MAPPING_LOOP(m->data)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
017b572011-10-28Henrik Grubbström (Grubba)  val_types |= 1 << TYPEOF(k->val); ind_types |= 1 << TYPEOF(k->ind);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(val_types & ~(m->data->val_types))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping value types out of order!\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(ind_types & ~(m->data->ind_types))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping indices types out of order!\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data->val_types = val_types; m->data->ind_types = ind_types;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
5eca4d2000-09-04Martin Stjernholm PMOD_EXPORT void mapping_set_flags(struct mapping *m, int flags) { struct mapping_data *md = m->data;
a0d7f32003-08-20Henrik Grubbström (Grubba)  if ((md->flags != flags) && (md->refs > 1)) {
f258372000-09-08Henrik Grubbström (Grubba)  struct keypair *k = NULL, *prev = NULL;
5eca4d2000-09-04Martin Stjernholm  COPYMAP2();
a0d7f32003-08-20Henrik Grubbström (Grubba)  md = m->data;
5eca4d2000-09-04Martin Stjernholm  }
c0e91b2001-01-25Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
0b5d2b2001-06-05Martin Stjernholm  if(flags & MAPPING_WEAK)
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  { debug_malloc_touch(m); debug_malloc_touch(md); } else { debug_malloc_touch(m); debug_malloc_touch(md); } #endif
5eca4d2000-09-04Martin Stjernholm  md->flags = flags; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void low_mapping_insert(struct mapping *m,
9cc28d2004-05-28Henrik Grubbström (Grubba)  const struct svalue *key, const struct svalue *val, int overwrite)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
a563932016-06-24Per Hedbor  size_t h,h2;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k, **prev;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md, *omd; #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
9076fa1997-02-17Fredrik Hübinette (Hubbe)  h2=hash_svalue(key);
13670c2015-05-25Martin Nilsson 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  LOW_FIND(is_eq, key, struct svalue *tmp=&k->ind; SAME_DATA(goto mi_set_value, omd=md; LOW_FIND(is_identical, tmp, free_mapping_data(omd); goto mi_set_value, free_mapping_data(omd); goto mi_do_nothing)), Z: SAME_DATA(goto mi_insert, omd=md; LOW_FIND2(is_eq, key, free_mapping_data(omd); goto mi_do_nothing, free_mapping_data(omd); goto Z))); mi_do_nothing: free_mapping_data(md); return; mi_set_value:
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data != md)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_insert!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free_mapping_data(md);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  if(!overwrite) return;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  PREPARE_FOR_DATA_CHANGE2(); PROPAGATE(); /* propagate after preparing */
017b572011-10-28Henrik Grubbström (Grubba)  md->val_types |= 1 << TYPEOF(*val); if (overwrite == 2 && TYPEOF(*key) == T_OBJECT)
a1202e2003-11-09Martin Stjernholm  /* Should replace the index too. It's only for objects that it's * possible to tell the difference. */ assign_svalue (&k->ind, key);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  assign_svalue(& k->val, val); #ifdef PIKE_DEBUG if(d_flag>1) check_mapping(m); #endif return; mi_insert: #ifdef PIKE_DEBUG if(m->data != md)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_insert!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m); #endif free_mapping_data(md); /* We do a re-hash here instead of copying the mapping. */
df9b622001-05-27Henrik Grubbström (Grubba)  if( #ifndef PIKE_MAPPING_KEYPAIR_LOOP (!md->free_list) || #else /* PIKE_MAPPING_KEYPAIR_LOOP */ (md->size >= md->num_keypairs) || #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */ md->refs>1)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
4fe8a52016-10-25Henrik Grubbström (Grubba)  rehash(m, md->hashsize?(md->hashsize<<1):AVG_LINK_LENGTH);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
9031422011-04-05Arne Goedeke  h=h2 & ( md->hashsize - 1);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no need to lock here since we are not calling is_eq - Hubbe */ k=md->free_list;
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->free_list=k->next;
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ md->free_list++; #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  k->next=md->hash[h]; md->hash[h]=k;
017b572011-10-28Henrik Grubbström (Grubba)  md->ind_types |= 1 << TYPEOF(*key); md->val_types |= 1 << TYPEOF(*val);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  assign_svalue_no_free(& k->ind, key); assign_svalue_no_free(& k->val, val);
54beb22000-02-01Fredrik Hübinette (Hubbe)  k->hval = h2;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->size++;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
10da6b2000-04-15Fredrik Hübinette (Hubbe)  if(m->data ==md) m->debug_size++;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_insert(struct mapping *m,
9cc28d2004-05-28Henrik Grubbström (Grubba)  const struct svalue *key, const struct svalue *val)
59e53e2000-01-31Fredrik Hübinette (Hubbe) { low_mapping_insert(m,key,val,1); }
a1202e2003-11-09Martin Stjernholm /* Inline the above in this file. */ #define mapping_insert(M, KEY, VAL) low_mapping_insert ((M), (KEY), (VAL), 1)
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT union anything *mapping_get_item_ptr(struct mapping *m,
466b662008-01-05Martin Nilsson  const struct svalue *key,
515b6c1996-06-09Fredrik Hübinette (Hubbe)  TYPE_T t)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
a563932016-06-24Per Hedbor  size_t h, h2;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k, **prev;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md,*omd;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(m->data);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  h2=hash_svalue(key); LOW_FIND(is_eq, key, struct svalue *tmp=&k->ind; SAME_DATA(goto mg_set_value, omd=md; LOW_FIND(is_identical, tmp, free_mapping_data(omd); goto mg_set_value, free_mapping_data(omd); goto mg_do_nothing)), Z: SAME_DATA(goto mg_insert, omd=md; LOW_FIND2(is_eq, key, free_mapping_data(omd); goto mg_do_nothing, free_mapping_data(omd); goto Z))); mg_do_nothing: free_mapping_data(md); return 0; mg_set_value:
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data != md)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_get_item_ptr!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag) check_mapping(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free_mapping_data(md);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(k->val) == t)
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  { PREPARE_FOR_DATA_CHANGE2(); PROPAGATE(); /* prepare then propagate */
13670c2015-05-25Martin Nilsson 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  return & ( k->val.u );
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  return 0;
13670c2015-05-25Martin Nilsson 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  mg_insert: #ifdef PIKE_DEBUG if(m->data != md)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_get_item_ptr!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag) check_mapping(m); #endif free_mapping_data(md); if(t != T_INT) return 0; /* no need to call PREPARE_* because we re-hash instead */
df9b622001-05-27Henrik Grubbström (Grubba)  if( #ifndef PIKE_MAPPING_KEYPAIR_LOOP !(md->free_list) || #else /* PIKE_MAPPING_KEYPAIR_LOOP */ (md->size >= md->num_keypairs) || #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */ md->refs>1)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
4fe8a52016-10-25Henrik Grubbström (Grubba)  rehash(m, md->hashsize?(md->hashsize<<1):AVG_LINK_LENGTH);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
9031422011-04-05Arne Goedeke  h=h2 & ( md->hashsize - 1);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
df9b622001-05-27Henrik Grubbström (Grubba)  k=md->free_list; #ifndef PIKE_MAPPING_KEYPAIR_LOOP
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->free_list=k->next;
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ md->free_list++; #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  k->next=md->hash[h]; md->hash[h]=k;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  assign_svalue_no_free(& k->ind, key);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(k->val, T_INT, NUMBER_NUMBER, integer, 0);
54beb22000-02-01Fredrik Hübinette (Hubbe)  k->hval = h2;
017b572011-10-28Henrik Grubbström (Grubba)  md->ind_types |= 1 << TYPEOF(*key);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->val_types |= BIT_INT; md->size++;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
10da6b2000-04-15Fredrik Hübinette (Hubbe)  if(m->data ==md) m->debug_size++;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe)  return & ( k->val.u );
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void map_delete_no_free(struct mapping *m,
466b662008-01-05Martin Nilsson  const struct svalue *key,
ea0be61999-11-11Fredrik Hübinette (Hubbe)  struct svalue *to)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
a563932016-06-24Per Hedbor  size_t h,h2;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k, **prev;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md,*omd;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  h2=hash_svalue(key); LOW_FIND(is_eq, key, struct svalue *tmp=&k->ind; SAME_DATA(goto md_remove_value, omd=md; LOW_FIND(is_identical, tmp, free_mapping_data(omd); goto md_remove_value, free_mapping_data(omd); goto md_do_nothing)), goto md_do_nothing); md_do_nothing:
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free_mapping_data(md);
ea0be61999-11-11Fredrik Hübinette (Hubbe)  if(to) {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, NUMBER_UNDEFINED, integer, 0);
ea0be61999-11-11Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  return; md_remove_value: #ifdef PIKE_DEBUG if(md->refs <= 1)
979ce92016-07-24Henrik Grubbström (Grubba)  Pike_fatal("Too few refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data != md)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_delete!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
979ce92016-07-24Henrik Grubbström (Grubba)  sub_ref(md);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  PREPARE_FOR_INDEX_CHANGE2(); /* No need to propagate */ *prev=k->next; free_svalue(& k->ind); if(to)
6dea232008-01-28Martin Stjernholm  move_svalue (to, &k->val);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  else free_svalue(& k->val);
df9b622001-05-27Henrik Grubbström (Grubba)  FREE_KEYPAIR(md, k);
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&md->free_list->ind); mark_free_svalue (&md->free_list->val);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->size--;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
10da6b2000-04-15Fredrik Hübinette (Hubbe)  if(m->data ==md) m->debug_size--;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
13670c2015-05-25Martin Nilsson 
353ba12016-10-25Henrik Grubbström (Grubba)  if (UNLIKELY(!md->size)) { md->ind_types = md->val_types = 0; }
e2001f2016-10-21Henrik Grubbström (Grubba)  if (!(md->flags & MAPPING_FLAG_NO_SHRINK)) {
e65af12016-10-24Henrik Grubbström (Grubba)  if((md->size * MIN_LINK_LENGTH_DENOMINATOR < md->hashsize * MIN_LINK_LENGTH_NUMERATOR) &&
e2001f2016-10-21Henrik Grubbström (Grubba)  (md->hashsize > AVG_LINK_LENGTH)) { debug_malloc_touch(m);
4fe8a52016-10-25Henrik Grubbström (Grubba)  rehash(m, md->hashsize>>1);
e2001f2016-10-21Henrik Grubbström (Grubba)  }
59e53e2000-01-31Fredrik Hübinette (Hubbe)  }
aa95de2008-06-24Henrik Grubbström (Grubba) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(d_flag>1) check_mapping(m); #endif return;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void check_mapping_for_destruct(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k, **prev; TYPE_FIELD ind_types, val_types;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md=m->data;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
853b832000-12-14Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE)
5aad932002-08-15Marcus Comstedt  Pike_fatal("check_mapping_for_destruct called in invalid pass inside gc.\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no is_eq -> no locking */
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!md->size) return; if((md->ind_types | md->val_types) & (BIT_OBJECT | BIT_FUNCTION))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  val_types = ind_types = 0;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->val_types |= BIT_INT; for(e=0;e<md->hashsize;e++)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  for(prev= md->hash + e;(k=*prev);)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
853b832000-12-14Martin Stjernholm  check_destructed(& k->val);
13670c2015-05-25Martin Nilsson 
017b572011-10-28Henrik Grubbström (Grubba)  if((TYPEOF(k->ind) == T_OBJECT || TYPEOF(k->ind) == T_FUNCTION) &&
4ab0aa1996-09-23Fredrik Hübinette (Hubbe)  !k->ind.u.object->prog)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
c5ae922000-04-16Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
5eca4d2000-09-04Martin Stjernholm  debug_malloc_touch(md);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  PREPARE_FOR_INDEX_CHANGE2();
853b832000-12-14Martin Stjernholm  *prev=k->next; free_svalue(& k->ind); free_svalue(& k->val);
df9b622001-05-27Henrik Grubbström (Grubba)  FREE_KEYPAIR(md, k);
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&md->free_list->ind); mark_free_svalue (&md->free_list->val);
853b832000-12-14Martin Stjernholm  md->size--;
aa95de2008-06-24Henrik Grubbström (Grubba) 
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
853b832000-12-14Martin Stjernholm  if(m->data ==md) { m->debug_size++; debug_malloc_touch(m); }
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
853b832000-12-14Martin Stjernholm  debug_malloc_touch(md);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }else{
017b572011-10-28Henrik Grubbström (Grubba)  val_types |= 1 << TYPEOF(k->val); ind_types |= 1 << TYPEOF(k->ind);
cb859e1996-09-23Fredrik Hübinette (Hubbe)  prev=&k->next;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } } }
5eca4d2000-09-04Martin Stjernholm 
cfa62c2001-11-12Martin Stjernholm  md->val_types = val_types; md->ind_types = ind_types;
e2001f2016-10-21Henrik Grubbström (Grubba)  if (!(md->flags & MAPPING_FLAG_NO_SHRINK)) {
e65af12016-10-24Henrik Grubbström (Grubba)  if((md->size * MIN_LINK_LENGTH_DENOMINATOR < md->hashsize * MIN_LINK_LENGTH_NUMERATOR) &&
e2001f2016-10-21Henrik Grubbström (Grubba)  (md->hashsize > AVG_LINK_LENGTH)) { debug_malloc_touch(m);
4fe8a52016-10-25Henrik Grubbström (Grubba)  rehash(m, md->hashsize>>1);
e2001f2016-10-21Henrik Grubbström (Grubba)  }
59e53e2000-01-31Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5eca4d2000-09-04Martin Stjernholm  if(d_flag>1) check_mapping(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *low_mapping_lookup(struct mapping *m,
9cc28d2004-05-28Henrik Grubbström (Grubba)  const struct svalue *key)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
a563932016-06-24Per Hedbor  size_t h,h2;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct keypair *k=0, **prev=0; struct mapping_data *md, *omd;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  h2=hash_svalue(key); #ifdef PIKE_DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif FIND(); if(k)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  PROPAGATE(); return &k->val;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *low_mapping_string_lookup(struct mapping *m,
466b662008-01-05Martin Nilsson  struct pike_string *p)
14dae91997-01-26Fredrik Hübinette (Hubbe) { struct svalue tmp;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(tmp, T_STRING, 0, string, p);
14dae91997-01-26Fredrik Hübinette (Hubbe)  return low_mapping_lookup(m, &tmp); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_string_insert(struct mapping *m,
466b662008-01-05Martin Nilsson  struct pike_string *p, const struct svalue *val)
a28dd21998-04-23Fredrik Hübinette (Hubbe) { struct svalue tmp;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(tmp, T_STRING, 0, string, p);
a28dd21998-04-23Fredrik Hübinette (Hubbe)  mapping_insert(m, &tmp, val); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_string_insert_string(struct mapping *m,
ea0be61999-11-11Fredrik Hübinette (Hubbe)  struct pike_string *p, struct pike_string *val) { struct svalue tmp;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(tmp, T_STRING, 0, string, val);
ea0be61999-11-11Fredrik Hübinette (Hubbe)  mapping_string_insert(m, p, &tmp); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *simple_mapping_string_lookup(struct mapping *m,
adb3b12004-03-22Martin Stjernholm  const char *p)
85f59e1998-01-08Fredrik Hübinette (Hubbe) { struct pike_string *tmp; if((tmp=findstring(p))) return low_mapping_string_lookup(m,tmp); return 0; }
f49b922007-10-03Henrik Grubbström (Grubba) /* Lookup in a mapping of mappings */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *mapping_mapping_lookup(struct mapping *m,
466b662008-01-05Martin Nilsson  const struct svalue *key1, const struct svalue *key2,
f49b922007-10-03Henrik Grubbström (Grubba)  int create)
8a5d441999-10-19Fredrik Hübinette (Hubbe) { struct svalue tmp; struct mapping *m2; struct svalue *s=low_mapping_lookup(m, key1);
1e38531999-10-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
8a5d441999-10-19Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
017b572011-10-28Henrik Grubbström (Grubba)  if(!s || TYPEOF(*s) != T_MAPPING)
8a5d441999-10-19Fredrik Hübinette (Hubbe)  { if(!create) return 0;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(tmp, T_MAPPING, 0, mapping, allocate_mapping(5));
8a5d441999-10-19Fredrik Hübinette (Hubbe)  mapping_insert(m, key1, &tmp);
1e38531999-10-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(tmp.u.mapping); free_mapping(tmp.u.mapping); /* There is one ref in 'm' */
8a5d441999-10-19Fredrik Hübinette (Hubbe)  s=&tmp; } m2=s->u.mapping;
1e38531999-10-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(m2);
8a5d441999-10-19Fredrik Hübinette (Hubbe)  s=low_mapping_lookup(m2, key2); if(s) return s; if(!create) return 0;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(tmp, T_INT, NUMBER_UNDEFINED, integer, 0);
8a5d441999-10-19Fredrik Hübinette (Hubbe)  mapping_insert(m2, key2, &tmp);
1e38531999-10-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(m2);
8a5d441999-10-19Fredrik Hübinette (Hubbe)  return low_mapping_lookup(m2, key2); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *mapping_mapping_string_lookup(struct mapping *m,
8a5d441999-10-19Fredrik Hübinette (Hubbe)  struct pike_string *key1, struct pike_string *key2, int create) { struct svalue k1,k2;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(k1, T_STRING, 0, string, key1); SET_SVAL(k2, T_STRING, 0, string, key2);
8a5d441999-10-19Fredrik Hübinette (Hubbe)  return mapping_mapping_lookup(m,&k1,&k2,create); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_index_no_free(struct svalue *dest,
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct mapping *m,
466b662008-01-05Martin Nilsson  const struct svalue *key)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct svalue *p;
4206f02006-11-07Martin Stjernholm  if(!IS_DESTRUCTED (key) && (p=low_mapping_lookup(m,key)))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
4139a22008-01-28Martin Stjernholm  assign_svalue_no_free(dest, p);
93d1e42008-01-27Henrik Grubbström (Grubba)  /* Never return NUMBER_UNDEFINED for existing entries. */
4139a22008-01-28Martin Stjernholm  /* Note: There is code that counts on storing UNDEFINED in mapping * values (using e.g. low_mapping_lookup to get them), so we have * to fix the subtype here rather than in mapping_insert. */
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*p) == T_INT) SET_SVAL_SUBTYPE(*dest, NUMBER_NUMBER);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }else{
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*dest, T_INT, NUMBER_UNDEFINED, integer, 0);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *mapping_indices(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct array *a; struct svalue *s; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
0279c82000-09-24Henrik Grubbström (Grubba)  check_mapping_for_destruct(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  a=allocate_array(m->data->size);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  s=ITEM(a);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no locking required */ NEW_MAPPING_LOOP(m->data) assign_svalue(s++, & k->ind);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  a->type_field = m->data->ind_types;
13670c2015-05-25Martin Nilsson 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return a; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *mapping_values(struct mapping *m)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k; struct array *a; struct svalue *s;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
0279c82000-09-24Henrik Grubbström (Grubba)  check_mapping_for_destruct(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  a=allocate_array(m->data->size);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  s=ITEM(a);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no locking required */ NEW_MAPPING_LOOP(m->data) assign_svalue(s++, & k->val);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  a->type_field = m->data->val_types;
06983f1996-09-22Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m); #endif
13670c2015-05-25Martin Nilsson 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return a; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *mapping_to_array(struct mapping *m)
2043ba1998-02-10Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k; struct array *a; struct svalue *s;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif a=allocate_array(m->data->size);
2043ba1998-02-10Fredrik Hübinette (Hubbe)  s=ITEM(a);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no locking required */ NEW_MAPPING_LOOP(m->data)
2043ba1998-02-10Fredrik Hübinette (Hubbe)  { struct array *b=allocate_array(2); assign_svalue(b->item+0, & k->ind); assign_svalue(b->item+1, & k->val);
017b572011-10-28Henrik Grubbström (Grubba)  b->type_field = (1 << TYPEOF(k->ind)) | (1 << TYPEOF(k->val)); SET_SVAL(*s, T_ARRAY, 0, array, b);
1757d81998-05-12Fredrik Hübinette (Hubbe)  s++;
2043ba1998-02-10Fredrik Hübinette (Hubbe)  } a->type_field = BIT_ARRAY; return a; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_replace(struct mapping *m,struct svalue *from, struct svalue *to)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data; if(md->size) { add_ref(md); NEW_MAPPING_LOOP(md) { if(is_eq(& k->val, from)) { PREPARE_FOR_DATA_CHANGE(); assign_svalue(& k->val, to);
017b572011-10-28Henrik Grubbström (Grubba)  md->val_types |= 1<<TYPEOF(*to);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  } } free_mapping_data(md); }
06983f1996-09-22Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *mkmapping(struct array *ind, struct array *val)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { struct mapping *m; struct svalue *i,*v; INT32 e;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(ind->size != val->size)
5aad932002-08-15Marcus Comstedt  Pike_fatal("mkmapping on different sized arrays.\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif m=allocate_mapping(MAP_SLOTS(ind->size)); i=ITEM(ind); v=ITEM(val);
a1202e2003-11-09Martin Stjernholm  for(e=0;e<ind->size;e++) low_mapping_insert(m, i++, v++, 2);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return m; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) /* deferred mapping copy! */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *copy_mapping(struct mapping *m)
57a4ab2000-01-27Fredrik Hübinette (Hubbe) { struct mapping *n; #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
54c9eb2016-08-16Arne Goedeke  n=allocate_mapping_no_init();
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  n->data=m->data;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
e945ee2000-02-09Fredrik Hübinette (Hubbe)  n->debug_size=n->data->size; #endif
50ea682003-03-14Henrik Grubbström (Grubba)  add_ref(n->data);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  n->data->valrefs++; n->data->hardlinks++;
765de02000-01-28Henrik Grubbström (Grubba)  debug_malloc_touch(n->data);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  return n; }
8696e62008-07-16Henrik Grubbström (Grubba) /* copy_mapping() for when destructive operations are ok. * * Note: It destructive operations on the resulting mapping *will* * affect eg NEW_MAPPING_LOOP() on the original mapping. */
9e63a72008-06-29Henrik Grubbström (Grubba) static struct mapping *destructive_copy_mapping(struct mapping *m) { if ((m->refs == 1) && !m->data->hardlinks && !(m->data->flags & MAPPING_WEAK)) { /* We may perform destructive operations on the mapping. */ add_ref(m); return m; } return copy_mapping(m); } /* NOTE: May perform destructive operations on either of the arguments * if it has only a single reference. */
4d38092003-11-12Henrik Grubbström (Grubba) static struct mapping *subtract_mappings(struct mapping *a, struct mapping *b) { struct mapping *res; struct keypair *k; struct mapping_data *a_md = a->data; struct mapping_data *b_md = b->data; INT32 e;
6491312003-11-12Henrik Grubbström (Grubba)  ONERROR err;
4d38092003-11-12Henrik Grubbström (Grubba)  /* First some special cases. */ if (!a_md->size || !b_md->size || !a_md->hashsize || !b_md->hashsize) {
9e63a72008-06-29Henrik Grubbström (Grubba)  return destructive_copy_mapping(a);
4d38092003-11-12Henrik Grubbström (Grubba)  } if (a_md == b_md) { return allocate_mapping(0); } /* FIXME: The break-even point should probably be researched. */ if (a_md->size < b_md->size) { /* Add the elements in a that aren't in b. */ res = allocate_mapping(a_md->size);
6491312003-11-12Henrik Grubbström (Grubba)  SET_ONERROR(err, do_free_mapping, res);
4d38092003-11-12Henrik Grubbström (Grubba)  NEW_MAPPING_LOOP(a_md) {
9031422011-04-05Arne Goedeke  size_t h = k->hval & ( b_md->hashsize - 1);
4d38092003-11-12Henrik Grubbström (Grubba)  struct keypair *k2; for (k2 = b_md->hash[h]; k2; k2 = k2->next) { if ((k2->hval == k->hval) && is_eq(&k2->ind, &k->ind)) { break; } } if (!k2) { mapping_insert(res, &k->ind, &k->val); } } } else { /* Remove the elements in a that are in b. */
9e63a72008-06-29Henrik Grubbström (Grubba)  res = destructive_copy_mapping(a);
6491312003-11-12Henrik Grubbström (Grubba)  SET_ONERROR(err, do_free_mapping, res);
4d38092003-11-12Henrik Grubbström (Grubba)  NEW_MAPPING_LOOP(b_md) { map_delete(res, &k->ind); } }
6491312003-11-12Henrik Grubbström (Grubba)  UNSET_ONERROR(err); return res; }
9e63a72008-06-29Henrik Grubbström (Grubba) /* NOTE: May perform destructive operations on either of the arguments * if it has only a single reference. */
6491312003-11-12Henrik Grubbström (Grubba) static struct mapping *and_mappings(struct mapping *a, struct mapping *b) { struct mapping *res; struct keypair *k; struct mapping_data *a_md = a->data; struct mapping_data *b_md = b->data; INT32 e; ONERROR err; /* First some special cases. */ if (!a_md->size || !b_md->size) return allocate_mapping(0);
9e63a72008-06-29Henrik Grubbström (Grubba)  if (a_md == b_md) return destructive_copy_mapping(a);
6491312003-11-12Henrik Grubbström (Grubba)  /* Copy the second mapping. */
8696e62008-07-16Henrik Grubbström (Grubba)  res = copy_mapping(b);
6491312003-11-12Henrik Grubbström (Grubba)  SET_ONERROR(err, do_free_mapping, res); /* Remove elements in res that aren't in a. */ NEW_MAPPING_LOOP(b_md) {
9031422011-04-05Arne Goedeke  size_t h = k->hval & ( a_md->hashsize - 1);
6491312003-11-12Henrik Grubbström (Grubba)  struct keypair *k2; for (k2 = a_md->hash[h]; k2; k2 = k2->next) { if ((k2->hval == k->hval) && is_eq(&k2->ind, &k->ind)) { break; } } if (!k2) { map_delete(res, &k->ind); } } UNSET_ONERROR(err); return res; }
9e63a72008-06-29Henrik Grubbström (Grubba) /* NOTE: May perform destructive operations on either of the arguments * if it has only a single reference. */
6491312003-11-12Henrik Grubbström (Grubba) static struct mapping *or_mappings(struct mapping *a, struct mapping *b) { struct mapping *res; struct keypair *k; struct mapping_data *a_md = a->data; struct mapping_data *b_md = b->data; INT32 e; ONERROR err; /* First some special cases. */
9e63a72008-06-29Henrik Grubbström (Grubba)  if (!a_md->size) return destructive_copy_mapping(b); if (!b_md->size) return destructive_copy_mapping(a); if (a_md == b_md) return destructive_copy_mapping(a);
6491312003-11-12Henrik Grubbström (Grubba) 
8840ea2008-06-28Henrik Grubbström (Grubba)  if (a_md->size <= b_md->size) { /* Copy the second mapping. */
9e63a72008-06-29Henrik Grubbström (Grubba)  res = destructive_copy_mapping(b);
8840ea2008-06-28Henrik Grubbström (Grubba)  SET_ONERROR(err, do_free_mapping, res);
6491312003-11-12Henrik Grubbström (Grubba) 
6c9d312008-06-29Henrik Grubbström (Grubba)  if (!b_md->hashsize) { Pike_fatal("Invalid hashsize.\n"); }
8840ea2008-06-28Henrik Grubbström (Grubba)  /* Add elements in a that aren't in b. */ NEW_MAPPING_LOOP(a_md) {
9031422011-04-05Arne Goedeke  size_t h = k->hval & ( b_md->hashsize - 1);
8840ea2008-06-28Henrik Grubbström (Grubba)  struct keypair *k2; for (k2 = b_md->hash[h]; k2; k2 = k2->next) { if ((k2->hval == k->hval) && is_eq(&k2->ind, &k->ind)) { break; } } if (!k2) { mapping_insert(res, &k->ind, &k->val);
6c9d312008-06-29Henrik Grubbström (Grubba)  b_md = b->data;
6491312003-11-12Henrik Grubbström (Grubba)  } }
8840ea2008-06-28Henrik Grubbström (Grubba)  UNSET_ONERROR(err); } else { /* Copy the first mapping. */
9e63a72008-06-29Henrik Grubbström (Grubba)  res = destructive_copy_mapping(a);
8840ea2008-06-28Henrik Grubbström (Grubba)  SET_ONERROR(err, do_free_mapping, res); /* Add all elements in b. */ NEW_MAPPING_LOOP(b_md) {
6491312003-11-12Henrik Grubbström (Grubba)  mapping_insert(res, &k->ind, &k->val); }
8840ea2008-06-28Henrik Grubbström (Grubba)  UNSET_ONERROR(err);
6491312003-11-12Henrik Grubbström (Grubba)  } return res; }
9e63a72008-06-29Henrik Grubbström (Grubba) /* NOTE: May perform destructive operations on either of the arguments * if it has only a single reference. */
6491312003-11-12Henrik Grubbström (Grubba) static struct mapping *xor_mappings(struct mapping *a, struct mapping *b) { struct mapping *res; struct keypair *k; struct mapping_data *a_md = a->data; struct mapping_data *b_md = b->data; INT32 e; ONERROR err; /* First some special cases. */
9e63a72008-06-29Henrik Grubbström (Grubba)  if (!a_md->size) return destructive_copy_mapping(b); if (!b_md->size) return destructive_copy_mapping(a);
6491312003-11-12Henrik Grubbström (Grubba)  if (a_md == b_md) return allocate_mapping(0); /* Copy the largest mapping. */ if (a_md->size > b_md->size) { struct mapping *tmp = a; a = b; b = tmp; a_md = b_md; b_md = b->data;
13670c2015-05-25Martin Nilsson  }
9e63a72008-06-29Henrik Grubbström (Grubba)  res = destructive_copy_mapping(b);
6491312003-11-12Henrik Grubbström (Grubba)  SET_ONERROR(err, do_free_mapping, res); /* Add elements in a that aren't in b, and remove those that are. */ NEW_MAPPING_LOOP(a_md) {
9031422011-04-05Arne Goedeke  size_t h = k->hval & ( b_md->hashsize - 1);
6491312003-11-12Henrik Grubbström (Grubba)  struct keypair *k2; for (k2 = b_md->hash[h]; k2; k2 = k2->next) { if ((k2->hval == k->hval) && is_eq(&k2->ind, &k->ind)) { break; } } if (!k2) { mapping_insert(res, &k->ind, &k->val); } else { map_delete(res, &k2->ind); }
6c9d312008-06-29Henrik Grubbström (Grubba)  b_md = b->data;
6491312003-11-12Henrik Grubbström (Grubba)  } UNSET_ONERROR(err);
4d38092003-11-12Henrik Grubbström (Grubba)  return res; }
9e63a72008-06-29Henrik Grubbström (Grubba) /* NOTE: May perform destructive operations on either of the arguments * if it has only a single reference. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op)
515b6c1996-06-09Fredrik Hübinette (Hubbe) {
a5cd6a2001-09-24Henrik Grubbström (Grubba)  ONERROR r1,r2,r3,r4;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct array *ai, *av; struct array *bi, *bv; struct array *ci, *cv;
5267b71995-08-09Fredrik Hübinette (Hubbe)  INT32 *zipper;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct mapping *m;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(a->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(b->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
6491312003-11-12Henrik Grubbström (Grubba)  switch (op) { case PIKE_ARRAY_OP_SUB:
4d38092003-11-12Henrik Grubbström (Grubba)  return subtract_mappings(a, b);
6491312003-11-12Henrik Grubbström (Grubba)  case PIKE_ARRAY_OP_AND: return and_mappings(a, b); case PIKE_ARRAY_OP_OR: return or_mappings(a, b); case PIKE_ARRAY_OP_XOR: return xor_mappings(a, b);
4d38092003-11-12Henrik Grubbström (Grubba)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  ai=mapping_indices(a);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r1,do_free_array,ai);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  av=mapping_values(a);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r2,do_free_array,av);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(ai->size > 1) { zipper=get_set_order(ai); order_array(ai, zipper); order_array(av, zipper);
0ec7522014-04-27Martin Nilsson  free(zipper);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  bi=mapping_indices(b);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r3,do_free_array,bi);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  bv=mapping_values(b);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r4,do_free_array,bv);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(bi->size > 1) { zipper=get_set_order(bi); order_array(bi, zipper); order_array(bv, zipper);
0ec7522014-04-27Martin Nilsson  free(zipper);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  zipper=merge(ai,bi,op);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  ci=array_zip(ai,bi,zipper);
49398c2000-11-08Fredrik Hübinette (Hubbe)  UNSET_ONERROR(r4); free_array(bi); UNSET_ONERROR(r3); free_array(ai);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  cv=array_zip(av,bv,zipper);
49398c2000-11-08Fredrik Hübinette (Hubbe)  UNSET_ONERROR(r2); free_array(bv); UNSET_ONERROR(r1); free_array(av);
0ec7522014-04-27Martin Nilsson  free(zipper);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  m=mkmapping(ci, cv); free_array(ci); free_array(cv); return m;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
6491312003-11-12Henrik Grubbström (Grubba) /* FIXME: What are the semantics for this function? * FIXME: It ought to be optimized just like the unordered variant. * /grubba 2003-11-12 */
13670c2015-05-25Martin Nilsson PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a,
2ad6b72000-01-29Mirar (Pontus Hagland)  struct array *b, INT32 op) {
49398c2000-11-08Fredrik Hübinette (Hubbe)  ONERROR r1,r2;
2ad6b72000-01-29Mirar (Pontus Hagland)  struct array *ai, *av;
37b8782000-11-02Henrik Grubbström (Grubba)  struct array *ci = NULL, *cv = NULL; INT32 *zipper = NULL;
2ad6b72000-01-29Mirar (Pontus Hagland)  struct mapping *m; ai=mapping_indices(a);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r1,do_free_array,ai);
2ad6b72000-01-29Mirar (Pontus Hagland)  av=mapping_values(a);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r2,do_free_array,av);
2ad6b72000-01-29Mirar (Pontus Hagland)  if(ai->size > 1) { zipper=get_set_order(ai); order_array(ai, zipper); order_array(av, zipper);
0ec7522014-04-27Martin Nilsson  free(zipper);
2ad6b72000-01-29Mirar (Pontus Hagland)  } switch (op) /* no elements from »b» may be selected */ { case PIKE_ARRAY_OP_AND: zipper=merge(b,ai,op); ci=array_zip(b,ai,zipper); /* b must not be used */ cv=array_zip(b,av,zipper); /* b must not be used */ break; case PIKE_ARRAY_OP_SUB: zipper=merge(ai,b,op); ci=array_zip(ai,b,zipper); /* b must not be used */ cv=array_zip(av,b,zipper); /* b must not be used */ break; default:
5aad932002-08-15Marcus Comstedt  Pike_fatal("merge_mapping_array on other than AND or SUB\n");
2ad6b72000-01-29Mirar (Pontus Hagland)  }
49398c2000-11-08Fredrik Hübinette (Hubbe)  UNSET_ONERROR(r2); free_array(av); UNSET_ONERROR(r1); free_array(ai);
13670c2015-05-25Martin Nilsson 
0ec7522014-04-27Martin Nilsson  free(zipper);
2ad6b72000-01-29Mirar (Pontus Hagland)  m=mkmapping(ci, cv); free_array(ci); free_array(cv); return m; }
13670c2015-05-25Martin Nilsson PMOD_EXPORT struct mapping *merge_mapping_array_unordered(struct mapping *a,
2ad6b72000-01-29Mirar (Pontus Hagland)  struct array *b, INT32 op) {
49398c2000-11-08Fredrik Hübinette (Hubbe)  ONERROR r1;
2ad6b72000-01-29Mirar (Pontus Hagland)  struct array *b_temp; INT32 *zipper; struct mapping *m; if (b->size>1) { zipper=get_set_order(b); b_temp=reorder_and_copy_array(b,zipper);
f43d4d2003-06-02Martin Stjernholm  free (zipper);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r1,do_free_array,b_temp);
2ad6b72000-01-29Mirar (Pontus Hagland)  m=merge_mapping_array_ordered(a,b_temp,op);
49398c2000-11-08Fredrik Hübinette (Hubbe)  UNSET_ONERROR(r1); free_array(b_temp);
2ad6b72000-01-29Mirar (Pontus Hagland)  } else m=merge_mapping_array_ordered(a,b,op); return m; }
e3832f2014-10-02Per Hedbor void o_append_mapping( INT32 args ) { struct svalue *lval = Pike_sp - args; struct svalue *val = lval + 2;
8194802015-02-08Henrik Grubbström (Grubba)  int lvalue_type;
e3832f2014-10-02Per Hedbor #ifdef PIKE_DEBUG if (args < 3) { Pike_fatal("Too few arguments to o_append_mapping(): %d\n", args); } #endif args -= 3; /* Note: val should always be a zero here! */
8194802015-02-08Henrik Grubbström (Grubba)  lvalue_type = lvalue_to_svalue_no_free(val, lval);
e3832f2014-10-02Per Hedbor 
8194802015-02-08Henrik Grubbström (Grubba)  if ((TYPEOF(*val) == T_MAPPING) && (lvalue_type != PIKE_T_GET_SET)) {
e3832f2014-10-02Per Hedbor  struct mapping *m = val->u.mapping; if( m->refs == 2 ) {
55d9c92015-03-25Henrik Grubbström (Grubba)  if ((TYPEOF(*lval) == T_OBJECT) && lval->u.object->prog && ((FIND_LFUN(lval->u.object->prog, LFUN_ASSIGN_INDEX) >= 0) || (FIND_LFUN(lval->u.object->prog, LFUN_ASSIGN_ARROW) >= 0))) { /* There's a function controlling assignments in this object, * so we can't alter the mapping in place. */ } else { int i; /* fprintf( stderr, "map_refs==2\n" ); */ for( i=0; i<args; i+=2 ) low_mapping_insert( m, Pike_sp-(i+2), Pike_sp-(i+1), 2 ); stack_pop_n_elems_keep_top(2+args); return; }
e3832f2014-10-02Per Hedbor  } } f_aggregate_mapping(args); f_add(2); assign_lvalue(lval, val); stack_pop_2_elems_keep_top(); }
9e63a72008-06-29Henrik Grubbström (Grubba) /* NOTE: May perform destructive operations on either of the arguments * if it has only a single reference. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *add_mappings(struct svalue *argp, INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
5cd1511998-04-27Fredrik Hübinette (Hubbe)  INT32 e,d;
59791f2000-09-08Fredrik Hübinette (Hubbe)  struct mapping *ret=0;
5cd1511998-04-27Fredrik Hübinette (Hubbe)  struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  for(e=d=0;d<args;d++) {
aa95de2008-06-24Henrik Grubbström (Grubba)  struct mapping *m = argp[d].u.mapping;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
aa95de2008-06-24Henrik Grubbström (Grubba)  if(d_flag>1) check_mapping(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
aa95de2008-06-24Henrik Grubbström (Grubba)  e += m->data->size;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  }
c193a62000-09-07Fredrik Hübinette (Hubbe)  if(!e) return allocate_mapping(0); d=0;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
c193a62000-09-07Fredrik Hübinette (Hubbe)  for(;d<args;d++)
50d1d62000-04-30Fredrik Hübinette (Hubbe)  {
c193a62000-09-07Fredrik Hübinette (Hubbe)  struct mapping *m=argp[d].u.mapping; struct mapping_data *md=m->data; if(md->size == 0) continue;
0b5d2b2001-06-05Martin Stjernholm  if(!(md->flags & MAPPING_WEAK))
59791f2000-09-08Fredrik Hübinette (Hubbe)  {
c193a62000-09-07Fredrik Hübinette (Hubbe) #if 1 /* major optimization */
ab59f42001-11-25Martin Stjernholm  if(e==md->size) return copy_mapping(m);
c193a62000-09-07Fredrik Hübinette (Hubbe) #endif
13670c2015-05-25Martin Nilsson 
59791f2000-09-08Fredrik Hübinette (Hubbe)  if(m->refs == 1 && !md->hardlinks) { add_ref( ret=m ); d++; break; }
c193a62000-09-07Fredrik Hübinette (Hubbe)  }
59791f2000-09-08Fredrik Hübinette (Hubbe)  ret=allocate_mapping(MAP_SLOTS(e)); break;
c193a62000-09-07Fredrik Hübinette (Hubbe) 
59791f2000-09-08Fredrik Hübinette (Hubbe)  }
c193a62000-09-07Fredrik Hübinette (Hubbe) 
59791f2000-09-08Fredrik Hübinette (Hubbe)  for(;d<args;d++) { struct mapping *m=argp[d].u.mapping; struct mapping_data *md=m->data;
13670c2015-05-25Martin Nilsson 
59791f2000-09-08Fredrik Hübinette (Hubbe)  add_ref(md); NEW_MAPPING_LOOP(md)
a1202e2003-11-09Martin Stjernholm  low_mapping_insert(ret, &k->ind, &k->val, 2);
59791f2000-09-08Fredrik Hübinette (Hubbe)  free_mapping_data(md);
50d1d62000-04-30Fredrik Hübinette (Hubbe)  }
59791f2000-09-08Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(!ret)
5aad932002-08-15Marcus Comstedt  Pike_fatal("add_mappings is confused!\n");
59791f2000-09-08Fredrik Hübinette (Hubbe) #endif return ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT int mapping_equal_p(struct mapping *a, struct mapping *b, struct processing *p)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct processing curr; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md; INT32 e,eq=1; #ifdef PIKE_DEBUG if(a->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(b->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(a==b) return 1;
5eca4d2000-09-04Martin Stjernholm 
a0d7f32003-08-20Henrik Grubbström (Grubba)  if (a->data == b->data) return 1;
14b9132008-06-25Henrik Grubbström (Grubba)  /* If either is weak, they're different. */ if ((a->data->flags | b->data->flags) & MAPPING_WEAK) return 0;
a0d7f32003-08-20Henrik Grubbström (Grubba) 
5eca4d2000-09-04Martin Stjernholm  check_mapping_for_destruct(a); check_mapping_for_destruct(b);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m_sizeof(a) != m_sizeof(b)) return 0;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
80ce5e2016-10-28Arne Goedeke  if (m_sizeof(a) == 0) return 1;
a2bcc72012-11-15Arne Goedeke  if (!check_type_overlaps(a->data->ind_types, b->data->ind_types) || !check_type_overlaps(a->data->val_types, b->data->val_types)) return 0;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  curr.pointer_a = a; curr.pointer_b = b; curr.next = p; for( ;p ;p=p->next) if(p->pointer_a == (void *)a && p->pointer_b == (void *)b) return 1;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=a->data; md->valrefs++; add_ref(md); NEW_MAPPING_LOOP(md)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { struct svalue *s;
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  if((s=low_mapping_lookup(b, & k->ind)))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!low_is_equal(s, &k->val, &curr)) { eq=0; break; }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }else{
4112122001-09-04Fredrik Hübinette (Hubbe)  INT32 d; struct mapping_data *bmd = b->data; struct keypair *kp; /* This is neither pretty nor fast, but it should * perform a bit more like expected... -Hubbe */ bmd->valrefs++; add_ref(bmd);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  eq=0;
4112122001-09-04Fredrik Hübinette (Hubbe)  for(d=0;d<(bmd)->hashsize;d++) { for(kp=bmd->hash[d];kp;kp=kp->next) { if(low_is_equal(&k->ind, &kp->ind, &curr) && low_is_equal(&k->val, &kp->val, &curr)) { eq=1; break; } } } bmd->valrefs--; free_mapping_data(bmd); if(!eq) break;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->valrefs--; free_mapping_data(md); return eq;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
e0cd662016-12-28Arne Goedeke void describe_mapping(struct byte_buffer *b, struct mapping *m,struct processing *p,int indent)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct processing doing;
674fae2000-01-14Fredrik Noring  struct array *a; JMP_BUF catch; ONERROR err; INT32 e,d;
5267b71995-08-09Fredrik Hübinette (Hubbe)  char buf[40];
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif if(! m->data->size)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, "([ ])");
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } doing.next=p; doing.pointer_a=(void *)m; for(e=0;p;e++,p=p->next) { if(p->pointer_a == (void *)m) {
f90e541995-08-17Fredrik Hübinette (Hubbe)  sprintf(buf,"@%ld",(long)e);
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, buf);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } }
d1cac52000-09-07Henrik Grubbström (Grubba) 
d786622007-03-09Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE) {
5f45a72001-12-16Martin Stjernholm  /* Have to do without any temporary allocations. */ struct keypair *k; int notfirst = 0; if (m->data->size == 1) {
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, "([ /* 1 element */\n");
5f45a72001-12-16Martin Stjernholm  } else { sprintf(buf, "([ /* %ld elements */\n", (long)m->data->size);
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, buf);
5f45a72001-12-16Martin Stjernholm  } NEW_MAPPING_LOOP(m->data) {
e0cd662016-12-28Arne Goedeke  if (notfirst) buffer_add_str(b, ",\n");
5f45a72001-12-16Martin Stjernholm  else notfirst = 1; for(d = 0; d < indent; d++)
e0cd662016-12-28Arne Goedeke  buffer_add_char(b, ' '); describe_svalue(b, &k->ind, indent+2, &doing); buffer_add_str (b, ": "); describe_svalue(b, &k->val, indent+2, &doing);
5f45a72001-12-16Martin Stjernholm  }
e0cd662016-12-28Arne Goedeke  buffer_add_char(b, '\n'); for(e=2; e<indent; e++) buffer_add_char(b, ' '); buffer_add_str(b, "])");
5f45a72001-12-16Martin Stjernholm  return; }
674fae2000-01-14Fredrik Noring  a = mapping_indices(m); SET_ONERROR(err, do_free_array, a);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
853b832000-12-14Martin Stjernholm  if(! m->data->size) { /* mapping_indices may remove elements */
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, "([ ])");
853b832000-12-14Martin Stjernholm  } else {
97ebb32003-01-09Henrik Grubbström (Grubba)  int save_t_flag = Pike_interpreter.trace_level;
f7b1eb2001-02-08Martin Stjernholm 
853b832000-12-14Martin Stjernholm  if (m->data->size == 1) {
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, "([ /* 1 element */\n");
853b832000-12-14Martin Stjernholm  } else { sprintf(buf, "([ /* %ld elements */\n", (long)m->data->size);
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, buf);
853b832000-12-14Martin Stjernholm  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
97ebb32003-01-09Henrik Grubbström (Grubba)  Pike_interpreter.trace_level = 0;
c1b8f02001-07-02Martin Stjernholm  if(SETJMP(catch)) { free_svalue(&throw_value);
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&throw_value);
c1b8f02001-07-02Martin Stjernholm  } else
853b832000-12-14Martin Stjernholm  sort_array_destructively(a); UNSETJMP(catch);
97ebb32003-01-09Henrik Grubbström (Grubba)  Pike_interpreter.trace_level = save_t_flag;
853b832000-12-14Martin Stjernholm  for(e = 0; e < a->size; e++) { struct svalue *tmp; if(e)
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, ",\n");
13670c2015-05-25Martin Nilsson 
853b832000-12-14Martin Stjernholm  for(d = 0; d < indent; d++)
e0cd662016-12-28Arne Goedeke  buffer_add_char(b, ' ');
8f6a982009-09-22Henrik Grubbström (Grubba) 
e0cd662016-12-28Arne Goedeke  describe_svalue(b, ITEM(a)+e, indent+2, &doing); buffer_add_str (b, ": ");
fe35fe2003-09-23Martin Stjernholm 
ab1b1e2001-01-17Fredrik Hübinette (Hubbe)  {
97ebb32003-01-09Henrik Grubbström (Grubba)  int save_t_flag=Pike_interpreter.trace_level; Pike_interpreter.trace_level=0;
13670c2015-05-25Martin Nilsson 
ab1b1e2001-01-17Fredrik Hübinette (Hubbe)  tmp=low_mapping_lookup(m, ITEM(a)+e);
13670c2015-05-25Martin Nilsson 
97ebb32003-01-09Henrik Grubbström (Grubba)  Pike_interpreter.trace_level=save_t_flag;
ab1b1e2001-01-17Fredrik Hübinette (Hubbe)  } if(tmp)
e0cd662016-12-28Arne Goedeke  describe_svalue(b, tmp, indent+2, &doing);
853b832000-12-14Martin Stjernholm  else
e0cd662016-12-28Arne Goedeke  buffer_add_str(b, "** gone **");
853b832000-12-14Martin Stjernholm  }
e0cd662016-12-28Arne Goedeke  buffer_add_char(b, '\n'); for(e=2; e<indent; e++) buffer_add_char(b, ' '); buffer_add_str(b, "])");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
674fae2000-01-14Fredrik Noring  UNSET_ONERROR(err); free_array(a);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
765de02000-01-28Henrik Grubbström (Grubba) node *make_node_from_mapping(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  mapping_fix_type_field(m);
84387d2001-09-24Fredrik Hübinette (Hubbe)  if(!mapping_is_constant(m,0))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct array *ind, *val; node *n; ind=mapping_indices(m);
69d94d1997-04-23Fredrik Hübinette (Hubbe)  val=mapping_values(m);
3c04e81997-03-13Fredrik Hübinette (Hubbe)  n=mkefuncallnode("mkmapping", mknode(F_ARG_LIST, make_node_from_array(ind), make_node_from_array(val)));
515b6c1996-06-09Fredrik Hübinette (Hubbe)  free_array(ind); free_array(val); return n; }else{
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct svalue s;
3c04e81997-03-13Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!m->data->size)
3c04e81997-03-13Fredrik Hübinette (Hubbe)  return mkefuncallnode("aggregate_mapping",0);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(s, T_MAPPING, 0, mapping, m);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return mkconstantsvaluenode(&s); } }
ce4d672001-01-31Henrik Grubbström (Grubba) /*! @decl mapping aggregate_mapping(mixed ... elems) *! *! Construct a mapping. *! *! Groups the arguments together two and two in key-index pairs and
c9e8202001-04-14Johan Sundström  *! creates a mapping of those pairs. Generally, the mapping literal
f79bd82003-04-01Martin Nilsson  *! syntax is handier: @expr{([ key1:val1, key2:val2, ... ])@}
ce4d672001-01-31Henrik Grubbström (Grubba)  *! *! @seealso *! @[sizeof()], @[mappingp()], @[mkmapping()] */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_aggregate_mapping(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) { INT32 e; struct mapping *m; if(args & 1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Uneven number of arguments to aggregate_mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  m=allocate_mapping(MAP_SLOTS(args / 2));
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e3b4c72004-07-02Henrik Grubbström (Grubba)  for(e=-args;e<0;e+=2) { STACK_LEVEL_START(-e); low_mapping_insert(m, Pike_sp+e, Pike_sp+e+1, 2); STACK_LEVEL_DONE(-e); }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(d_flag) check_mapping(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  push_mapping(m);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *copy_mapping_recursively(struct mapping *m,
9cc28d2004-05-28Henrik Grubbström (Grubba)  struct mapping *p)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
65dc532010-07-11Martin Stjernholm  int not_complex;
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *ret;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md; #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
20b19f2000-02-09Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
9e398c2000-02-08Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m);
20b19f2000-02-09Fredrik Hübinette (Hubbe) #endif
65dc532010-07-11Martin Stjernholm  if((m->data->val_types | m->data->ind_types) & BIT_COMPLEX) { not_complex = 0; ret=allocate_mapping(MAP_SLOTS(m->data->size)); } else { not_complex = 1; ret = copy_mapping(m); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
0f5a822010-07-11Jonas Wallden  if (p) {
65dc532010-07-11Martin Stjernholm  struct svalue aa, bb;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(aa, T_MAPPING, 0, mapping, m); SET_SVAL(bb, T_MAPPING, 0, mapping, ret);
0f5a822010-07-11Jonas Wallden  mapping_insert(p, &aa, &bb); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
65dc532010-07-11Martin Stjernholm  if (not_complex) return ret;
a12df92000-09-17Henrik Grubbström (Grubba)  ret->data->flags = m->data->flags;
f152401996-06-21Fredrik Hübinette (Hubbe)  check_stack(2);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data; md->valrefs++; add_ref(md);
c193a62000-09-07Fredrik Hübinette (Hubbe)  NEW_MAPPING_LOOP(md)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
e3b4c72004-07-02Henrik Grubbström (Grubba)  /* Place holders. * * NOTE: copy_svalues_recursively_no_free() may store stuff in * the destination svalue, and then call stuff that uses * the stack (eg itself). */ push_int(0); push_int(0); copy_svalues_recursively_no_free(Pike_sp-2,&k->ind, 1, p); copy_svalues_recursively_no_free(Pike_sp-1,&k->val, 1, p);
13670c2015-05-25Martin Nilsson 
a1202e2003-11-09Martin Stjernholm  low_mapping_insert(ret, Pike_sp-2, Pike_sp-1, 2);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  pop_n_elems(2); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->valrefs--; free_mapping_data(md);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_search_no_free(struct svalue *to,
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *m,
466b662008-01-05Martin Nilsson  const struct svalue *look_for, const struct svalue *key /* start */)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md, *omd; #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif md=m->data;
9001b42000-01-27Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size) {
a563932016-06-24Per Hedbor  size_t h2,h=0;
9001b42000-01-27Fredrik Hübinette (Hubbe)  struct keypair *k=md->hash[0], **prev;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
9001b42000-01-27Fredrik Hübinette (Hubbe)  if(key)
9076fa1997-02-17Fredrik Hübinette (Hubbe)  {
9001b42000-01-27Fredrik Hübinette (Hubbe)  h2=hash_svalue(key);
13670c2015-05-25Martin Nilsson 
9001b42000-01-27Fredrik Hübinette (Hubbe)  FIND();
13670c2015-05-25Martin Nilsson 
9001b42000-01-27Fredrik Hübinette (Hubbe)  if(!k)
9076fa1997-02-17Fredrik Hübinette (Hubbe)  {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, NUMBER_UNDEFINED, integer, 0);
9001b42000-01-27Fredrik Hübinette (Hubbe)  return; }
a11c9f2000-02-05Fredrik Hübinette (Hubbe)  k=k->next;
9001b42000-01-27Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson 
9001b42000-01-27Fredrik Hübinette (Hubbe)  md=m->data; if(md->size) { md->valrefs++; add_ref(md);
13670c2015-05-25Martin Nilsson 
9001b42000-01-27Fredrik Hübinette (Hubbe)  if(h < (unsigned INT32)md->hashsize) { while(1)
9076fa1997-02-17Fredrik Hübinette (Hubbe)  {
9001b42000-01-27Fredrik Hübinette (Hubbe)  while(k) { if(is_eq(look_for, &k->val)) { assign_svalue_no_free(to,&k->ind);
13670c2015-05-25Martin Nilsson 
9001b42000-01-27Fredrik Hübinette (Hubbe)  md->valrefs--; free_mapping_data(md); return; } k=k->next; } h++; if(h>= (unsigned INT32)md->hashsize) break; k=md->hash[h];
9076fa1997-02-17Fredrik Hübinette (Hubbe)  } }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson 
9001b42000-01-27Fredrik Hübinette (Hubbe)  md->valrefs--; free_mapping_data(md);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, NUMBER_UNDEFINED, integer, 0);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe) 
466b662008-01-05Martin Nilsson void check_mapping(const struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
e2d5221998-05-16Fredrik Hübinette (Hubbe)  int e,num; struct keypair *k;
466b662008-01-05Martin Nilsson  const struct mapping_data *md;
c5ae922000-04-16Fredrik Hübinette (Hubbe)  static int in_check_mapping; if(in_check_mapping) return; in_check_mapping=1;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data;
e2d5221998-05-16Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(m->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping has zero refs.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!m->data)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping has no data block.\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
765de02000-01-28Henrik Grubbström (Grubba)  if (!m->data->refs)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping data block has zero refs.\n");
765de02000-01-28Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(m->next && m->next->prev != m)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping ->next->prev != mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
20b19f2000-02-09Fredrik Hübinette (Hubbe)  if(m->debug_size != md->size)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  {
d9ad012000-04-16Fredrik Hübinette (Hubbe)  if(Pike_in_gc) {
3a5f8e2010-02-21Stephen R. van den Berg  fprintf(stderr,"Pike was in GC stage %d when this fatal occurred:\n",Pike_in_gc);
d9ad012000-04-16Fredrik Hübinette (Hubbe)  Pike_in_gc=0; }
13670c2015-05-25Martin Nilsson 
c5ae922000-04-16Fredrik Hübinette (Hubbe)  fprintf(stderr,"--MAPPING ZAPPING (%d!=%d), mapping:\n",m->debug_size,md->size);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe(m);
c5ae922000-04-16Fredrik Hübinette (Hubbe)  fprintf(stderr,"--MAPPING ZAPPING (%d!=%d), mapping data:\n",m->debug_size,md->size);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe(md);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping zapping detected (%d != %d)!\n",m->debug_size,md->size);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
5eca4d2000-09-04Martin Stjernholm #endif
9e398c2000-02-08Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(m->prev) { if(m->prev->next != m)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping ->prev->next != mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ if(first_mapping != m)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping ->prev == 0 but first_mapping != mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->valrefs <0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("md->valrefs < 0\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->hardlinks <0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("md->valrefs < 0\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->refs < md->valrefs+1)
5aad932002-08-15Marcus Comstedt  Pike_fatal("md->refs < md->valrefs+1\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->valrefs < md->hardlinks)
5aad932002-08-15Marcus Comstedt  Pike_fatal("md->refs < md->valrefs+1\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->hashsize < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Assert: I don't think he's going to make it Jim.\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Core breach, evacuate ship!\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->num_keypairs < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Starboard necell on fire!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size > md->num_keypairs)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Pretty mean hashtable there buster!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
1fbbfd2011-09-04Henrik Grubbström (Grubba)  if(md->hashsize & (md->hashsize - 1)) Pike_fatal("Invalid hashtable size: 0x%08lx\n", (long)md->hashsize);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->hashsize > md->num_keypairs)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Pretty mean hashtable there buster %d > %d (2)!\n",md->hashsize,md->num_keypairs);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
4fe8a52016-10-25Henrik Grubbström (Grubba)  if(md->num_keypairs > (md->hashsize + AVG_LINK_LENGTH - 1) * AVG_LINK_LENGTH)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping from hell detected, attempting to send it back...\n");
13670c2015-05-25Martin Nilsson 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size > 0 && (!md->ind_types || !md->val_types))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping type fields are... wrong.\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
e2d5221998-05-16Fredrik Hübinette (Hubbe)  num=0;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  NEW_MAPPING_LOOP(md)
e2d5221998-05-16Fredrik Hübinette (Hubbe)  { num++;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(k->ind) > MAX_TYPE)
8696e62008-07-16Henrik Grubbström (Grubba)  Pike_fatal("Invalid maping keypair index type: %s\n",
017b572011-10-28Henrik Grubbström (Grubba)  get_name_of_type(TYPEOF(k->ind))); if(! ( (1 << TYPEOF(k->ind)) & (md->ind_types) ))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping indices type field lies.\n");
e2d5221998-05-16Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(k->val) > MAX_TYPE)
8696e62008-07-16Henrik Grubbström (Grubba)  Pike_fatal("Invalid mapping keypair value type: %s\n",
017b572011-10-28Henrik Grubbström (Grubba)  get_name_of_type(TYPEOF(k->val))); if(! ( (1 << TYPEOF(k->val)) & (md->val_types) ))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping values type field lies.\n");
59edba1998-08-05Fredrik Hübinette (Hubbe) 
0e46fc1998-08-05Fredrik Hübinette (Hubbe)  check_svalue(& k->ind); check_svalue(& k->val);
e2d5221998-05-16Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size != num)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Shields are failing, hull integrity down to 20%%\n");
c5ae922000-04-16Fredrik Hübinette (Hubbe)  in_check_mapping=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) void check_all_mappings(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct mapping *m; for(m=first_mapping;m;m=m->next)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  check_mapping(m); } #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5e83442008-05-11Martin Stjernholm static void visit_mapping_data (struct mapping_data *md, int action,
d056542014-06-17Henrik Grubbström (Grubba)  void *extra)
5e83442008-05-11Martin Stjernholm {
c42e092014-06-18Henrik Grubbström (Grubba)  visit_enter(md, T_MAPPING_DATA, extra);
8775df2015-06-04Martin Karlgren  switch (action & VISIT_MODE_MASK) {
5e83442008-05-11Martin Stjernholm #ifdef PIKE_DEBUG default: Pike_fatal ("Unknown visit action %d.\n", action); case VISIT_NORMAL: case VISIT_COMPLEX_ONLY: break; #endif case VISIT_COUNT_BYTES: mc_counted_bytes += MAPPING_DATA_SIZE (md->hashsize, md->num_keypairs); break; }
8775df2015-06-04Martin Karlgren  if (!(action & VISIT_NO_REFS) && (md->ind_types | md->val_types) &
5e83442008-05-11Martin Stjernholm  (action & VISIT_COMPLEX_ONLY ? BIT_COMPLEX : BIT_REF_TYPES)) { int ind_ref_type = md->flags & MAPPING_WEAK_INDICES ? REF_TYPE_WEAK : REF_TYPE_NORMAL; int val_ref_type = md->flags & MAPPING_WEAK_VALUES ? REF_TYPE_WEAK : REF_TYPE_NORMAL; INT32 e; struct keypair *k; NEW_MAPPING_LOOP (md) {
7c36d52014-06-17Henrik Grubbström (Grubba)  visit_svalue (&k->ind, ind_ref_type, extra); visit_svalue (&k->val, val_ref_type, extra);
5e83442008-05-11Martin Stjernholm  } }
c42e092014-06-18Henrik Grubbström (Grubba)  visit_leave(md, T_MAPPING_DATA, extra);
5e83442008-05-11Martin Stjernholm }
d056542014-06-17Henrik Grubbström (Grubba) PMOD_EXPORT void visit_mapping (struct mapping *m, int action, void *extra)
5e83442008-05-11Martin Stjernholm {
c42e092014-06-18Henrik Grubbström (Grubba)  visit_enter(m, T_MAPPING, extra);
8775df2015-06-04Martin Karlgren  switch (action & VISIT_MODE_MASK) {
5e83442008-05-11Martin Stjernholm #ifdef PIKE_DEBUG default: Pike_fatal ("Unknown visit action %d.\n", action); case VISIT_NORMAL: case VISIT_COMPLEX_ONLY: break; #endif case VISIT_COUNT_BYTES: mc_counted_bytes += sizeof (struct mapping); break; } visit_ref (m->data, REF_TYPE_INTERNAL,
d056542014-06-17Henrik Grubbström (Grubba)  (visit_thing_fn *) &visit_mapping_data, extra);
c42e092014-06-18Henrik Grubbström (Grubba)  visit_leave(m, T_MAPPING, extra);
5e83442008-05-11Martin Stjernholm }
853b832000-12-14Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG #define DO_IF_MAPPING_SIZE_DEBUG(x) x #else #define DO_IF_MAPPING_SIZE_DEBUG(x) #endif
e1a35e2003-09-08Martin Stjernholm #define GC_RECURSE_MD_IN_USE(MD, RECURSE_FN, IND_TYPES, VAL_TYPES) do { \
853b832000-12-14Martin Stjernholm  INT32 e; \ struct keypair *k; \
c1089d2001-12-02Martin Stjernholm  IND_TYPES = MD->ind_types; \ NEW_MAPPING_LOOP(MD) { \ if (!IS_DESTRUCTED(&k->ind) && RECURSE_FN(&k->ind, 1)) { \
e1a35e2003-09-08Martin Stjernholm  DO_IF_DEBUG(Pike_fatal("Didn't expect an svalue zapping now.\n")); \
853b832000-12-14Martin Stjernholm  } \
c1089d2001-12-02Martin Stjernholm  RECURSE_FN(&k->val, 1); \
017b572011-10-28Henrik Grubbström (Grubba)  VAL_TYPES |= 1 << TYPEOF(k->val); \
853b832000-12-14Martin Stjernholm  } \ } while (0)
d4741b2007-10-04Henrik Grubbström (Grubba) #ifdef PIKE_MAPPING_KEYPAIR_LOOP
5e83442008-05-11Martin Stjernholm #error Broken code below!
d4741b2007-10-04Henrik Grubbström (Grubba) #define GC_RECURSE(M, MD, REC_KEYPAIR, TYPE, IND_TYPES, VAL_TYPES) do { \ int remove; \ struct keypair *k,**prev_; \ /* no locking required (no is_eq) */ \ for(k = MD_KEYPAIRS(md, md->hashsize);k < MD->free_list;) \ { \ REC_KEYPAIR(remove, \ PIKE_CONCAT(TYPE, _svalues), \ PIKE_CONCAT(TYPE, _weak_svalues), \ PIKE_CONCAT(TYPE, _without_recurse), \ PIKE_CONCAT(TYPE, _weak_without_recurse)); \ if (remove) { \ /* Find and unlink k. */ \ unsigned INT32 h_; \
9031422011-04-05Arne Goedeke  h_ = k->hval & ( md->hashsize - 1); \
d4741b2007-10-04Henrik Grubbström (Grubba)  prev_ = md->hash + h_; \ DO_IF_DEBUG( \ if (!*prev_) { \ Pike_fatal("Node to unlink not found!\n"); \ } \ ); \ while (*prev_ != k) { \ prev_ = &((*prev_)->next); \ DO_IF_DEBUG( \ if (!*prev_) { \ Pike_fatal("Node to unlink not found!\n"); \ } \ ); \ } \ (*prev_)->next = k->next; \ FREE_KEYPAIR(MD, k); \
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&MD->free_list->ind); \ mark_free_svalue (&MD->free_list->val); \
d4741b2007-10-04Henrik Grubbström (Grubba)  MD->size--; \ DO_IF_MAPPING_SIZE_DEBUG( \ if(M->data ==MD) \ M->debug_size--; \ ); \ } else { \
017b572011-10-28Henrik Grubbström (Grubba)  VAL_TYPES |= 1 << TYPEOF(k->val); \ IND_TYPES |= 1 << TYPEOF(k->ind); \
d4741b2007-10-04Henrik Grubbström (Grubba)  k++; \ } \ } \ } while (0) #else /* !PIKE_MAPPING_KEYPAIR_LOOP */
e1a35e2003-09-08Martin Stjernholm #define GC_RECURSE(M, MD, REC_KEYPAIR, TYPE, IND_TYPES, VAL_TYPES) do { \
853b832000-12-14Martin Stjernholm  INT32 e; \
0b5d2b2001-06-05Martin Stjernholm  int remove; \
853b832000-12-14Martin Stjernholm  struct keypair *k,**prev; \ /* no locking required (no is_eq) */ \
0b5d2b2001-06-05Martin Stjernholm  for(e=0;e<MD->hashsize;e++) \
853b832000-12-14Martin Stjernholm  { \
0b5d2b2001-06-05Martin Stjernholm  for(prev= MD->hash + e;(k=*prev);) \
853b832000-12-14Martin Stjernholm  { \
0b5d2b2001-06-05Martin Stjernholm  REC_KEYPAIR(remove, \ PIKE_CONCAT(TYPE, _svalues), \ PIKE_CONCAT(TYPE, _weak_svalues), \ PIKE_CONCAT(TYPE, _without_recurse), \ PIKE_CONCAT(TYPE, _weak_without_recurse)); \ if (remove) \
853b832000-12-14Martin Stjernholm  { \ *prev=k->next; \
0b5d2b2001-06-05Martin Stjernholm  FREE_KEYPAIR(MD, k); \
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&MD->free_list->ind); \ mark_free_svalue (&MD->free_list->val); \
0b5d2b2001-06-05Martin Stjernholm  MD->size--; \
853b832000-12-14Martin Stjernholm  DO_IF_MAPPING_SIZE_DEBUG( \
e1a35e2003-09-08Martin Stjernholm  if(M->data ==MD) \ M->debug_size--; \
0b5d2b2001-06-05Martin Stjernholm  ); \
853b832000-12-14Martin Stjernholm  }else{ \
017b572011-10-28Henrik Grubbström (Grubba)  VAL_TYPES |= 1 << TYPEOF(k->val); \ IND_TYPES |= 1 << TYPEOF(k->ind); \
853b832000-12-14Martin Stjernholm  prev=&k->next; \ } \ } \ } \ } while (0)
d4741b2007-10-04Henrik Grubbström (Grubba) #endif /* PIKE_MAPPING_KEYPAIR_LOOP */
853b832000-12-14Martin Stjernholm 
0b5d2b2001-06-05Martin Stjernholm #define GC_REC_KP(REMOVE, N_REC, W_REC, N_TST, W_TST) do { \ if ((REMOVE = N_REC(&k->ind, 1))) \ gc_free_svalue(&k->val); \ else \ N_REC(&k->val, 1); \ } while (0) #define GC_REC_KP_IND(REMOVE, N_REC, W_REC, N_TST, W_TST) do { \ if ((REMOVE = W_REC(&k->ind, 1))) \ gc_free_svalue(&k->val); \ else \ N_REC(&k->val, 1); \ } while (0) #define GC_REC_KP_VAL(REMOVE, N_REC, W_REC, N_TST, W_TST) do { \ if ((REMOVE = N_TST(&k->ind))) /* Don't recurse now. */ \ gc_free_svalue(&k->val); \ else if ((REMOVE = W_REC(&k->val, 1))) \ gc_free_svalue(&k->ind); \
99ac3c2015-05-31Henrik Grubbström (Grubba)  else if (N_REC(&k->ind, 1)) /* Now we can recurse the index. */ \ Pike_fatal("Mapping: %s and %s don't agree.\n", \ TOSTR(N_TST), TOSTR(N_REC)); \
0b5d2b2001-06-05Martin Stjernholm } while (0) #define GC_REC_KP_BOTH(REMOVE, N_REC, W_REC, N_TST, W_TST) do { \ if ((REMOVE = W_TST(&k->ind))) /* Don't recurse now. */ \ gc_free_svalue(&k->val); \ else if ((REMOVE = W_REC(&k->val, 1))) \ gc_free_svalue(&k->ind); \
99ac3c2015-05-31Henrik Grubbström (Grubba)  else if (W_REC(&k->ind, 1)) /* Now we can recurse the index. */ \ Pike_fatal("Mapping: %s and %s don't agree.\n", \ TOSTR(W_TST), TOSTR(W_REC)); \
853b832000-12-14Martin Stjernholm } while (0)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  void gc_mark_mapping_as_referenced(struct mapping *m) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(m->data);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
613c342009-11-28Martin Stjernholm  if(gc_mark(m, T_MAPPING))
e1a35e2003-09-08Martin Stjernholm  GC_ENTER (m, T_MAPPING) { struct mapping_data *md = m->data; if (m == gc_mark_mapping_pos) gc_mark_mapping_pos = m->next; if (m == gc_internal_mapping) gc_internal_mapping = m->next; else { DOUBLEUNLINK(first_mapping, m); DOUBLELINK(first_mapping, m); /* Linked in first. */
853b832000-12-14Martin Stjernholm  }
e1a35e2003-09-08Martin Stjernholm 
613c342009-11-28Martin Stjernholm  if(gc_mark(md, T_MAPPING_DATA) && ((md->ind_types | md->val_types) & BIT_COMPLEX)) {
5e83442008-05-11Martin Stjernholm  TYPE_FIELD ind_types = 0, val_types = 0; if (MAPPING_DATA_IN_USE(md)) { /* Must leave the mapping data untouched if it's busy. */ debug_malloc_touch(m); debug_malloc_touch(md); GC_RECURSE_MD_IN_USE(md, gc_mark_svalues, ind_types, val_types); gc_assert_checked_as_nonweak(md);
0b5d2b2001-06-05Martin Stjernholm  }
5e83442008-05-11Martin Stjernholm  else switch (md->flags & MAPPING_WEAK) { case 0: debug_malloc_touch(m); debug_malloc_touch(md); GC_RECURSE(m, md, GC_REC_KP, gc_mark, ind_types, val_types); gc_assert_checked_as_nonweak(md); break; case MAPPING_WEAK_INDICES: debug_malloc_touch(m); debug_malloc_touch(md); GC_RECURSE(m, md, GC_REC_KP_IND, gc_mark, ind_types, val_types); gc_assert_checked_as_weak(md); break; case MAPPING_WEAK_VALUES: debug_malloc_touch(m); debug_malloc_touch(md); GC_RECURSE(m, md, GC_REC_KP_VAL, gc_mark, ind_types, val_types); gc_assert_checked_as_weak(md); break; default: debug_malloc_touch(m); debug_malloc_touch(md); GC_RECURSE(m, md, GC_REC_KP_BOTH, gc_mark, ind_types, val_types); gc_assert_checked_as_weak(md); break;
e1a35e2003-09-08Martin Stjernholm  }
5e83442008-05-11Martin Stjernholm  md->val_types = val_types; md->ind_types = ind_types;
e1a35e2003-09-08Martin Stjernholm  } } GC_LEAVE;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
45d87e2000-07-18Martin Stjernholm void real_gc_cycle_check_mapping(struct mapping *m, int weak)
e2d9e62000-06-10Martin Stjernholm {
e1a35e2003-09-08Martin Stjernholm  GC_CYCLE_ENTER(m, T_MAPPING, weak) {
5eca4d2000-09-04Martin Stjernholm  struct mapping_data *md = m->data;
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
5eca4d2000-09-04Martin Stjernholm 
e2d9e62000-06-10Martin Stjernholm #ifdef PIKE_DEBUG
5eca4d2000-09-04Martin Stjernholm  if(md->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
e2d9e62000-06-10Martin Stjernholm #endif
853b832000-12-14Martin Stjernholm  if ((md->ind_types | md->val_types) & BIT_COMPLEX) { TYPE_FIELD ind_types = 0, val_types = 0;
5eca4d2000-09-04Martin Stjernholm  if (MAPPING_DATA_IN_USE(md)) {
0b5d2b2001-06-05Martin Stjernholm  /* Must leave the mapping data untouched if it's busy. */
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
853b832000-12-14Martin Stjernholm  GC_RECURSE_MD_IN_USE(md, gc_cycle_check_svalues, ind_types, val_types);
595dac2000-09-30Martin Stjernholm  gc_assert_checked_as_nonweak(md);
5eca4d2000-09-04Martin Stjernholm  }
0b5d2b2001-06-05Martin Stjernholm  else switch (md->flags & MAPPING_WEAK) { case 0:
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
e1a35e2003-09-08Martin Stjernholm  GC_RECURSE(m, md, GC_REC_KP, gc_cycle_check, ind_types, val_types);
0b5d2b2001-06-05Martin Stjernholm  gc_assert_checked_as_nonweak(md); break; case MAPPING_WEAK_INDICES:
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
e1a35e2003-09-08Martin Stjernholm  GC_RECURSE(m, md, GC_REC_KP_IND, gc_cycle_check, ind_types, val_types);
0b5d2b2001-06-05Martin Stjernholm  gc_assert_checked_as_weak(md); break; case MAPPING_WEAK_VALUES:
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
e1a35e2003-09-08Martin Stjernholm  GC_RECURSE(m, md, GC_REC_KP_VAL, gc_cycle_check, ind_types, val_types);
0b5d2b2001-06-05Martin Stjernholm  gc_assert_checked_as_weak(md); break; default:
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
e1a35e2003-09-08Martin Stjernholm  GC_RECURSE(m, md, GC_REC_KP_BOTH, gc_cycle_check, ind_types, val_types);
0b5d2b2001-06-05Martin Stjernholm  gc_assert_checked_as_weak(md); break; }
853b832000-12-14Martin Stjernholm  md->val_types = val_types; md->ind_types = ind_types;
45d87e2000-07-18Martin Stjernholm  }
e2d9e62000-06-10Martin Stjernholm  } GC_CYCLE_LEAVE; }
5e83442008-05-11Martin Stjernholm static void gc_check_mapping(struct mapping *m)
515b6c1996-06-09Fredrik Hübinette (Hubbe) {
5e83442008-05-11Martin Stjernholm  struct mapping_data *md = m->data;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
5e83442008-05-11Martin Stjernholm  if((md->ind_types | md->val_types) & BIT_COMPLEX) GC_ENTER (m, T_MAPPING) { INT32 e; struct keypair *k; if(!debug_gc_check (md, " as mapping data block of a mapping")) { if (!(md->flags & MAPPING_WEAK) || MAPPING_DATA_IN_USE(md)) /* Disregard the weak flag if the mapping data is busy; we must * leave it untouched in that case anyway. */ NEW_MAPPING_LOOP(md) { debug_gc_check_svalues(&k->ind, 1, " as mapping index"); debug_gc_check_svalues(&k->val, 1, " as mapping value"); } else { switch (md->flags & MAPPING_WEAK) { case MAPPING_WEAK_INDICES: NEW_MAPPING_LOOP(md) { debug_gc_check_weak_svalues(&k->ind, 1, " as mapping index"); debug_gc_check_svalues(&k->val, 1, " as mapping value"); } break; case MAPPING_WEAK_VALUES: NEW_MAPPING_LOOP(md) { debug_gc_check_svalues(&k->ind, 1, " as mapping index"); debug_gc_check_weak_svalues(&k->val, 1, " as mapping value"); } break; default: NEW_MAPPING_LOOP(md) { debug_gc_check_weak_svalues(&k->ind, 1, " as mapping index"); debug_gc_check_weak_svalues(&k->val, 1, " as mapping value"); } break; } gc_checked_as_weak(md);
ad8d052008-05-02Martin Stjernholm  }
5e83442008-05-11Martin Stjernholm  } } GC_LEAVE;
20513c2000-04-12Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) 
e2d9e62000-06-10Martin Stjernholm unsigned gc_touch_all_mappings(void)
7bf6232000-04-23Martin Stjernholm {
e2d9e62000-06-10Martin Stjernholm  unsigned n = 0;
7bf6232000-04-23Martin Stjernholm  struct mapping *m;
e2d9e62000-06-10Martin Stjernholm  if (first_mapping && first_mapping->prev)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Error in mapping link list.\n");
7bf6232000-04-23Martin Stjernholm  for (m = first_mapping; m; m = m->next) { debug_gc_touch(m); n++;
e2d9e62000-06-10Martin Stjernholm  if (m->next && m->next->prev != m)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Error in mapping link list.\n");
7bf6232000-04-23Martin Stjernholm  } return n; }
20513c2000-04-12Fredrik Hübinette (Hubbe) void gc_check_all_mappings(void) { struct mapping *m; for(m=first_mapping;m;m=m->next) { #ifdef DEBUG_MALLOC
5e83442008-05-11Martin Stjernholm  if (((int) PTR_TO_INT (m->data)) == 0x55555555) {
20513c2000-04-12Fredrik Hübinette (Hubbe)  fprintf(stderr, "** Zapped mapping in list of active mappings!\n");
6e7eea2001-08-22Henrik Grubbström (Grubba)  describe_something(m, T_MAPPING, 0,2,0, NULL);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zapped mapping in list of active mappings!\n");
20513c2000-04-12Fredrik Hübinette (Hubbe)  } #endif /* DEBUG_MALLOC */
5e83442008-05-11Martin Stjernholm  gc_check_mapping(m);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
0816292000-07-03Martin Stjernholm  if(d_flag > 1) check_mapping_type_fields(m);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_mark_all_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) {
e2d9e62000-06-10Martin Stjernholm  gc_mark_mapping_pos = gc_internal_mapping; while (gc_mark_mapping_pos) { struct mapping *m = gc_mark_mapping_pos; gc_mark_mapping_pos = m->next;
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(m->data);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(gc_is_referenced(m)) gc_mark_mapping_as_referenced(m);
e2d9e62000-06-10Martin Stjernholm  } } void gc_cycle_check_all_mappings(void) { struct mapping *m; for (m = gc_internal_mapping; m; m = m->next) {
45d87e2000-07-18Martin Stjernholm  real_gc_cycle_check_mapping(m, 0); gc_cycle_run_queue();
e2d9e62000-06-10Martin Stjernholm  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
45d87e2000-07-18Martin Stjernholm void gc_zap_ext_weak_refs_in_mappings(void) { gc_mark_mapping_pos = first_mapping; while (gc_mark_mapping_pos != gc_internal_mapping && gc_ext_weak_refs) { struct mapping *m = gc_mark_mapping_pos; gc_mark_mapping_pos = m->next; gc_mark_mapping_as_referenced(m); }
e1a35e2003-09-08Martin Stjernholm  gc_mark_discard_queue();
45d87e2000-07-18Martin Stjernholm }
88cf4f2003-01-11Martin Stjernholm size_t gc_free_all_unreferenced_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { struct mapping *m,*next;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
a1b3872003-01-11Martin Stjernholm  size_t unreferenced = 0;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
e2d9e62000-06-10Martin Stjernholm  for(m=gc_internal_mapping;m;m=next)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(m->data);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(gc_do_free(m)) {
e2d9e62000-06-10Martin Stjernholm  /* Got an extra ref from gc_cycle_pop(). */
27bec92000-02-15Henrik Grubbström (Grubba)  md = m->data;
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
27bec92000-02-15Henrik Grubbström (Grubba)  /* Protect against unlink_mapping_data() recursing too far. */
1f342f2000-02-04Fredrik Hübinette (Hubbe)  m->data=&empty_data;
9a6d002001-06-26Fredrik Hübinette (Hubbe)  add_ref(m->data);
27bec92000-02-15Henrik Grubbström (Grubba)  unlink_mapping_data(md);
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
e945ee2000-02-09Fredrik Hübinette (Hubbe)  m->debug_size=0; #endif
e2d9e62000-06-10Martin Stjernholm  gc_free_extra_ref(m);
69ee4b2000-04-06Fredrik Hübinette (Hubbe)  SET_NEXT_AND_FREE(m, free_mapping);
3b589f1999-02-04Fredrik Hübinette (Hubbe)  } else {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  next=m->next; }
a1b3872003-01-11Martin Stjernholm  unreferenced++;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
88cf4f2003-01-11Martin Stjernholm 
a1b3872003-01-11Martin Stjernholm  return unreferenced;
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
61e9a01998-01-25Fredrik Hübinette (Hubbe)  void simple_describe_mapping(struct mapping *m) {
e0cd662016-12-28Arne Goedeke  struct byte_buffer buf = BUFFER_INIT(); describe_mapping(&buf,m,0,2); buffer_add_str(&buf, "\n"); fputs(buffer_get_string(&buf), stderr); buffer_free(&buf);
61e9a01998-01-25Fredrik Hübinette (Hubbe) } void debug_dump_mapping(struct mapping *m) {
5eca4d2000-09-04Martin Stjernholm  fprintf(stderr, "Refs=%d, next=%p, prev=%p", m->refs, m->next, m->prev);
f5757f2000-08-11Henrik Grubbström (Grubba)  if (((ptrdiff_t)m->data) & 3) {
18bc0c2000-03-08Henrik Grubbström (Grubba)  fprintf(stderr, ", data=%p (unaligned)\n", m->data); } else {
5eca4d2000-09-04Martin Stjernholm  fprintf(stderr, ", flags=0x%x, size=%d, hashsize=%d\n", m->data->flags, m->data->size, m->data->hashsize);
86f1862004-03-16Martin Stjernholm  fprintf(stderr, "Indices type field =");
18bc0c2000-03-08Henrik Grubbström (Grubba)  debug_dump_type_field(m->data->ind_types); fprintf(stderr, "\n");
86f1862004-03-16Martin Stjernholm  fprintf(stderr, "Values type field =");
18bc0c2000-03-08Henrik Grubbström (Grubba)  debug_dump_type_field(m->data->val_types); fprintf(stderr, "\n");
375bed2000-03-08Henrik Grubbström (Grubba)  simple_describe_mapping(m);
18bc0c2000-03-08Henrik Grubbström (Grubba)  }
61e9a01998-01-25Fredrik Hübinette (Hubbe) } #endif
84387d2001-09-24Fredrik Hübinette (Hubbe) int mapping_is_constant(struct mapping *m, struct processing *p) {
c7ad762001-10-03Fredrik Hübinette (Hubbe)  int ret=1;
84387d2001-09-24Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k; struct mapping_data *md=m->data; if( (md->ind_types | md->val_types) & ~(BIT_INT|BIT_FLOAT|BIT_STRING)) { md->valrefs++; add_ref(md); NEW_MAPPING_LOOP(md) {
c7ad762001-10-03Fredrik Hübinette (Hubbe)  if(!svalues_are_constant(&k->ind, 1, md->ind_types, p) || !svalues_are_constant(&k->val, 1, md->val_types, p)) { ret=0; e=md->hashsize; break; }
84387d2001-09-24Fredrik Hübinette (Hubbe)  } md->valrefs--; free_mapping_data(md); }
c7ad762001-10-03Fredrik Hübinette (Hubbe)  return ret;
84387d2001-09-24Fredrik Hübinette (Hubbe) }