// UHeaders.cp
// UHeaders.h
// ----------------------------------------------------------------------------------
// File Header class for the Spell Checker project.
//
// Note: This file is proprietary and confidential to Art Pollard
//	and Lextek Internation.  
// Copyright 1994 Art Pollard / LexTek International
//
// A static class that represents the data header for a file.  It is static
// and then never actualized into a real object.  Basically this class 
// keeps all the methods dealing with reading and writing header variables
// in one place.  This enables headers to be changed without needing to
// search all over the project for where headers are accessed.
//
// ----------------------------------------------------------------------------------
// History:
// 		Art Pollard			June 94
//			Original.  Simple read/write functions.
//		Clark Goble			08/13/94
//			Made into an static C++ class.
//
// ----------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------
// Includes

//#define TEST
#include <stdio.h>

#include "UHead.h"
#include "UError.h"

#ifdef TEST
#include <StandardFile.h>
#endif


// ----------------------------------------------------------------------------------
//	WriteMagicNumber1	-	Writes a special number to to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WriteMagicNumber1( Uio *DictFile, long MagicNumber )
{
	return ( WriteNumber( DictFile, MagicNumber, 0) );

} // WriteMagicNumber1

short
UHeaders::WriteMagicNumber1( FILE *DictFile, long MagicNumber )
{
	return ( WriteNumber( DictFile, MagicNumber, 0) );

} // WriteMagicNumber1


// ----------------------------------------------------------------------------------
//	ReadMagicNumber1	-	Reads a special number from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadMagicNumber1(Uio *DictFile)
{
	return ( ReadNumber( DictFile, 0) );

} // ReadMagicNumber1

long
UHeaders::ReadMagicNumber1(FILE *DictFile)
{
	return ( ReadNumber( DictFile, 0) );

} // ReadMagicNumber1

// ----------------------------------------------------------------------------------
//	WriteBloomFilterSize	-	Writes the bloom filter's size to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WriteBloomFilterSize( Uio *DictFile, long BloomFilterSize )
{
	return ( WriteNumber( DictFile, BloomFilterSize, 4) );

} // WriteBloomFilterSize

short
UHeaders::WriteBloomFilterSize( FILE *DictFile, long BloomFilterSize )
{
	return ( WriteNumber( DictFile, BloomFilterSize, 4) );

} // WriteBloomFilterSize


// ----------------------------------------------------------------------------------
//	ReadBloomFilterSize	-	Reads the bloom filter's size from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadBloomFilterSize(Uio *DictFile)
{
	return ( ReadNumber( DictFile, 4) );

} // ReadBloomFilterSize

long
UHeaders::ReadBloomFilterSize(FILE *DictFile)
{
	return ( ReadNumber( DictFile, 4) );

} // ReadBloomFilterSize

// ----------------------------------------------------------------------------------
//	WriteBloomFilterOffset	-	Writes the bloom filter's offset to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WriteBloomFilterOffset( Uio *DictFile, long BloomFilterOffset )
{
	return ( WriteNumber( DictFile, BloomFilterOffset, 8) );

} // WriteBloomFilterOffset


short
UHeaders::WriteBloomFilterOffset( FILE *DictFile, long BloomFilterOffset )
{
	return ( WriteNumber( DictFile, BloomFilterOffset, 8) );

} // WriteBloomFilterOffset


// ----------------------------------------------------------------------------------
//	ReadBloomFilterOffset	-	Reads the bloom filter's offset from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadBloomFilterOffset(Uio *DictFile)
{
	return ( ReadNumber( DictFile, 8) );

} // ReadBloomFilterOffset

long
UHeaders::ReadBloomFilterOffset(FILE *DictFile)
{
	return ( ReadNumber( DictFile, 8) );

} // ReadBloomFilterOffset

// ----------------------------------------------------------------------------------
//	WriteIndexOffset	-	Writes the offset to the index to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WriteIndexOffset( Uio *DictFile, long IndexOffset )
{
	return ( WriteNumber( DictFile, IndexOffset, 12 ) );

} // WriteIndexOffset

short
UHeaders::WriteIndexOffset(FILE *DictFile, long IndexOffset )
{
	return ( WriteNumber( DictFile, IndexOffset, 12 ) );

} // WriteIndexOffset


// ----------------------------------------------------------------------------------
//	ReadIndexOffset	-	Reads the offset to the index to disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadIndexOffset( Uio *DictFile )
{
	return ( ReadNumber( DictFile, 12 ) );

} // ReadIndexOffset

long
UHeaders::ReadIndexOffset(FILE *DictFile )
{
	return ( ReadNumber( DictFile, 12 ) );

} // ReadIndexOffset

// ----------------------------------------------------------------------------------
//	WriteIndexLength	-	Writes the index's length to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WriteIndexLength( Uio *DictFile, long IndexLength )
{
	return ( WriteNumber( DictFile, IndexLength, 16) );

} // WriteIndexLength

