/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
/* libmwaw: tools
* Version: MPL 2.0 / LGPLv2+
*
* The contents of this file are subject to the Mozilla Public License Version
* 2.0 (the "License"); you may not use this file except in compliance with
* the License or as specified alternatively below. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Major Contributor(s):
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
*
*
* All Rights Reserved.
*
* For minor contributions see the git repository.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
* in which case the provisions of the LGPLv2+ are applicable
* instead of those above.
*/
#include <string.h>
#include <iostream>
#include "file_internal.h"
#include "input.h"
namespace libmwaw_tools
{
//
// InputStream
//
InputStream::~InputStream()
{
}
unsigned char InputStream::readU8()
{
unsigned long nRead;
unsigned char const *data = read(1, nRead);
if (!data || nRead != 1) return 0;
return data[0];
}
unsigned short InputStream::readU16()
{
unsigned long nRead;
unsigned char const *data = read(2, nRead);
if (!data || nRead != 2) return 0;
return static_cast<unsigned short>((data[0]<<8)+data[1]);
}
unsigned int InputStream::readU32()
{
unsigned long nRead;
unsigned char const *data = read(4, nRead);
if (!data || nRead != 4) return 0;
return static_cast<unsigned int>((data[0]<<24)+(data[1]<<16)+(data[2]<<8)+data[3]);
}
char InputStream::read8()
{
unsigned long nRead;
unsigned char const *data = read(1, nRead);
if (!data || nRead != 1) return 0;
return static_cast<char>(data[0]);
}
short InputStream::read16()
{
unsigned long nRead;
unsigned char const *data = read(2, nRead);
if (!data || nRead != 2) return 0;
return static_cast<short>((data[0]<<8)+data[1]);
}
int InputStream::read32()
{
unsigned long nRead;
unsigned char const *data = read(4, nRead);
if (!data || nRead != 4) return 0;
return static_cast<int>((data[0]<<24)+(data[1]<<16)+(data[2]<<8)+data[3]);
}
int InputStream::seek(long _offset, SeekType seekType)
{
long sz = length();
if (seekType == SK_CUR)
m_offset += _offset;
else if (seekType == SK_SET)
m_offset = _offset;
else if (seekType == SK_END)
m_offset = sz+_offset;
if (m_offset < 0) {
m_offset = 0;
return 1;
}
if (m_offset > sz) {
m_offset = sz;
return 1;
}
return 0;
}
//
// StringStream
//
StringStream::StringStream(const unsigned char *data, const unsigned long dataSize)
: InputStream()
, m_buffer(dataSize)
{
memcpy(&m_buffer[0], data, dataSize);
}
const unsigned char *StringStream::read(unsigned long numBytes, unsigned long &numBytesRead)
{
numBytesRead = 0;
if (numBytes == 0)
return 0;
unsigned long numBytesToRead;
if ((static_cast<unsigned long>(m_offset)+numBytes) < m_buffer.size())
numBytesToRead = numBytes;
else
numBytesToRead = static_cast<unsigned long>(static_cast<long>(m_buffer.size()) - m_offset);
numBytesRead = numBytesToRead; // about as paranoid as we can be..
if (numBytesToRead == 0)
return 0;
long oldOffset = m_offset;
m_offset += numBytesToRead;
return &m_buffer[size_t(oldOffset)];
}
//
// FileStream
//
FileStream::FileStream(char const *path)
: InputStream()
, m_file(0)
, m_isOk(true)
, m_buffer()
, m_bufferPos(0)
{
m_file = fopen(path,"r");
if (m_file)
return;
#ifdef DEBUG
std::cerr << "FileStream:FileStream can not open " << path << "\n";
#endif
m_isOk = false;
}
FileStream::~FileStream()
{
if (!m_isOk) return;
if (m_file) fclose(m_file);
}
unsigned char const *FileStream::read(unsigned long numBytes, unsigned long &numBytesRead)
{
numBytesRead = 0;
if (!m_isOk || !m_file)
return 0;
long lastPos = m_offset+long(numBytes);
long fileLength = length();
if (lastPos > fileLength) lastPos = fileLength;
// check if the buffer is or not ok
auto bufSize = long(m_buffer.size());
if (m_offset < m_bufferPos || lastPos > m_bufferPos+bufSize) {
auto numToRead = size_t(numBytes);
if (numToRead < 4096 && m_offset+4096 <= fileLength)
numToRead = 4096;
else if (numToRead < 4096)
numToRead = size_t(fileLength-m_offset);
if (numToRead==0)
return 0;
// try to read numToRead bytes
m_bufferPos = m_offset;
m_buffer.resize(size_t(numToRead));
#if 0
MWAW_DEBUG_MSG(("FileStream::read called with %ld[%ld]: read %ld bytes\n", m_offset, numBytes, numToRead));
#endif
if (fseek(m_file, m_offset, SEEK_SET)==-1) {
MWAW_DEBUG_MSG(("FileStream::read get error when doing a seek\n"));
m_buffer.clear();
return 0;
}
size_t nRead = fread(&(m_buffer[0]), 1, numToRead, m_file);
if (nRead != numToRead) {
MWAW_DEBUG_MSG(("FileStream::read get error when reading data\n"));
m_buffer.resize(size_t(nRead));
}
}
bufSize = long(m_buffer.size());
if (!bufSize)
return 0;
numBytesRead = static_cast<unsigned long>(m_bufferPos + bufSize - m_offset);
if (numBytesRead > numBytes)
numBytesRead = numBytes;
unsigned char const *res = &(m_buffer[size_t(m_offset-m_bufferPos)]);
m_offset += long(numBytesRead);
return res;
}
long FileStream::length()
{
if (!m_isOk || !m_file) return 0;
if (fseek(m_file, 0, SEEK_END)==-1) {
MWAW_DEBUG_MSG(("FileStream::length get error when reading data\n"));
return 0;
}
return long(ftell(m_file));
}
}
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: