
#include <QtCore/QString.h>

#include "xdart/x_at_file.h"

#include "xpace/util/file.h"

AT_File::AT_File
  (const byte* fname) :
    x_File(new Xpace::File)
{
  size_t len(strlen((const char*) fname) + 1);
  file_name.resize(len);
  strcpy_s((char*) &file_name[0], len, (const char*)fname);
}

AT_File::AT_File
  (const AT_File& rhs) :
    x_File(new Xpace::File(*rhs.x_File)),
    file_name(rhs.file_name)
{
}

AT_File& AT_File::operator=
  (const AT_File& rhs)
{
  x_File = new Xpace::File(*rhs.x_File);
  file_name = rhs.file_name;
  return *this;
}

AT_File::~AT_File
  ()
{
  delete x_File;
}

bool AT_File::operator!
  ()
  const
{
  return !x_File || !*x_File;
}

bool AT_File::close
  ()
{
  return x_File->close();
}
    
uint64 AT_File::getPos
  ()
  const
{
  return x_File->getPos();
}

uint64 AT_File::getSize
  ()
  const
{
  return x_File->getLength();
}

uint AT_File::getBlockSize
  ()
  const
{
  return x_File->getBufSize();
}

uint64 AT_File::align
  ()
{
  Xpace::File::Position pos(x_File->getPos());
  pos |= (x_File->getBufSize() - 1);
  x_File->seek(++pos);
  return pos;
}
  
uint AT_File::alignFree             // returns #bytes left in this block
  ()
  const
{
  Xpace::File::Position pos(x_File->getPos());
  return x_File->getBufSize() - (pos & x_File->getBufSize() - 1);
}

bool AT_File::getFullName
  (byte *name,
   uint sz)
  const
{
  memcpy(name, &file_name[0], std::min(sz, file_name.size()));
  if (sz > file_name.size())
    name[file_name.size()] = 0;
  return true;
}

const byte *const AT_File::fullName
  ()
  const
{
  return &file_name[0];
}

AT_File_Type AT_File::getType
  ()
  const
{
  assert(0);
  return AT_File_Type(0);
}

uint16 AT_File::getVersion
  ()
  const
{
  return 0;
}

uint64 SEARCH_DECL GetFileSize
  (const byte * fname)
{
  assert(0);
  return 0;
}

// ================================== RANDOM-ACCESS FILE ======

AT_Read_Rand_File::AT_Read_Rand_File
  (AT_String fname,
   AT_File_Type type,
   uint blockSize) :
    AT_File(fname)
{
  x_File->open(QString(fname), Xpace::File::ReadSequential);
}

AT_Read_Rand_File::~AT_Read_Rand_File
  ()
{
}

bool AT_Read_Rand_File::seek
	 (uint64 pos)
 {
 return x_File->seek(pos);
 }

bool AT_Read_Rand_File::read
  (void *buf,
   uint len)
{
  return x_File->read(buf, len);
}

bool AT_Read_Rand_File::read
  (void   *buf,
   uint64 off,
   uint   len)
{
  return x_File->seek(off) && x_File->read(buf, len);
}

AT_Write_Rand_File::AT_Write_Rand_File
  (AT_String fname,
   AT_File_Type type,
   uint blockSize,
   bool overwriteExisting) :
    AT_File(fname)
{
}

AT_Write_Rand_File::~AT_Write_Rand_File
  ()
{
}

 bool AT_Write_Rand_File::setHeader
  (uint16 vers,
   uint16 type)
 {
   assert(0);
   return false;
 }

 bool AT_Write_Rand_File::setVersion
  (uint16 vers)
 {
   assert(0);
   return false;
 }

 bool AT_Write_Rand_File::seek
	 (uint64 pos)
 {
 return x_File->seek(pos);
 }

 bool AT_Write_Rand_File::write
   (const void *const buf,
    uint len)
 {
   return x_File->write((const byte*) buf, len);
 }

