Code rewrite week 2 Notes

Everything related to the code /
Tout ce qui touche au code
Post Reply
User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Code rewrite week 2 Notes

Post by Cire » Mon Nov 20, 2006 11:08 pm

Completed new HPI File handling, requires a slight change to TA3D_Platfrom, specifically in stl includes, need to add a #include <list>, this should be all thats needed to get it to work, main changes from last week include no longer needs a global HPIInfo variable to the class, as well as fixed several memory leaks, and tracks hpi files it works with so it can close them when the hpi file manager class object is destoryed.

Also added quite a few notes throughout the code to make it easier to read and follow along.

I am not going to 'paste' code here form now on, instead I will upload all code changes I've made to my website on fridays and zuf can then download and implement them.

++Cire.

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Tue Nov 21, 2006 3:53 am

Ok i've started to work through the remaining files to get the complete project to compile under VC 2005 without any serious issues, however that said i've run into quite a few issues.

First and formost is with the configuration file, which is a good thing but in alot of cases it uses #define blah 1 or #define blah true, now you don't need to declare things like this simply #define blah will do the trick, if you don't want the use of it set it to #undef blah, to check use #if defined blah or #ifdef blah, in many cases i find most of your checks as #if blah which is throwing compiler issues on my end. This is also the more 'standarized' way of doing things.

Next remember that we MUST include stdafx.h at the top of every cpp file and before we include anything else, that said everything included in stdafx and ta3d_platfrom will be aviliable to all .h files as well as that cpp file, thus no need of including string/lib/stdio ect throughout all .h, .cpp files.

Next running into macro redifincations on language in ta3dbase, for these:

Code: Select all

#define LANG_ENGLISH		0x0
#define LANG_FRENCH			0x1
#define LANG_GERMAN			0x2
#define LANG_SPANISH		0x3
#define LANG_ITALIAN		0x4
are also defined in winnt, i havn't checked how they are used throughout the package but one probably could simply undef them if already defined, then redefine them to 'quite' compling.

++Cire.

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Tue Nov 21, 2006 4:17 am

This ...

Code: Select all

#ifndef ALLEGRO_WINDOWS

int min(int a,int b)
{
	return (a<b ? a : b);
}

float min(float a,float b)
{
	return (a<b ? a : b);
}

int max(int a,int b)
{
	return (a<b ? b : a);
}

float max(float a,float b)
{
	return (a<b ? b : a);
}

#endif
Can be removed from ta3d.h, they are now in platforms.h as macros. for the record when writting multiple instances of a function like this its better to use a template function. You coulda written these as 1 function using template instead of multiple. However that said the macros should do the same trick.

++Cire.

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Tue Nov 21, 2006 7:28 am

While working with gaf, I found another serious issue, that i'am not sure how you got to compile. Again it was the dynamic size of an array, which is located in the function [get_gaf_entry_name], the line is:

Code: Select all

	int pointers[header.Entries];
I'am totally bewildered on how you get this to compile, as its against most C/C++ rules, this allocates a dynamic array, which C does not support, so either your compile is adjusting by inserting some code to handle this, or something, in either case thier is seriious chances of causing crashers with this type of allocation, i strongly suggest that we try to get outa the habbit of doing this.

Zuff: Using the new hpi system. After attaining the newest code from me on friday i'am hoping we can get this into play, I do realize that it will break lots of code but it shouln't take too long to search through and quickly fix everything, I believe the benifits of using it will outweight its troubles...Anyhow to use it is rather simple

First you will need to do something similar to..

Code: Select all

using namespace TA3D::UTILS::HPI;
Do this at the top of ta3d.cpp, then assign a global hpi file object suchas...

Code: Select all

cHPIHandler *g_HPIHandler;
Now as I suggested while intro is playing in another thread, create the hpihandler and it should build the directory structure pretty fast, something like...

Code: Select all

   guard( Starting HPI Handler and building directory structures );
       g_HPIHandler = new cHPIHandler( "" );
   unguard;
This requires that the exception code that I gave eariler in another thread be included. You do not need to put stuff between () in the guard call in quotes. :) this should catch any errors thou problem is it will continue reguardless of any seirous issues, u could use other guard functions to catch errors and display a message as well.

Anyhow after the directory structure is built it simply a matter of calling to the hpi handler to retreive data in byte * format such as...

Code: Select all

  byte *blah;

  blah = g_HPIHandler->PullFromHPI( "blah.ext" );
  if( blah )
     // call went good and data retreived.
  else
    // file not found
