/*********************************************************
** Copyright (c) 2005
** University of Washington
** Licensed under the terms set forth by University of
** Washington. If you did not sign such a license, you
** are using this software/code illegally and you do not
** have permission to use, modify, or redistribute
** this or any files in this software package.
**
** File: DataIO.cpp
**
**********************************************************/
#include "DataIO.h"
#include <assert.h>
#include <stdlib.h>
#include <sstream>

CDelimitedMatrixWriter::CDelimitedMatrixWriter()
  : m_cDelim('\t')
{
}

CDelimitedMatrixWriter::CDelimitedMatrixWriter(char cDelim)
  : m_cDelim(cDelim)
{
}

void CDelimitedMatrixWriter::Write
(double** ppMatrix, int rowCount, int rowLength, ostream &ostr)
{
  for (int row = 0; row < rowCount; row++)
    {
      int col;
      for(col = 0; col < rowLength - 1; col++)
	{
	  ostr << ppMatrix[row][col] << m_cDelim;
	}
      ostr << ppMatrix[row][col] << "\n";
    }
}

CDelimitedMatrixReader::CDelimitedMatrixReader()
  : m_cDelim('\t')
{
}

CDelimitedMatrixReader::CDelimitedMatrixReader(char cDelim)
  : m_cDelim(cDelim)
{
}

void CDelimitedMatrixReader::Read(istream &istr, int* pRowCount, int* pRowLength, TDoubleVector*** pppVectors)
{
  assert( NULL != pRowCount );
  assert( NULL != pRowLength );
  assert( NULL != pppVectors );

  assert (istr.good());

  char c;
  istr.get(c);
  bool bFirstRow = true;
  vector<TDoubleVector*> vecRows;
  TDoubleVector* pVec = NULL;
  
  while (!istr.eof())
    {
      pVec = new TDoubleVector();
      while (c != '\n' && !istr.eof())
	{
	  string tok;
	  while (c != '\t' && c != '\n' && !istr.eof())
	    {
	      tok.push_back(c);
	      istr.get(c);
	    }

	  pVec->push_back(atof(tok.c_str()));
       	  if('\n' != c && !istr.eof())
	    {
	      istr.get(c);
	    }
	}
      if (bFirstRow)
	{
	  *pRowLength = pVec->size();
	  bFirstRow = false;
	}
      vecRows.push_back(pVec);
      if (!istr.eof())
	istr.get(c);
    }

  *pRowCount = vecRows.size();

  *pppVectors = new TDoubleVector*[*pRowCount];

  vector<TDoubleVector*>::iterator rowIter = vecRows.begin();
  for(int row = 0; row < *pRowCount; row++, rowIter++)
    {
      (*pppVectors)[row] = *rowIter;
    }

}

/*void CDelimitedMatrixReader::Read(istream &istr, int* pRowCount, int* pRowLength, TDoubleVector*** pppVectors)
{
  assert( NULL != pRowCount );
  assert( NULL != pRowLength );
  assert( NULL != pppVectors );

  char c[256];
  stringbuf linebuf;

  // get the first line.
  istr.get(linebuf);
  // get and ignore the end-of-line character.
  istr.get();

  // put it into its own istream
  stringstream linestr(linebuf.str());

  // count the number of elements while inserting them into a new vector
  TDoubleVector* pVec = new vector<double>();
  int col;
  while(!linestr.eof())
    {
      linestr.getline(c, 256, m_cDelim);
      pVec->push_back(atof(c));
    }

  *pRowLength = pVec->size();

  vector<TDoubleVector*> vecRows;
  vecRows.push_back(pVec);

  while (!istr.eof())
    {
      pVec = new TDoubleVector();

      char cPeek = istr.peek();
      if (cPeek == EOF)
	break;

      int col;
      for(col = 0; col < *pRowLength - 1; col++)
	{
	  assert (!istr.eof());
	  istr.getline(c, 256, m_cDelim);
	  pVec->push_back(atof(c));
	}
      istr.getline(c, 256, '\n');
      pVec->push_back(atof(c));
      
      vecRows.push_back(pVec);
    }
  *pRowCount = vecRows.size();

  *pppVectors = new TDoubleVector*[*pRowCount];

  vector<TDoubleVector*>::iterator rowIter = vecRows.begin();
  for(int row = 0; row < *pRowCount; row++, rowIter++)
    {
      (*pppVectors)[row] = *rowIter;
    }

}
*/

void CDelimitedMatrixReader::Read(istream &istr, int* pRowCount, int* pRowLength, double*** pppMatrix)
{
  TDoubleVector** ppVecs;
  Read(istr, pRowCount, pRowLength, &ppVecs);
  assert( NULL != ppVecs);

  // convert each vector into an array of doubles
  // then free the vectors
  *pppMatrix = new double*[*pRowCount];

  for(int i = 0; i < *pRowCount; i++)
    {
      assert(ppVecs[i]->size() == (unsigned int)*pRowLength);

      (*pppMatrix)[i] = new double[*pRowLength];

      TDoubleVector::iterator jIter = ppVecs[i]->begin();
      for(int j = 0; jIter != ppVecs[i]->end(); jIter++, j++)
	{
	  (*pppMatrix)[i][j] = *jIter;
	}

      delete ppVecs[i];
    }

  
  delete ppVecs;
}
