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.