short
UHeaders::WriteIndexLength( FILE *DictFile, long IndexLength )
{
	return ( WriteNumber( DictFile, IndexLength, 16) );

} // WriteIndexLength

// ----------------------------------------------------------------------------------
//	ReadIndexLength	-	Reads the index's length from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadIndexLength( Uio *DictFile )
{
	return ( ReadNumber( DictFile,16 ) );

} // ReadIndexLength

long
UHeaders::ReadIndexLength( FILE *DictFile )
{
	return ( ReadNumber( DictFile,16 ) );

} // ReadIndexLength

// ----------------------------------------------------------------------------------
//	WriteNumPages	-	Writes the number of 'pages' in the index to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WriteNumPages( Uio *DictFile, long NumPages )
{
	return ( WriteNumber( DictFile, NumPages, 20) );

} // WriteNumPages

short
UHeaders::WriteNumPages( FILE *DictFile, long NumPages )
{
	return ( WriteNumber( DictFile, NumPages, 20) );

} // WriteNumPages


// ----------------------------------------------------------------------------------
//	ReadNumPages	-	Reads the number of 'pages' in the index from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadNumPages(Uio *DictFile)
{
	return ( ReadNumber( DictFile, 20) );

} // ReadIndexLength

long
UHeaders::ReadNumPages(FILE *DictFile)
{
	return ( ReadNumber( DictFile, 20) );

} // ReadIndexLength


// ----------------------------------------------------------------------------------
//	WritePageSize	-	Writes the size of a 'page' to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WritePageSize( Uio *DictFile, long PageSize )
{
	return ( WriteNumber( DictFile, PageSize, 24) );

} // WritePageSize


short
UHeaders::WritePageSize( FILE *DictFile, long PageSize )
{
	return ( WriteNumber( DictFile, PageSize, 24) );

} // WritePageSize

// ----------------------------------------------------------------------------------
//	ReadPageSize	-	Reads the number of 'pages' in the index from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadPageSize(Uio *DictFile)
{
	return ( ReadNumber( DictFile, 24) );

} // ReadPageSize


long
UHeaders::ReadPageSize(FILE *DictFile)
{
	return ( ReadNumber( DictFile, 24) );

} // ReadPageSize


// ----------------------------------------------------------------------------------
//	WritePageOffset	-	Writes the offset to the 'pages' to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WritePageOffset( Uio *DictFile, long PageOffset )
{
	return ( WriteNumber( DictFile, PageOffset, 28) );

} // WritePageOffset

short
UHeaders::WritePageOffset( FILE *DictFile, long PageOffset )
{
	return ( WriteNumber( DictFile, PageOffset, 28) );

} // WritePageOffset


// ----------------------------------------------------------------------------------
//	ReadPageOffset	-	Reads the offset to the 'pages' from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadPageOffset(Uio *DictFile)
{
	return ( ReadNumber( DictFile, 28) );

} // ReadPageOffset

long
UHeaders::ReadPageOffset(FILE *DictFile)
{
	return ( ReadNumber( DictFile, 28) );

} // ReadPageOffset


// ----------------------------------------------------------------------------------
//	WriteMagicNumber2	-	Writes a special number to to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WriteMagicNumber2( Uio *DictFile, long MagicNumber2 )
{
	return ( WriteNumber( DictFile, MagicNumber2, 32) );

} // WriteMagicNumber2

short
UHeaders::WriteMagicNumber2( FILE *DictFile, long MagicNumber2 )
{
	return ( WriteNumber( DictFile, MagicNumber2, 32) );

} // WriteMagicNumber2


// ----------------------------------------------------------------------------------
//	ReadMagicNumber2	-	Reads a special number from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadMagicNumber2(Uio *DictFile)
{
	return ( ReadNumber( DictFile, 32) );

} // ReadMagicNumber2


long
UHeaders::ReadMagicNumber2(FILE *DictFile)
{
	return ( ReadNumber( DictFile, 32) );

} // ReadMagicNumber2

// ----------------------------------------------------------------------------------
//	WriteVersion	-	Writes the dictionary version to to disk
// ----------------------------------------------------------------------------------

short
UHeaders::WriteVersion( Uio *DictFile, long Version )
{
	return ( WriteNumber( DictFile, Version, 36) );

} // WriteVersion


short
UHeaders::WriteVersion( FILE *DictFile, long Version )
{
	return ( WriteNumber( DictFile, Version, 36) );

} // WriteVersion


// ----------------------------------------------------------------------------------
//	ReadVersion	-	Reads the dictionary version from disk
// ----------------------------------------------------------------------------------

long
UHeaders::ReadVersion(Uio *DictFile)
{
	return ( ReadNumber( DictFile, 36) );

} // ReadVersion


long
UHeaders::ReadVersion(FILE *DictFile)
{
	return ( ReadNumber( DictFile, 36) );

} // ReadVersion

// ----------------------------------------------------------------------------------



// ----------------------------------------------------------------------------------
// 	NumToChar		- Utility to convert numbers to characters
// ----------------------------------------------------------------------------------
// This writes out a long into characters to get around big endian, little endian
// problems that raise their little ugly heads at times

