4728522003-03-06Henrik Grubbström (Grubba) #pike __REAL_VERSION__
1b3d4e2003-03-08Martin Nilsson #pragma strict_types
83c38b2004-09-14Henrik Grubbström (Grubba)  //! Various Abstract Data Types.
8a4e052003-03-27Henrik Grubbström (Grubba) #if constant(_ADT)
d25bf52003-02-12Andreas Pettersson inherit _ADT;
8a4e052003-03-27Henrik Grubbström (Grubba) #endif /* _ADT */
4728522003-03-06Henrik Grubbström (Grubba) 
83c38b2004-09-14Henrik Grubbström (Grubba) constant List = __builtin.List;
25616a2004-03-23Martin Nilsson 
e391e72005-01-04Martin Nilsson // Internal stuff for ADT.Struct
9eaf1d2008-06-28Martin Nilsson protected int item_counter;
e391e72005-01-04Martin Nilsson int get_item_id() { return item_counter++; }
d5ab1f2014-05-04Martin Nilsson protected class structError { inherit Error.Generic; constant ADT_struct = 1; }
5b15a92003-03-07Martin Nilsson //! String buffer with the possibility to read and write data //! as they would be formatted in structs.
4728522003-03-06Henrik Grubbström (Grubba) class struct {
cb65012014-10-01Martin Nilsson  inherit Stdio.Buffer;
4728522003-03-06Henrik Grubbström (Grubba) 
5b15a92003-03-07Martin Nilsson  //! Create a new buffer, optionally initialized with the //! value @[s].
7fc2bb2013-12-08Henrik Grubbström (Grubba)  void create(void|string(0..255) s)
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  if( s && strlen(s) ) ::create(s); else ::create(); set_error_mode(structError);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Trims the buffer to only contain the data after the //! read pointer and returns the contents of the buffer.
7fc2bb2013-12-08Henrik Grubbström (Grubba)  string(0..255) contents()
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  return (string(8bit))this;
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Adds the data @[s] verbatim to the end of the buffer.
b44ad22014-05-04Martin Nilsson  this_program add_data(string(0..255) s)
4728522003-03-06Henrik Grubbström (Grubba)  {
b866a82014-09-02Per Hedbor  return [object(this_program)]add(s);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Return all the data in the buffer and empties it.
7fc2bb2013-12-08Henrik Grubbström (Grubba)  string(0..255) pop_data()
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  return read();
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Appends an unsigned integer in network order to the buffer.
4728522003-03-06Henrik Grubbström (Grubba)  //! //! @param i
5b15a92003-03-07Martin Nilsson  //! Unsigned integer to append.
4728522003-03-06Henrik Grubbström (Grubba)  //! @param len
5b15a92003-03-07Martin Nilsson  //! Length of integer in bytes.
b44ad22014-05-04Martin Nilsson  this_program put_uint(int i, int(0..) len)
4728522003-03-06Henrik Grubbström (Grubba)  {
b866a82014-09-02Per Hedbor  return [object(this_program)]add_int(i,len);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Appends a variable string @[s] preceded with an unsigned integer //! of the size @[len_width] declaring the length of the string. The //! string @[s] should be 8 bits wide.
b44ad22014-05-04Martin Nilsson  this_program put_var_string(string(0..255) s, int(0..) len_width)
4728522003-03-06Henrik Grubbström (Grubba)  {
b866a82014-09-02Per Hedbor  return [object(this_program)]add_hstring(s,len_width);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Appends a bignum @[i] as a variable string preceded with an //! unsigned integer of the size @[len_width] declaring the length //! of the string. @[len_width] defaults to 2.
b44ad22014-05-04Martin Nilsson  this_program put_bignum(Gmp.mpz i, int(0..)|void len_width)
4728522003-03-06Henrik Grubbström (Grubba)  {
b866a82014-09-02Per Hedbor  return [object(this_program)]add_hstring(i->digits(256),len_width||2);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Appends the fix sized string @[s] to the buffer.
b44ad22014-05-04Martin Nilsson  this_program put_fix_string(string(0..255) s)
4728522003-03-06Henrik Grubbström (Grubba)  {
b866a82014-09-02Per Hedbor  return [object(this_program)]add(s);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Appends an array of unsigned integers of width @[item_size] //! to the buffer.
b44ad22014-05-04Martin Nilsson  this_program put_fix_uint_array(array(int) data, int(0..) item_size)
4728522003-03-06Henrik Grubbström (Grubba)  {
b866a82014-09-02Per Hedbor  return [object(this_program)]add_ints(data,item_size);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Appends an array of unsigned integers of width @[item_size] //! to the buffer, preceded with an unsigned integer @[len] declaring
ff2e2c2014-05-08Martin Nilsson  //! the size of the array in bytes.
b44ad22014-05-04Martin Nilsson  this_program put_var_uint_array(array(int) data, int(0..) item_size, int(0..) len)
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  add_int(sizeof(data)*item_size, len );
b866a82014-09-02Per Hedbor  return [object(this_program)]add_ints(data,item_size);
2ccca22014-05-10Martin Nilsson  }
49a2122014-05-31Martin Nilsson  //! Appends an array of variable length strings with @[item_size] //! bytes hollerith coding, prefixed by a @[len] bytes large integer //! declaring the total size of the array in bytes.
2ccca22014-05-10Martin Nilsson  this_program put_var_string_array(array(string(8bit)) data, int(0..) item_size, int(0..) len) {
cb65012014-10-01Martin Nilsson  Stdio.Buffer sub = Stdio.Buffer();
2ccca22014-05-10Martin Nilsson  foreach(data, string(8bit) s)
be63f92014-09-01Per Hedbor  sub->add_hstring(s, item_size); add_int(sizeof(sub),len);
b866a82014-09-02Per Hedbor  return [object(this_program)]add(sub);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Reads an unsigned integer from the buffer. int(0..) get_uint(int len)
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  return read_int(len);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Reads a fixed sized string of length @[len] from the buffer.
7fc2bb2013-12-08Henrik Grubbström (Grubba)  string(0..255) get_fix_string(int len)
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  return read(len);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Reads a string written by @[put_var_string] from the buffer.
7fc2bb2013-12-08Henrik Grubbström (Grubba)  string(0..255) get_var_string(int len)
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  return read_hstring(len);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Reads a bignum written by @[put_bignum] from the buffer. Gmp.mpz get_bignum(int|void len)
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  return Gmp.mpz(read_hstring(len||2),256);
4728522003-03-06Henrik Grubbström (Grubba)  }
5b15a92003-03-07Martin Nilsson  //! Get the remaining data from the buffer and clears the buffer.
7fc2bb2013-12-08Henrik Grubbström (Grubba)  string(0..255) get_rest()
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  return read();
4728522003-03-06Henrik Grubbström (Grubba)  }
328cf92003-11-07Martin Nilsson  //! Reads an array of integers as written by @[put_fix_uint_array]
5b15a92003-03-07Martin Nilsson  //! from the buffer.
b6345f2004-01-23Martin Nilsson  array(int) get_fix_uint_array(int item_size, int size)
4728522003-03-06Henrik Grubbström (Grubba)  {
6f628b2014-11-24Martin Nilsson  return read_ints(size, item_size);
4728522003-03-06Henrik Grubbström (Grubba)  }
328cf92003-11-07Martin Nilsson  //! Reads an array of integers as written by @[put_var_uint_array]
5b15a92003-03-07Martin Nilsson  //! from the buffer.
b6345f2004-01-23Martin Nilsson  array(int) get_var_uint_array(int item_size, int len)
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  int size = read_int(len);
ff2e2c2014-05-08Martin Nilsson  int elems = size/item_size; if( elems*item_size != size ) throw(structError("Impossible uint array length value.\n"));
6f628b2014-11-24Martin Nilsson  return read_ints(elems, item_size);
4728522003-03-06Henrik Grubbström (Grubba)  }
be63f92014-09-01Per Hedbor  //! Returns one if there is any more data to read.
5b15a92003-03-07Martin Nilsson  int(0..1) is_empty()
4728522003-03-06Henrik Grubbström (Grubba)  {
be63f92014-09-01Per Hedbor  return !sizeof(this);
ff95532013-11-13Martin Nilsson  }
4728522003-03-06Henrik Grubbström (Grubba) }