I noticed while starting to dig deeper into code that you need to be able to read directory structures and search for stuff. I'am going to expand the hpi handler to be able to do this later this week.

I'am currently rewritting gaf handler as the code also needs rewritten, and I will use a system similar to the hpi handler.

++Cire.

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Wed Nov 22, 2006 3:11 am

I havn't had much time today do to much, but I have been thinking about how to further improve the engine and what not with what I have done so far.

I did get around to doing a bit more research on gaf's and, to laying framework for searching for files using a signal * wildcard from within hpi directories.

One idea I"am kicking around is rather then having a load function on 3do/texturs/gaf's ect I think what I will do is place a function within the hpi manager class that will construct and return a class for whatever you want to load, so for example we would have..

gaf = hpimanager->loadgaf( "blah.gaf" );

If anyone has any other ideas that they would like to see implement in respects to hpi manager and what not i'd like to hear them.

++Cire.

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Wed Nov 22, 2006 10:33 am

I finished the search algorithim required to do lookups in hpi files. Basically you pass it a std::string that contains the search pattern, and a pointer to a list object, and it will populate the list with whatever files are found. It only supports the '*' wildcard which is all we should need.

I also fully tested the code using current variable definations and all is good. I think thats all we need from the hpi file manager.

Now i'am going to move on to handling gafs. Anyhow, I need to get something off my chest, I seem to be about the only one active throughout the week yet we are supposed to have a sizeable team, perhaps its just my need to 'blog' things, and it certinaly would be nice to see others making entries about thier progress as well so that others know we are moving along. Hate to say it but anyone looking in on this would feel its a one man show, which its not, so i'd like to encourage other developers/staff to post thier progress.

++Cire.

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Fri Nov 24, 2006 1:58 am

I had to put a halt on gaf handling mainly because i'am not entirely sure how zuff would like to use them in, weather or not he watns access to a bitmap or something direct byte ect...

I'll confer with him over the weekend and see how it stands, untill then I will ocntinue working on the new website.

++Cire.

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Fri Nov 24, 2006 8:11 pm

okay I am currently fixing a few things in the code and adding your HPI handler to read files from HPI files. I am sorry for not posting very often but I am home only the weekend so...

as far as config.h is concerned, I didn't write this file, it's done automatically by a script which configure the build process on linux by auto detecting the compiler, the linker, needed paths, etc... and I can't remove it because it's needed to build on linux but you can add a windows version of it.

PS: I will need your updated version of the HPI code
=>;-D Penguin Powered

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Sat Nov 25, 2006 7:02 pm

ok new hpi code:

Code: Select all

/*
**  File: TA3D_hpi.h
** Notes:
**   Cire: The original author of most of this code is Joe D, aka Kingbot
**           I modified it to be more complain with C++ as it was mostly
**           C based.  I wrapped it neatly in a class, and exposed only
**           those methods that the game engine need to access.
**         TODO: If this is to be accessed by multiple threads it should be
**           rewritten as it currently can not handle multiple calls.
**               HPIITEM might be expanded to keep a reference track of
**           how many times it gets asked to decode some file, if it
**           reaches some point it might just keep that 'data' in its
**           self and return it instead of having to decode each time.
*/

#pragma once

namespace TA3D
{
	namespace UTILS
	{
		namespace HPI
		{
			#define HEX_HAPI 0x49504148
			#define HPI_V1 0x00010000

			#ifndef MAX_PATH
				#define MAX_PATH 260
			#endif
			class cHPIHandler
			{
			// Member Declarations:
			private:
				#pragma pack(1) // Byte alignment.

				struct HPIVERSION 
				{
					sint32 HPIMarker; /* Must be HEX_HAPI */
					sint32 Version;   /* Must be HPI_V1 */
				};

				struct HPIHEADER 
				{
					sint32 DirectorySize; /* Directory size */
					sint32 Key;           /* Decode key */
					sint32 Start;         /* Directory offset */
				};

				struct HPIENTRY 
				{
					sint32 NameOffset;
					sint32 CountOffset;
					sint8 Flag;
				};

				struct HPICHUNK 
				{
					sint32 Marker;           /* always 0x48535153 (SQSH) */
					sint8  Unknown1;         /* I have no idea what these mean */
					sint8  CompMethod;       /* 1 = lz77, 2 = zlib */
					sint8  Encrypt;          /* Is the chunk encrypted? */
					sint32 CompressedSize;   /* the length of the compressed data */
					sint32 DecompressedSize; /* the length of the decompressed data */
					sint32 Checksum;         /* check sum */
				};

