Difference for common/object.c from version 1.98 to 1.99


version 1.98 version 1.99
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_object_c =   * static char *rcsid_object_c =
  *   "$Id: object.c,v 1.98 2005/08/12 13:46:34 ryo_saeba Exp $";   *   "$Id: object.c,v 1.99 2005/08/23 05:42:58 mwedel Exp $";
  */   */
   
 /*  /*
Line 68
 
Line 68
   0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8,    0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8,
   1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8};    1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8};
   
 /* Moved this out of define.h and in here, since this is the only file  
  * it is used in.  Also, make it an inline function for cleaner  /* Returns TRUE if every key_values in wants has a partner with the same value in has. */
  * design.  static int compare_ob_value_lists_one(object * wants, object * has) {
  *      key_value * wants_field;
  * Function examines the 2 objects given to it, and returns true if     
       /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both
        * objects with lists are rare, and lists stay short. If not, use a
        * different structure or at least keep the lists sorted...
        */
      
       /* For each field in wants, */
       for (wants_field = wants->key_values; wants_field != NULL; wants_field = wants_field->next) {
           key_value * has_field;
          
           /* Look for a field in has with the same key. */
           has_field = get_ob_key_link(has, wants_field->key);
          
           if (has_field == NULL) {
               /* No field with that name. */
               return FALSE;
           }
          
           /* Found the matching field. */
           if (has_field->value != wants_field->value) {
               /* Values don't match, so this half of the comparison is false. */
               return FALSE;
           }
          
           /* If we get here, we found a match. Now for the next field in wants. */
       }
      
       /* If we get here, every field in wants has a matching field in has. */
       return TRUE;
   }
   
   /* Returns TRUE if ob1 has the same key_values as ob2. */
   static int compare_ob_value_lists(object * ob1, object * ob2) {
       /* However, there may be fields in has which aren't partnered in wants,
        * so we need to run the comparison *twice*. :(
        */
       return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1);
   }
   
   /* Function examines the 2 objects given to it, and returns true if
  * they can be merged together.   * they can be merged together.
  *   *
  * Note that this function appears a lot longer than the macro it   * Note that this function appears a lot longer than the macro it
Line 161
 
Line 200
     if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED))      if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED))
  return 0;   return 0;
   
       if (ob1->key_values != NULL || ob2->key_values != NULL) {
           /* At least one of these has key_values. */
           if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) {
               /* One has fields, but the other one doesn't. */
               return 0;
           } else {
               return compare_ob_value_lists(ob1, ob2);
           }
       }
   
     switch (ob1->type) {      switch (ob1->type) {
  case SCROLL:   case SCROLL:
      if (ob1->level != ob2->level) return 0;       if (ob1->level != ob2->level) return 0;
Line 481
 
Line 530
     op->events=NULL;      op->events=NULL;
     clear_object(op);      clear_object(op);
 }  }
   
   /* Zero the key_values on op, decrementing the shared-string
    * refcounts and freeing the links.
    */
   static void free_key_values(object * op) {
       key_value * i;
       key_value * next = NULL;
      
       if (op->key_values == NULL) return;
      
       for (i = op->key_values; i != NULL; i = next) {
           /* Store next *first*. */
           next = i->next;
          
    if (i->key) FREE_AND_CLEAR_STR(i->key);
    if (i->value) FREE_AND_CLEAR_STR(i->value);
           i->next = NULL;
           free(i);
       }
      
       op->key_values = NULL;
   }
   
   
 /*  /*
  * clear_object() frees everything allocated by an object, and also   * clear_object() frees everything allocated by an object, and also
  * clears all variables and flags to default settings.   * clears all variables and flags to default settings.
Line 507
 
Line 580
     }      }
     op->events = NULL;      op->events = NULL;
   
       free_key_values(op);
   
     /* the memset will clear all these values for us, but we need      /* the memset will clear all these values for us, but we need
      * to reduce the refcount on them.       * to reduce the refcount on them.
Line 566
 
Line 640
     int is_freed=QUERY_FLAG(op,FLAG_FREED),is_removed=QUERY_FLAG(op,FLAG_REMOVED);      int is_freed=QUERY_FLAG(op,FLAG_FREED),is_removed=QUERY_FLAG(op,FLAG_REMOVED);
     event *evt, *evt2, *evt_new;      event *evt, *evt2, *evt_new;
   
       /* Decrement the refcounts, but don't bother zeroing the fields;
       they'll be overwritten by memcpy. */
     if(op->name!=NULL) free_string(op->name);      if(op->name!=NULL) free_string(op->name);
     if(op->name_pl!=NULL) free_string(op->name_pl);      if(op->name_pl!=NULL) free_string(op->name_pl);
     if(op->title!=NULL) free_string(op->title);      if(op->title!=NULL) free_string(op->title);
Line 589
 
Line 665
     }      }
     op->events = NULL;      op->events = NULL;
   
       free_key_values(op);
   
       /* op is the destination, op2 is the source. */
     (void) memcpy((void *)((char *) op +offsetof(object,name)),      (void) memcpy((void *)((char *) op +offsetof(object,name)),
                 (void *)((char *) op2+offsetof(object,name)),                  (void *)((char *) op2+offsetof(object,name)),
                 sizeof(object)-offsetof(object, name));                  sizeof(object)-offsetof(object, name));
Line 630
 
