#include "base/multidimarray.h"

loadMultiDimArray::loadMultiDimArray
  (AT_Write_Rand_File *f,
   uint num_dims) :
  file(f),
  tot_dims(num_dims),
  header(new uint64[num_dims + 1])
{
  file->write(&tot_dims, sizeof(tot_dims));
  header_pos = f->getPos();

  file->seek(header_pos + sizeof(uint64) * (tot_dims + 1));
}

void loadMultiDimArray::startDim
  (uint dim)
{
  header[dim] = file->getPos();
}

void loadMultiDimArray::addNum
  (term_val n)
{
  file->write(&n, sizeof(term_val));
}

void loadMultiDimArray::write
  ()
{
  uint64 save_pos = file->getPos();

  file->seek(header_pos);

  header[tot_dims] = save_pos;
  
  file->write(header.get(), sizeof(uint64) * (tot_dims + 1));

  file->seek(save_pos);
}

readMultiDimArray::readMultiDimArray
  (AT_Read_Rand_File *f) :
  file(f),
  cur_pos(0),
  cur_size(0),
  page_cnt(0)
{
  file->read(&tot_dims, sizeof(tot_dims));
  header = new uint64 [tot_dims + 1];

  file->read(header.get(), sizeof(uint64) * (tot_dims + 1));
}

bool readMultiDimArray::startDim
  (uint dim)
{
  if (dim >= tot_dims)
    return false;

  uint term_off = header[dim];
  cur_size = uint(header[dim + 1] - term_off);

  file->seek(term_off);
  file->read(buf, std::min(cur_size, (uint)MAX_READ_SIZE));

  cur_pos = 0;
  page_cnt = 0;

  return true;
}


term_val readMultiDimArray::getNum
  ()
{
  term_val ret = 0;

  if ((cur_pos / sizeof(term_val)) >= count())
    return MAXUINT;

  if ((cur_pos - page_cnt * MAX_READ_SIZE) < MAX_READ_SIZE)
    ret = *((term_val *)&buf[cur_pos - page_cnt * MAX_READ_SIZE]);
  else
  {
    file->read(buf, std::min(cur_size - cur_pos, (uint)MAX_READ_SIZE));
    ++page_cnt;
    ret = *((term_val *)&buf[cur_pos - page_cnt * MAX_READ_SIZE]);
  }
  cur_pos += sizeof(term_val);
  
  return ret;
}

