diff --git a/src/builtin_functions.c b/src/builtin_functions.c index a6938b205b6470669e2122f0c22177c34f5c0730..211def40ca9c6dce7d92f6bf21be390d81a5cb92 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.246 2000/03/24 01:24:49 hubbe Exp $"); +RCSID("$Id: builtin_functions.c,v 1.247 2000/03/26 01:55:11 mast Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -5981,6 +5981,10 @@ void init_builtin_efuns(void) ADD_EFUN("encode_value", f_encode_value, tFunc(tMix tOr(tVoid,tObj),tStr), OPT_TRY_OPTIMIZE); + /* function(mixed,void|object:string) */ + ADD_EFUN("encode_value_canonic", f_encode_value_canonic, + tFunc(tMix tOr(tVoid,tObj),tStr), OPT_TRY_OPTIMIZE); + /* function(string,void|object:mixed) */ ADD_EFUN("decode_value", f_decode_value, tFunc(tStr tOr(tVoid,tObj),tMix), OPT_TRY_OPTIMIZE); diff --git a/src/encode.c b/src/encode.c index 9608efbc2ff64851d27d437efc8884bcaa119e48..301ddcdecccf49f3699012e0cb0c97d9b3aef0b1 100644 --- a/src/encode.c +++ b/src/encode.c @@ -25,7 +25,7 @@ #include "version.h" #include "bignum.h" -RCSID("$Id: encode.c,v 1.54 2000/02/16 03:58:16 per Exp $"); +RCSID("$Id: encode.c,v 1.55 2000/03/26 01:55:11 mast Exp $"); /* #define ENCODE_DEBUG */ @@ -103,6 +103,7 @@ double LDEXP(double x, int exp) struct encode_data { + int canonic; struct object *codec; struct svalue counter; struct mapping *encoded; @@ -360,7 +361,9 @@ static void encode_value2(struct svalue *val, struct encode_data *data) break; case T_TYPE: - error("Encoding of the type type not supported yet!"); + if (data->canonic) + error("Canonical encoding of the type type not supported.\n"); + error("Encoding of the type type not supported yet!\n"); break; case T_FLOAT: @@ -404,6 +407,22 @@ static void encode_value2(struct svalue *val, struct encode_data *data) ref_push_mapping(val->u.mapping); f_values(1); + if (data->canonic) { + INT32 *order; + if (val->u.mapping->data->ind_types & ~(BIT_BASIC & ~BIT_TYPE)) { + mapping_fix_type_field(val->u.mapping); + if (val->u.mapping->data->ind_types & ~(BIT_BASIC & ~BIT_TYPE)) + /* This doesn't let bignums through. That's necessary as + * long as they aren't handled deterministically by the + * sort function. */ + error("Canonical encoding requires basic types in indices.\n"); + } + order = get_switch_order(sp[-2].u.array); + order_array(sp[-2].u.array, order); + order_array(sp[-1].u.array, order); + free((char *) order); + } + code_entry(TAG_MAPPING, sp[-2].u.array->size,data); for(i=0; i<sp[-2].u.array->size; i++) { @@ -415,8 +434,28 @@ static void encode_value2(struct svalue *val, struct encode_data *data) case T_MULTISET: code_entry(TAG_MULTISET, val->u.multiset->ind->size,data); - for(i=0; i<val->u.multiset->ind->size; i++) - encode_value2(ITEM(val->u.multiset->ind)+i, data); + if (data->canonic) { + INT32 *order; + if (val->u.multiset->ind->type_field & ~(BIT_BASIC & ~BIT_TYPE)) { + array_fix_type_field(val->u.multiset->ind); + if (val->u.multiset->ind->type_field & ~(BIT_BASIC & ~BIT_TYPE)) + /* This doesn't let bignums through. That's necessary as + * long as they aren't handled deterministically by the + * sort function. */ + error("Canonical encoding requires basic types in indices.\n"); + } + check_stack(1); + ref_push_array(val->u.multiset->ind); + order = get_switch_order(sp[-1].u.array); + order_array(sp[-1].u.array, order); + free((char *) order); + for (i = 0; i < sp[-1].u.array->size; i++) + encode_value2(ITEM(sp[-1].u.array)+i, data); + pop_stack(); + } + else + for(i=0; i<val->u.multiset->ind->size; i++) + encode_value2(ITEM(val->u.multiset->ind)+i, data); break; case T_OBJECT: @@ -442,6 +481,8 @@ static void encode_value2(struct svalue *val, struct encode_data *data) } #endif + if (data->canonic) + error("Canonical encoding of objects not supported.\n"); push_svalue(val); apply(data->codec, "nameof", 1); switch(sp[-1].type) @@ -472,6 +513,8 @@ static void encode_value2(struct svalue *val, struct encode_data *data) break; case T_FUNCTION: + if (data->canonic) + error("Canonical encoding of functions not supported.\n"); check_stack(1); push_svalue(val); apply(data->codec,"nameof", 1); @@ -518,6 +561,8 @@ static void encode_value2(struct svalue *val, struct encode_data *data) case T_PROGRAM: { int d; + if (data->canonic) + error("Canonical encoding of programs not supported.\n"); check_stack(1); push_svalue(val); apply(data->codec,"nameof", 1); @@ -627,6 +672,38 @@ void f_encode_value(INT32 args) check_all_args("encode_value", args, BIT_MIXED, BIT_VOID | BIT_OBJECT, 0); initialize_buf(&data->buf); + data->canonic = 0; + data->encoded=allocate_mapping(128); + data->counter.type=T_INT; + data->counter.u.integer=COUNTER_START; + if(args > 1) + { + data->codec=sp[1-args].u.object; + }else{ + data->codec=get_master(); + } + + SET_ONERROR(tmp, free_encode_data, data); + addstr("\266ke0", 4); + encode_value2(sp-args, data); + UNSET_ONERROR(tmp); + + free_mapping(data->encoded); + + pop_n_elems(args); + push_string(low_free_buf(&data->buf)); +} + +void f_encode_value_canonic(INT32 args) +{ + ONERROR tmp; + struct encode_data d, *data; + data=&d; + + check_all_args("encode_value_canonic", args, BIT_MIXED, BIT_VOID | BIT_OBJECT, 0); + + initialize_buf(&data->buf); + data->canonic = 1; data->encoded=allocate_mapping(128); data->counter.type=T_INT; data->counter.u.integer=COUNTER_START; diff --git a/src/encode.h b/src/encode.h index 77e4f42a65796354cb8defd349d43ef7b6bb44b3..4b3d489d9b4ea5de3401c0f882812070b156ec8c 100644 --- a/src/encode.h +++ b/src/encode.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: encode.h,v 1.2 1998/03/28 15:31:23 grubba Exp $ + * $Id: encode.h,v 1.3 2000/03/26 01:55:11 mast Exp $ */ #ifndef ENCODE_H #define ENCODE_H @@ -13,6 +13,7 @@ /* Prototypes begin here */ struct encode_data; void f_encode_value(INT32 args); +void f_encode_value_canonic(INT32 args); struct decode_data; void f_decode_value(INT32 args); /* Prototypes end here */