This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| File Stream Wrapper Submitted by

Well, this code isn't specifically game-related, but I *am* using it in the current game project I'm working-on. =] The code is very straightforward, so I commented very little. This is just a simple wrapper for the FILE* streams used in libc's stdio.h. I'm not fond of iostream's input stream at all, and anything else like Microsoft's file handles or CFile aren't portable at all and are generally slower. I put all the function declarations in the class so that it would all be inline and cause no overhead, however small, for its use. Use it in any way you want, as there are no restrictions on this code. Also, platform.h includes the definitions of the types I used in file.h. I use them to provide for cross-platform support and any future upgrade in operating systems to 64-bit.

Currently browsing [filestream.zip] (2,912 bytes) - [platform.h] - (1,070 bytes)

    #ifndef PLATFORM_H
    #define PLATFORM_H

    #ifdef WIN32

    	typedef	unsigned char		byte;
    	typedef char				int8;
    	typedef	short				int16;
    	typedef	int					int32;
    	typedef __int64				int64;
    	typedef unsigned char		uint8;
    	typedef	unsigned short		uint16;
    	typedef	unsigned int		uint32;
    	typedef unsigned __int64	uint64;
    	typedef	float				real32;
    	typedef	double				real64;
    	typedef	real32				real;

    	#define bool  uint32
    	#define boolean	bool

    	#ifndef true
    	#define true  bool(1)
    	#define false bool(0)
    	#endif

    #else

    	typedef unsigned char		boolean;
    	typedef	unsigned char		byte;
    	typedef char				int8;
    	typedef	short				int16;
    	typedef	long				int32;
    	typedef long long			int64;
    	typedef unsigned char		uint8;
    	typedef	unsigned short		uint16;
    	typedef	unsigned long		uint32;
    	typedef unsigned long long	uint64;
    	typedef	float				real32;
    	typedef	double				real64;
    	typedef	float				real;

    	#define bool  uint32
    	#define boolean bool

    	#ifndef true
    	#define true  bool(1)
    	#define false bool(0)
    	#endif

    #endif

    #endif

