Branch: Tag:

1997-10-07

1997-10-07 11:50:37 by Fredrik Hübinette (Hubbe) <hubbe@hubbe.net>

new encode handles cyclic object references

Rev: src/encode.c:1.11

13:   #include "mapping.h"   #include "array.h"   #include "multiset.h" - #include "builtin_functions.h" +    #include "dynamic_buffer.h"   #include "error.h" -  + #include "operators.h" + #include "builtin_functions.h"      #ifdef _AIX   #include <net/nh.h>
119:    }   }    + #ifdef DEBUG + #define encode_value2 encode_value2_ + #endif +    static void encode_value2(struct svalue *val, struct encode_data *data) -  +  + #ifdef DEBUG + #undef encode_value2 + #define encode_value2(X,Y) do { struct svalue *_=sp; encode_value2_(X,Y); if(sp!=_) fatal("encode_value2 failed!\n"); } while(0); + #endif +    { -  +  static struct svalue dested = { T_INT, NUMBER_DESTRUCTED };    INT32 i;    struct svalue *tmp; -  +  +  if((val->type == T_OBJECT || val->type==T_FUNCTION) && !val->u.object->prog) +  val=&dested; +     if((tmp=low_mapping_lookup(data->encoded, val)))    {    code_entry(T_AGAIN, tmp->u.integer, data);
132:    data->counter.u.integer++;    }    +     switch(val->type)    {    case T_INT:
176:       case T_MAPPING:    check_stack(2); -  val->u.mapping->refs++; -  push_mapping(val->u.mapping); +  ref_push_mapping(val->u.mapping);    f_indices(1);    -  val->u.mapping->refs++; -  push_mapping(val->u.mapping); +  ref_push_mapping(val->u.mapping);    f_values(1);       code_entry(T_MAPPING, sp[-2].u.array->size,data);
200:    break;       case T_OBJECT: +  check_stack(1); +  push_svalue(val); +  APPLY_MASTER("nameof", 1); +  switch(sp[-1].type) +  { +  case T_INT: +  if(sp[-1].subtype == NUMBER_UNDEFINED) +  { +  struct svalue s; +  s.type = T_PROGRAM; +  s.u.program=val->u.object->prog; +  +  pop_stack(); +  code_entry(val->type, 1,data); +  encode_value2(&s, data); +  +  push_svalue(val); +  APPLY_MASTER("encode_object",1); +  break; +  } +  /* FALL THROUGH */ +  +  default: +  code_entry(val->type, 0,data); +  break; +  +  } +  encode_value2(sp-1, data); +  pop_stack(); +  break; +     case T_FUNCTION: -  +  check_stack(1); +  push_svalue(val); +  APPLY_MASTER("nameof", 1); +  if(sp[-1].type == T_INT && sp[-1].subtype==NUMBER_UNDEFINED) +  { +  if(val->subtype != FUNCTION_BUILTIN) +  { +  int eq; +  code_entry(val->type, 1, data); +  push_svalue(val); +  sp[-1].type=T_OBJECT; +  ref_push_string(ID_FROM_INT(val->u.object->prog, val->subtype)->name); +  f_arrow(2); +  eq=is_eq(sp-1, val); +  pop_stack(); +  if(eq) +  { +  /* We have to remove ourself from the cache for now */ +  struct svalue tmp=data->counter; +  tmp.u.integer--; +  map_delete(data->encoded, val); +  +  push_svalue(val); +  sp[-1].type=T_OBJECT; +  encode_value2(sp-1, data); +  ref_push_string(ID_FROM_INT(val->u.object->prog, val->subtype)->name); +  encode_value2(sp-1, data); +  pop_n_elems(3); +  +  /* Put value back in cache */ +  mapping_insert(data->encoded, val, &tmp); +  return; +  } +  } +  } +  +  code_entry(val->type, 0,data); +  encode_value2(sp-1, data); +  pop_stack(); +  break; +  +     case T_PROGRAM:    check_stack(1);    push_svalue(val);
271:    } \    if(what & T_NEG) num=~num    + #ifdef DEBUG + #define decode_value2 decode_value2_ + #endif +    static void decode_value2(struct decode_data *data) -  +  + #ifdef DEBUG + #undef decode_value2 + #define decode_value2(X) do { struct svalue *_=sp; decode_value2_(X); if(sp!=_+1) fatal("decode_value2 failed!\n"); } while(0); + #endif +  +    {    INT32 what, e, num;    struct svalue tmp, *tmp2;
387:    return;    }    +     case T_OBJECT: -  +  tmp=data->counter; +  data->counter.u.integer++; +  decode_value2(data); +  +  switch(num) +  { +  case 0: +  APPLY_MASTER("objectof", 1); +  break; +  +  case 1: +  if(IS_ZERO(sp-1)) +  { +  mapping_insert(data->decoded, &tmp, sp-1); +  decode_value2(data); +  pop_stack(); +  }else{ +  f_call_function(1); +  mapping_insert(data->decoded, &tmp, sp-1); +  push_svalue(sp-1); +  decode_value2(data); +  APPLY_MASTER("decode_object",2); +  pop_stack(); +  } +  return; +  +  default: +  error("Object coding not compatible.\n"); +  break; +  } +  break; +     case T_FUNCTION: -  case T_PROGRAM: +     tmp=data->counter;    data->counter.u.integer++;    decode_value2(data); -  switch(what & T_MASK) +  +  switch(num)    { -  case T_OBJECT: APPLY_MASTER("objectof", 1); break; -  case T_FUNCTION: APPLY_MASTER("functionof", 1); break; -  case T_PROGRAM: APPLY_MASTER("programof", 1); break; +  case 0: +  APPLY_MASTER("objectof", 1); +  break; +  +  case 1: +  decode_value2(data); +  f_arrow(2); +  break; +  +  default: +  error("Function coding not compatible.\n"); +  break;    }    break;    -  +  +  case T_PROGRAM: +  tmp=data->counter; +  data->counter.u.integer++; +  decode_value2(data); +  APPLY_MASTER("programof", 1); +  break; +     default:    error("Failed to restore string. (Illegal type)\n");    }
542:    struct pike_string *s;       if(args != 1 || (sp[-1].type != T_STRING)) -  error("Illegal argument to restore_value(STRING)\n"); +  error("Illegal argument to decode_value()\n");       s = sp[-1].u.string;    if(!my_decode(s))