/******************************************************************************
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
#include <qfile.h>
#include <assert.h>
#include "store.h"
#ifndef FILESTORAGE_H
#define FILESTORAGE_H
/** @brief Store implementation based on a file.
Writing is linear, after that the file is re-opened for reading.
Reading is random (seek+read).
*/
class FileStorage : public StorageIntf
{
public:
FileStorage() : m_readOnly(FALSE) {}
FileStorage( const QString &name) :
m_readOnly(FALSE) { m_file.setName(name); }
int read(char *buf,uint size) { return m_file.readBlock(buf,size); }
int write(const char *buf,uint size) { assert(m_readOnly==FALSE); return m_file.writeBlock(buf,size); }
bool open( int m ) { m_readOnly = m==IO_ReadOnly; return m_file.open(m); }
bool seek(int64 pos) { return m_file.seek(pos); }
int64 pos() const { return m_file.pos(); }
void close() { m_file.close(); }
void setName( const char *name ) { m_file.setName(name); }
private:
bool m_readOnly;
QFile m_file;
};
#if 0 // experimental version using mmap after opening the file as read only.
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
class FileStorage : public StorageIntf
{
public:
FileStorage() : m_readOnly(FALSE), m_map(0), m_off(0), m_size(0) {}
FileStorage( const QString &name) :
m_readOnly(FALSE) { m_file.setName(name); }
void setName( const char *name ) { m_file.setName(name); }
bool open( int m )
{
if (m==IO_ReadOnly)
{
m_readOnly=TRUE;
QString name = m_file.name();
m_file.close();
m_fd = ::open(name.data(),O_RDONLY);
struct stat stat;
fstat(m_fd,&stat);
m_size = stat.st_size;
m_map = mmap(NULL,m_size,PROT_READ,MAP_SHARED,m_fd,0);
if (m_map==MAP_FAILED) perror("mmap failed");
assert(m_map!=MAP_FAILED);
m_off = 0;
return TRUE;
}
else
{
m_readOnly = FALSE;
return m_file.open(m);
}
}
int write(const char *buf,uint size)
{
assert(m_map==0);
return m_file.writeBlock(buf,size);
}
int read(char *buf,uint size)
{
assert(m_map!=0);
memcpy(buf,((char *)m_map)+m_off,size);
m_off+=size;
return size;
}
bool seek(int64 pos)
{
m_off=pos;
return TRUE;
}
int64 pos() const
{
if (m_readOnly)
{
return m_off;
}
else
{
return m_file.pos();
}
}
void close()
{
if (m_readOnly)
{
munmap(m_map,m_size);
::close(m_fd);
exit(1);
}
else
{
m_file.close();
}
}
private:
bool m_readOnly;
QFile m_file;
int m_fd;
void *m_map;
off_t m_off;
off_t m_size;
};
#endif
#endif