Currently browsing [filestream.zip] (2,912 bytes) - [file.h] - (8,640 bytes)

    #ifndef FILE_H
    #define FILE_H

    #include <stdio.h>
    #include "platform.h"
    #include <string>
    #include <list>
    using namespace std;

    enum {
    	FILE_TEXT = 1,
    	FILE_BINARY = 2,
    	FILE_APPEND = 4,
    	FILE_SIMUL = 8,  // simultaneous read/write
    	FILE_READ = 16,
    	FILE_WRITE = 32,
    	FILE_LITTLE = 64,
    	FILE_BIG = 128
    };

    #define DEFAULT_MAX_SIZE 2048
    #ifdef __BIG_ENDIAN__
    #define SYSTEM_ENDIAN 128
    #else
    #define SYSTEM_ENDIAN 64
    #endif

    typedef struct REF
    {
    	REF(FILE *_f) { f = _f;  Count = 1; }
    	FILE	*f;
    	uint32	Count;
    } REF;

    std::list <REF> RefCount;
    std::list <REF>::iterator Iter;

    class CFile
    {
    public:
    	CFile()
    	{
    		this->File = NULL;
    		this->OpenMode = TEXT;
    		this->TermString = " /\n\r\t";
    		this->Endian = SYSTEM_ENDIAN;
    	}

    	CFile(char *_FileName, char *_Mode = "rb")
    	{
    		this->File = fopen(_FileName, _Mode);
    		this->OpenMode = this->SetMode(_Mode);
    		this->TermString = " /\n\r\t";
    		this->Endian = SYSTEM_ENDIAN;
    	}

    	CFile(std::string &_FileName, std::string &_Mode = string("rb"))
    	{
    		this->File = fopen(_FileName.c_str(), _Mode.c_str());
    		this->OpenMode = this->SetMode((char*)_Mode.c_str());
    		this->TermString = " /\n\r\t";
    		this->Endian = SYSTEM_ENDIAN;
    	}

    	CFile(char *_FileName, uint32 _Mode)
    	{
    		std::string Mode;

    		if (_Mode == 0) {
    			*this = CFile();
    			return;
    		}

    		if (_Mode & FILE_APPEND) {
    			Mode += "a";
    		}
    		if (_Mode & FILE_SIMUL) {
    			Mode += "+";
    		}
    		if (_Mode & FILE_READ) {
    			Mode += "r";
    		}
    		if (_Mode & FILE_WRITE) {
    			Mode += "w";
    		}
    		if (_Mode & FILE_TEXT) {
    			Mode += "t";
    			this->OpenMode = TEXT;
    		}
    		if (_Mode & FILE_BINARY) {
    			Mode += "b";
    			this->OpenMode = BINARY;
    		}

    		this->TermString = " /\n\r\t";
    		this->File = fopen(_FileName, (char*)Mode.c_str());
    		this->Endian = SYSTEM_ENDIAN;

    		return;
    	}

    	CFile(string &_FileName, uint32 _Mode)
    	{
    		*this = CFile((char*)_FileName.c_str(), _Mode);
    	}

    	CFile(FILE *_File)
    	{
    		this->File = _File;
    		this->OpenMode = BINARY;  // basically just have to assume...
    		this->TermString = " /\n\r\t";
    		this->Endian = SYSTEM_ENDIAN;
    		this->AddRef(_File);
    	}

    	CFile(CFile &_File)
    	{
    		this->File = _File.GetFile();
    		this->OpenMode = _File.OpenMode;
    		this->TermString = _File.TermString;
    		this->Endian = _File.Endian;
    		this->AddRef(_File.GetFile());
    	}

    	virtual ~CFile()
    	{
    		if (this->File && SafeToDel(this->File))
    			fclose(this->File);
    		this->File = NULL;
    	}

    	inline boolean Open(char *_FileName, char *_Mode = "rb")
    	{
    		if (this->File && SafeToDel(this->File))
    			fclose(this->File);
    		return (this->File = fopen(_FileName, _Mode)) != NULL;
    	}

    	inline boolean Open(string &_FileName, string &_Mode = string("rb"))
    	{
    		return this->Open((char*)_FileName.c_str(), (char*)_Mode.c_str());
    	}

    	inline void Close(void)
    	{
    		if (this->File && SafeToDel(this->File)) {
    			fclose(this->File);
    			this->File = NULL;
    		}
    	}

    	inline void SetEndian(int32 _Endian)
    	{
    		if (_Endian != FILE_LITTLE && _Endian != FILE_BIG)
    			return;
    		this->Endian = _Endian;
    	}

    	inline uint32 Read(void *_Ptr, uint32 _Size)
    	{
    		return fread(_Ptr, 1, _Size, this->File);
    	}

    	inline uint32 Write(void *_Ptr, uint32 _Size)
    	{
    		return fwrite(_Ptr, 1, _Size, this->File);
    	}

    	inline int32 Seek(int32 _Offset, int32 _Mode)
    	{
    		return fseek(this->File, _Offset, _Mode);
    	}

    	inline void Rewind(void)
    	{
    		rewind(this->File);
    	}

    	inline int32 Eof(void)
    	{
    		return feof(this->File);
    	}

    	inline int32 Flush(void)
    	{
    		return fflush(this->File);
    	}

    	inline byte GetChar(void)
    	{
    		return fgetc(this->File);
    	}

    	inline uint16 GetShort(void)
    	{
    		static uint16 S;
    		fread(&S, sizeof(uint16), 1, this->File);
    		if (this->Endian != SYSTEM_ENDIAN)
    			return (S>>8) | (S<<8);
    		else
    			return S;
    	}

    	inline uint32 GetInt(void)
    	{
    		static uint32 I;
    		fread(&I, sizeof(uint32), 1, this->File);
    		if (this->Endian != SYSTEM_ENDIAN)
    			return (I>>24) | ((I>>8) & 0xff00) | ((I<<8) & 0xff0000) | (I<<24);
    		else
    			return I;
    	}

    	inline int32 Reverse(void)
    	{
    		return fseek(this->File, -1, SEEK_CUR);
    	}

    	inline char *GetS(char *_String, uint32 _MaxLen = DEFAULT_MAX_SIZE)
    	{
    		return fgets(_String, _MaxLen, this->File);
    	}

    	inline string &GetS(string &_String)
    	{
    		char *String = new char[DEFAULT_MAX_SIZE];
    		this->GetS(String);
    		_String = String;
    		delete []String;
    		return _String;
    	}

    	inline string &GetS(void)
    	{
    		string String;
    		return this->GetS(String);
    	}

    	inline int32 Print(const char *_Format, ...)
    	{
    		return fprintf(this->File, _Format);
    	}

    	inline int32 Pos(void)
    	{
    		return ftell(this->File);
    	}

    	inline boolean Temp(void)
    	{
    		if (this->File && SafeToDel(this->File))
    			fclose(this->File);
    		return (this->File = tmpfile()) != NULL;
    	}

    	// Sets the terminating characters for the >> operator
    	inline void SetTerm(char *_TermString)
    	{
    		if (_TermString)
    			TermString = _TermString;
    		return;
    	}

    	// Same as above
    	inline void SetTerm(string &_TermString)
    	{
    		TermString = _TermString;
    		return;
    	}

    	inline boolean Valid(void)
    	{
    		return (this->File != NULL);
    	}

    	inline FILE *GetFile(void)
    	{
    		return this->File;
    	}

    	inline CFile& operator = (FILE *_File)
    	{
    		if (this->File && SafeToDel(this->File))
    			fclose(this->File);
    		this->File = _File;
    		this->OpenMode = TEXT;  // Just have to guess...?
    		this->TermString = " /\n\r\t";
    		this->AddRef(_File);

    		return *this;
    	}

    	inline CFile& operator = (CFile &_File)
    	{
    		if (this->File && SafeToDel(this->File))
    			fclose(this->File);
    		this->File = _File.GetFile();
    		this->OpenMode = _File.OpenMode;
    		this->TermString = _File.TermString;
    		this->AddRef(_File.GetFile());

    		return *this;
    	}

    	// Can possibly go too far...?
    	inline CFile& operator >> (string &_String)
    	{
    		char Current;

    		_String = string();  // reset string

    		while (1) {
    			fread(&Current, 1, 1, this->File);
    			if (!NotTerm(Current) || feof(this->File)) {
    				while (1) {  // Take care of multiple terminating characters
    					fread(&Current, 1, 1, this->File);
    					if (NotTerm(Current) || feof(this->File))
    						return *this;
    				}
    			}
    			_String += Current;
    		}

    		return *this;
    	}

    	inline CFile& operator >> (char *_String)
    	{
    		string String;
    		this->operator >> (String);
    		_String = strdup(String.c_str());
    		return *this;
    	}

    	inline CFile& operator << (string &_String)
    	{
    		fwrite((void*)_String.c_str(), 1, _String.length(), this->File);
    		return *this;
    	}

    	inline CFile& operator << (char *_String)
    	{
    		fwrite(_String, 1, strlen(_String), this->File);
    		return *this;
    	}

    	inline CFile& operator << (int32 _Num)
    	{
    		if (this->OpenMode == BINARY)
    			fwrite(&_Num, 1, sizeof(_Num), this->File);
    		else
    			fprintf(this->File, "%d", _Num);
    		return *this;
    	}

    	inline CFile& operator << (real64 _Num)
    	{
    		if (this->OpenMode == BINARY)
    			fwrite(&_Num, 1, sizeof(_Num), this->File);
    		else
    			fprintf(this->File, "%f", _Num);
    		return *this;
    	}

    	inline boolean operator ! (void)
    	{
    		return (this->File == NULL);
    	}

    	int32	OpenMode;  // Wish it could be protected...oh well.
    	string	TermString;  // Same here
    	int32	Endian;

    protected:
    	FILE	*File;

    	enum	{ BINARY, TEXT };

    	// Just returns if _Char is a terminating character in TermString
    	inline boolean NotTerm(char _Char)
    	{
    		uint32 Count = 0;
    		while (Count < TermString.length()) {
    			if (TermString[Count++] == _Char)
    				return false;
    		}
    		return true;
    	}

    	// Returns what kind of mode _String specifies or else TEXT
    	inline int32 SetMode(char *_String)
    	{
    		uint32 Len = strlen(_String);

    		for (uint32 i = 0; i < Len; i++) {
    			if (_String[i] == 'b') {
    				return BINARY;
    			}
    			else if (_String[i] == 't') {
    				return TEXT;
    			}
    		}

    		return TEXT;  // Default is text.
    	}

    private:
    	void AddRef(FILE *_File)
    	{
    		for (Iter = RefCount.begin(); Iter != RefCount.end(); Iter++) {
    			if (Iter->f == File) {
    				Iter->Count++;
    				return;
    			}
    		}

    		RefCount.insert(RefCount.begin(), REF(_File));
    	}

    	boolean SafeToDel(FILE *_File)
    	{
    		boolean InList = false;

    		for (Iter = RefCount.begin(); Iter != RefCount.end(); Iter++) {
    			if (Iter->f == File) {
    				InList = true;
    				if (Iter->Count == 0) {
    					RefCount.erase(Iter);
    					return true;
    				}
    			}
                      Iter->f--;
    		}

    		if (InList)
    			return false;
    		return true;
    	}

    };

    #endif//FILE_H

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.