void
UHeaders::NumToChar(short NumBytes, unsigned long Num, char *Buff)
{
	while (NumBytes -- > 0)
	{
		*Buff++ = (unsigned char) Num & 0xff;
		Num >>=8;
	}
} // NumToChar

// ----------------------------------------------------------------------------------
// 	CharToNum		- Utility to transform packed characters to integers
// ----------------------------------------------------------------------------------
// This converts a character to an unsigned integer.  It is here to enable packed
// character data to be converted into integers and longs

unsigned long
UHeaders::CharToNum(short NumBytes, char *Buff)
{
	unsigned long result;
	short shift_count;
	unsigned long temp;
	short Counter;
	
	result = 0;
	shift_count = 0;
	//while ( NumBytes-- > 0 ) 
	for (Counter = NumBytes - 1 ; Counter >= 0; Counter--)
	{
	/*
		temp = ((unsigned long) *Buff )<< shift_count;
		*Buff++;
		result = result << shift_count;
		 result |= temp;
	    shift_count += 8; */
	    temp = 0xFF & Buff[Counter];
	    result = result << 8;
	  	result += temp;	  	
	}
	return( result );
	
} // NumToChar


// ----------------------------------------------------------------------------------
// 	WriteNumber		- Write a number to disk.
// ----------------------------------------------------------------------------------
// Writes to the header at the beginning of the dictionary.  This enables us to
// only change one or two methods without going pig wild when changing the header
// format.

short
UHeaders::WriteNumber( Uio *File, long Number, long Offset )
{
	char Buffer[4];


	File->SetPos(Offset, SEEK_SET);
	if ( ErrorFunc(0, GET) < eNo_Err )
		return ( ErrorFunc(0, GET) );

	NumToChar( 4,Number,Buffer);

	File->WriteData(Buffer, 4);
	if ( ErrorFunc(0, GET) < eNo_Err )
		return ( ErrorFunc(0, GET) );

	return (OK);
} // WriteNumber


short
UHeaders::WriteNumber( FILE *File, long Number, long Offset )
{
	char Buffer[4];


	if(fseek(File,Offset,SEEK_SET) != 0)
		return ERROR;
	//File->SetPos(Offset, SEEK_SET);
	//if ( ErrorFunc(0, GET) < eNo_Err )
	//	return ( ErrorFunc(0, GET) );

	NumToChar( 4,Number,Buffer);

	if(fwrite(Buffer,1,4,File) != 4)
		return ERROR;
	//File->WriteData(Buffer, 4);
	//if ( ErrorFunc(0, GET) < eNo_Err )
	//	return ( ErrorFunc(0, GET) );

	return (OK);
} // WriteNumber

// ----------------------------------------------------------------------------------
// 	ReadNumber		- Reads a number from disk.
// ----------------------------------------------------------------------------------
// Reads from the header at the beginning of the dictionary.  This enables us to
// only change one or two methods without going pig wild when changing the header
// format.

long
UHeaders::ReadNumber(Uio *File,long Offset)
{
	char Buffer[4];
	long Number;

	#ifdef TEST
	printf("%d , %d", Offset, SEEK_SET);
	#endif

	File->SetPos(Offset, SEEK_SET);
	if ( ErrorFunc(0, GET) < eNo_Err )
		return ( ErrorFunc(0, GET) );

	File->ReadData(Buffer, 4);
	if ( ErrorFunc(0, GET) < eNo_Err )
		return ( ErrorFunc(0, GET) );

	Number = CharToNum( 4,( char * ) Buffer);
	return ( Number );

} // ReadNumber

long
UHeaders::ReadNumber(FILE *File,long Offset)
{
	char Buffer[4];
	long Number;

	#ifdef TEST
	printf("%d , %d", Offset, SEEK_SET);
	#endif

	if(fseek(File,Offset,SEEK_SET) != 0)
		return ERROR;
	//File->SetPos(Offset, SEEK_SET);
	//if ( ErrorFunc(0, GET) < eNo_Err )
	//	return ( ErrorFunc(0, GET) );

	if(fread(Buffer,1,4,File) != 4)
		return  ERROR;
	//File->ReadData(Buffer, 4);
	//if ( ErrorFunc(0, GET) < eNo_Err )
	//	return ( ErrorFunc(0, GET) );

	Number = CharToNum( 4,( char * ) Buffer);
	return ( Number );

} // ReadNumber


#ifdef TEST

short main()
{
	printf("UHeader...\n");
	StandardFileReply	reply;
	SFTypeList	types = {'TEXT'};
	StandardGetFile(nil, 1, types, &reply);


	Uio *theFile = new Uio(reply.sfFile);
	theFile->Open();
	short	t;
	t = UHeaders::ReadMagicNumber1( theFile);
	printf("Magic1 %d\n", t);

	t = UHeaders::ReadMagicNumber2( theFile );
	printf("Magic2 %d\n", t);

	theFile->Close();
}
	
#endif



