http://code.google.com/p/libarchive/
i has at the beginning only read support (like ZipArchive), write support will i add later
Code: Select all
#ifndef __OgreLibArchive_H__
#define __OgreLibArchive_H__
#include <Ogre.h>
#include <OgreArchiveFactory.h>
#include <archive.h>
#include <archive_entry.h>
#include <sstream>
namespace Ogre {
class _OgreExport LibarchiveArchive : public Archive
{
public:
LibarchiveArchive(const String& name);
~LibarchiveArchive();
bool isCaseSensitive(void) const { return true; }
/// @copydoc Archive::load
void load() {}
/// @copydoc Archive::unload
void unload() {}
/// @copydoc Archive::open
DataStreamPtr open(const String& filename, bool readOnly = true) const;
/// @copydoc Archive::create
DataStreamPtr create(const String& filename) const;
/// @copydoc Archive::remove
void remove(const String& filename) const;
/// @copydoc Archive::list
StringVectorPtr list(bool recursive = true, bool dirs = false);
/// @copydoc Archive::listFileInfo
FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false);
/// @copydoc Archive::find
StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false);
/// @copydoc Archive::findFileInfo
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
bool dirs = false);
/// @copydoc Archive::exists
bool exists(const String& filename);
/// @copydoc Archive::getModifiedTime
time_t getModifiedTime(const String& filename);
};
// /** Specialisation of ArchiveFactory for Libarchive files. */
class LibarchiveArchiveFactory : public Ogre::ArchiveFactory
{
public:
virtual ~LibarchiveArchiveFactory() {}
/// @copydoc FactoryObj::getType
const String& getType(void) const;
/// @copydoc FactoryObj::createInstance
Archive *createInstance( const String& name )
{
return OGRE_NEW LibarchiveArchive(name);
}
/// @copydoc FactoryObj::destroyInstance
void destroyInstance( Archive* arch) { OGRE_DELETE arch; }
};
/** Specialisation of DataStream to handle streaming data from libarchive archives. */
class _OgrePrivate LibarchiveDataStream : public DataStream
{
std::stringstream buff;
public:
/// Constructor
LibarchiveDataStream(Ogre::String name,size_t size,uint16 accessMode);
~LibarchiveDataStream();
/// @copydoc DataStream::read
size_t read(void* buf, size_t count);
/// @copydoc DataStream::write
size_t write(void* buf, size_t count);
/// @copydoc DataStream::skip
void skip(long count);
/// @copydoc DataStream::seek
void seek( size_t pos );
/// @copydoc DataStream::seek
size_t tell(void) const;
/// @copydoc DataStream::eof
bool eof(void) const;
/// @copydoc DataStream::close
void close(void);
};
}
#endif /* __OgreLibArchive_H__ */
Code: Select all
#include "OgreLibarchive.hpp"
#define LIBARCHIVE_TYPE "libarchive"
Ogre::LibarchiveArchive::LibarchiveArchive(const String& name)
: Ogre::Archive(name, LIBARCHIVE_TYPE)
{
}
Ogre::DataStreamPtr Ogre::LibarchiveArchive::open(const String& filename, bool readOnly) const
{
Ogre::DataStreamPtr result;
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
if(archive_read_open_filename(a,this->mName.c_str(),10240))
{
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
if(filename.compare(archive_entry_pathname(entry))==0){
size_t size = 0,bytes_read;
if(archive_entry_size_is_set(entry))
size = archive_entry_size(entry);
result = Ogre::DataStreamPtr(new LibarchiveDataStream(filename,size,Ogre::DataStream::READ));
char buff[8192];
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
result->write(buff,bytes_read);
result->seek(0);
}
}
archive_read_close(a);
}else
OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,"Could not open resource: " + this->mName, "LibarchiveArchive::open");
return result;
}
Ogre::DataStreamPtr Ogre::LibarchiveArchive::create(const String& filename) const
{
OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
"Modification of archives is not supported yet",
"LibarchiveArchive::create");
}
void Ogre::LibarchiveArchive::remove(const String& filename) const
{
OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
"Modification of archives is not supported yet",
"LibarchiveArchive::remove");
}
Ogre::StringVectorPtr Ogre::LibarchiveArchive::list(bool recursive,bool dirs)
{
Ogre::StringVectorPtr result;
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
if(archive_read_open_filename(a,this->mName.c_str(),10240))
{
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
if(!dirs && archive_entry_filetype(entry)==AE_IFDIR){
}else if(Ogre::String(archive_entry_pathname(entry)).find('/') != std::string::npos && !recursive){
}else
result->push_back(Ogre::String(archive_entry_pathname(entry)));
}
archive_read_close(a);
}else
OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,"Could not open resource: " + this->mName, "LibarchiveArchive::list");
return result;
}
Ogre::FileInfoListPtr Ogre::LibarchiveArchive::listFileInfo(bool recursive,bool dirs)
{
Ogre::FileInfoListPtr result;
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
if(archive_read_open_filename(a,this->mName.c_str(),10240))
{
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
if(!dirs && archive_entry_filetype(entry)==AE_IFDIR){
}else if(Ogre::String(archive_entry_pathname(entry)).find('/') != std::string::npos && !recursive){
}else{
FileInfo fileinfo;
fileinfo.archive = this;
fileinfo.filename = Ogre::String(archive_entry_pathname(entry));
Ogre::StringUtil::splitFilename(fileinfo.filename,fileinfo.basename,fileinfo.path);
if(archive_entry_size_is_set(entry))
fileinfo.uncompressedSize = archive_entry_size(entry);
result->push_back(fileinfo);
}
}
archive_read_close(a);
}else
OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,"Could not open resource: " + this->mName, "LibarchiveArchive::listFileInfo");
return result;
}
Ogre::StringVectorPtr Ogre::LibarchiveArchive::find(const String& pattern, bool recursive, bool dirs)
{
Ogre::StringVectorPtr result;
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
if(archive_read_open_filename(a,this->mName.c_str(),10240))
{
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
if(!dirs && archive_entry_filetype(entry)==AE_IFDIR){
}else if(Ogre::String(archive_entry_pathname(entry)).find('/') != std::string::npos && !recursive){
}else if(Ogre::StringUtil::match(Ogre::String(archive_entry_pathname(entry)),pattern))
result->push_back(Ogre::String(archive_entry_pathname(entry)));
}
archive_read_close(a);
}else
OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,"Could not open resource: " + this->mName, "LibarchiveArchive::find");
return result;
}
Ogre::FileInfoListPtr Ogre::LibarchiveArchive::findFileInfo(const String& pattern, bool recursive, bool dirs)
{
Ogre::FileInfoListPtr result;
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
if(archive_read_open_filename(a,this->mName.c_str(),10240))
{
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
if(!dirs && archive_entry_filetype(entry)==AE_IFDIR){
}else if(Ogre::String(archive_entry_pathname(entry)).find('/') != std::string::npos && !recursive){
}else if(Ogre::StringUtil::match(Ogre::String(archive_entry_pathname(entry)),pattern)){
FileInfo fileinfo;
fileinfo.archive = this;
fileinfo.filename = Ogre::String(archive_entry_pathname(entry));
Ogre::StringUtil::splitFilename(fileinfo.filename,fileinfo.basename,fileinfo.path);
if(archive_entry_size_is_set(entry))
fileinfo.uncompressedSize = archive_entry_size(entry);
result->push_back(fileinfo);
}
}
archive_read_close(a);
}else
OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,"Could not open resource: " + this->mName, "LibarchiveArchive::findFileInfo");
return result;
}
bool Ogre::LibarchiveArchive::exists(const Ogre::String& filename)
{
bool result = false;
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
if(archive_read_open_filename(a,this->mName.c_str(),10240))
{
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
if(filename.compare(archive_entry_pathname(entry))==0){
result = true;
break;
}
}
archive_read_close(a);
}else
OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,"Could not open resource: " + this->mName, "LibarchiveArchive::exists");
return result;
}
time_t Ogre::LibarchiveArchive::getModifiedTime(const Ogre::String& filename)
{
time_t result;
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
if(archive_read_open_filename(a,this->mName.c_str(),10240))
{
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
if(filename.compare(archive_entry_pathname(entry))==0)
result = archive_entry_mtime(entry);
}
archive_read_close(a);
}else
OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,"Could not open resource: " + this->mName, "LibarchiveArchive::getModifiedTime");
return result;
}
void Ogre::LibarchiveDataStream::skip(long count)
{
this->buff.seekg(count,std::ios_base::cur);
this->buff.seekp(count,std::ios_base::cur);
}
void Ogre::LibarchiveDataStream::seek(size_t count)
{
this->buff.seekg(count);
this->buff.seekp(count);
}
size_t Ogre::LibarchiveDataStream::tell() const
{
return const_cast<std::stringstream*>(&(this->buff))->tellp();
}
bool Ogre::LibarchiveDataStream::eof() const
{
return this->buff.eof();
}
size_t Ogre::LibarchiveDataStream::read(void* buf, size_t count)
{
return this->buff.readsome((char*)buf,count);
}
size_t Ogre::LibarchiveDataStream::write(void* buf, size_t count)
{
size_t result = this->buff.tellp();
char buffer[count];
this->buff.write(buffer,count);
buf = buffer;
return (size_t)(this->buff.tellp()) - result;
}
const Ogre::String& Ogre::LibarchiveArchiveFactory::getType(void) const
{
static String name = LIBARCHIVE_TYPE;
return name;
}
Ogre::LibarchiveDataStream::LibarchiveDataStream(Ogre::String name,size_t size,uint16 accessMode)
: Ogre::DataStream(name,accessMode)
{
mSize = size;
}
int main (int argc, char const* argv[])
{
// Ogre::ArchiveFactory *fac = new Ogre::LibarchiveArchiveFactory;
// Ogre::LibarchiveArchive *archive =(Ogre::LibarchiveArchive*) fac->createInstance("path");
// archive->exists("file");
// archive->remove("file");
return 0;
}
