/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/sgx/filesystem/baseio.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/filesystem/filesystem.hpp"

#define SGX_BUFFER_SIZE 256

static tUCHAR8 ms_Buffer[SGX_BUFFER_SIZE];
    

//
// Overloaded File.read routines
//

CSGXFile& operator>>(CSGXFile&File, tREAL32 &val)
{
    sgxAssert(File.isLoading()); 

    File.read((tBYTE *)&val, sizeof(val));

    if (File.swapEndian()) {
        register tUINT32 t = *(tUINT32 *)&val;

        *(tUINT32 *)&val = sgxEndianSwap32(t);
    }

    return File;
}

CSGXFile& operator>>(CSGXFile&File, tUINT32 &val)
{
    sgxAssert(File.isLoading()); 

    File.read((tBYTE *)&val, sizeof(val));

    if (File.swapEndian()) {
        val = sgxEndianSwap32(val);
    }

    return File;
}

CSGXFile& operator>>(CSGXFile&File, tINT32 &val)
{
    sgxAssert(File.isLoading()); 

    File.read((tBYTE *)&val, sizeof(val));

    if (File.swapEndian()) {
        val = sgxEndianSwap32(val);
    }

    return File;
}

CSGXFile& operator>>(CSGXFile&File, tUINT16 &val)
{
    sgxAssert(File.isLoading()); 

    File.read((tBYTE *)&val, sizeof(val));

    if (File.swapEndian()) {
        val = sgxEndianSwap16(val);
    }

    return File;
}

CSGXFile& operator>>(CSGXFile&File, tINT16 &val)
{
    sgxAssert(File.isLoading()); 

    File.read((tBYTE *)&val, sizeof(val));

    if (File.swapEndian()) {
        val = sgxEndianSwap16(val);
    }

    return File;
}

CSGXFile& operator>>(CSGXFile&File, tUINT8 &val)
{
    sgxAssert(File.isLoading()); 

    File.read((tBYTE *)&val, sizeof(val));

    return File;
}

CSGXFile& operator>>(CSGXFile&File, tINT8 &val)
{
    sgxAssert(File.isLoading()); 

    File.read((tBYTE *)&val, sizeof(val));

    return File;
}

CSGXFile& operator>>(CSGXFile&File, sgxString &str)
{
    sgxAssert(File.isLoading()); 
    tUINT32 bytesRead;
    tUINT32 length;

    File >> length;

	// NOTE: This temporary buffer is not thread-safe.
	// It relies on the file operations occuring in only
	// one thread.
    str = "";
    do
    {
        bytesRead = File.read((tBYTE *)ms_Buffer, sgxMin((tMEM_SIZE)length, (tMEM_SIZE)sizeof(ms_Buffer)));

        if (bytesRead) {
            str += sgxString((char *)ms_Buffer);
        }
    }
    while(sizeof(ms_Buffer) == bytesRead);

    return File;
}


//
// Overloaded File.write routines
//
CSGXFile& operator<<(CSGXFile&File, const tREAL32 &val)
{
    sgxAssert(File.isSaving()); 

    tREAL32 swp = val;

    if (File.swapEndian()) {
        register tUINT32 t = *(tUINT32 *)&swp;

        *(tUINT32 *)&swp = sgxEndianSwap32(t);
    }

    File.write((tBYTE *)&swp, sizeof(swp));

    return File;
}

CSGXFile& operator<<(CSGXFile&File, const tUINT32 &val)
{
    sgxAssert(File.isSaving()); 

    register tUINT32 swp = val;

    if (File.swapEndian()) {
        swp = sgxEndianSwap32(swp);
    }

    File.write((tBYTE *)&swp, sizeof(swp));

    return File;
}

CSGXFile& operator<<(CSGXFile&File, const tINT32 &val)
{
    sgxAssert(File.isSaving()); 

    register tINT32 swp = val;

    if (File.swapEndian()) {
        swp = sgxEndianSwap32(swp);
    }

    File.write((tBYTE *)&swp, sizeof(swp));

    return File;
}

CSGXFile& operator<<(CSGXFile&File, const tUINT16 &val)
{
    sgxAssert(File.isSaving()); 

    register tUINT16 swp = val;

    if (File.swapEndian()) {
        swp = sgxEndianSwap16(swp);
    }

    File.write((tBYTE *)&swp, sizeof(swp));

    return File;
}

CSGXFile& operator<<(CSGXFile&File, const tINT16 &val)
{
    sgxAssert(File.isSaving()); 

    register tINT16 swp = val;

    if (File.swapEndian()) {
        swp = sgxEndianSwap16(swp);
    }

    File.write((tBYTE *)&swp, sizeof(swp));

    return File;
}

CSGXFile& operator<<(CSGXFile&File, const tUINT8 &val)
{
    sgxAssert(File.isSaving()); 

    File.write((tBYTE *)&val, sizeof(val));

    return File;
}

CSGXFile& operator<<(CSGXFile&File, const tINT8 &val)
{
    sgxAssert(File.isSaving()); 

    File.write((tBYTE *)&val, sizeof(val));

    return File;
}

CSGXFile& operator<<(CSGXFile&File, const sgxString &str)
{
    sgxAssert(File.isSaving()); 
    tUINT32 length = str.length()+1;

    File << length;
    File.write((tBYTE *)str.c_str(), length);

    return File;
}