bool AT_Write_Rand_File::write
  (const void *const buf,
   uint64 off,
   uint len)
{
  return x_File->seek(off) && x_File->write((const byte*) buf, len);
}

 bool AT_Write_Rand_File::truncate
   ()
 {
   assert(0);
   return false;
 }

  bool AT_Write_Rand_File::truncate
   (uint64 off)
 {
   assert(0);
   return false;
 }

#if 0
 AT_Rand_Buffer::AT_Rand_Buffer
   (AT_File_Type type,
   uint blockSize) :
     AT_File((const byte*)"")
 {
   assert(0);
 }

 AT_Rand_Buffer::~AT_Rand_Buffer
    ()
{
}

bool AT_Rand_Buffer::seek
  (uint64 pos)
{
  return false;
}
 
bool AT_Rand_Buffer::write
  (const void *const buf,
   uint len)
{
  return false;
}

bool AT_Rand_Buffer::read
  (void *buf,
   uint len)
{
  return false;
}

bool AT_Rand_Buffer::Load
  (AT_File *file)
{
  return false;
}

bool  AT_Rand_Buffer::Dump
  (AT_File * file)
{
  return false;
}
#endif
  
// ================================== SEQUENTIAL-ACCESS FILE ==

AT_Read_Seq_File::AT_Read_Seq_File
  (uint maxRead,
   uint bufSize) :
    AT_File((const byte*)"")
{
}

AT_Read_Seq_File::AT_Read_Seq_File
  (AT_String fname,
   AT_File_Type type,
	 uint maxRead,
   uint bufSize) :
    AT_File(fname)
{
  x_File->open(QString(fname), Xpace::File::ReadSequential, bufSize);
}

bool AT_Read_Seq_File::operator!
  ()
  const
{
  return !x_File;
}

bool AT_Read_Seq_File::open
  (AT_String fname,
   AT_File_Type type,
	 uint maxRead,
   uint bufSize)
{
  return x_File->open(QString(fname), Xpace::File::ReadSequential, bufSize);
}

AT_Read_Seq_File::~AT_Read_Seq_File
  ()
{
}

void* AT_Read_Seq_File::read
  (uint size)
{
  assert(size);
  byte* p;
  return (x_File->get(&p, size) == size) ? (void*)p : 0;
}

bool AT_Read_Seq_File::read   		 
  (void *p,
	 uint size)
{
  return x_File->read(p, size);
};

AT_Write_Seq_File::AT_Write_Seq_File
  (uint blockSize,
  uint bufSize) :
    AT_File((const byte*)"")
{
}

AT_Write_Seq_File::AT_Write_Seq_File
  (AT_String fname,
   AT_File_Type type,
   uint blockSize,
   uint bufSize) :
    AT_File(fname)
{
  x_File->open(QString(fname), Xpace::File::WriteSequential, bufSize);
}

bool AT_Write_Seq_File::operator!
  ()
  const
{
  return !x_File;
}

bool AT_Write_Seq_File::open
  (AT_String fname,
   AT_File_Type type,
   uint bufSize)
{
  return x_File->open(QString(fname), Xpace::File::WriteSequential, bufSize);
}

bool AT_Write_Seq_File::close
  ()
{
  x_File->close();
  return true;
}

AT_Write_Seq_File::~AT_Write_Seq_File
 ()
{
}

uint64 AT_Write_Seq_File::getSize
  ()
  const
{
  return x_File->getLength();
}

bool AT_Write_Seq_File::setHeader
  (uint16 vers,
   uint16 type)
{
  assert(0);
  return false;
}

bool AT_Write_Seq_File::setVersion
  (uint16 vers)
{
  assert(0);
  return false;
}

bool AT_Write_Seq_File::write
	(const void *const p,
	 uint size)
{
  return x_File->write(p, size);
}

bool AT_Write_Seq_File::write
  (AT_Read_Seq_File *f)
{
  assert(0);
  return false;
}