/**************************************************************************
 * Source Id :
 *
 * $Id: idxinfo.cpp,v 1.3 2001/04/20 10:15:01 georgetasker Exp $
 *-------------------------------------------------------------------------
 * Project Notes :
 *
 *  Diamond Base
 *  ============
 *      A solid database implementation, spurred on by the continuing
 *  Metal (Lead) Base saga.
 *
 *  Project Team :
 *        A. Davison
 *        K. Lentin
 *        D. Platt
 *
 *	Project Commenced : 05-02-1993
 *
 *-------------------------------------------------------------------------
 *  Module Notes :
 *
 *		Code to support the field and header strctures for the database
 *	files themselves.
 *
 *  Original Author : Andy
 *
 **************************************************************************/

// FOR NOW::
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#include <diamond/dbconf.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif

#if HAVE_MALLOC_H && !MALLOC_H_INCLUDED
extern "C" {
	#include <malloc.h>
}
#define MALLOC_H_INCLUDED 1
#endif

#include <diamond/idxinfo.h>

//--------------------------------------------------------------
// Constructor
//

DIA_EXPORT
indexInfo::indexInfo(const dbString& newName, const int32 type, const TIndicies indicies )
{
	idxType = type;
	for(int i=0;i<MAX_FIELDS_IN_INDEX;i++)
	{
		idxFields[i] = indicies[i];
	}
	nextIdx = 0;
	name = newName;
}

DIA_EXPORT indexInfo::~indexInfo()
{
	if (nextIdx)
		delete nextIdx;
}

DIA_EXPORT fieldInfo::fieldInfo(const char* name, const int32 ty, const int32 sz)
{
	fldName = new char[strlen(name)+1];
	strcpy(fldName,name);
	fldType = ty;
	fldSize = sz;

	nextFld = 0;
}

DIA_EXPORT fieldInfo::~fieldInfo()
{
	delete fldName;
	if (nextFld)
		delete nextFld;
}

//--------------------------------------------------------------
// Stream checking routines.

bool
checkStream(ifstream& s,const char*text)
{
	if (!s)	{
		if (strcmp(text,"")) {
			dbErr(db_corrupt,text);
		}
		return false;
	}      
	return true;
}

bool checkStream(ofstream& s,const char *text)
{
	if (!s)	{
		dbErr(db_corrupt,text);
		return false;
	}      
	return true;
}

//--------------------------------------------------------------
// Standard stream insertors/extractors.

ostream& DIA_EXPORT operator << (ostream& s, const indexList& list)
{
	if (list.indicies!=0)
		s << *(list.indicies);
	return s;
}


ostream& DIA_EXPORT operator << (ostream& s, const indexInfo& info)
{
	s << "Indexed on field " << info.idxFields[0];
	for(int i=1;i<MAX_FIELDS_IN_INDEX;i++)
	{
		if(info.idxFields[i] != -1)
			s << ", " << info.idxFields[i];
	}
	if (info.idxType & IDX_NODUPLICATES)
		s << " without duplicates." << endl;
	else
		s << " with duplicate indicies permitted." << endl;
	if (info.nextIdx)
		s << *(info.nextIdx);

	return s;
}

ostream& DIA_EXPORT operator << (ostream& s, const fieldList& list)
{
	s << *(list.fields);
	return s;
}

ostream& DIA_EXPORT operator << (ostream& s, const fieldInfo& info)
{
	s << "Name : " << info.fldName << endl;
	s << "Type : " << info.fldType << endl;
	s << "Size : " << info.fldSize << " bytes" << endl;

	if (info.nextFld)
		s << *(info.nextFld);
	return s;
}
//----------------------------------------------------------------
// File stream insertors/extractors.

ofstream& DIA_EXPORT operator << (ofstream& s, const indexList& list)
{
	s.write((const char*)&IDX_LIST_MAGIC,sizeof IDX_LIST_MAGIC);
	if (!checkStream(s,"writing IDX_LIST_MAGIC")) return s;
	s.write((const char*)&list.numIndicies,sizeof list.numIndicies);
	if (!checkStream(s,"writing number of indicies")) return s;

	if(list.indicies != 0)
		s << *(list.indicies);
	return s;
}

ofstream& DIA_EXPORT operator << (ofstream& s, const indexInfo& info)
{
	s.write((const char*)&IDX_INFO_MAGIC, sizeof IDX_INFO_MAGIC);
	if (!checkStream(s,"Writing IDX_INFO_MAGIC")) return s;
	s.write((const char*)&info.idxType,sizeof info.idxType);
	if (!checkStream(s,"Writing idxType")) return s;
	s.write((const char*)&info.idxFields[0],(int)MAX_FIELDS_IN_INDEX*sizeof info.idxFields[0]);
	if (!checkStream(s,"Writing idx fields")) return s;

	if (info.nextIdx != 0)
		s << *(info.nextIdx);
	return s;
}