				struct HPIFILEDATA 
				{
					HPIHEADER	H1;
					sint8		Key;
					std::string HPIFileName;
					sint8		*Directory;
					FILE		*HPIFile;
				};

				struct HPIITEM 
				{
				  HPIFILEDATA	*hfd;
				  HPIENTRY		*E1;
				  sint32		IsDir;
				  sint8			*Name;
				  sint32		Size;
				};
				#pragma pack()

			// Member Functions:
			private:
				void AddArchive( const std::string &FileName );
				void LocateAndReadFiles( const std::string &Path, const std::string &FileSearch );
				void ProcessRoot( HPIFILEDATA *hfd, const std::string &StartPath, sint32 offset );
				void ProcessSubDir( HPIITEM *hi );

				sint32  ReadAndDecrypt( sint32 fpos, byte *buff, sint32 buffsize, HPIFILEDATA *HPIInfo );
				sint32 ZLibDecompress( byte *out, byte *in, HPICHUNK *Chunk );
				sint32 LZ77Decompress( byte *out, byte *in, HPICHUNK *Chunk );
				sint32 Decompress( byte *out, byte *in, HPICHUNK *Chunk );
				void CloseHPIFile( HPIFILEDATA *hfd );
			//	void cHPIHandler::CloseCurrentFile( void );
				byte *DecodeFileToMem( HPIITEM *hi );

			public:
				void SearchDirForArchives( const std::string &Path );

				// constructor:
				cHPIHandler::cHPIHandler( const std::string &Path  ) 
				{ 
					SearchDirForArchives( Path );
				}
				sint32 cHPIHandler::GetFilelist( const std::string &Search, std::list<std::string> *li );

				// DeConstructor
				~cHPIHandler();

#if defined( DEBUG )
				void ShowArchive(); // for debug only we don't need it.
#endif
				byte *PullFromHPI( const std::string &FileName );

				// Member Variables:
			private:
				std::string m_cDir;     // used when building dir structurs.

				// A map of dir/filenames for key, while value is a HPIITEM;
				typedef std::map< std::string, HPIITEM *> HPIARCHIVE;
				HPIARCHIVE m_Archive;

				// A list of HPIFILEDATA, needed only for cleanup.
				std::list< HPIFILEDATA * > m_HPIFiles;
			}; // class cHPIHandler;
		} // namespace HPI
	} // namespace utils
} // namespace TA3D

and the cpp file

Code: Select all

/*
**  File: TA3D_hpi.cpp
** Notes:
**   Cire: See notes in TA3D_hpp.h
*/

#include "stdafx.h"
#include "TA3D_hpi.h"
#include <algorithm>
#if defined TA3D_PLATFORM_WINDOWS
	#include "tools/win32/include/zlib.h"
	#pragma comment(lib, "tools/win32/libs/zlib.lib")
#elif
	#include <zlib.h>
#endif

using namespace std;
using namespace TA3D::UTILS::HPI;

sint32  cHPIHandler::ReadAndDecrypt( sint32 fpos, byte *buff, sint32 buffsize, HPIFILEDATA *HPIInfo)
{
	sint32 count, tkey, result;
	
	fseek(HPIInfo->HPIFile, fpos, SEEK_SET);

	result = (sint32)fread(buff, buffsize, 1, HPIInfo->HPIFile);

	if (HPIInfo->Key)
	{
		for (count = 0; count < buffsize; count++) 
		{
			tkey = (fpos + count) ^ HPIInfo->Key;
			buff[count] = tkey ^ ~buff[count];
		}
	}

	return result;
}

sint32 cHPIHandler::ZLibDecompress( byte *out, byte *in, HPICHUNK *Chunk)
{
	z_stream zs;
	sint32 result;
	
	zs.next_in = in;
	zs.avail_in = Chunk->CompressedSize;
	zs.total_in = 0;
	
	zs.next_out = out;
	zs.avail_out = Chunk->DecompressedSize;
	zs.total_out = 0;
	
	zs.msg = NULL;
	zs.state = NULL;
	zs.zalloc = Z_NULL;
	zs.zfree = Z_NULL;
	zs.opaque = NULL;
	
	zs.data_type = Z_BINARY;
	zs.adler = 0;
	zs.reserved = 0;
	
	result = inflateInit(&zs);
	if (result != Z_OK) {
		//printf("Error on inflateInit %d\nMessage: %s\n", result, zs.msg);
		return 0;
	}
	
	result = inflate(&zs, Z_FINISH);
	if (result != Z_STREAM_END) {
		//printf("Error on inflate %d\nMessage: %s\n", result, zs.msg);
		zs.total_out = 0;
	}
	
	result = inflateEnd(&zs);
	if (result != Z_OK) {
		//printf("Error on inflateEnd %d\nMessage: %s\n", result, zs.msg);
		return 0;
	}
	
	return zs.total_out;
}