Line 709
   
  evt2 = evt_new;   evt2 = evt_new;
     }      }
       /* Copy over key_values, if any. */
       if (op2->key_values != NULL) {
    key_value * tail = NULL;
    key_value * i;
   
    op->key_values = NULL;
   
    for (i = op2->key_values; i != NULL; i = i->next) {
        key_value * new_link = malloc(sizeof(key_value));
   
        new_link->next = NULL;
        new_link->key = add_refcount(i->key);
        if (i->value)
    new_link->value = add_refcount(i->value);
        else
    new_link->value = NULL;
   
        /* Try and be clever here, too. */
        if (op->key_values == NULL) {
    op->key_values = new_link;
    tail = new_link;
        } else {
    tail->next = new_link;
    tail = new_link;
        }
    }
       }
    
     update_ob_speed(op);      update_ob_speed(op);
 }  }
Line 999
 
Line 1105
     if(ob->msg!=NULL)     FREE_AND_CLEAR_STR(ob->msg);      if(ob->msg!=NULL)     FREE_AND_CLEAR_STR(ob->msg);
     if(ob->materialname!=NULL) FREE_AND_CLEAR_STR(ob->materialname);      if(ob->materialname!=NULL) FREE_AND_CLEAR_STR(ob->materialname);
   
      
       /* Why aren't events freed? */
       free_key_values(ob);
   
 #if 0 /* MEMORY_DEBUG*/  #if 0 /* MEMORY_DEBUG*/
     /* This is a nice idea.  Unfortunately, a lot of the code in crossfire      /* This is a nice idea.  Unfortunately, a lot of the code in crossfire
      * presumes the freed_object will stick around for at least a little       * presumes the freed_object will stick around for at least a little
Line 2415
 
Line 2525
     return NULL;      return NULL;
 }  }
   
   /* If ob has a field named key, return the link from the list,
    * otherwise return NULL.
    *
    * key must be a passed in shared string - otherwise, this won't
    * do the desired thing.
    */
   key_value * get_ob_key_link(object * ob, const char * key) {
       key_value * link;
      
       for (link = ob->key_values; link != NULL; link = link->next) {
           if (link->key == key) {
               return link;
           }
       }
      
       return NULL;
   } 
   
   /*
    * Returns the value of op has an extra_field for key, or NULL.
    *
    * The argument doesn't need to be a shared string.
    *
    * The returned string is shared.
    */
   const char * get_ob_key_value(object * op, const char * const key) {
       key_value * link;
       const char * canonical_key;
      
       canonical_key = find_string(key);
      
       if (canonical_key == NULL) {
           /* 1. There being a field named key on any object
            *    implies there'd be a shared string to find.
            * 2. Since there isn't, no object has this field.
            * 3. Therefore, *this* object doesn't have this field.
            */
           return NULL;
       }
   
       /* This is copied from get_ob_key_link() above -
        * only 4 lines, and saves the function call overhead.
        */
       for (link = op->key_values; link != NULL; link = link->next) {
           if (link->key == key) {
               return link->value;
           }
       }
       return NULL;
   }
   
   
   /*
    * Updates the canonical_key in op to value.
    *
    * canonical_key is a shared string (value doesn't have to be).
    *
    * Unless add_key is TRUE, it won't add fields, only change the value of existing
    * keys.
    *
    * Returns TRUE on success.
    */
   int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) {
       key_value * field = NULL, *last=NULL;
      
       LOG(llevDebug, "set_ob_value_s: '%s' '%s' %d\n", canonical_key, value, add_key);
   
       for (field=op->key_values; field != NULL; field=field->next) {
    if (field->key != canonical_key) {
        last = field;
        continue;
    }
      
    if (field->value) FREE_AND_CLEAR_STR(field->value);
    if (value)
        field->value = add_string(value);
    else {
        /* Basically, if the archetype has this key set,
         * we need to store the null value so when we save
         * it, we save the empty value so that when we load,
         * we get this value back again.
         */
        if (get_ob_key_link(&op->arch->clone, canonical_key))
    field->value = NULL;
        else {
    /* Delete this link */
    if (field->key) FREE_AND_CLEAR_STR(field->key);
    if (field->value) FREE_AND_CLEAR_STR(field->value);
    if (last) last->next = field->next;
    else op->key_values = field->next;
    free(field);
        }
    }
           return TRUE;
       }
       /* IF we get here, key doesn't exist */
   
       /* No field, we'll have to add it. */
      
       if (!add_key) {
           return FALSE;
       }
       /* There isn't any good reason to store a null
        * value in the key/value list.  If the archetype has
        * this key, then we should also have it, so shouldn't
        * be here.  If user wants to store empty strings,
        * should pass in ""
        */
       if (value == NULL) return TRUE;
      
       field = malloc(sizeof(key_value));
      
       field->key = add_refcount(canonical_key);
       field->value = add_string(value);
       /* Usual prepend-addition. */
       field->next = op->key_values;
       op->key_values = field;
      
       return TRUE;
   }
   
   /*
    * Updates the key in op to value.
    *
    * Unless add_key is TRUE, it won't add fields, only change the value of existing
    * keys.
    *
    * Returns TRUE on success.
    */
   int set_ob_key_value(object * op, const char * key, const char * value, int add_key) {
       const char * canonical_key = NULL;
       int floating_ref = FALSE;
       int ret;
      
       /* HACK This mess is to make sure set_ob_value() passes a shared string
        * to get_ob_key_link(), without leaving a leaked refcount.
        */
      
       canonical_key = find_string(key);
       if (canonical_key == NULL) {
           canonical_key = add_string(key);
           floating_ref = TRUE;
       }
      
       ret = set_ob_key_value_s(op, canonical_key, value, add_key);
      
       if (floating_ref) {
           free_string(canonical_key);
       }
      
       return ret;
   }


Legend:
line(s) removed in v.1.98 
line(s) changed
 line(s) added in v.1.99

File made using version 1.98 of cvs2html by leaf at 2011-07-21 17:14