ofstream& DIA_EXPORT operator << (ofstream& s, const fieldList& list)
{
	long tmp = FLD_LIST_MAGIC;
	s.write((const char*)&tmp,sizeof tmp);
	if (!checkStream(s,"Writing FLD_LIST_MAGIC")) return s;
#ifdef DEBUG
	cout << "Dumping :" << hex << FLD_LIST_MAGIC << dec << endl;
#endif
	s.write((const char*)&list.numFields,sizeof list.numFields);
#ifdef DEBUG
	cout << "Number of fields = " << list.numFields << endl;
#endif
	if (!checkStream(s,"Writing num fields")) return s;

	if (list.fields != 0)
		s << *(list.fields);
	return s;
}

ofstream& DIA_EXPORT operator << (ofstream& s, const fieldInfo& info)
{
	s.write((const char*)&FLD_INFO_MAGIC,sizeof FLD_INFO_MAGIC);
	if (!checkStream(s,"Writing FLD_INFO_MAGIC")) return s;
	s.write((const char*)&info.fldType,sizeof info.fldType);
	if (!checkStream(s,"Writing fldType")) return s;
	s.write((const char*)&info.fldSize,sizeof info.fldSize);
	if (!checkStream(s,"Writing field size")) return s;
	int32 len = strlen(info.fldName)+1;
	s.write((const char*)&len,sizeof len);
	if (!checkStream(s,"Writing fldName len")) return s;
	s.write((const char*)info.fldName,(int)len);
	if (!checkStream(s,"Writing fldName")) return s;

	if (info.nextFld != 0)
		s << *(info.nextFld);

	return s;
}

// Extract the fieldlist from a stream

ifstream& operator >> (ifstream& s, fieldList& list)
{
	int32 temp;

#ifdef DEBUG
	cout <<"Reading field list magic number." << endl;
#endif
	s.read((char*)&temp,sizeof temp);
	if (!checkStream(s,"Reading field list magic number")) return s;
	if(temp != FLD_LIST_MAGIC)	{
		dbErr(db_corrupt,"Bad field list in relation file. Aborting.");
		return s;
	}
#ifdef DEBUG
	cout <<"Reading number of fields" << endl;
#endif

	s.read((char*)&list.numFields,sizeof list.numFields);
	if (!checkStream(s,"reading num fields")) return s;

	fieldInfo* currentFld = 0;

	for(int i=0;i<list.numFields;i++)
	{
		int32 type,size,len;
		char* name;
#ifdef DEBUG
	cout <<"Reading field info magic number." << endl;
#endif

		s.read((char*)&temp,sizeof temp);
		if (!checkStream(s,"reading field info magic number")) return s;
		if(temp != FLD_INFO_MAGIC) {
			dbErr(db_corrupt,"Bad field info in relation file. Aborting.");
			return s;
		}
#ifdef DEBUG
	cout <<"Reading type of field." << endl;
#endif
		s.read((char*)&type,sizeof type);
		checkStream(s,"reading type of field");
#ifdef DEBUG
	cout << "Reading size of field." << endl;
#endif
		s.read((char*)&size,sizeof size);
		if (!checkStream(s,"reading size of field")) return s;
#ifdef DEBUG
	cout <<"Reading length of field name." << endl;
#endif
		s.read((char*)&len,sizeof len);
		if (!checkStream(s,"reading length of field name")) return s;
		name = new char[len+1];
#ifdef DEBUG
	cout << "Reading field name." << endl;
#endif
		s.read((char*)name, (int)len);
		if (!checkStream(s,"reading name")) return s;

		fieldInfo* tInfo = new fieldInfo(name,type,size);
		delete name;

		if(currentFld != 0)
			currentFld->nextFld = tInfo;
		else
			list.fields = tInfo;
		currentFld = tInfo;
	}
#ifdef DEBUG
	cout << "Finished reading field information." << endl;
#endif
	return s;
}

// Extract the indexlist from a stream

