## SoLoud::File

SoLoud has a unified file i/o interface. All of the audio sources in SoLoud that require files
use the File class internally and support loading through a File class.

This enables SoLoud to load from memory pointers, stream data from memory, as well as support
virtual filesystems such as PhysFS by extending the File class.

![File class hierarcy](images/file)

SoLoud has two File-extended classes, DiskFile which uses stdio FILE* interfaces internally, 
and MemoryFile which uses an in-memory buffer.

The File class only supports loading.

### File class

The File class is abstract, and provides some helper functions.

	class File
	{
	public:
		unsigned int read8();
		unsigned int read16();
		unsigned int read32();
		virtual int eof() = 0;
		virtual unsigned int read(unsigned char *aDst, unsigned int aBytes) = 0;
		virtual unsigned int length() = 0;
		virtual void seek(int aOffset) = 0;
		virtual unsigned int pos() = 0;
		virtual FILE * getFilePtr() { return 0; }
		virtual unsigned char * getMemPtr() { return 0; }
	};

### File.read8(), File.read16(), File.read32()

Helper functions reading 8, 16 and 32 bits from the file stream.

    unsigned char  foo = myfile.read8();
    unsigned short bar = myfile.read16();
    unsigned int   baz = myfile.read32();

Note that the output of these helpers are unsigned, which may cause problems
unless you remember to cast to signed when handling signed data, such as
samples.

### File.getFilePtr()

Returns FILE pointer if avaiable, 0 if not. Useful to check if we're using
DiskFile (or compatible), and avoids casting between File class subtypes
if access to the FILE pointer is needed.

### File.getMemPtr()

Returns memory pointer if avaiable, 0 if not. Useful to check if we're using
MemoryFile (or compatible), and avoids casting between File class subtypes
if access to the memory pointer is needed.

### File.eof()

Returns non-zero if the stream is at end of file, zero otherwise.

### File.read()

Read up to aBytes worth of bytes from stream. Return number of bytes actually read.

### File.length()

Return length of the file in bytes.

### File.seek()

Seek to byte offset from beginning of stream.

### File.pos()

Return current byte position in stream.

### Typical File Interfaces

Using the File interface we easily support the following kind of interfaces:


    load(const char* aFilename);
    
Load file from disk.


    loadMem(unsigned char *aData, unsigned int aDataLength, 
            bool aCopy=false, bool aTakeOwnership=true);
    
Load file from a memory pointer, optionally taking a copy of the data, and also 
optionally taking ownership and calling delete[] on the data when closing the file.


    LoadFile(File *aFile);
    
Load file through File class, useful if you have custom File-extended class.


    LoadToMem(const char *aFilename);
    
Load file from disk to a memory buffer, and then use it as a memory file.


    LoadFileToMem(File *aFile);
    
Combination of LoadToMem and LoadFile.

Some interfaces don't supply all of the above, because they either don't need to
keep the file data around, or if they are always storing the data in a memory
buffer.

### soloud_file_hack_on.h / soloud_file_hack_off.h

SoLoud comes with a pair of headers you can use to fool code which uses the FILE*
interface to use File* instead. 

The files use preprocessor macros to turn FILE* calls into SoLoud's wrapper
function calls which in turn use the File class interfaces. Since it's a 
preprocessor hack, the soloud\_file\_hack\_on.h must be included after stdio.h,
or it will break stdio.h.

To switch the hack off again, you can include the soloud\_file\_hack\_off.h, which
will undefine the preprocessor macros.

Current version of the hack overrides fgetc, fread, fseek, ftell, fclose and fopen.
The wrapper functions can be found in soloud_file.cpp.
