/* 
 * Thomas Pantzer: readln.cc, Version: v0.1a  16.02.2000 18:02 
 * 
 * 
 * Copyright 2000 by Thomas Pantzer
 * 
 * Permission to use, copy, modify, and distribute this software for noncommercial 
 * use and without fee is hereby granted, provided that the above copyright notice 
 * appear in all copies and that both that copyright notice and this permission 
 * notice appear in supporting documentation, and that the name of the Author not be 
 * used in advertising or publicity pertaining to distribution of the software 
 * without specific, written prior permission. The Author makes no representations about
 * the suitability of this software for any purpose.  It is provided "as is" 
 * without expressed or implied warranty. 
 * 
 * 
 * pantec@zorro.informatik.uni-leipzig.de   (Thomas Pantzer) 
 * 
 */





#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>


#include "readln.h"
#include "copyright.h"


char t_buffer::Init(char *fn, int bs)
{
	bufsize = 0;
	buffer = NULL;

	rd = 0;
	offs = 0;
	filelen = 0;
	lines = 0;
//	nchars = 0;
	eot = 0;
	fend = false;
	fsize = 0;

	fd = open(fn,O_RDONLY);

	if (fd < 0)
	   {
	    char st[256];
	    sprintf(st,"t_buffer::Init(%s,%d)",fn,bs);		
	    perror(st); 
	    return false;
	   } 

	fsize = lseek(fd,0,SEEK_END);
	lseek(fd,0,SEEK_SET);

	bufsize = bs;
	buffer = new char[(bufsize*2)+1024];

	for (int i=0; i<(bufsize*2)+512; i++)
 	   buffer[i] = '\0';

	return true;
}	

long int t_buffer::Pos(void)
{
	return lseek(fd,0,SEEK_CUR);
}

char *t_buffer::ReadLn(void)
{
	char *s = &buffer[offs];
	char *nl = strchr(s,'\n');

	long int no = offs + ((nl - s)  + 1); 

	if ((nl != NULL) && (no < eot))
	   {
	    offs = no;
	    *nl = '\0';
	    lines++;	
	    return s;
	   }

	if (fend == true)
	   return NULL;	

	lshifts++;

	if (eot >= offs)
	   {
	    for (long int i=offs; i<eot; i++)
	       buffer[i-offs] = buffer[i];

	    int len = eot - offs;
	    int toload = (bufsize - len);

	    rd = read(fd,&buffer[len],toload); 

	    if (rd == 0)
	       {	
#ifdef DEBUG
   	        fprintf(stderr,"read(%d,&buffer[%d],%d) = %ld failed after %ld bytes (%ld/%ld lines)\n",
	  	        	  fd,len,toload,rd,filelen,lines,lshifts);
#endif
		eot = len+5;
		offs = 0;

		for (int i=0; i<8; i++)
		  {
		   buffer[eot +i] = '\n';
		   buffer[eot +i + 8] = '\0';	
		  }

		fend = true;

		return ReadLn();
	       }	

	    if (rd > 0)
	       {
		offs = 0;
		filelen += rd; 	
		eot = len + rd;

		for (int i=0; i<64; i++)
		   buffer[eot + i] = '\0'; 

		return ReadLn();
	       }
	   }
	 else	
	   fprintf(stderr,"should not happen (%ld,%ld)\n",rd,offs);	


#ifdef DEBUG
	fprintf(stderr,"read(%d,&buffer[%d],%d) = %ld failed after %ld bytes\n",fd,len,BUFSIZE - len,rd,filelen);
#endif
	return NULL;
}



void t_buffer::Done(void)
{
	close(fd);
	delete buffer;
	buffer = NULL;
}











