home *** CD-ROM | disk | FTP | other *** search
- /*
-
- 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));
- }
-
-
-
-