/*

	fileofdouble.cpp: sequential file of "double" items

	2.4.2001

	Copyright (C) 2001 by Josef Pelikan, MFF UK Prague
		http://sun3.ms.mff.cuni.cz/~pepca/

    VUCAKO Bench is Open Source software (see http://www.opensource.org/
    for description what Open Source is); you may distributed it and/or
    modify it under the terms of GNU General Public License as published
    by the Free Software Foundation; either version 2, or (at your option)
    any later version.

    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.

    A copy of the GNU General Public License is available as
    `/usr/doc/copyright/GPL' in the Debian GNU/Linux distribution or on
    the World Wide Web at http://www.gnu.org/copyleft/gpl.html.  You can
    also obtain it by writing to the Free Software Foundation, Inc., 59
    Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "pch.h"
#include "fileofdouble.h"

FileOfDouble::FileOfDouble ( const char *fileName, bool RW )
{
    readWrite = RW;
    strncpy(fn,fileName,MaxFileName);
    fn[MaxFileName-1] = (char)0;
    f = fopen(fn,RW ? "w+b" : "rb");
    fPos = 0;
    used = ptr = 0;
    changed = false;
}

void FileOfDouble::rewrite ()
{
    if ( !readWrite ) return;
    if ( f ) fclose(f);
    f = fopen(fn,"w+b");
    fPos = 0;
    used = ptr = 0;
    changed = false;
}

void FileOfDouble::flushBuffer ()
{
    if ( changed ) {
        fseek(f,fPos*sizeof(double),SEEK_SET);
        fwrite(b,sizeof(double),used,f);
        changed = false;
        }
}

void FileOfDouble::readBuffer ()
{
    flushBuffer();
    fPos += ptr;
    fseek(f,fPos*sizeof(double),SEEK_SET);
    used = fread(b,sizeof(double),FileBuffer,f);
    ptr = 0;
}

void FileOfDouble::seek ( int pos )
{
    if ( pos < fPos || pos > fPos + used ) {
        flushBuffer();
        fPos = pos;
        used = ptr = 0;
        }
    else
        ptr = pos - fPos;
}

int FileOfDouble::tell () const
{
    return( fPos + ptr );
}

void FileOfDouble::put ( double d )
{
    if ( !readWrite ) return;
    if ( ptr == FileBuffer ) {
        flushBuffer();
        fPos += ptr;
        used -= ptr;
        ptr = 0;
        }
    b[ptr++] = d;
    if ( ptr > used ) used = ptr;
    changed = true;
}


double FileOfDouble::get ()
{
    if ( ptr == used ) readBuffer();
    if ( ptr == used ) return -1.0;
    return b[ptr++];
}

void FileOfDouble::close ()
{
    if ( f ) {
        flushBuffer();
        fclose(f);
        f = NULL;
        }
    fPos = used = ptr = 0;
}

FileOfDouble::~FileOfDouble ()
{
    close();
}