sint32 cHPIHandler::LZ77Decompress( byte *out, byte *in, HPICHUNK *Chunk)
{
	sint32 x, work1, work2, work3, inptr, outptr, done, DPtr;
	schar DBuff[4096];
	
	done = 0;
	inptr = 0;
	outptr = 0;
	work1 = 1;
	work2 = 1;
	work3 = in[inptr++];
	
	while (!done) 
	{
		if ((work2 & work3) == 0) 
		{
			out[outptr++] = in[inptr];
			DBuff[work1] = in[inptr];
			work1 = (work1 + 1) & 0xFFF;
			inptr++;
		}
		else 
		{ int
			count = *((uint16 *) (in+inptr));
			inptr += 2;
			DPtr = count >> 4;
			if (DPtr == 0) 
				return outptr;
			else 
			{
				count = (count & 0x0f) + 2;
				if (count >= 0) 
				{
					for (x = 0; x < count; x++) 
					{
						out[outptr++] = DBuff[DPtr];
						DBuff[work1] = DBuff[DPtr];
						DPtr = (DPtr + 1) & 0xFFF;
						work1 = (work1 + 1) & 0xFFF;
					}
					
				}
			}
		}
		work2 *= 2;
		if (work2 & 0x0100) 
		{
			work2 = 1;
			work3 = in[inptr++];
		}
	}
	
	return outptr;
}

sint32 cHPIHandler::Decompress( byte *out, byte *in, HPICHUNK *Chunk )
{
	sint32 x, Checksum;
	
	Checksum = 0;
	for (x = 0; x < Chunk->CompressedSize; x++) {
		Checksum += (byte) in[x];
		if (Chunk->Encrypt)
			in[x] = (in[x] - x) ^ x;
	}
	
	if (Chunk->Checksum != Checksum) 
	{
		// GlobalDebugger-> Checksum error! Calculated: 0x%X  Actual: 0x%X\n", Checksum, Chunk->Checksum);
		return 0;
	}
	
	switch (Chunk->CompMethod) {
	case 1 : return LZ77Decompress(out, in, Chunk);
	case 2 : return ZLibDecompress(out, in, Chunk);
	default : return 0;
	}
}

byte *cHPIHandler::DecodeFileToMem(HPIITEM *hi)
{
	sint32 DeCount,DeLen, x, WriteSize, WritePtr, Offset, Length, FileFlag, *DeSize;
	byte *DeBuff, *WriteBuff;
	HPIENTRY *Entry;
	HPICHUNK *Chunk;

	if (!hi)
		return NULL;
	
	Entry = hi->E1;
	
	Offset = *((sint32 *) (hi->hfd->Directory + Entry->CountOffset));
	Length = *((sint32 *) (hi->hfd->Directory + Entry->CountOffset + 4));
	FileFlag = *(hi->hfd->Directory + Entry->CountOffset + 8);
	
	WriteBuff = (byte *)GetMem(Length+1, 0);
	if (!WriteBuff) 
	{
		// NO NEED to global deubber this, get meme shoulda done it for us.
		return NULL;
	}
	WriteBuff[Length] = 0;
	
	if (FileFlag) {
		DeCount = Length / 65536;
		if (Length % 65536)
			DeCount++;
		DeLen = DeCount * sizeof(sint32);
		
		DeSize = (sint32 *)GetMem(DeLen, 0);
		
		ReadAndDecrypt(Offset, (byte *) DeSize, DeLen, hi->hfd );
		
		Offset += DeLen;
		
		WritePtr = 0;
		
		for (x = 0; x < DeCount; x++) {
			Chunk = (HPICHUNK *)GetMem(DeSize[x], 0);
			ReadAndDecrypt(Offset, (byte *) Chunk, DeSize[x], hi->hfd);
			Offset += DeSize[x];
			
			DeBuff = (byte *) (Chunk+1);
			
			WriteSize = Decompress(WriteBuff+WritePtr, DeBuff, Chunk);
			WritePtr += WriteSize;
			
			free(Chunk);
		}
		free(DeSize);
	}
	else {
		// file not compressed
		ReadAndDecrypt(Offset, WriteBuff, Length, hi->hfd );
	}
	
	return WriteBuff;
}

