BinaryFile.cpp
Go to the documentation of this file.
00001 /*      
00002  * File: BinaryFile.cpp
00003  * Project: DUtils library
00004  * Author: Dorian Galvez-Lopez
00005  * Date: April 2010
00006  * Description: reads and writes binary files in network byte order.
00007  *    Manages endianness and data size automatically.
00008  *
00009  * 
00010  * This program is free software: you can redistribute it and/or modify
00011  * it under the terms of the GNU Lesser General Public License as published by
00012  * the Free Software Foundation, either version 3 of the License, or
00013  * any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public License
00021  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00022  *
00023  */
00024 
00025 #include "FileModes.h"
00026 #include "BinaryFile.h"
00027 
00028 #ifdef WIN32
00029 #include <winsock2.h>
00030 #else
00031 #include <netinet/in.h>
00032 #endif
00033 
00034 #ifdef _MSC_VER
00035 // Microsoft Visual Studio does not ship stdint.h
00036 typedef __int32 int32_t;
00037 typedef unsigned __int32 uint32_t;
00038 typedef __int64 int64_t;
00039 typedef unsigned __int32 uint64_t;
00040 #else
00041 #include <stdint.h>
00042 #endif
00043 
00044 
00045 using namespace DUtils;
00046 
00047 BinaryFile::BinaryFile(void): m_is_little_endian(-1)
00048 {
00049         setEndianness();
00050 }
00051 
00052 BinaryFile::~BinaryFile(void)
00053 {
00054         Close();
00055 }
00056 
00057 void BinaryFile::Close()
00058 {
00059         if(m_f.is_open()) m_f.close();
00060 }
00061 
00062 BinaryFile::BinaryFile(const char *filename, const FILE_MODES mode)
00063 {
00064         Init(filename, mode);
00065 }
00066 
00067 BinaryFile::BinaryFile(const string &filename, const FILE_MODES mode)
00068 {
00069         Init(filename.c_str(), mode);
00070 }
00071 
00072 void BinaryFile::Init(const char *filename, const FILE_MODES mode)
00073 {
00074         m_is_little_endian = -1;
00075         setEndianness();
00076         
00077         if(mode & READ){
00078                 OpenForReading(filename);
00079         }else if((mode & WRITE) && (mode & APPEND)){
00080                 OpenForAppending(filename);
00081         }else if(mode & WRITE){
00082                 OpenForWriting(filename);
00083         }else{
00084                 throw DException("Wrong access mode");
00085         }
00086 }
00087 
00088 void BinaryFile::OpenForReading(const char *filename)
00089 {
00090         Close();
00091 
00092         m_f.open(filename, ios::in | ios::binary);
00093         if(!m_f.is_open()){
00094                 throw DException(string("Cannot open ") + filename + " for reading");
00095         }else{
00096                 m_mode = READ;
00097         }
00098 }
00099 
00100 void BinaryFile::OpenForWriting(const char *filename)
00101 {
00102         Close();
00103         
00104         m_f.open(filename, ios::out | ios::binary);
00105         if(!m_f.is_open()){
00106                 throw DException(string("Cannot open ") + filename + " for writing");
00107         }else{
00108                 m_mode = WRITE;
00109         }
00110 }
00111 
00112 void BinaryFile::OpenForAppending(const char *filename)
00113 {
00114         Close();
00115 
00116         m_f.open(filename, ios::out | ios::app | ios::binary);
00117         if(!m_f.is_open()){
00118                 throw DException(string("Cannot open ") + filename + " for writing at the end");
00119         }else{
00120                 m_mode = DUtils::FILE_MODES(WRITE | APPEND);
00121         }
00122 }
00123 
00124 void BinaryFile::DiscardBytes(int count)
00125 {
00126         if(!m_f.is_open()) throw DException("File is not open");
00127 
00128         if(m_mode & READ){
00129                 m_f.ignore(count);
00130         }else
00131                 throw DException("Wrong access mode");
00132 }
00133 
00134 inline bool BinaryFile::Eof()
00135 {
00136         return(!m_f.is_open() || m_f.eof());
00137 }
00138 
00139 unsigned int BinaryFile::BytesRead()
00140 {
00141         if(m_mode & READ){
00142                 return (unsigned int)m_f.tellg();
00143         }else
00144                 throw DException("Wrong access mode");
00145 }
00146 
00147 BinaryFile& BinaryFile::operator<< (char v)
00148 {
00149         if(!m_f.is_open()) throw DException("File is not open");
00150 
00151         if(m_mode & WRITE){
00152                 m_f.write(&v, 1);
00153         }else
00154                 throw DException("Wrong access mode");
00155         
00156         return *this;
00157 }
00158 
00159 BinaryFile& BinaryFile::operator<< (int v)
00160 {
00161         if(!m_f.is_open()) throw DException("File is not open");
00162 
00163         if(m_mode & WRITE){
00164                 uint32_t w = htonl(v);
00165                 m_f.write((const char *)&w, 4);
00166         }else
00167                 throw DException("Wrong access mode");
00168         
00169         return *this;
00170 }
00171 
00172 BinaryFile& BinaryFile::operator<< (float v)
00173 {
00174         if(!m_f.is_open()) throw DException("File is not open");
00175 
00176         if(m_mode & WRITE){
00177                 hton_f(v, m_aux);
00178                 m_f.write(m_aux, 4);
00179         }else
00180                 throw DException("Wrong access mode");
00181         
00182         return *this;
00183 }
00184 
00185 BinaryFile& BinaryFile::operator<< (double v)
00186 {
00187         if(!m_f.is_open()) throw DException("File is not open");
00188 
00189         if(m_mode & WRITE){
00190                 hton_d(v, m_aux);
00191                 m_f.write(m_aux, 8);
00192         }else
00193                 throw DException("Wrong access mode");
00194         
00195         return *this;
00196 }
00197 
00198 BinaryFile& BinaryFile::operator>>(char &v)
00199 {
00200         if(!m_f.is_open()) throw DException("File is not open");
00201 
00202         if(m_mode & READ){
00203                 m_f.read(&v, 1);
00204         }else
00205                 throw DException("Wrong access mode");
00206         
00207         return *this;
00208 }
00209 
00210 BinaryFile& BinaryFile::operator>>(int &v)
00211 {
00212         if(!m_f.is_open()) throw DException("File is not open");
00213 
00214         if(m_mode & READ){
00215                 m_f.read(m_aux, 4);
00216                 uint32_t *w = ((uint32_t*)&m_aux[0]);
00217                 v = (int)htonl(*w);
00218         }else
00219                 throw DException("Wrong access mode");
00220         
00221         return *this;
00222 }
00223 
00224 BinaryFile& BinaryFile::operator>>(float &v)
00225 {
00226         if(!m_f.is_open()) throw DException("File is not open");
00227 
00228         if(m_mode & READ){
00229                 m_f.read(m_aux, 4);
00230                 v = ntoh_f(m_aux);
00231         }else
00232                 throw DException("Wrong access mode");
00233         
00234         return *this;
00235 }
00236 
00237 BinaryFile& BinaryFile::operator>>(double &v)
00238 {
00239         if(!m_f.is_open()) throw DException("File is not open");
00240 
00241         if(m_mode & READ){
00242                 m_f.read(m_aux, 8);
00243                 v = ntoh_d(m_aux);
00244         }else
00245                 throw DException("Wrong access mode");
00246         
00247         return *this;
00248 }
00249 
00250 
00251 void BinaryFile::hton_f(float v, char buf[8]) const
00252 {
00253         unsigned char *w = (unsigned char *)&v;
00254 
00255         // network order is big endian
00256         if(isLittleEndian()){
00257                 buf[0] = w[3];
00258                 buf[1] = w[2];
00259                 buf[2] = w[1];
00260                 buf[3] = w[0];
00261         }else{
00262                 buf[0] = w[0];
00263                 buf[1] = w[1];
00264                 buf[2] = w[2];
00265                 buf[3] = w[3];
00266         }
00267 }
00268 
00269 float BinaryFile::ntoh_f(char buf[8]) const
00270 {
00271         float v;
00272         unsigned char *w = (unsigned char*)&v;
00273 
00274         // network order is big endian
00275         if(isLittleEndian()){
00276                 w[3] = buf[0];
00277                 w[2] = buf[1];
00278                 w[1] = buf[2];
00279                 w[0] = buf[3];
00280         }else{
00281                 w[0] = buf[0];
00282                 w[1] = buf[1];
00283                 w[2] = buf[2];
00284                 w[3] = buf[3];
00285         }
00286 
00287         return v;
00288 }
00289 
00290 void BinaryFile::hton_d(double v, char buf[8]) const
00291 {
00292         unsigned char *w = (unsigned char *)&v;
00293 
00294         // network order is big endian
00295         if(isLittleEndian()){
00296                 buf[0] = w[7];
00297                 buf[1] = w[6];
00298                 buf[2] = w[5];
00299                 buf[3] = w[4];
00300                 buf[4] = w[3];
00301                 buf[5] = w[2];
00302                 buf[6] = w[1];
00303                 buf[7] = w[0];
00304         }else{
00305                 buf[0] = w[0];
00306                 buf[1] = w[1];
00307                 buf[2] = w[2];
00308                 buf[3] = w[3];
00309                 buf[4] = w[4];
00310                 buf[5] = w[5];
00311                 buf[6] = w[6];
00312                 buf[7] = w[7];
00313         }
00314 }
00315 
00316 double BinaryFile::ntoh_d(char buf[8]) const
00317 {
00318         double v;
00319         unsigned char *w = (unsigned char*)&v;
00320 
00321         // network order is big endian
00322         if(isLittleEndian()){
00323                 w[7] = buf[0];
00324                 w[6] = buf[1];
00325                 w[5] = buf[2];
00326                 w[4] = buf[3];
00327                 w[3] = buf[4];
00328                 w[2] = buf[5];
00329                 w[1] = buf[6];
00330                 w[0] = buf[7];
00331         }else{
00332                 w[0] = buf[0];
00333                 w[1] = buf[1];
00334                 w[2] = buf[2];
00335                 w[3] = buf[3];
00336                 w[4] = buf[4];
00337                 w[5] = buf[5];
00338                 w[6] = buf[6];
00339                 w[7] = buf[7];
00340         }
00341 
00342         return v;
00343 }
00344 
00345 void BinaryFile::setEndianness()
00346 {
00347         if(m_is_little_endian == -1){
00348                 char SwapTest[2] = { 1, 0 }; 
00349                 short *p = (short *) SwapTest;
00350                 m_is_little_endian = (*p == 1 ? 1 : 0);
00351         }
00352 }
00353         


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:30:47