1 | /* |
1 | /* |
2 | * static char *rcsid_object_c = |
2 | * static char *rcsid_object_c = |
3 | * "$Id: object.c,v 1.1.1.1 2006/02/03 07:11:38 root Exp $"; |
3 | * "$Id: object.c,v 1.4 2006/03/31 21:16:24 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
52 | |
52 | |
53 | object *objects; /* Pointer to the list of used objects */ |
53 | object *objects; /* Pointer to the list of used objects */ |
54 | object *free_objects; /* Pointer to the list of unused objects */ |
54 | object *free_objects; /* Pointer to the list of unused objects */ |
55 | object *active_objects; /* List of active objects that need to be processed */ |
55 | object *active_objects; /* List of active objects that need to be processed */ |
56 | |
56 | |
|
|
57 | void (*object_free_callback)(object *ob); |
57 | |
58 | |
58 | short freearr_x[SIZEOFFREE]= |
59 | short freearr_x[SIZEOFFREE]= |
59 | {0,0,1,1,1,0,-1,-1,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1, |
60 | {0,0,1,1,1,0,-1,-1,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1, |
60 | 0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1}; |
61 | 0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1}; |
61 | short freearr_y[SIZEOFFREE]= |
62 | short freearr_y[SIZEOFFREE]= |
… | |
… | |
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, |
69 | 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, |
69 | 1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8}; |
70 | 1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8}; |
70 | |
71 | |
71 | |
72 | |
72 | /* Returns TRUE if every key_values in wants has a partner with the same value in has. */ |
73 | /* Returns TRUE if every key_values in wants has a partner with the same value in has. */ |
73 | static int compare_ob_value_lists_one(object * wants, object * has) { |
74 | static int compare_ob_value_lists_one(const object * wants, const object * has) { |
74 | key_value * wants_field; |
75 | key_value * wants_field; |
75 | |
76 | |
76 | /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both |
77 | /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both |
77 | * objects with lists are rare, and lists stay short. If not, use a |
78 | * objects with lists are rare, and lists stay short. If not, use a |
78 | * different structure or at least keep the lists sorted... |
79 | * different structure or at least keep the lists sorted... |
… | |
… | |
102 | /* If we get here, every field in wants has a matching field in has. */ |
103 | /* If we get here, every field in wants has a matching field in has. */ |
103 | return TRUE; |
104 | return TRUE; |
104 | } |
105 | } |
105 | |
106 | |
106 | /* Returns TRUE if ob1 has the same key_values as ob2. */ |
107 | /* Returns TRUE if ob1 has the same key_values as ob2. */ |
107 | static int compare_ob_value_lists(object * ob1, object * ob2) { |
108 | static int compare_ob_value_lists(const object * ob1, const object * ob2) { |
108 | /* However, there may be fields in has which aren't partnered in wants, |
109 | /* However, there may be fields in has which aren't partnered in wants, |
109 | * so we need to run the comparison *twice*. :( |
110 | * so we need to run the comparison *twice*. :( |
110 | */ |
111 | */ |
111 | return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1); |
112 | return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1); |
112 | } |
113 | } |
… | |
… | |
197 | (ob1->materialname != ob2->materialname) || |
198 | (ob1->materialname != ob2->materialname) || |
198 | (ob1->lore != ob2->lore) || |
199 | (ob1->lore != ob2->lore) || |
199 | (ob1->subtype != ob2->subtype) || |
200 | (ob1->subtype != ob2->subtype) || |
200 | (ob1->move_type != ob2->move_type) || |
201 | (ob1->move_type != ob2->move_type) || |
201 | (ob1->move_block != ob2->move_block) || |
202 | (ob1->move_block != ob2->move_block) || |
|
|
203 | (ob1->move_allow != ob2->move_allow) || |
202 | (ob1->move_on != ob2->move_on) || |
204 | (ob1->move_on != ob2->move_on) || |
203 | (ob1->move_off != ob2->move_off) || |
205 | (ob1->move_off != ob2->move_off) || |
204 | (ob1->move_slow != ob2->move_slow) || |
206 | (ob1->move_slow != ob2->move_slow) || |
205 | (ob1->move_slow_penalty != ob2->move_slow_penalty) |
207 | (ob1->move_slow_penalty != ob2->move_slow_penalty) |
206 | ) |
208 | ) |
… | |
… | |
384 | * get_nearest_part(multi-object, object 2) returns the part of the |
386 | * get_nearest_part(multi-object, object 2) returns the part of the |
385 | * multi-object 1 which is closest to the second object. |
387 | * multi-object 1 which is closest to the second object. |
386 | * If it's not a multi-object, it is returned. |
388 | * If it's not a multi-object, it is returned. |
387 | */ |
389 | */ |
388 | |
390 | |
389 | object *get_nearest_part(object *op,object *pl) { |
391 | object *get_nearest_part(object *op, const object *pl) { |
390 | object *tmp,*closest; |
392 | object *tmp,*closest; |
391 | int last_dist,i; |
393 | int last_dist,i; |
392 | if(op->more==NULL) |
394 | if(op->more==NULL) |
393 | return op; |
395 | return op; |
394 | for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more) |
396 | for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more) |
… | |
… | |
413 | * Returns the first object which has a name equal to the argument. |
415 | * Returns the first object which has a name equal to the argument. |
414 | * Used only by the patch command, but not all that useful. |
416 | * Used only by the patch command, but not all that useful. |
415 | * Enables features like "patch <name-of-other-player> food 999" |
417 | * Enables features like "patch <name-of-other-player> food 999" |
416 | */ |
418 | */ |
417 | |
419 | |
418 | object *find_object_name(char *str) { |
420 | object *find_object_name(const char *str) { |
419 | const char *name=add_string(str); |
421 | const char *name=add_string(str); |
420 | object *op; |
422 | object *op; |
421 | for(op=objects;op!=NULL;op=op->next) |
423 | for(op=objects;op!=NULL;op=op->next) |
422 | if(op->name==name) |
424 | if(op->name==name) |
423 | break; |
425 | break; |
… | |
… | |
1018 | if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE)) |
1020 | if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE)) |
1019 | update_now=1; |
1021 | update_now=1; |
1020 | |
1022 | |
1021 | if ((move_on | op->move_on) != move_on) update_now=1; |
1023 | if ((move_on | op->move_on) != move_on) update_now=1; |
1022 | if ((move_off | op->move_off) != move_off) update_now=1; |
1024 | if ((move_off | op->move_off) != move_off) update_now=1; |
|
|
1025 | /* This isn't perfect, but I don't expect a lot of objects to |
|
|
1026 | * to have move_allow right now. |
|
|
1027 | */ |
1023 | if ((move_block | op->move_block) != move_block) update_now=1; |
1028 | if (((move_block | op->move_block) & ~op->move_allow) != move_block) |
|
|
1029 | update_now=1; |
1024 | if ((move_slow | op->move_slow) != move_slow) update_now=1; |
1030 | if ((move_slow | op->move_slow) != move_slow) update_now=1; |
1025 | } |
1031 | } |
1026 | /* if the object is being removed, we can't make intelligent |
1032 | /* if the object is being removed, we can't make intelligent |
1027 | * decisions, because remove_ob can't really pass the object |
1033 | * decisions, because remove_ob can't really pass the object |
1028 | * that is being removed. |
1034 | * that is being removed. |
… | |
… | |
1060 | void free_object(object *ob) { |
1066 | void free_object(object *ob) { |
1061 | free_object2(ob, 0); |
1067 | free_object2(ob, 0); |
1062 | } |
1068 | } |
1063 | void free_object2(object *ob, int free_inventory) { |
1069 | void free_object2(object *ob, int free_inventory) { |
1064 | object *tmp,*op; |
1070 | object *tmp,*op; |
|
|
1071 | |
|
|
1072 | if (object_free_callback) |
|
|
1073 | object_free_callback (ob); |
1065 | |
1074 | |
1066 | if (!QUERY_FLAG(ob,FLAG_REMOVED)) { |
1075 | if (!QUERY_FLAG(ob,FLAG_REMOVED)) { |
1067 | LOG(llevDebug,"Free object called with non removed object\n"); |
1076 | LOG(llevDebug,"Free object called with non removed object\n"); |
1068 | dump_object(ob); |
1077 | dump_object(ob); |
1069 | #ifdef MANY_CORES |
1078 | #ifdef MANY_CORES |
… | |
… | |
1507 | if(op->more!=NULL) { |
1516 | if(op->more!=NULL) { |
1508 | /* The part may be on a different map. */ |
1517 | /* The part may be on a different map. */ |
1509 | |
1518 | |
1510 | object *more = op->more; |
1519 | object *more = op->more; |
1511 | |
1520 | |
|
|
1521 | /* We really need the caller to normalize coordinates - if |
|
|
1522 | * we set the map, that doesn't work if the location is within |
|
|
1523 | * a map and this is straddling an edge. So only if coordinate |
|
|
1524 | * is clear wrong do we normalize it. |
|
|
1525 | */ |
|
|
1526 | if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) { |
1512 | /* Debugging information so you can see the last coordinates this object had */ |
1527 | /* Debugging information so you can see the last coordinates this object had */ |
1513 | more->ox = more->x; |
1528 | more->ox = more->x; |
1514 | more->oy = more->y; |
1529 | more->oy = more->y; |
1515 | more->map = get_map_from_coord(m, &more->x, &more->y); |
1530 | more->map = get_map_from_coord(m, &more->x, &more->y); |
|
|
1531 | } else if (!more->map) { |
|
|
1532 | /* For backwards compatibility - when not dealing with tiled maps, |
|
|
1533 | * more->map should always point to the parent. |
|
|
1534 | */ |
|
|
1535 | more->map = m; |
|
|
1536 | } |
1516 | |
1537 | |
1517 | if (insert_ob_in_map(more, more->map, originator, flag) == NULL) { |
1538 | if (insert_ob_in_map(more, more->map, originator, flag) == NULL) { |
1518 | if ( ! op->head) |
1539 | if ( ! op->head) |
1519 | LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); |
1540 | LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); |
1520 | return NULL; |
1541 | return NULL; |
… | |
… | |
1702 | |
1723 | |
1703 | /* this function inserts an object in the map, but if it |
1724 | /* this function inserts an object in the map, but if it |
1704 | * finds an object of its own type, it'll remove that one first. |
1725 | * finds an object of its own type, it'll remove that one first. |
1705 | * op is the object to insert it under: supplies x and the map. |
1726 | * op is the object to insert it under: supplies x and the map. |
1706 | */ |
1727 | */ |
1707 | void replace_insert_ob_in_map(char *arch_string, object *op) { |
1728 | void replace_insert_ob_in_map(const char *arch_string, object *op) { |
1708 | object *tmp; |
1729 | object *tmp; |
1709 | object *tmp1; |
1730 | object *tmp1; |
1710 | |
1731 | |
1711 | /* first search for itself and remove any old instances */ |
1732 | /* first search for itself and remove any old instances */ |
1712 | |
1733 | |
… | |
… | |
2080 | * present_arch(arch, map, x, y) searches for any objects with |
2101 | * present_arch(arch, map, x, y) searches for any objects with |
2081 | * a matching archetype at the given map and coordinates. |
2102 | * a matching archetype at the given map and coordinates. |
2082 | * The first matching object is returned, or NULL if none. |
2103 | * The first matching object is returned, or NULL if none. |
2083 | */ |
2104 | */ |
2084 | |
2105 | |
2085 | object *present_arch(archetype *at, mapstruct *m, int x, int y) { |
2106 | object *present_arch(const archetype *at, mapstruct *m, int x, int y) { |
2086 | object *tmp; |
2107 | object *tmp; |
2087 | if(m==NULL || out_of_map(m,x,y)) { |
2108 | if(m==NULL || out_of_map(m,x,y)) { |
2088 | LOG(llevError,"Present_arch called outside map.\n"); |
2109 | LOG(llevError,"Present_arch called outside map.\n"); |
2089 | return NULL; |
2110 | return NULL; |
2090 | } |
2111 | } |
… | |
… | |
2116 | * present_in_ob(type, object) searches for any objects with |
2137 | * present_in_ob(type, object) searches for any objects with |
2117 | * a matching type variable in the inventory of the given object. |
2138 | * a matching type variable in the inventory of the given object. |
2118 | * The first matching object is returned, or NULL if none. |
2139 | * The first matching object is returned, or NULL if none. |
2119 | */ |
2140 | */ |
2120 | |
2141 | |
2121 | object *present_in_ob(unsigned char type,object *op) { |
2142 | object *present_in_ob(unsigned char type, const object *op) { |
2122 | object *tmp; |
2143 | object *tmp; |
2123 | for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) |
2144 | for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) |
2124 | if(tmp->type==type) |
2145 | if(tmp->type==type) |
2125 | return tmp; |
2146 | return tmp; |
2126 | return NULL; |
2147 | return NULL; |
… | |
… | |
2139 | * the object name, not the archetype name. this is so that the |
2160 | * the object name, not the archetype name. this is so that the |
2140 | * spell code can use one object type (force), but change it's name |
2161 | * spell code can use one object type (force), but change it's name |
2141 | * to be unique. |
2162 | * to be unique. |
2142 | */ |
2163 | */ |
2143 | |
2164 | |
2144 | object *present_in_ob_by_name(int type, char *str,object *op) { |
2165 | object *present_in_ob_by_name(int type, const char *str, const object *op) { |
2145 | object *tmp; |
2166 | object *tmp; |
2146 | |
2167 | |
2147 | for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { |
2168 | for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { |
2148 | if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name))) |
2169 | if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name))) |
2149 | return tmp; |
2170 | return tmp; |
… | |
… | |
2155 | * present_arch_in_ob(archetype, object) searches for any objects with |
2176 | * present_arch_in_ob(archetype, object) searches for any objects with |
2156 | * a matching archetype in the inventory of the given object. |
2177 | * a matching archetype in the inventory of the given object. |
2157 | * The first matching object is returned, or NULL if none. |
2178 | * The first matching object is returned, or NULL if none. |
2158 | */ |
2179 | */ |
2159 | |
2180 | |
2160 | object *present_arch_in_ob(archetype *at, object *op) { |
2181 | object *present_arch_in_ob(const archetype *at, const object *op) { |
2161 | object *tmp; |
2182 | object *tmp; |
2162 | for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) |
2183 | for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) |
2163 | if( tmp->arch == at) |
2184 | if( tmp->arch == at) |
2164 | return tmp; |
2185 | return tmp; |
2165 | return NULL; |
2186 | return NULL; |
… | |
… | |
2219 | * to know if the space in question will block the object. We can't use |
2240 | * to know if the space in question will block the object. We can't use |
2220 | * the archetype because that isn't correct if the monster has been |
2241 | * the archetype because that isn't correct if the monster has been |
2221 | * customized, changed states, etc. |
2242 | * customized, changed states, etc. |
2222 | */ |
2243 | */ |
2223 | |
2244 | |
2224 | int find_free_spot(object *ob, mapstruct *m,int x,int y,int start,int stop) { |
2245 | int find_free_spot(const object *ob, mapstruct *m,int x,int y,int start,int stop) { |
2225 | int i,index=0, flag; |
2246 | int i,index=0, flag; |
2226 | static int altern[SIZEOFFREE]; |
2247 | static int altern[SIZEOFFREE]; |
2227 | |
2248 | |
2228 | for(i=start;i<stop;i++) { |
2249 | for(i=start;i<stop;i++) { |
2229 | flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]); |
2250 | flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]); |
… | |
… | |
2250 | * find_free_spot(), but it will search max number of squares. |
2271 | * find_free_spot(), but it will search max number of squares. |
2251 | * But it will return the first available spot, not a random choice. |
2272 | * But it will return the first available spot, not a random choice. |
2252 | * Changed 0.93.2: Have it return -1 if there is no free spot available. |
2273 | * Changed 0.93.2: Have it return -1 if there is no free spot available. |
2253 | */ |
2274 | */ |
2254 | |
2275 | |
2255 | int find_first_free_spot(object *ob, mapstruct *m,int x,int y) { |
2276 | int find_first_free_spot(const object *ob, mapstruct *m,int x,int y) { |
2256 | int i; |
2277 | int i; |
2257 | for(i=0;i<SIZEOFFREE;i++) { |
2278 | for(i=0;i<SIZEOFFREE;i++) { |
2258 | if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i])) |
2279 | if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i])) |
2259 | return i; |
2280 | return i; |
2260 | } |
2281 | } |
… | |
… | |
2361 | /* |
2382 | /* |
2362 | * distance(object 1, object 2) will return the square of the |
2383 | * distance(object 1, object 2) will return the square of the |
2363 | * distance between the two given objects. |
2384 | * distance between the two given objects. |
2364 | */ |
2385 | */ |
2365 | |
2386 | |
2366 | int distance(object *ob1,object *ob2) { |
2387 | int distance(const object *ob1, const object *ob2) { |
2367 | int i; |
2388 | int i; |
2368 | i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+ |
2389 | i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+ |
2369 | (ob1->y - ob2->y)*(ob1->y - ob2->y); |
2390 | (ob1->y - ob2->y)*(ob1->y - ob2->y); |
2370 | return i; |
2391 | return i; |
2371 | } |
2392 | } |
… | |
… | |
2536 | * core dumps if they do. |
2557 | * core dumps if they do. |
2537 | * |
2558 | * |
2538 | * Add a check so we can't pick up invisible objects (0.93.8) |
2559 | * Add a check so we can't pick up invisible objects (0.93.8) |
2539 | */ |
2560 | */ |
2540 | |
2561 | |
2541 | int can_pick(object *who,object *item) { |
2562 | int can_pick(const object *who, const object *item) { |
2542 | return /*QUERY_FLAG(who,FLAG_WIZ)||*/ |
2563 | return /*QUERY_FLAG(who,FLAG_WIZ)||*/ |
2543 | (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&& |
2564 | (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&& |
2544 | !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible && |
2565 | !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible && |
2545 | (who->type==PLAYER||item->weight<who->weight/3)); |
2566 | (who->type==PLAYER||item->weight<who->weight/3)); |
2546 | } |
2567 | } |
… | |
… | |
2581 | |
2602 | |
2582 | return dst; |
2603 | return dst; |
2583 | } |
2604 | } |
2584 | |
2605 | |
2585 | /* return true if the object was destroyed, 0 otherwise */ |
2606 | /* return true if the object was destroyed, 0 otherwise */ |
2586 | int was_destroyed (object *op, tag_t old_tag) |
2607 | int was_destroyed (const object *op, tag_t old_tag) |
2587 | { |
2608 | { |
2588 | /* checking for FLAG_FREED isn't necessary, but makes this function more |
2609 | /* checking for FLAG_FREED isn't necessary, but makes this function more |
2589 | * robust */ |
2610 | * robust */ |
2590 | return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED); |
2611 | return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED); |
2591 | } |
2612 | } |
… | |
… | |
2595 | /* load_object on it. I admit it is a highly inefficient way to make things, */ |
2616 | /* load_object on it. I admit it is a highly inefficient way to make things, */ |
2596 | /* but it was simple to make and allows reusing the load_object function. */ |
2617 | /* but it was simple to make and allows reusing the load_object function. */ |
2597 | /* Remember not to use load_object_str in a time-critical situation. */ |
2618 | /* Remember not to use load_object_str in a time-critical situation. */ |
2598 | /* Also remember that multiparts objects are not supported for now. */ |
2619 | /* Also remember that multiparts objects are not supported for now. */ |
2599 | |
2620 | |
2600 | object* load_object_str(char *obstr) |
2621 | object* load_object_str(const char *obstr) |
2601 | { |
2622 | { |
2602 | object *op; |
2623 | object *op; |
2603 | FILE *tempfile; |
2624 | FILE *tempfile; |
2604 | char filename[MAX_BUF]; |
2625 | char filename[MAX_BUF]; |
2605 | sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir); |
2626 | sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir); |
… | |
… | |
2629 | |
2650 | |
2630 | /* This returns the first object in who's inventory that |
2651 | /* This returns the first object in who's inventory that |
2631 | * has the same type and subtype match. |
2652 | * has the same type and subtype match. |
2632 | * returns NULL if no match. |
2653 | * returns NULL if no match. |
2633 | */ |
2654 | */ |
2634 | object *find_obj_by_type_subtype(object *who, int type, int subtype) |
2655 | object *find_obj_by_type_subtype(const object *who, int type, int subtype) |
2635 | { |
2656 | { |
2636 | object *tmp; |
2657 | object *tmp; |
2637 | |
2658 | |
2638 | for (tmp=who->inv; tmp; tmp=tmp->below) |
2659 | for (tmp=who->inv; tmp; tmp=tmp->below) |
2639 | if (tmp->type == type && tmp->subtype == subtype) return tmp; |
2660 | if (tmp->type == type && tmp->subtype == subtype) return tmp; |
… | |
… | |
2645 | * otherwise return NULL. |
2666 | * otherwise return NULL. |
2646 | * |
2667 | * |
2647 | * key must be a passed in shared string - otherwise, this won't |
2668 | * key must be a passed in shared string - otherwise, this won't |
2648 | * do the desired thing. |
2669 | * do the desired thing. |
2649 | */ |
2670 | */ |
2650 | key_value * get_ob_key_link(object * ob, const char * key) { |
2671 | key_value * get_ob_key_link(const object * ob, const char * key) { |
2651 | key_value * link; |
2672 | key_value * link; |
2652 | |
2673 | |
2653 | for (link = ob->key_values; link != NULL; link = link->next) { |
2674 | for (link = ob->key_values; link != NULL; link = link->next) { |
2654 | if (link->key == key) { |
2675 | if (link->key == key) { |
2655 | return link; |
2676 | return link; |
… | |
… | |
2664 | * |
2685 | * |
2665 | * The argument doesn't need to be a shared string. |
2686 | * The argument doesn't need to be a shared string. |
2666 | * |
2687 | * |
2667 | * The returned string is shared. |
2688 | * The returned string is shared. |
2668 | */ |
2689 | */ |
2669 | const char * get_ob_key_value(object * op, const char * const key) { |
2690 | const char * get_ob_key_value(const object * op, const char * const key) { |
2670 | key_value * link; |
2691 | key_value * link; |
2671 | const char * canonical_key; |
2692 | const char * canonical_key; |
2672 | |
2693 | |
2673 | canonical_key = find_string(key); |
2694 | canonical_key = find_string(key); |
2674 | |
2695 | |
… | |
… | |
2704 | * Returns TRUE on success. |
2725 | * Returns TRUE on success. |
2705 | */ |
2726 | */ |
2706 | int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) { |
2727 | int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) { |
2707 | key_value * field = NULL, *last=NULL; |
2728 | key_value * field = NULL, *last=NULL; |
2708 | |
2729 | |
2709 | LOG(llevDebug, "set_ob_value_s: '%s' '%s' %d\n", canonical_key, value, add_key); |
|
|
2710 | |
|
|
2711 | for (field=op->key_values; field != NULL; field=field->next) { |
2730 | for (field=op->key_values; field != NULL; field=field->next) { |
2712 | if (field->key != canonical_key) { |
2731 | if (field->key != canonical_key) { |
2713 | last = field; |
2732 | last = field; |
2714 | continue; |
2733 | continue; |
2715 | } |
2734 | } |