void cHPIHandler::CloseHPIFile(HPIFILEDATA *hfd)
{
	if (!hfd)
		return;
	
	if (hfd->Directory) 
	{
		free(hfd->Directory);
		hfd->Directory = NULL;
	}

	if (hfd->HPIFile)
		fclose(hfd->HPIFile);

	hfd->HPIFile = NULL;
}

void cHPIHandler::ProcessSubDir( HPIITEM *hi )
{
	sint32 *FileCount, *FileLength, *EntryOffset, *Entries, count;
	schar *Name;
	HPIENTRY *Base, *Entry;
    HPIITEM *li;
	
	Base = hi->E1;
	if (Base)
		Entries = (sint32 *) (hi->hfd->Directory + Base->CountOffset);
	else
		Entries = (sint32 *) (hi->hfd->Directory + hi->hfd->H1.Start);
	
	EntryOffset = Entries + 1;
	Entry = (HPIENTRY *) (hi->hfd->Directory + *EntryOffset);
	
	for (count = 0; count < *Entries; count++) {
		Name = hi->hfd->Directory + Entry->NameOffset;
		FileCount = (sint32 *) (hi->hfd->Directory + Entry->CountOffset);
		FileLength = FileCount + 1;
		
		li = (HPIITEM *)GetMem(sizeof(HPIITEM), 1);
		li->hfd = hi->hfd;
		li->Name = Name;
		li->E1 = Entry;

		if (Entry->Flag == 1)	
		{
			std::string sDir = m_cDir; // save directory
			m_cDir += (char *)Name;	 // add new path to directory.
			m_cDir += "\\";			 // don't forget to end path with /

			ProcessSubDir( li );     // process new directory

			free( li );	// free the item.
			li = NULL;	// really free the item.

			m_cDir = sDir; // restore dir with saved dir
		} else {
			std::string f = Lowercase( m_cDir + (char *)Name );

			HPIARCHIVE::iterator iterFind = m_Archive.find( f );

			if( iterFind != m_Archive.end() )
			{ // its in our map, free the memory, erase it, add new one.
				HPIITEM *hi = iterFind->second;
				iterFind->second = NULL;

				m_Archive.erase( iterFind );

				free( hi );
				hi = NULL;
			}

			li->Size = *FileLength;
			m_Archive[f] = li;
		}

		Entry++;
	}
}

void  cHPIHandler::ProcessRoot(HPIFILEDATA *hfd, const std::string &StartPath, sint32 offset )
{
	sint32 *Entries, *FileCount, *EntryOffset;
	schar *Name;
	std::string MyPath;

	Entries = (sint32 *)(hfd->Directory + offset);
	EntryOffset = Entries + 1;
	HPIENTRY *Entry = (HPIENTRY *)(hfd->Directory + *EntryOffset);

	for( sint32 count = 0; count < *Entries; count++ ) 
	{
		Name = hfd->Directory + Entry->NameOffset;
		FileCount = (sint32 *) (hfd->Directory + Entry->CountOffset);
		if (Entry->Flag == 1)	
		{
			MyPath = StartPath;
			if( MyPath.length() )
				MyPath += "\\";
			MyPath += (char *)Name;
			m_cDir = MyPath + "\\";

			HPIITEM *hi = (HPIITEM *)GetMem(sizeof(HPIITEM), 1);
				
			hi->hfd = hfd;
			hi->IsDir = 1;
			hi->Size = 0;
			hi->Name = Name;
			hi->E1 = Entry;
				
			ProcessSubDir( hi );

			free( hi );
			hi = NULL;
		}
		Entry++;
	}
}

