summaryrefslogtreecommitdiff
path: root/reader.cpp
diff options
context:
space:
mode:
authorTobias Klauser <tklauser@distanz.ch>2008-10-08 19:22:25 +0200
committerTobias Klauser <tklauser@xenon.tklauser.home>2008-10-08 19:22:25 +0200
commit2a441ecbea378da1a2cdea969c48bb7d9e547135 (patch)
tree63e071a86374ad86615c67f4c75534c4df8b6ab3 /reader.cpp
parent226f961c4b7fef115ae2c7950abe0e1973efc6a4 (diff)
Import new upstream release 0.42
Diffstat (limited to 'reader.cpp')
-rw-r--r--reader.cpp363
1 files changed, 0 insertions, 363 deletions
diff --git a/reader.cpp b/reader.cpp
deleted file mode 100644
index 07e267e..0000000
--- a/reader.cpp
+++ /dev/null
@@ -1,363 +0,0 @@
-/* $Id: reader.cpp,v 1.10 2006/11/05 04:42:43 ganzhorn Exp $
- * This file is part of lfhex.
- * Copyright (C) 2006 Salem Ganzhorn <eyekode@yahoo.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation version 2.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <stdexcept>
-#include <algorithm>
-#include <new>
-
-// for stat:
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-// for strerror and errno:
-#include <string.h>
-#include <errno.h>
-
-#include <assert.h>
-
-#include <stdexcept>
-
-#include "local.h"
-#include "reader.hpp" // some systems #define to map fn's to thier 64 bit
- // equivalents. make sure the header gets processed the
- // same as the .cc file
-
-Reader::Reader( const string& filename, off_t npages, off_t pageSize )
- : _filename(filename),
- _pageSize(pageSize)
-{
- _maxPages = _freePages = (npages < 10) ? 10: npages;
- _error = "";
- _is_open = false;
- _offset = 0;
- _size = 0;
- _firstPage = -1;
- _lastPage = -1;
-
- if( !filename.empty() )
- open(filename);
-}
-
-Reader::~Reader()
-{
- if( _is_open )
- close();
-}
-
-//
-// public methods
-//
-
-bool Reader::open( const string& filename )
-{
- // clear old data
- if( is_open() ) {
- this->close();
- if( is_open() ) // only occurs if close somehow fails.
- return false;
- } else {
- _is_open = false;
- }
-
- if( 0 == (_fptr = fopen( filename.c_str() , "r" )) ) {
- _error = "Failed to open \"" + filename + "\"";
- return false;
- }
-
- // get filesize
- struct stat statBuf;
- if( -1 == stat(filename.c_str(), &statBuf) ) {
- _error = "Could not stat \"" + filename + "\"";
- return false;
- }
-
- off_t filesize = statBuf.st_size;
- _size = filesize;
- // calculate necessary number of pages
- off_t npages = filesize/_pageSize +1;
- // initialize page pointers
- _data.resize(npages);
- fill( _data.begin(), _data.begin()+npages, (uchar*)0 );
-
- _filename = filename;
- _is_open = true;
- _firstPage = _lastPage = 0;
- return loadPage(0);
-}
-
-bool Reader::close()
-{
- if( !is_open() ) {
- _error = "attempted to close non-open reader.";
- return false;
- }
-
- _filename = "";
- _error = "";
- if( EOF == fclose(_fptr) ) {
- _error = strerror(errno);
- return false;
- }
- // free data pages
- vector<uchar*>::iterator itr;
- for( itr = _data.begin(); itr != _data.end(); ++itr )
- delete [] (*itr);
- _is_open = false;
- _firstPage = _lastPage = -1;
- _freePages = _maxPages;
- return true;
-}
-
-bool Reader::is_open() const
-{
- return _is_open;
-}
-
-size_t Reader::read(vector<uchar>& v, size_t numBytes)
-{
- int lastPageIdx = 0;
- size_t bytesRead;
-
- // if we don't have enough bytes left... then set page_end to lastPageIdx
- // to the last page and set bytesRead to the remaining number of bytes
- if( _offset+numBytes >= size() ) {
- _eof = true;
- lastPageIdx = _data.size()-1;
- bytesRead = size()-tell();
- // we use numBytes as a counter for the number of operations to make
- // so limit numBytes to the actual the max number of bytes left
- numBytes = bytesRead;
- } else {
- lastPageIdx = (_offset+numBytes)/_pageSize;
- bytesRead = numBytes;
- }
-
- if( !numBytes )
- return numBytes;
-
- // only do one realloc if necessary
- v.erase(v.begin(),v.end());
- v.reserve(v.size()+numBytes);
-
- // int byte_end; // == lastByteIndex+1
- // copy the data a page at a time
- for(int page = _offset/_pageSize; page <= lastPageIdx; page++) {
- // ensure the page is loaded.
- try {
- loadPage( page );
- }
- catch (bad_alloc){
- // out of memory
- _error = "Out of memory.";
- // return the number of bytes read
- return (_offset/_pageSize - page)*_pageSize;
- }
-
- int start = _offset%_pageSize;
- int stop = (page == lastPageIdx)? start+numBytes: _pageSize;
- for(int i = start; i < stop; i++) {
- v.push_back(_data[page][i]);
- }
- numBytes -= stop-start;
- _offset += stop-start;
- }
- return bytesRead;
-}
-bool Reader::eof()
-{
- return (is_open())? _eof : 0;
-}
-off_t Reader::seek(off_t offset)
-{
- if( !is_open() )
- return -1;
-
- // seek resets eof... even if the seek is past eof
- _eof = false;
-
- _offset = max( min( offset, size()-1 ), (off_t)0);
- if( fseek(_fptr, _offset, SEEK_SET) ) {
- _error = "Seek to offset:";
- _error += _offset;
- _error += " failed.";
- return -1;
- }
- assert(_offset == ftell(_fptr));
- return _offset;
-}
-
-off_t Reader::tell() const
-{
- if(!is_open())
- return -1;
- return _offset;
-}
-
-off_t Reader::size() const
-{
- return _size;
-}
-
-const char* Reader::lastError() const
-{
- return _error.c_str();
-}
-const char* Reader::filename() const
-{
- return _filename.c_str();
-}
-
-//
-// Protected member fn's
-//
-
-bool Reader::loadPage(off_t pageIdx)
-{
- if( !is_open() )
- return false;
- if(_data[pageIdx] != 0)
- return true;
-
- if( !nFreePages() ) {
- // free the page which is the furthest away from the page we are loading
-
- // this could be trouble if off_t is unsigned!
- if( abs(_firstPage - pageIdx) > abs(_lastPage - pageIdx) )
- while(!freePage(_firstPage++));
- else
- while(!freePage(_lastPage--));
- }
- _data[pageIdx] = new uchar [_pageSize];
- // page added, subtract from num available
- --nFreePages();
-
- fseek(_fptr,pageIdx*_pageSize, SEEK_SET);
-
- off_t retval = fread(_data[pageIdx], sizeof(uchar), _pageSize, _fptr);
-
- if( retval ) {
- if( pageIdx < _firstPage )
- _firstPage = pageIdx;
-
- if( pageIdx > _lastPage )
- _lastPage = pageIdx;
- }
- return retval;
-}
-
-bool Reader::freePage(off_t pageIdx)
-{
- // check range
- if( pageIdx < 0 || (unsigned)pageIdx >= _data.size() || !_data[pageIdx] )
- return false;
-
- delete [] _data[pageIdx];
- _data[pageIdx] = 0;
- ++nFreePages(); // page freed
- return true;
-}
-
-uchar Reader::operator[] (off_t offset)
-{
- if( !is_open() )
- throw logic_error("Reader::operator[] - attempt to access non-open file.");
- if( offset < 0 )
- throw out_of_range("Reader::operator[] - "
- "attempt to access negative offset.");
- if( offset >= size() )
- throw out_of_range("Reader::operator[] - "
- "attempt to access past end of file");
-
- off_t page_idx = offset/_pageSize;
- assert( loadPage( page_idx ) );
- return _data[page_idx][ offset%_pageSize ];
-}
-
-off_t
-Reader::nFreePages() const
-{
- return _freePages;
-}
-
-off_t&
-Reader::nFreePages()
-{
- return _freePages;
-}
-
-bool
-Reader::dataIsAtOffset( const vector<uchar>& data, off_t pos )
-{
- size_t i = 0;
- while( i < data.size() ) {
- if( data[i] != (*this)[pos+i] ) {
- return false;
- }
- ++i;
- }
- return true;
-}
-
-
-off_t
-Reader::findIndex( off_t start, const vector<uchar>& data, off_t stop )
-{
- off_t pos = start;
- while( pos <= stop ) {
- if( data[0] == (*this)[pos] ) {
- if( dataIsAtOffset( data, pos ) ) {
- return pos;
- }
- }
- ++pos;
- }
- return size();
-}
-
-off_t
-Reader::rFindIndex( off_t start, const vector<uchar>& data, off_t stop )
-{
- off_t pos = start;
- while( pos >= stop ) {
- if( data[0] == (*this)[pos] ) {
- if( dataIsAtOffset( data, pos ) ) {
- return pos;
- }
- }
- --pos;
- }
- return size();
-}
-
-//
-// ReadBuffer friends and aquaintances (only for debugging)
-//
-
-#if 0
-ostream& operator<< (ostream&out, const ReadBuffer& buff)
-{
- ios_base::fmtflags old_flags = out.flags();
- out.flags(old_flags | ios::hex | ios::showbase);
- for(size_t i = 0; i < buff.size(); i++)
- out << buff[i];
- // restore old flags
- out.flags(old_flags);
- return out;
-}
-#endif