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