/* binio.cc */ #include "binio.h" #include "inf.h" #include "ioexception.h" #include // function memcpy OPEN_NAMESPACE /********************************* INPUT **********************************/ TInput::TInput (): InpStream (NULL), BufPos (0), BufLen (0), // ignore Buf FileName (""), release_stream (NULL) { } TInput::~TInput () { if (release_stream != NULL) { delete release_stream; release_stream = NULL; } } void TInput::Init () { BufPos = 0; BufLen = 0; // do not change already initialized InpStream, FileName and release_stream } void TInput::Open (istream & stream) { InpStream = & stream; assert (InpStream != NULL); Init (); } void TInput::Open (string name) { SetFileName (name); ifstream * tmp = new ifstream; tmp->open (name.c_str ()); if (!tmp->good ()) { Error ("Cannot open " + name); delete tmp; } else { assert (release_stream == NULL); release_stream = tmp; Open (*tmp); } } /* ---------------------------------------------------------------------- */ void TInput::Message (MessageLevel level, const string msg) { message (level, msg, FileName, 0, 0); } void TInput::Info (const string msg) { Message (InfoLevel, msg); } void TInput::Note (const string msg) { Message (NoteLevel, msg); } void TInput::Warning (const string msg) { Message (WarningLevel, msg); } void TInput::Error (const string msg) { Message (ErrorLevel, msg); } void TInput::Abort (const string msg) { Message (AbortLevel, msg); } /* ---------------------------------------------------------------------- */ void TInput::ReadBuf () { assert (InpStream != NULL); if (! InpStream->good ()) // important for string streams { BufLen = 0; } else { InpStream->read (static_cast (static_cast (& Buf)), BufSize); BufLen = InpStream->gcount (); } BufPos = 0; } void TInput::ReadData (void * adr, size_t size) { size_t step; assert (BufPos >= 0); assert (BufPos <= BufLen); assert (BufLen >= 0); assert (BufLen <= BufSize); while (size > 0) { if (BufPos >= BufLen) { ReadBuf (); if (BufLen == 0) Error ("End of file"); } step = BufLen - BufPos; if (step > size) step = size; assert (step > 0); assert (step <= size); assert (BufPos >= 0); assert (BufPos + step <= BufLen); assert (BufLen >= 0); assert (BufLen <= BufSize); memcpy (adr, & Buf[BufPos], step); BufPos += step; size -= step; adr = (void *) ((char *) (adr) + step); assert (size >= 0); } } /********************************* OUTPUT *********************************/ TOutput::TOutput () : OutStream (NULL), BufLen (0), // ignore Buf FileName (), release_stream (NULL) { } TOutput::~TOutput () { Flush (); if (release_stream != NULL) { delete release_stream; release_stream = NULL; } } void TOutput::Init () { BufLen = 0; // do not change already initialized InpStream, FileName and release_stream } void TOutput::Open (ostream & stream) { assert (OutStream == NULL); OutStream = & stream; Init (); } void TOutput::Open (string name) { SetFileName (name); ofstream * tmp = new ofstream; tmp->open (name.c_str ()); if (!tmp->good ()) { Error ("Cannot open file for writing " + name); delete tmp; } else { assert (release_stream == NULL); release_stream = tmp; Open (*tmp); } } /* ---------------------------------------------------------------------- */ void TOutput::Message (MessageLevel level, const string msg) { message (level, msg, FileName, 0, 0); } void TOutput::Info (const string msg) { Message (InfoLevel, msg); } void TOutput::Note (const string msg) { Message (NoteLevel, msg); } void TOutput::Warning (const string msg) { Message (WarningLevel, msg); } void TOutput::Error (const string msg) { Message (ErrorLevel, msg); } void TOutput::Abort (const string msg) { Message (AbortLevel, msg); } /* ---------------------------------------------------------------------- */ void TOutput::WriteBuf () { assert (OutStream != NULL); OutStream->write (static_cast (static_cast (& Buf)), BufLen); if (OutStream->bad()) Error ("Error writing to output"); BufLen = 0; } void TOutput::WriteData (const void * adr, size_t size) { if (BufLen >= BufSize) WriteBuf (); size_t step; while (size > 0) { step = BufSize - BufLen; if (step > size) step = size; assert (step > 0); assert (step <= size); assert (BufLen >= 0); assert (BufLen + step <= BufSize); memcpy (& Buf[BufLen], adr, step); BufLen += step; size -= step; adr = (void *) ((char *) (adr) + step); if (BufLen == BufSize) WriteBuf (); } } void TOutput::WriteOneByte (byte value) { if (BufLen >= BufSize) WriteBuf (); Buf [BufLen] = value; BufLen ++; } void TOutput::WriteSameBytes (byte value, size_t size) { if (BufLen >= BufSize) WriteBuf (); size_t step; while (size > 0) { step = BufSize - BufLen; if (step > size) step = size; assert (step > 0); assert (step <= size); assert (BufLen >= 0); assert (BufLen + step <= BufSize); memset (& Buf[BufLen], value, step); BufLen += step; size -= step; if (BufLen == BufSize) WriteBuf (); } } void TOutput::Flush () { if (BufLen > 0) WriteBuf (); } /****************************** BINARY INPUT ******************************/ #ifdef BIN_INPUT_OUTPUT #if 0 TBinInput::TBinInput () : { } TBinInput::~TBinInput () : { } #endif void TBinInput::CheckEof () { bool eof = (BufPos == BufLen); if (eof) { ReadBuf (); eof = (BufLen == 0); } if (! eof) Error ("End of file expected"); } /* ---------------------------------------------------------------------- */ bool TBinInput::ReadBool () { bool result; ReadData (& result, sizeof (result)); return result; } char TBinInput::ReadChar () { char result; ReadData (& result, sizeof (result)); return result; } wchar_t TBinInput::ReadWideChar () { wchar_t result; ReadData (& result, sizeof (result)); return result; } /* ---------------------------------------------------------------------- */ int8 TBinInput::ReadInt8 () { int8 result; ReadData (& result, sizeof (result)); return result; } int16 TBinInput::ReadInt16 () { int16 result; ReadData (& result, sizeof (result)); return result; } int32 TBinInput::ReadInt32 () { int32 result; ReadData (& result, sizeof (result)); return result; } #ifdef INT64 int64 TBinInput::ReadInt64 () { int64 result; ReadData (& result, sizeof (result)); return result; } #endif /* ---------------------------------------------------------------------- */ uint8 TBinInput::ReadUInt8 () { uint8 result; ReadData (& result, sizeof (result)); return result; } uint16 TBinInput::ReadUInt16 () { uint16 result; ReadData (& result, sizeof (result)); return result; } uint32 TBinInput::ReadUInt32 () { uint32 result; ReadData (& result, sizeof (result)); return result; } #ifdef INT64 uint64 TBinInput::ReadUInt64 () { uint64 result; ReadData (& result, sizeof (result)); return result; } #endif /* ---------------------------------------------------------------------- */ float TBinInput::ReadFloat () { float result; ReadData (& result, sizeof (result)); return result; } double TBinInput::ReadDouble () { double result; ReadData (& result, sizeof (result)); return result; } size_t TBinInput::ReadCode () { uint8 n = ReadUInt8 (); if (n < 255) return n; else return ReadUInt32 (); } /* ---------------------------------------------------------------------- */ string TBinInput::ReadString () { // size_t n = ReadUtf8 (); size_t n = ReadCode (); char * txt = new char [n+1]; ReadData (txt, n); txt[n] = 0; return string (txt); } /***************************** BINARY OUTPUT ******************************/ #if 0 TBinOutput::TBinOutput () { } TBinOutput::~TBinOutput () { } #endif void TBinOutput::WriteBool (bool value) { WriteData (& value, sizeof (value)); } void TBinOutput::WriteChar (char value) { WriteData (& value, sizeof (value)); } void TBinOutput::WriteWideChar (wchar_t value) { WriteData (& value, sizeof (value)); } /* ---------------------------------------------------------------------- */ void TBinOutput::WriteInt8 (int8 value) { WriteData (& value, sizeof (value)); } void TBinOutput::WriteInt16 (int16 value) { WriteData (& value, sizeof (value)); } void TBinOutput::WriteInt32 (int32 value) { WriteData (& value, sizeof (value)); } #ifdef INT64 void TBinOutput::WriteInt64 (int64 value) { WriteData (& value, sizeof (value)); } #endif /* ---------------------------------------------------------------------- */ void TBinOutput::WriteUInt8 (uint8 value) { WriteData (& value, sizeof (value)); } void TBinOutput::WriteUInt16 (uint16 value) { WriteData (& value, sizeof (value)); } void TBinOutput::WriteUInt32 (uint32 value) { WriteData (& value, sizeof (value)); } #ifdef INT64 void TBinOutput::WriteUInt64 (uint64 value) { WriteData (& value, sizeof (value)); } #endif /* ---------------------------------------------------------------------- */ void TBinOutput::WriteFloat (float value) { WriteData (& value, sizeof (value)); } void TBinOutput::WriteDouble (double value) { WriteData (& value, sizeof (value)); } /* ---------------------------------------------------------------------- */ void TBinOutput::WriteCode (size_t code) { if ((code >= 0) && (code <= 254)) WriteUInt8 (code); else { WriteUInt8 (255); WriteUInt32 (code); } } void TBinOutput::WriteString (const string s) { size_t n = s.length (); // if (n >= 0x10000) Error ("String too long"); // WriteUtf8 (n); WriteCode (n); WriteData (s.c_str (), n); } /******************************* ENCODING *********************************/ /* 8 1000 9 1001 A 1010 B 1011 C 1100 D 1101 E 1110 F 1111 */ /* uint16 TBinInput::ReadUtf8 () { uint16 result; uint8 n = ReadUInt8 (); if (n < 0x80) // 0 <7 bits> result = n; else { int cnt = 0; if ((n & 0xe0) == 0xc0) // 110 <5 bits> { result = n & 0x1f; // 5 bits cnt = 1; // 1 byte (6 bits) } else if ((n & 0xf0) == 0xe0) // 1110 <4 bits> { result = n & 0x0f; // 4 bits cnt = 2; // 2 bytes (12 bits) } else { Error ("Bad UTF-8 code"); } for (int i = 0; i < cnt; i++) { n = ReadUInt8 (); if ((n & 0xc0) == 0x80) // 10 <6 bits> result = (result << 6) | (n & 0x3f); else Error ("Bad UTF-8 code"); } } return result; } void TBinOutput::WriteUtf8 (uint16 code) { code &= 0xffff; if (code < 0x80) // 7 bits { WriteUInt8 (code); // 0 <7 bits> } else if (code < 0x0800) // 11 bits { WriteUInt8 (0xc0 | (code >> 6)); // 110 <5 bits> WriteUInt8 (0x80 | (code & 0x3f)); // 10 <6 bits> } else { WriteUInt8 (0xe0 | (code >> 12)); // 1110 <4 bits> WriteUInt8 (0x80 | ((code >> 6) && 0x3f)); // 10 <6 bits> WriteUInt8 (0x80 | (code & 0x3f)); // 10 <6 bits> } } */ /* ---------------------------------------------------------------------- */ #endif // BIN_INPUT_OUTPUT CLOSE_NAMESPACE