ifstream& operator >> (ifstream& s, indexList& list)
{
	int32 temp;

	s.read((char*)&temp,sizeof temp);
	if (!checkStream(s,"reading IDX_LIST_MAGIC")) return s;
	if(temp != IDX_LIST_MAGIC)	{
		dbErr(db_corrupt,"Bad index list in relation file. Aborting.");
		return s;
	}

#ifdef DEBUG
	cout <<"Reading Number of indicies." << endl;
#endif
	s.read((char*)&list.numIndicies,sizeof list.numIndicies);
	if (!checkStream(s,"reading #indicies")) return s;

	indexInfo* currentIdx = 0;

	for(int i=0;i<list.numIndicies;i++)
	{
		int32 type
		//,field1,field2
		;

#ifdef DEBUG
	cout <<"Reading Index Info Magic number." << endl;
#endif
		s.read((char*)&temp,sizeof temp);
		checkStream(s,"reading index info magic number");
		if(temp != IDX_INFO_MAGIC) {
			dbErr(db_corrupt,"Bad index info in relation file. Aborting.");
			return s;
		}
		TIndicies indicies;
#ifdef DEBUG
	cout <<"Reading type of index." << endl;
#endif
		s.read((char*)&type,sizeof type);
		checkStream(s,"Reading type of index");
#ifdef DEBUG
	cout << "Reading index field array." << endl;
#endif
		s.read((char*)indicies, (int)MAX_FIELDS_IN_INDEX*sizeof indicies[0]);
		if (!checkStream(s,"Reading index field array")) return s;

		indexInfo* tInfo = new indexInfo("Unknown",type,indicies);
		if(currentIdx != 0)
			currentIdx->nextIdx = tInfo;
		else
			list.indicies = tInfo;

		currentIdx = tInfo;
	}
	return s;
}

//////////////////////////////////////////////////////////////////////////
// Revision History:
//
// $Log: idxinfo.cpp,v $
// Revision 1.3  2001/04/20 10:15:01  georgetasker
// Cygwin compilation fixes, compilation speed enhancements
// Code modified to get rid of some compiler warnings
//
// Revision 1.2  2001/04/19 21:12:54  georgetasker
// cygwin compilation fixes
//
// Revision 1.1  2001/04/04 12:05:49  aleksandras
// forgotten diamond .cpps
//
// Revision 1.24  1996/08/22  12:42:10  dmb
// Improved file I/O error handling
//
// Revision 1.23  1996/03/05 22:04:29  dmb
// removed ^M.
//
// Revision 1.22  1996/03/05  21:42:35  dmb
// Preliminary modifications to get Dos/Windows 0.4 portability.
//
// Revision 1.21  1996/02/01  22:24:12  dmb
// long->int32.
//
// Revision 1.20  1995/09/14  04:29:07  kevinl
// Added a name to each index.
//
// Revision 1.19  1994/12/22 03:55:51  kevinl
// write requires a const char*, not a char*
//
// Revision 1.18  1994/12/12  03:52:10  kevinl
// stdlib.h
// removed & on array
//
// Revision 1.17  1994/05/15  04:58:17  kevinl
// Type fixups.
//
// Revision 1.16  1994/02/24  06:35:30  darrenp
// DOS/Windows modifications.
//
// Revision 1.15  1994/02/03  06:01:32  kevinl
// Moved include files to diamond/ and fixed HAVE_MALLOC_H
//
// Revision 1.14  1993/12/23  22:58:48  kevinl
// dbErr uses dbString, autoconf stuff, moved logs, added const and size_t
//
// Revision 1.13  1993/06/23  05:21:22  kevinl
// Mallocs are now in angular brackets
//
// Revision 1.12  1993/05/26  01:01:39  kevinl
// MALLOC_H_MISSING
//
// Revision 1.11  1993/05/06  04:00:19  kevinl
// SASC define for malloc.h
//
// Revision 1.10  1993/05/03  23:35:47  kevinl
// the MAGIC nums are const
//
// Revision 1.9  1993/05/03  01:35:37  kevinl
// Got rid of externs on the consts
//
// Revision 1.8  1993/04/28  11:31:09  kevinl
// Fixed up inlines
//
// Revision 1.7  1993/04/27  07:00:19  kevinl
// Comments
//
// Revision 1.6  1993/04/15  06:06:38  davison
// Fixed up inline not expanded errors etc
//
// Revision 1.5  1993/04/15  04:21:52  kevinl
// Moved malloc.h
//
// Revision 1.4  1993/04/08  05:26:40  kevinl
// FGixed some memory leaks
//
// Revision 1.3  1993/03/29  08:06:22  darrenp
// Can't add to a pointer. Add to size of data instead
// malloc lib.
//
// Revision 1.2  1993/03/15  19:09:15  davison
// Implemented a few nice things, like more than 2 index fields, line number
// reporting on syntax errors, and usage reporting.
//
// Just for you, Daz :-)
//
// Revision 1.1  1993/03/15  19:07:31  davison
// Initial revision
//
//////////////////////////////////////////////////////////////////////////
