#include <cassert>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>

using namespace std;


#include <streamconversion.h>


void asciitodig::forward( string & os, istream & is ) 
{
  char ch;
  uint w;
  is.unsetf(ios::skipws);
  while (is.eof()==false)
  {
    is >> ch;
    if (is.eof())
      break;
    w = (uint)ch;
  
    stringstream ss;
    if (w==0)
      ss << "000";
    else
    if (w<10)
      ss << "00" << w;
    else
    if (w<100)
      ss << "0" << w;
    else
      ss << w;

    os += ss.str();
  }
}

void asciitodig::reverse
(
  ostream & os,
  string const & in
) 
{
  assert((in.size()%3)==0);
  uintc n = in.size()/3;

  string s;
  char c;
  uint x;
  for (uint k=0; k<n; ++k) 
  {
    s = in.substr(3*k,3);
    stringstream ss(s.c_str());
    ss >> x;
    c = (char)x;
    os << c;
  }
}


  


// digdiv::pad  Note:
//   This is written out and is public when the object is saved.
//   If this class is used for cryptography then this is only
//   ok when the algorithm is safe against the enemy having both
//   plain text and cipher text. eg RSA is ok.


void digdiv::forward(string const & in )
{
  assert(blksz>0);

  uintc sz = in.size();
  uint i=0;
  vi.clear();
  i += blksz;
  for ( ; i<=sz; )
  {
    vi.push_back(in.substr(i-blksz,blksz));
    i += blksz;
  }  

  if ((sz%blksz)!=0)
  {
    pad = blksz - (sz%blksz);
    string s;
    for (uint k=0; k<pad; ++k)
      s += '0';
    s += in.substr(i-blksz);
    vi.push_back(s);
  }
  else
    pad=0;
}
    
void digdiv::reverse( string & os ) 
{
  if (vi.empty())
    return;

  os.clear();
  
  uintc sz = vi.size();

  // Correct the block sizes
  for (uint i=0; i<sz; ++i)
  {
    uintc si = vi[i].size();
    if (si != blksz)
    {
      if (si<blksz)
      {
        string tmp;
        for (uint k=si; k<blksz; ++k)
          tmp += '0';
        tmp += vi[i];
        vi[i] = tmp;
      }
      else
      {
        // A function should reduce the block size.
        assert(false);
      }
    }
  }
      
  if (pad==0)
  {
    for (uint i=0; i<sz; ++i)
      os += vi[i];
    return;
  }

  string last = vi[sz-1];
  last = last.substr(pad);
  for (uint i=0; i<sz-1; ++i)
    os += vi[i];
  os += last;
}
  
void digdiv::save(ostream & os) const
{
  os << pad << endl;
  os << blksz << endl;
  for (uint i=0; i<vi.size(); ++i)
    os << vi[i] << endl;
}

void digdiv::restore(istream & in)
{
  if (in.eof()==false)
    in >> pad;
  else
    return;

  if (in.eof()==false)
    in >> blksz;
  else
    return;

  string s;
  in >> s;
  while (in.eof()==false)
  {
    vi.push_back(s);
    s.clear();
    in >> s;
  }
}
  

  