void cHPIHandler::AddArchive( const std::string &FileName )
{
	HPIFILEDATA *hfd = (HPIFILEDATA *)GetMem(sizeof(HPIFILEDATA), 1);
	if (!hfd) 
		return; // No Need to generate error here as getmem already did it.

	hfd->HPIFileName = FileName;

#if defined TA3D_PLATFORM_WINDOWS
	errno_t err;
	if( ( err = fopen_s( &hfd->HPIFile, hfd->HPIFileName.c_str(), "rb" )) != 0 )
#else
	hfd->HPIFile=fopen( hfd->HPIFileName.c_str(), "rb" );
	if( !hfd->HPIFile )
#endif
	{
		CloseHPIFile(hfd);
		free(hfd);
//		GlobalDebugger-> Failed to open hpi file for reading.
		return;
	}

	HPIVERSION hv;
	fread(&hv, sizeof(HPIVERSION), 1, hfd->HPIFile);
	
	if( hv.Version != HPI_V1 || hv.HPIMarker != HEX_HAPI )
	{
		CloseHPIFile(hfd);
		free(hfd);
		
		hfd = NULL;

		return;
	}

	fread(&hfd->H1, sizeof(HPIHEADER), 1, hfd->HPIFile);
	if (hfd->H1.Key)
		hfd->Key = ~((hfd->H1.Key * 4)	| (hfd->H1.Key >> 6));
	else
		hfd->Key = 0;

	int start = hfd->H1.Start;
	int size = hfd->H1.DirectorySize;
	
	hfd->Directory = (sint8 *)GetMem(size, 1);

	ReadAndDecrypt(start, (byte *)hfd->Directory + start, size - start, hfd );
	m_cDir = "";

	m_HPIFiles.push_front( hfd );

	ProcessRoot(hfd, "", start);
}

void cHPIHandler::LocateAndReadFiles( const std::string &Path, const std::string &FileSearch )
{
	al_ffblk search;

	if( al_findfirst(FileSearch.c_str(), &search, FA_RDONLY | FA_ARCH ) ==0 )
	{
		do
		{
			AddArchive( Path + search.name );
		} while( al_findnext( &search ) == 0 );

		al_findclose(&search);
	}
}

void cHPIHandler::SearchDirForArchives( const std::string &Path )
{
	schar ext[4][6] = { "*.ufo", "*.hpi", "*.ccx", "*.gp3" };

	for( uint32 i = 0; i < 4; i++ )
		LocateAndReadFiles( Path, Path + (char *)ext[i] );
}

cHPIHandler::~cHPIHandler()
{
	// Cleanup:
	//   Walk the map, setting value to NULL, and freeing HPIITEMS.
	for( HPIARCHIVE::iterator iter = m_Archive.begin(); iter != m_Archive.end(); ++iter ) 
	{
		HPIITEM *hi = iter->second;
		iter->second = NULL;

		free( hi );
		hi = NULL;
	}

	m_Archive.clear();  // Now do a clear which will purge keys.

	// Now close and free hpi files.
	if( m_HPIFiles.size() == 0 )
		return;

	std::list< HPIFILEDATA * >::iterator cur;
	HPIFILEDATA *hfd;

	do
	{
		cur = m_HPIFiles.begin();
		hfd = (*cur);

		m_HPIFiles.pop_front();
	
		CloseHPIFile( hfd );
		free( hfd );
		hfd = NULL;
	} while(  m_HPIFiles.size() != 0 );
}

#if defined( DEBUG ) // no need for bloating in release builds.
	void cHPIHandler::ShowArchive()
	{
		for(HPIARCHIVE::iterator iter = m_Archive.begin(); iter != m_Archive.end(); iter++)
			printf( "(arch)%s\n", (*iter).first.c_str() );
	}
#endif

byte *cHPIHandler::PullFromHPI( const std::string &FileName )
{

	HPIARCHIVE::const_iterator iterFind = m_Archive.find( Lowercase( FileName ) );

	return ( (iterFind != m_Archive.end()) ? 
		DecodeFileToMem( (HPIITEM *)iterFind->second ) : NULL );
}

sint32 cHPIHandler::GetFilelist( const std::string &Search, std::list<std::string> *li )
{
	std::string first, last;
	std::basic_string <char>::size_type iFind;
    static const std::basic_string <char>::size_type NotFound = -1;

	iFind = Search.find( "*" );

	if( iFind != NotFound )
	{
		first = Lowercase( Search.substr(0,(iFind)) );
		last = Lowercase( Search.substr( iFind+1) );
	}
	else
	{
		first = Lowercase( Search );
		last = "";
	}
	

	for( HPIARCHIVE::iterator iter = m_Archive.begin(); iter != m_Archive.end(); ++iter ) 
	{
		std::string f = iter->first;

		if( f.length() < first.length() || f.length() < last.length() )
			continue;

		if( f.substr(0,first.length() ) == first )
		{
			if( f.substr( f.length() - last.length(), last.length() ) == last )
				li->push_back( f );
		}
	}

	return 0;
}

Post Reply

Who is online

Users browsing this forum: No registered users and 39 guests