an Archive for libarchive

What it says on the tin: a place to discuss proposed new features.
Post Reply
Hanmac
Gnoblar
Posts: 13
Joined: Wed May 25, 2011 12:41 pm

an Archive for libarchive

Post by Hanmac » Wed May 25, 2011 1:12 pm

i added support to read a variety of formats, including tar, pax, cpio, zip, xar, lha, ar, cab, mtree, and ISO images. and many compression.

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;
}
0 x

User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
Contact:

Re: an Archive for libarchive

Post by Jabberwocky » Fri Jun 03, 2011 5:41 am

Which archive file type are you using? Do you know off-hand if any of them perform more quickly (faster load time) than the others?
0 x
Image

Hanmac
Gnoblar
Posts: 13
Joined: Wed May 25, 2011 12:41 pm

Re: an Archive for libarchive

Post by Hanmac » Fri Jun 10, 2011 5:16 pm

it can use many formats, i prefer tar.xz is is small and relative fast decompressed
0 x

Post Reply