home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magazyn Exec 3
/
CD_Magazyn_EXEC_nr_3.iso
/
Recent
/
misc
/
edu
/
WhirlDisc.lha
/
WhirlDisc
/
Source
/
index.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-08-13
|
7KB
|
324 lines
/*
File: index.c
Author: Neil Cafferkey
Copyright (C) 2000 Neil Cafferkey
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/
#include "viewer.h"
#include <dos/dos.h>
#include <dos/dostags.h>
#include <exec/memory.h>
#include <string.h>
#include "index_protos.h"
#include "index_record_protos.h"
#include "general_protos.h"
#include <proto/exec.h>
const TEXT FIRST_REC_STRING[]="%FIRST-REC%";
#define FIRST_REC_SIZE 11
static UBYTE *DataSearch(ULONG length_1,ULONG length_2,UBYTE *buf_1,
UBYTE *buf_2);
static BOOL DataEqual(ULONG length,UBYTE *buf_1,UBYTE *buf_2);
/* Function: CreateIndex
* =====================
* Creates an Index.
*/
Index CreateIndex(TEXT *master_file_name,TEXT *index_file_name)
{
Index index;
struct FileInfoBlock *temp_fib;
BPTR master_file;
if((index=(Index)AllocMem(sizeof(Index_imp),MEMF_CLEAR))!=NULL)
{
/* Open the main index file */
if(!(index->index_file=Open(index_file_name,MODE_OLDFILE)))
ReportError(NULL,ERROR_REPORT_FILE,index_file_name,0);
/* Open the master index file */
master_file=Open(master_file_name,MODE_OLDFILE);
/* Copy master index file into memory */
if(master_file)
{
if((temp_fib=(struct FileInfoBlock *)AllocDosObjectTags(
DOS_FIB,TAG_END))!=NULL)
{
/* Get master file size */
ExamineFH(master_file,temp_fib);
index->block_count=temp_fib->fib_Size/MASTER_REF_SIZE;
FreeDosObject(DOS_FIB,temp_fib);
/* Allocate memory for master file data */
index->master_index=(UBYTE *)AllocMem(index->block_count
*MASTER_REF_SIZE,MEMF_ANY);
/* Read link data into memory */
if(index->master_index!=NULL)
Read(master_file,index->master_index,index->block_count
*MASTER_REF_SIZE);
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
}
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
}
Close(master_file);
}
else
{
ReportError(NULL,ERROR_REPORT_FILE,master_file_name,0);
}
/* Check if there were any errors */
if((index->index_file==NULL)||(index->master_index==NULL))
{
KillIndex(index);
index=NULL;
}
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
}
return index;
}
/* Function: FindIndexRecords
* ==========================
* Searches for records within an index.
*/
struct List *FindIndexRecords(Index index,TEXT *search_string)
{
IndexRecord index_rec;
UWORD first_block,last_block,mid;
WORD low,high;
UBYTE *p,*q,*index_buffer;
struct List *rec_list;
BOOL success=TRUE;
/* Create a new list to contain the results */
rec_list=AllocMem(sizeof(struct List),MEMF_PUBLIC);
if(rec_list!=NULL)
{
NewList(rec_list);
/* Convert search string to uppercase */
for(p=search_string;*p!='\0';p++)
*p=toupper(*p);
/* Do a binary search to find the first block needed */
p=index->master_index;
low=-1;
high=index->block_count-1;
while(high-low!=1)
{
mid=low+(high-low)/2;
for(q=p+mid*MASTER_REF_SIZE;*q!=0;q-=MASTER_REF_SIZE);
if(strncmp(search_string,q+1,MASTER_REF_SIZE-1)<=0)
high=mid;
else
low=mid;
}
first_block=high;
/* Do a binary search to find the last block needed */
low=-1;
high=index->block_count-1;
while(high-low!=1)
{
mid=low+(high-low)/2;
for(q=p+mid*MASTER_REF_SIZE;*q!=0;q-=MASTER_REF_SIZE);
if(strncmp(search_string,q+1,MASTER_REF_SIZE-1)<0)
high=mid;
else
low=mid;
}
last_block=high;
/* Allocate the index buffer */
index_buffer=AllocMem((last_block-first_block+1)*INDEX_BLOCK_SIZE,
MEMF_ANY);
if(index_buffer)
{
/* Read relevant index blocks into memory */
Seek(index->index_file,first_block*INDEX_BLOCK_SIZE,
OFFSET_BEGINNING);
Read(index->index_file,index_buffer,(last_block-first_block+1)
*INDEX_BLOCK_SIZE);
/* Find first-record marker */
p=DataSearch(FIRST_REC_SIZE,2*INDEX_BLOCK_SIZE,
FIRST_REC_STRING,index_buffer);
/* Find first matching record */
p+=FIRST_REC_SIZE;
while(strcmp(p+10,search_string)<0)
p+=GetLittleEndianUWord(p);
/* Put all matching records into the list */
while(strcmp(p+10,search_string)==0)
{
index_rec=CreateIndexRecord(p);
if(index_rec!=NULL)
AddTail(rec_list,&index_rec->node);
p+=GetLittleEndianUWord(p);
}
FreeMem(index_buffer,(last_block-first_block+1)*INDEX_BLOCK_SIZE);
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
return rec_list;
}
/* Function: KillIndexResults
* ==========================
*/
VOID KillIndexResults(struct List *list)
{
IndexRecord rec;
while(rec=(IndexRecord)RemHead(list))
KillIndexRecord(rec);
FreeMem(list,sizeof(struct List));
return;
}
/* Function: DataSearch
* ====================
* Searches for one sequence within another sequence.
*/
static UBYTE *DataSearch(ULONG length_1,ULONG length_2,UBYTE *buf_1,
UBYTE *buf_2)
{
ULONG i,last=length_2-length_1;
REGISTER UBYTE first=*buf_1;
BOOL equal=FALSE;
for(i=0;(i<=last)&&!equal;i++)
{
if(first==*buf_2) equal=DataEqual(length_1,buf_1,buf_2);
buf_2++;
}
if(i<=last) return --buf_2;
return NULL;
}
/* Function: DataEqual
* ===================
* Returns TRUE if two data sequences are equal.
*/
static BOOL DataEqual(ULONG length,UBYTE *buf_1,UBYTE *buf_2)
{
ULONG i;
for(i=0;(i<length)&&(*(buf_1++)==*(buf_2++));i++);
return (i==length);
}
/* Function: KillIndex
* ===================
* Destroys an index.
*/
VOID KillIndex(Index index)
{
if(index->index_file!=NULL)
Close(index->index_file);
if(index->master_index!=NULL)
FreeMem(index->master_index,index->block_count*MASTER_REF_SIZE);
FreeMem(index,sizeof(Index_imp));
}