#include "xentax.h"

real32 float_16_to_32(uint16 value)
{
 // sign/exponent/mantissa
 const uint16 s = (value & 0x8000);
 const uint16 e = (value & 0x7C00) >> 10;
 const uint16 m = (value & 0x03FF);

 // ok
 const real32 sgn = (s ? -1.0f : 1.0f);
 if(e == 0) return sgn*(m == 0 ? 0.0f : std::pow(2.0f, -14.0f)*((real32)m/1024.0f));
 if(e < 32) return sgn*std::pow(2.0f, (real32)e - 15.0f)*(1.0f + ((real32)m/1024.0f));

 // not ok!
 if(m == 0) return std::numeric_limits<real32>::quiet_NaN();
 return std::numeric_limits<real32>::quiet_NaN();
}

bool read_string(std::istream& ifile, char* data, size_t size)
{ 
 return read_string(ifile, data, size, (char)0);
}

bool read_string(std::istream& ifile, char* data, size_t size, char delimiter)
{
 if(size == 0) return false;
 for(size_t curr = 0; ; curr++) {
     char c = (char)ifile.peek();
     if(ifile.fail() || ifile.eof()) return false;
     ifile.seekg(1, std::ios::cur);
     if(ifile.fail()) return false;
     if(c == delimiter) { data[curr] = '\0'; break; }
     else data[curr] = c;     
    }
 return true;
}

bool write_aligned_string_02(std::ofstream& ofile, const char* str)
{
 // length of string including null terminator (very important to include terminator!)
 uint32 elem = strlen(str) + 1;
 if(!elem) return false;

 // length of aligned string
 uint32 size = align02(elem);
 if(!size) return false;

 // copy string
 boost::shared_array<char> data(new char[size]);
 for(size_t i = 0; i < size; i++) data[i] = '\0';
 memmove(data.get(), str, elem);

 // write string
 ofile.write(data.get(), size);
 if(ofile.fail()) return false;

 return true;
}

bool write_aligned_string_04(std::ofstream& ofile, const char* str)
{
 // length of string including null terminator (very important to include terminator!)
 uint32 elem = strlen(str) + 1;
 if(!elem) return false;

 // length of aligned string
 uint32 size = align04(elem);
 if(!size) return false;

 // copy string
 boost::shared_array<char> data(new char[size]);
 for(size_t i = 0; i < size; i++) data[i] = '\0';
 memmove(data.get(), str, elem);

 // write string
 ofile.write(data.get(), size);
 if(ofile.fail()) return false;

 return true;
}