/*
 * $Id: wide_values.c,v 1.3 1997/10/25 16:55:02 grubba Exp $
 *
 * Wide values
 */

#include "machine.h"
#include "global.h"
RCSID("$Id: wide_values.c,v 1.3 1997/10/25 16:55:02 grubba Exp $");
#include "stralloc.h"
#include "pike_macros.h"
#include "object.h"
#include "program.h"
#include "interpret.h"
#include "builtin_functions.h"
#include "module_support.h"
#include "error.h"

static void f_wide_values(INT32 args)
{
  struct pike_string *s;
  INT32 item, i, n, size;
  unsigned char *str;
  
  get_all_args("WideValues.wide_values", args, "%S%i", &s, &n);
  s->refs++;
  pop_n_elems(args);
  
  if(n < 1 || n > 4)
    error("wide_values: illegal divisor size.\n");
  if(s->len%n)
    error("wide_values: string not evenly divisible.\n");

  size = s->len;
  str = (unsigned char *)s->str;
  switch(n) {
  case 1:
    for(i = 0; i < size; i++)
      push_int(*((unsigned char *)s->str+i));
    break;
  case 2:
    for(i = 0; i < size; i += 2) {
      item = (str[i]<<8) + str[i+1];
      push_int(item);
    }
    break;
  case 3:
    for(i = 0; i < size; i += 3) {
      item = (str[i]<<16) + (str[i+1]<<8) + str[i+2];
      push_int(item);
    }
    break;
  case 4:
    for(i = 0; i < size; i += 4) {
      item = (str[i]<<24) + (str[i+1]<<16) + (str[i+2]<<8) + str[i+3];
      push_int(item);
    }
    break;
  }
  f_aggregate(size/n);
  free_string(s);
}

void pike_module_init(void)
{
  add_function_constant("wide_values", f_wide_values,
			"function(string,int:array(int))", OPT_TRY_OPTIMIZE);
}

void pike_module_exit( void )
{
}
