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.208 2008/06/28 21:37:34 grubba Exp $ + || $Id: mapping.c,v 1.209 2008/06/29 08:57:03 grubba Exp $   */      #include "global.h"   #include "main.h"   #include "object.h"   #include "mapping.h"   #include "svalue.h"   #include "array.h"   #include "pike_macros.h"   #include "pike_error.h"
pike.git/src/mapping.c:1414:   #endif    add_ref(n->data);    n->data->valrefs++;    n->data->hardlinks++;    debug_malloc_touch(n->data);    return n;   }      #endif    + 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. +  */   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); +  return destructive_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) {
pike.git/src/mapping.c:1449:    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); +  res = destructive_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;   }    -  + /* NOTE: May perform destructive operations on either of the arguments +  * if it has only a single reference. +  */   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); +  if (a_md == b_md) return destructive_copy_mapping(a);       /* Copy the second mapping. */ -  res = copy_mapping(b); +  res = destructive_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;   }    -  + /* NOTE: May perform destructive operations on either of the arguments +  * if it has only a single reference. +  */   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); +  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);       if (a_md->size <= b_md->size) {    /* Copy the second mapping. */ -  res = copy_mapping(b); +  res = destructive_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);    } else {    /* Copy the first mapping. */ -  res = copy_mapping(a); +  res = destructive_copy_mapping(a);    SET_ONERROR(err, do_free_mapping, res);       /* Add all elements in b. */    NEW_MAPPING_LOOP(b_md) {    mapping_insert(res, &k->ind, &k->val);    }    UNSET_ONERROR(err);    }    return res;   }    -  + /* NOTE: May perform destructive operations on either of the arguments +  * if it has only a single reference. +  */   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->size) return destructive_copy_mapping(b); +  if (!b_md->size) return destructive_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); +  res = destructive_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;    }
pike.git/src/mapping.c:1584:    if (!k2) {    mapping_insert(res, &k->ind, &k->val);    } else {    map_delete(res, &k2->ind);    }    }    UNSET_ONERROR(err);    return res;   }    + /* NOTE: May perform destructive operations on either of the arguments +  * if it has only a single reference. +  */   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
pike.git/src/mapping.c:1736:    SET_ONERROR(r1,do_free_array,b_temp);    m=merge_mapping_array_ordered(a,b_temp,op);    UNSET_ONERROR(r1); free_array(b_temp);    }    else    m=merge_mapping_array_ordered(a,b,op);       return m;   }    + /* NOTE: May perform destructive operations on either of the arguments +  * if it has only a single reference. +  */   PMOD_EXPORT struct mapping *add_mappings(struct svalue *argp, INT32 args)   {    INT32 e,d;    struct mapping *ret=0;    struct keypair *k;       for(e=d=0;d<args;d++)    {    struct mapping *m = argp[d].u.mapping;   #ifdef PIKE_DEBUG