Blame src/tools/file/input.cpp

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