W
Hallo erstmal!,
ich bekomme es nicht hin diese object für dev-cpp zu übersetzen,
ich habe devc++ wirklich ganz doll lieb aber wir führen eine schwierige beziehung.
ich glaube aber es liegt an den pointern und void`s
könnte mir jemand helfen?
thx .
/****************************************************************************/
/********* CDBFile, a dBase III / .DBF file handling object ***********/
/****************************************************************************/
/*
Copyright (C) 1997 Hervé GOURMELON, ENSSAT
gourmelon@enssat.fr
http://www.enssat.fr
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library (COPYING2.TXT); if not, write to the
Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
MA 02139, USA.
*/
// If you are building a Windoze MFC app under Visual C++, remove the comment
// slashes in front of the following line:
//#include "stdafx.h"
// and turn the following lines into comments:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "cdbfile.h"
/* Implementation of the member functions for CField */
// Default constructor
CField::CField()
{ Name[0]='\0';
Type='C';
Length=0;
DecCount=0;
FieldNumber=0;
Offset=0;
Next=this;
}
// Constructor with an initialization of most data members
CField::CField(char* NName,char NType,unsigned char NLength,
unsigned char NDecCount,unsigned char FieldNum)
{
strcpy(Name, NName);
Type=NType;
Length=NLength;
DecCount=NDecCount;
FieldNumber=FieldNum;
}
// Destructor
CField::~CField()
{}
unsigned short CField::GetNumberOfFields(CField* Start, unsigned short i)
{
if (Start==NULL)
{ Start=this; // NULL is passed for the initial call of
i=1;
return Next->GetNumberOfFields(Start, i);
} // this recursive function in the program
else
if (Start==this) return i; // We've checked all the elements of
else // the dynamic ring: return i */
{ i+=1;
return Next->GetNumberOfFields(Start, i);
/* Proceed to next element */
}
}
/* Implementation of the member functions of CDBFile */
/* public : */
// Default constructor
CDBFile::CDBFile() // Classical init procedure
{
PathName[0]=0;
FileHandle=NULL;
HeaderSize=0;
FieldCount=0;
RecordCount=0;
ModifiedFlag=FALSE;
FullFileInMemory=FALSE;
RecordLength=0;
RecordList=NULL;
FirstField=NULL;
}
CDBFile::CDBFile(char* Path) // Creating the object with a path as argument
// Automatically opens the file
{
if (OpenFile(Path)==FALSE) Path[0]=0;
}
BOOL CDBFile::Clean()
// Resets the CDBFile object, regardless of any modifications to be written
{
CField *Delendum;
Record *DelRec;
if (FileHandle!=NULL)
fclose(FileHandle); // Closes the file by default
// Resets all the member data
PathName[0]=0;
FileHandle=NULL;
HeaderSize=0;
FieldCount=0;
RecordCount=0;
ModifiedFlag=FALSE;
FullFileInMemory=FALSE;
RecordLength=0;
if (FirstField!=NULL) // Delete the dynamic list of fields
{
while (FirstField->GetNext()!=FirstField)
{ Delendum=FirstField->GetNext();
FirstField->SetNext(Delendum->GetNext());
delete Delendum;
}
delete FirstField;
FirstField=NULL;
}
if (RecordList!=NULL) // Delete the dynamic list of records
{
while (RecordList->Next!=NULL)
{ DelRec=RecordList->Next;
RecordList->Next=DelRec->Next;
delete[] DelRec->Contents;
delete DelRec;
}
delete[] RecordList->Contents;
delete RecordList;
RecordList=NULL;
}
return TRUE;
}
CDBFile::~CDBFile() // Default destructor
{
Clean();
}
void CDBFile::ClearAllRecords()
// Cleaning the contents before rewriting the file (without changing the
// data structure)
{
Record* DelRec;
if (FileHandle==NULL) return;
RecordCount=0;
if (RecordList!=NULL) // Delete the dynamic list of records
{
while (RecordList->Next!=NULL)
{ DelRec=RecordList->Next;
RecordList->Next=DelRec->Next;
delete[] DelRec->Contents;
delete DelRec;
}
delete[] RecordList->Contents;
delete RecordList;
RecordList=NULL;
}
}
BOOL CDBFile::OpenFile(char* Path)
{
unsigned char dBaseVersion,NLength,NDecCount;
char NType, NName[11];
unsigned short Offst;
CField *Tail, *Current;
// Please refer to the dBase III file structure to debug
// this procedure
Clean(); // Closes the previous active file and resets the object
if (strlen(Path)>256)
{ fprintf (stderr, "File path too long : %s \n", Path);
return FALSE;
}
strcpy (PathName, Path);
FileHandle = fopen (PathName, "r+");
if (FileHandle==NULL) return FALSE; // error opening the file
fseek (FileHandle, 0L, SEEK_SET);
fread (&dBaseVersion, 1, sizeof (char), FileHandle);
if (dBaseVersion != 3) // typical of the dBase III files; ignores the
// case of a DBF file with an associated DBT file
{
fprintf (stderr, "%s is not a dBASE III file!\n", Path);
return FALSE;
}
// Reading the header:
// I ignored the date of last udate. If anybody finds it necessary, just
// add it to the member data and read it here...
fseek (FileHandle, 4L, SEEK_SET);
fread (&RecordCount, sizeof (RecordCount), 1, FileHandle);
fseek (FileHandle, 8L, SEEK_SET);
fread (&HeaderSize, sizeof (HeaderSize), 1, FileHandle);
FieldCount = HeaderSize / 32 - 1;
fread (&RecordLength, sizeof (RecordLength), 1, FileHandle);
Offst=1; // Data records are preceded by one byte that is 0x20 (space)
// Reading the field descriptor arrays:
for (unsigned char i=1; i<=FieldCount; i++)
{
fseek (FileHandle, (long) 32 * i, SEEK_SET);
fread (NName, 11, sizeof (char), FileHandle);
fread (&NType, 1, sizeof (char), FileHandle);
fseek (FileHandle, (long)(32*i+16), SEEK_SET);
fread (&NLength, 1, sizeof (unsigned char), FileHandle);
fread (&NDecCount, 1, sizeof (unsigned char), FileHandle);
Current=new CField(NName,NType,NLength,NDecCount,i);
if (FirstField==NULL) // Creating the list of CFields
{
FirstField=Current;
Current->SetNext(FirstField);
Tail=FirstField;
}
else
{
Tail->SetNext(Current);
Tail=Current;
Current->SetNext(FirstField);
}// end if
Current->SetOffset(Offst);
Offst+=NLength;
}// end for
return TRUE;
}
BOOL CDBFile::CloseFile() // If anybody finds any use to it...
{
return Clean();
}
unsigned long CDBFile::LoadFileToMemory()
// Loads all the records to memory. Necessary when you have to sort them or to
// delete some of them from the file, or to save it as another file.
{
unsigned long i;
Record *Current;
// If the file is closed or the records are already loaded, return.
if ((FileHandle==NULL)||(FullFileInMemory==TRUE)) return FALSE;
else
{
for (i=1;i<=RecordCount;i++)
{
Current=ReadRecord(i);
Append(Current); // This will overwrite the records with the
// same numbers, unless their ModifFlag is set to TRUE
// (see the Append function)
if (Current==NULL) return i-1;
}
FullFileInMemory=TRUE;
return i;
}
}
unsigned long CDBFile::WriteAllToFile(char* Path)
// Saves the file as "Path". If "Path"==NULL, the current file is overwritten.
// Returns the number of records actually written.
{
unsigned long i;
Record *CurRec;
// If the file is closed or not all the records are loaded, return.
if ((FileHandle==NULL)||(FullFileInMemory==FALSE)) return 0L;
else
{
if (WriteHeader(Path)==TRUE) // Writes the header of the file.
{
CurRec = RecordList;
for (i=1;i<=RecordCount;i++)
{
if (WriteRecord(CurRec, i))
{
if (CurRec->Next==NULL) return i-1;
else CurRec=CurRec->Next;
}
else return i-1;
}// end for
return i;
}//end if WriteHeader
else return 0L;
}//end if
}//end
unsigned long CDBFile::WriteModified()
{
unsigned long i=0;
Record* CurRec;
if ((FileHandle==NULL)||(FullFileInMemory==TRUE)) return FALSE;
else
{ CurRec=RecordList;
do
{ if(CurRec->ModifFlag==TRUE)
{
if (WriteRecord(CurRec, CurRec->RecordNumber)) i++;
else return i;
}
CurRec=CurRec->Next;
}while(CurRec!=NULL);
return i;
}
}
void CDBFile::SortAllRecords(Record *Head, Record *Tail,
CField* Criter1 /*, CField* Criter2*/)
// Warning : "Tail" must not be the last record in the list. There must be
// an empty cell following Tail in the list, which should be non-NULL.
// The function below is an implementation of the quick sort algorithm.
{
Record *i, *j, *s;
void *v1, *vj /*, *v2*/;
if ((Head->RecordNumber)<(Tail->RecordNumber))
{
v1=GetFieldValue(Head, Criter1);
i=Head;
j=Head->Next;
s=Tail->Next;
while ((j->RecordNumber)<(s->RecordNumber))
{
// Sorting on primary criterium
vj = GetFieldValue(j,Criter1);
if (IsSmaller(vj, v1, Criter1))
{
Swap (i,j);
i=i->Next;
j=j->Next;
}
else if (IsBigger(vj, v1, Criter1))
{
Swap(j, s->Previous);
s=s->Previous;
}
/* attempt to sort on a secundary criterium. Unfortunately, this method failed.
Any idea ?
else if (Criter2!=NULL)
{
v2=GetFieldValue(Head, Criter2);
if (IsSmaller(GetFieldValue(j,Criter2), v2, Criter2))
{
Swap (i,j);
i=i->Next;
j=j->Next;
}
else
if (IsBigger(GetFieldValue(j,Criter2), v2, Criter2))
{
Swap(j, s->Previous);
s=s->Previous;
}
else j=j->Next;
} */
else j=j->Next;
DeleteVoidPointer(vj, Criter1);
DeleteVoidPointer(v1, Criter1);
}
SortAllRecords(Head, i->Previous, Criter1/*, Criter2*/);
SortAllRecords(s, Tail, Criter1/*, Criter2*/);
}//end if
}
void CDBFile::SortOn(unsigned short Criterium1/* , unsigned short Criterium2*/)
// Calls SortAllRecords(); the criterium is specified by the field number
{
Record *Head, *Tail, *CurRec;
CField *Crit1 /*, *Crit2*/; /* Crit2 : optional secundary field */
if (FullFileInMemory!=TRUE) return;
CurRec=RecordList;
while (CurRec->Next!=NULL) CurRec=CurRec->Next;
// Two additional records have to be appended temporarily to the list,
// in order to execute the quick sort correctly.
Tail=new Record; Head=new Record;
Head->Next=RecordList; Tail->Previous=CurRec;
RecordList->Previous=Head; CurRec->Next=Tail;
Head->Previous=NULL; Tail->Next=NULL;
Head->Contents=NULL; Tail->Contents=NULL;
Head->RecordNumber=0L; Tail->RecordNumber=RecordCount+1;
Crit1=FirstField->GetField(Criterium1);
/*Crit2=FirstField->GetField(Criterium2);*/
SortAllRecords(RecordList, CurRec, Crit1/*, Crit2*/);
RecordList->Previous=NULL; CurRec->Next=NULL;
delete Head; delete Tail;
}
void* CDBFile::GetFieldValue(Record* Rec, CField* Field)
// Returns a pointer to the value of the field *Field in the record *Rec.
// Since we do not know the type of the value, we have to return a "void*"
// pointer, which has to be deleted by the recipient of the pointer.
// See also : SetFieldValue(), DeleteVoidPointer().
{
char* Data;
char* RecContents;
RecContents = &(Rec->Contents[Field->GetOffset()]);
// RecContents points at the beginning of the field within the record.
Data=new char[Field->GetLength()+1]; // Data is allocated dynamically
strncpy(Data, RecContents, Field->GetLength());
// Data now contains the string that has to be converted.
switch(Field->GetType())
{
case 'N': // The field is of numeric type, either :
if (Field->GetDecCount()==0) // an integer (no decimals)
{
long *Result1;
Result1=new long;
*Result1=atol(Data);
delete []Data;
return (void*)Result1;
}
else // a double
{
double *Result1;
Result1=new double;
*Result1=atof(Data);
delete []Data;
return (void*)Result1;
}
case 'D': // I won't do any specific conversion for dates
// Please feel free to do it if you feel like.
case 'C': // Here, we add a Clipper / FoxPro notion: the field decimal
// count is considered as an additional field length number.
char* Result2;
Result2=strncpy(Data, RecContents,
Field->GetLength()+256*Field->GetDecCount()+1);
Result2[Field->GetLength()+256*Field->GetDecCount()]=0;
return (void*)Result2;
case 'L': // Here I decided that Logical values should be converted to
// booleans. I could have kept it as a single character.
char c;
BOOL* Result3;
Result3=new BOOL;
sscanf(Data, "%c", c);
*Result3=(BOOL)((c=='Y')||(c=='y')||(c=='T')||(c=='t'));
delete []Data;
return (void*)Result3;
case 'M':
default:
return NULL;
}// end switch;
}
// Overloaded, public versions of GetFieldValue. :
void* CDBFile::GetFieldValue(char* Field)
{return GetFieldValue(CurrentRec,FirstField->GetField(Field));}
void* CDBFile::GetFieldValue(unsigned short FieldNum)
{return GetFieldValue(CurrentRec,FirstField->GetField(FieldNum));}
void CDBFile::DeleteVoidPointer(void* Pointer, CField* Field)
// This function should be used to delete the void pointers allocated and
// returned by GetFieldValue(). It detects the type of the pointers.
{
switch (Field->GetType())
{
case 'N' :
case 'L' :
delete Pointer;
break;
case 'D' :
case 'C' :
default :
delete []Pointer;
}
}
// Public overloaded versions of DeleteVoidPointer()
void CDBFile::DeleteVoidPointer(void* Pointer, unsigned short Field)
{DeleteVoidPointer(Pointer,FirstField->GetField(Field));}
void CDBFile::DeleteVoidPointer(void* Pointer, char* Field)
{DeleteVoidPointer(Pointer,FirstField->GetField(Field));}
Record* CDBFile::GetRecord(unsigned long Number)
// This function returns a record identified by its number. This is for
// records that are already loaded in memory.
{
Record* Current;
Current=RecordList;
if (RecordList==NULL) return NULL;
else
{
if (Current->RecordNumber==Number) return Current;
else
{
while (Current->Next!=NULL)
{
Current=Current->Next;
if (Current->RecordNumber==Number) return Current;
}
// The matching record was not found in memory : it
// must be on the disk... Return the first record.
return RecordList;
}
}//end "if (RecordList==NULL)"
}
Record* CDBFile::CreateNewRecord()
// When an additional record is created, the number of records in the files is
// incremented, the file is modified.
{
Record* Current;
Current=new Record;
Current->Next=NULL;
Current->Previous=NULL;
Current->Contents=new char[RecordLength];
for (int i=0; i<RecordLength; i++)
Current->Contents[i]=0x20;
Current->ModifFlag=FALSE;
Current->RecordNumber=RecordCount+1;
RecordCount++;
ModifiedFlag=TRUE;
return Current;
}
void CDBFile::Append(Record* Rec, Record* Tail)
// Inserts Rec after Tail in the list if Tail!=NULL; inserts it in order
// of RecordNumber if Tail==NULL (which is the default) and if a record with
// the same number is not already present in the list. In that case, the
// contents of the former record is replaced by Rec->Contents, unless the
// former record has been modified and is not saved yet.
{
Record* Current;
if (Tail==NULL) // by default...
{
Current=RecordList;
if (RecordList==NULL) // The list is empty
{
RecordList=Rec; // Create a new list
return;
}
while(Current!=NULL)
{
if (Current->RecordNumber>Rec->RecordNumber)
// This is the right place to insert Rec
{
Rec->Next=Current;
if (Current->Previous!=NULL) (Current->Previous)->Next=Rec;
else RecordList=Rec;
Rec->Previous=Current->Previous;
Current->Previous=Rec;
ModifiedFlag=TRUE;
return;
}
else if (Current->RecordNumber==Rec->RecordNumber)
{
if(Current->ModifFlag==TRUE)
// Current has been modified, but not saved yet
{
delete Rec->Contents;
delete Rec;
return;
}
else
// Current can be replaced by Rec without losing modifications
{
delete Current->Contents;
Current->Contents=Rec->Contents;
Current->ModifFlag=Rec->ModifFlag;
delete Rec;
}
// The file has been modified (by adding this record:)
ModifiedFlag=TRUE;
return;
}
else if (Current->Next==NULL)
// This is the right place to append Rec
{
Rec->Previous=Current;
Current->Next=Rec;
Rec->Next=NULL;
return;
}//end if
Current=Current->Next;
}// end while
}// end if
else
{ // Rec is to be inserted after Tail
Current=Tail;
Rec->Next=Current->Next;
Rec->Previous=Current;
if (Current->Next!=NULL) (Current->Next)->Previous=Rec;
Current->Next=Rec;
}
}//end Append
void CDBFile::DeleteRecord(Record* Rec)
{ // This function really deletes a record if all the records are loaded
// in memory and if the whole data is saved to a file (current file
// or a new one). If only a few records are loaded, it will delete the
// pointed record from the memory, discarding any changes.
if (Rec==NULL) return;
if (Rec==RecordList)
{ RecordList=RecordList->Next;
if (RecordList) RecordList->Previous=NULL;
delete(Rec);
if (FullFileInMemory==TRUE) RecordCount--;
ModifiedFlag=TRUE;
return;
}
else
{
(Rec->Previous)->Next=Rec->Next;
if (Rec->Next) (Rec->Next)->Previous=Rec->Previous;
delete(Rec);
ModifiedFlag=TRUE;
if (FullFileInMemory==TRUE) RecordCount--;
}
}
void CDBFile::AddField(CField* NewField); // Not implemented in this version
void CDBFile::SetFieldValue(Record* Rec, CField* Field, void* Value)
// Here we have the same problems as in GetFieldValue(), see above.
{
char* Data;
char* RecContents;
unsigned short FLength;
unsigned short ResLength;
if (Field->GetType()=='C')
FLength=Field->GetLength()+256*Field->GetDecCount();
else
FLength=Field->GetLength();
RecContents = &(Rec->Contents[Field->GetOffset()]);
// RecContents points at the beginning of the field within the record.
Data=new char[FLength+1]; // Data is allocated dynamically
for (int i=0; i<FLength; i++) Data[i]=' '; // Data is blanked
Data[FLength]=0; // Last character is set to null, '\0' (end of string)
switch(Field->GetType())
{
case 'N': // Numeric
if (Field->GetDecCount()==0) // Integer (long)
{
char *Num=new char[FLength+1];
long *Result1;
Result1=(long *)Value;
ltoa(*Result1, Num, 10);
ResLength=strlen(Num);
// Text alignment for numbers is flush-right :
strncpy(&Data[FLength-ResLength], Num, ResLength);
strncpy(RecContents, Data, FLength);
delete []Num;
break;
}
else // Float (double)
{
char *Num=new char[FLength+1];
double *Result1;
Result1=(double *)Value;
gcvt(*Result1, FLength,Num);
ResLength=strlen(Num);
// Text alignment for numbers is flush-right :
strncpy(&Data[FLength-ResLength], Num, ResLength);
strncpy(RecContents, Data, FLength);
delete []Num;
break;
}
case 'D': // Date : no specific conversion (for portability)
case 'C': // Character :
ResLength=strlen((char *)Value);
strncpy(Data, (char *)Value, ResLength);
strncpy(RecContents, Data, FLength);
break;
case 'L': // Logical : conversion from 'BOOL' type
BOOL* Result3;
Result3=(BOOL *)Value;
if (*Result3==TRUE) Data[0]='Y';
else Data[0]='N';
strncpy(RecContents, Data, FLength);
break;
case 'M':
default:
break;
}// end switch;
delete []Data;
Rec->ModifFlag=TRUE;
}
// Overloaded, public versions of SetFieldValue. :
void CDBFile::SetFieldValue(char* Field, void* Value)
{ SetFieldValue(CurrentRec,FirstField->GetField(Field), Value);}
void CDBFile::SetFieldValue(unsigned short FieldNum, void* Value)
{ SetFieldValue(CurrentRec,FirstField->GetField(FieldNum), Value);}
void CDBFile::DumpCurrentContents(int i, char* String)
// Dumps the contents of the current record (raw ascii, no formatting)
{
if (CurrentRec!=NULL)
{
strncpy(String, CurrentRec->Contents, i);
String[i]=0;
}
else String[0]=0;
}
Record* CDBFile::ReadRecord(unsigned long RecNum)
// Reads a record from the file, returns a newly allocated *Record pointer
// The file offset is determined by RecNum and RecordLength.
{
unsigned char Res;
char* Buffer;
Record *NewRec;
if ((FileHandle==NULL)||(RecNum>RecordCount)||(RecNum<1)) return NULL;
else
{
Buffer=new char[RecordLength];
fseek (FileHandle, (long)(HeaderSize + (RecNum-1)*RecordLength), SEEK_SET);
Res=fread (Buffer, RecordLength, 1, FileHandle);
if (Res==0) return NULL;
NewRec=new Record;
NewRec->Contents=Buffer;
NewRec->ModifFlag=FALSE;
NewRec->RecordNumber=RecNum;
NewRec->Next=NULL;
NewRec->Previous=NULL;
return NewRec;
}
}
BOOL CDBFile::WriteHeader(char* Path)
// Use that function to rewrite or to save the current file under another
// name. It writes the header of the current CDBFile. In order to update the
// "date of last update" field, I introduced two structures : time_t Date, and
// tm *Date_s, which will have to be changed for a port under UNIX. For more
// details, have a look at OpenFile() above and the dBase III file structure.
{
unsigned char NLength,NDecCount;
char NType;
char Written;
CField *Current;
char dBaseVersion=0x03;
char FieldTerm=0x0D;
time_t Date;
struct tm *Date_s;
char Zero[256];
char Day, Year, Month;
// Initialize a zero buffer;
for (unsigned short j=0; j<256; j++) Zero[j]=0x00;
// Validity of the path name
if (Path!=NULL)
{
if (strlen(Path)>256)
{
fprintf (stderr, "File path too long : %s \n", Path);
return FALSE;
}
strcpy (PathName, Path);
}
// Close the currently open file
if (FileHandle!=NULL) fclose(FileHandle);
FileHandle = fopen (PathName, "w");
if (FileHandle==NULL) return FALSE;
fseek (FileHandle, 0L, SEEK_SET);
Written=fwrite (&dBaseVersion, 1, sizeof (char), FileHandle);
time(&Date);
Date_s = gmtime(&Date);
Year=(char)(Date_s->tm_year);
Month=(char)(Date_s->tm_mon);
Day=(char)(Date_s->tm_mday);
fseek (FileHandle, 1L, SEEK_SET);
Written=fwrite (&Year, sizeof (char), 1, FileHandle);
Written=fwrite (&Month, sizeof (char), 1, FileHandle);
Written=fwrite (&Day, sizeof (char), 1, FileHandle);
fseek (FileHandle, 4L, SEEK_SET);
Written=fwrite (&RecordCount, sizeof (RecordCount), 1, FileHandle);
fseek (FileHandle, 8L, SEEK_SET);
Written=fwrite (&HeaderSize, sizeof (HeaderSize), 1, FileHandle);
Written=fwrite (&RecordLength, sizeof (RecordLength), 1, FileHandle);
Written=fwrite (&Zero, sizeof(char), 20, FileHandle);
for (unsigned short i=1; i<=FieldCount; i++)
{
Current=FirstField->GetField(i);
NLength=Current->GetLength();
NType=Current->GetType();
NDecCount=Current->GetDecCount();
fwrite (Current->GetName(), 11, sizeof (char), FileHandle);
fwrite (&NType, sizeof (char), 1, FileHandle);
fwrite (&Zero, sizeof(char), 4, FileHandle);
fwrite (&NLength, sizeof (unsigned char), 1, FileHandle);
fwrite (&NDecCount, sizeof (unsigned char), 1, FileHandle);
fwrite (&Zero, sizeof(char), 14, FileHandle);
}// end for
fwrite (&FieldTerm, sizeof (char), 1, FileHandle);
return TRUE;
}
BOOL CDBFile::WriteRecord(Record* Current, unsigned long RecNum)
// Writes a record at the specified place,using RecNum to calculate the offset
{
size_t Res;
if ((FileHandle==NULL)||(RecNum>RecordCount)||(RecNum<1)) return FALSE;
else
{
fseek(FileHandle,(long)(HeaderSize+(RecNum-1)*RecordLength),SEEK_SET);
Res=fwrite (Current->Contents, RecordLength, 1, FileHandle);
if (Res==1)
{
Current->ModifFlag=FALSE;
// now that it has been written to file, it's no longer modified.
return TRUE;
}
else return FALSE;
}
}
BOOL CDBFile::Swap(Record* Rec1, Record* Rec2)
// swaps the contents of Rec1 and Rec2 (used in the SortAll function)
{
char* BufCont;
BOOL BufFlag;
BufCont=Rec1->Contents;
BufFlag=Rec1->ModifFlag;
Rec1->Contents=Rec2->Contents;
Rec1->ModifFlag=Rec2->ModifFlag;
Rec2->Contents=BufCont;
Rec2->ModifFlag=BufFlag;
return TRUE;
}
BOOL CDBFile::IsBigger(void *v1, void *v2, CField* Criterium)
// Compares v1 and v2 using Criterium to determine their type.
{
switch(Criterium->GetType())
{
case 'N': // Numeric
double *val1, *val2;
val1=(double*)v1; val2=(double*)v2;
return(BOOL)(*val1>*val2);
case 'C':
default : // Caracter
char *str1, *str2;
str1=(char*)v1; str2=(char*)v2;
return(BOOL)(strcmp(str1, str2)>0);
}
}
BOOL CDBFile::IsSmaller(void *v1, void *v2, CField* Criterium)
// Compares v1 and v2 using Criterium to determine their type.
{
switch(Criterium->GetType())
{
case 'N': // Numeric
double *val1, *val2;
val1=(double*)v1; val2=(double*)v2;
return(BOOL)(*val1<*val2);
case 'C':
default : // Caracter
char *str1, *str2;
str1=(char*)v1; str2=(char*)v2;
return(BOOL)(strcmp(str2, str1)>0);
}
}