pike.git / src / mapping.c

version» Context lines:

pike.git/src/mapping.c:1:   /*   || 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. - || $Id: mapping.c,v 1.175 2003/11/12 09:31:51 grubba Exp $ + || $Id: mapping.c,v 1.176 2003/11/12 14:07:04 grubba Exp $   */      #include "global.h" - RCSID("$Id: mapping.c,v 1.175 2003/11/12 09:31:51 grubba Exp $"); + RCSID("$Id: mapping.c,v 1.176 2003/11/12 14:07:04 grubba Exp $");   #include "main.h"   #include "object.h"   #include "mapping.h"   #include "svalue.h"   #include "array.h"   #include "pike_macros.h"   #include "pike_error.h"   #include "pike_memory.h"   #include "dynamic_buffer.h"   #include "interpret.h"
pike.git/src/mapping.c:1366:      #endif      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; +  ONERROR err;       /* First some special cases. */    if (!a_md->size || !b_md->size || !a_md->hashsize || !b_md->hashsize) {    return copy_mapping(a);    }    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); -  +  SET_ONERROR(err, do_free_mapping, res);    NEW_MAPPING_LOOP(a_md) {    size_t h = k->hval % b_md->hashsize;    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. */    res = copy_mapping(a); -  +  SET_ONERROR(err, do_free_mapping, res);    NEW_MAPPING_LOOP(b_md) {    map_delete(res, &k->ind);    }    } -  +  UNSET_ONERROR(err);    return res;   }    -  + 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); +  if (a_md == b_md) return copy_mapping(a); +  +  /* Copy the second mapping. */ +  res = copy_mapping(b); +  SET_ONERROR(err, do_free_mapping, res); +  +  /* Remove elements in res that aren't in a. */ +  NEW_MAPPING_LOOP(b_md) { +  size_t h = k->hval % a_md->hashsize; +  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; + } +  + 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. */ +  if (!a_md->size) return copy_mapping(b); +  if (!b_md->size) return copy_mapping(a); +  if (a_md == b_md) return copy_mapping(a); +  +  /* Copy the second mapping. */ +  res = copy_mapping(b); +  SET_ONERROR(err, do_free_mapping, res); +  +  /* Add elements in a that aren't in b. */ +  NEW_MAPPING_LOOP(a_md) { +  size_t h = k->hval % b_md->hashsize; +  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); +  } +  } +  UNSET_ONERROR(err); +  return res; + } +  + 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. */ +  if (!a_md->size) return copy_mapping(b); +  if (!b_md->size) return copy_mapping(a); +  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; +  } +  res = copy_mapping(b); +  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) { +  size_t h = k->hval % b_md->hashsize; +  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); +  } +  } +  UNSET_ONERROR(err); +  return res; + } +    PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op)   {    ONERROR r1,r2,r3,r4;    struct array *ai, *av;    struct array *bi, *bv;    struct array *ci, *cv;    INT32 *zipper;    struct mapping *m;      #ifdef PIKE_DEBUG    if(a->data->refs <=0)    Pike_fatal("Zero refs in mapping->data\n");    if(b->data->refs <=0)    Pike_fatal("Zero refs in mapping->data\n");   #endif    -  if (op == PIKE_ARRAY_OP_SUB) { +  switch (op) { +  case PIKE_ARRAY_OP_SUB:    return subtract_mappings(a, b); -  +  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);    }       ai=mapping_indices(a);    SET_ONERROR(r1,do_free_array,ai);       av=mapping_values(a);    SET_ONERROR(r2,do_free_array,av);       if(ai->size > 1)    {
pike.git/src/mapping.c:1469:       free((char *)zipper);       m=mkmapping(ci, cv);    free_array(ci);    free_array(cv);       return m;   }    + /* FIXME: What are the semantics for this function? +  * FIXME: It ought to be optimized just like the unordered variant. +  * /grubba 2003-11-12 +  */   PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a,    struct array *b, INT32 op)   {    ONERROR r1,r2;    struct array *ai, *av;    struct array *ci = NULL, *cv = NULL;    INT32 *zipper = NULL;    struct mapping *m;       ai=mapping_indices(a);