/*******************************************************************************
 *	BEntry.cc	Database entry system
 *			T.Barnaby,	BEAM Ltd,	10/5/93
 *******************************************************************************
 */
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <BEntry.h>

BEntry::BEntry(){
}

BEntry::BEntry(BString name, BString value){
	oname = name;
	ovalue = value;
}

BEntry::BEntry(BString line){
	setLine(line);
}

BString BEntry::getName(){
	return oname;
}
BString BEntry::getValue(){
	return ovalue;
}

void BEntry::setLine(BString line){
	const char*	s;
	const char*	m;
	const char*	e;

	m = s = line.retStr();
	if(*m && isspace(*m)){
		while(*m && isspace(*m))
			m++;
	}
	e = m;
	while(*e && !isspace(*e))
		e++;
	oname = line.subString(m - s, e - m);
	while(*e && isspace(*e))
		e++;

	ovalue = e;
}
void BEntry::setName(BString name){
	oname = name;
}

void BEntry::setValue(BString value){
	ovalue = value;
}

void BEntry::print(){
	printf("%-15s\t%s\n", oname.retStr(), ovalue.retStr());
}

BString BEntry::line(){
	BString	s;

	s = oname;
	if(s.len() < 16)
		s.pad(16);
	else
		s = s + " ";
	s = s + ovalue;
	return s;
}

BEntryList::BEntryList(){
	olastPos = 0;
}

BEntry* BEntryList::find(BString name){
	BIter	i;
	
	if(olastPos){
		i = olastPos;
	}
	else {
		i = begin();
	}

	// Search down from i
	for(; !isEnd(i); next(i)){
		if(name == get(i).getName()){
			olastPos = i;
			return &get(i);
		}
	}

	if(olastPos){
		for(start(i); (i != olastPos) && !isEnd(i); next(i)){
			if(name == get(i).getName()){
				olastPos = i;
				return &get(i);
			}
		}
	}
	
	return NULL;
}

BString BEntryList::findValue(BString name){
	BEntry*	e;

	if(e = find(name))
		return e->getValue();
	else
		return "";
}
int BEntryList::setValue(BString name, BString value){
	BEntry*	e;

	if(e = find(name)){
		e->setValue(value);
		return 0;
	}
	else {
		append(BEntry(name, value));
		return 0;
	}
}

int BEntryList::setValueRaw(BString name, BString value){
	append(BEntry(name, value));
	return 0;
}

void BEntryList::deleteEntry(BString name){
	BIter	i;
	
	for(i = begin(); !isEnd(i); ){
		if(name == get(i).getName())
			del(i);
		else
			next(i);
	}
}


int BEntryList::isSet(BString name){
	BIter	i;
	BString	value;
	BString lname;

	for(i = begin(); !isEnd(i); next(i)){
		lname = get(i).getName();
		value = get(i).getValue();
		if((name == lname) && value.len())
			return 1;
	}
	return 0;
}
void BEntryList::print(){
	BIter	i;
	
	for(i = begin(); !isEnd(i); next(i)){
		get(i).print();
	}
}
BString BEntryList::getString(){
	BIter	i;
	BString	s;

	for(i = begin(); !isEnd(i); next(i)){
		s = s + get(i).getName().pad(16) + get(i).getValue() + "\n";
	}
	return s;
}

void BEntryList::clear(){
	BList<BEntry>::clear();
	olastPos = 0;
}

void BEntryList::insert(BIter& i, const BEntry& item){
	BList<BEntry>::insert(i, item);
	olastPos = 0;
}

void BEntryList::del(BIter& i){
	BList<BEntry>::del(i);
	olastPos = 0;
}



BEntryFile::BEntryFile(){
}

BEntryFile::BEntryFile(BString filename){
	open(filename);
}

int BEntryFile::open(BString filename){
	ofilename = filename;
	return access(ofilename.retStr(), R_OK);
}

BEntryFile::~BEntryFile(){
	clear();
}
void BEntryFile::clear(){
	BEntryList::clear();
	ocomments = "";
}
int BEntryFile::read(){
	char	buf[10240];
	char	name[1024];
	char*	t;
	char*	f;
	FILE*	ofile;

	clear();
	if((ofile = fopen(ofilename.retStr(), "r")) == NULL)
		return -1;

	while(fgets(buf, sizeof(buf), ofile)){
		if(strlen(buf)){
			if((buf[0] != '#') && (buf[0] != '\n') && (buf[0] != '\r')){
				buf[strlen(buf) - 1] = '\0';
				if((strlen(buf) > 0) && (buf[strlen(buf) - 1] == '\r'))
					buf[strlen(buf) - 1] = '\0';
				
				for(t = name, f = buf; (*f && !isspace(*f));
					t++, f++){
					*t = *f;
				}
				*t = 0;
				while(*f && isspace(*f))
					f++;
				t = f;
				while(*t)
					t++;
				*t = 0;

				append(BEntry(name, f));
			}
			else if(buf[0] == '#'){
				ocomments = ocomments + buf;
			}
		}
	}
	fclose(ofile);
	return 0;
}
int BEntryFile::write(){
	return writeList(*this);
}
int BEntryFile::writeList(BEntryList& l){
	BIter	i;
	FILE*	ofile;
	BString	name;
	BString	value;

	if((ofile = fopen(ofilename.retStr(), "w")) == NULL)
		return -1;

	fprintf(ofile, "%s", ocomments.retStr());
	for(i = l.begin(); !l.isEnd(i); l.next(i)){
		name = l.get(i).getName();
		value = l.get(i).getValue();
		fprintf(ofile, "%-15s\t%s\n", name.retStr(), value.retStr());
	}
	fclose(ofile);
	return 0;
}
