234 lines
8.6 KiB
HTML
234 lines
8.6 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<META name=vsisbn content="1576101746">
|
|
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
|
|
<META name=vsauthor content="Michael Abrash">
|
|
<META name=vspublisher content="The Coriolis Group">
|
|
<META name=vspubdate content="07/01/97">
|
|
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Crossing the Border</TITLE>
|
|
|
|
<!-- HEADER -->
|
|
<!-- Empty Reference Subhead -->
|
|
|
|
<!--ISBN=1576101746//-->
|
|
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
|
|
<!--AUTHOR=Michael Abrash//-->
|
|
<!--PUBLISHER=The Coriolis Group, Inc.//-->
|
|
<!--CHAPTER=05//-->
|
|
<!--PAGES=118-121//-->
|
|
<!--UNASSIGNED1//-->
|
|
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
|
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="05-02.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="05-04.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
<P><BR></P>
|
|
<P><B>LISTING 5.1 SEARCH.C</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
/* Program to search the file specified by the first command-line
|
|
* argument for the string specified by the second command-line
|
|
* argument. Performs the search by reading and searching blocks
|
|
* of size BLOCK_SIZE. */
|
|
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <alloc.h> /* alloc.h for Borland compilers,
|
|
malloc.h for Microsoft compilers */
|
|
|
|
#define BLOCK_SIZE 0x4000 /* we’ll process the file in 16K blocks */
|
|
|
|
/* Searches the specified number of sequences in the specified
|
|
buffer for matches to SearchString of SearchStringLength. Note
|
|
that the calling code should already have shortened SearchLength
|
|
if necessary to compensate for the distance from the end of the
|
|
buffer to the last possible start of a matching sequence in the
|
|
buffer.
|
|
*/
|
|
|
|
int SearchForString(unsigned char *Buffer, int SearchLength,
|
|
unsigned char *SearchString, int SearchStringLength)
|
|
{
|
|
unsigned char *PotentialMatch;
|
|
|
|
/* Search so long as there are potential-match locations
|
|
remaining */
|
|
while ( SearchLength ) {
|
|
/* See if the first character of SearchString can be found */
|
|
if ( (PotentialMatch =
|
|
memchr(Buffer, *SearchString, SearchLength)) == NULL ) {
|
|
break; /* No matches in this buffer */
|
|
}
|
|
/* The first character matches; see if the rest of the string
|
|
also matches */
|
|
if ( SearchStringLength == 1 ) {
|
|
return(1); /* That one matching character was the whole
|
|
search string, so we’ve got a match */
|
|
}
|
|
else {
|
|
/* Check whether the remaining characters match */
|
|
if ( !memcmp(PotentialMatch + 1, SearchString + 1,
|
|
SearchStringLength - 1) ) {
|
|
return(1); /* We’ve got a match */
|
|
}
|
|
}
|
|
/* The string doesn’t match; keep going by pointing past the
|
|
potential match location we just rejected */
|
|
SearchLength -= PotentialMatch - Buffer + 1;
|
|
Buffer = PotentialMatch + 1;
|
|
}
|
|
|
|
return(0); /* No match found */
|
|
}
|
|
|
|
main(int argc, char *argv[]) {
|
|
int Done; /* Indicates whether search is done */
|
|
int Handle; /* Handle of file being searched */
|
|
int WorkingLength; /* Length of current block */
|
|
int SearchStringLength; /* Length of string to search for */
|
|
int BlockSearchLength; /* Length to search in current block */
|
|
int Found; /* Indicates final search completion
|
|
status */
|
|
int NextLoadCount; /* # of bytes to read into next block,
|
|
accounting for bytes copied from the
|
|
last block */
|
|
unsigned char *WorkingBlock; /* Block storage buffer */
|
|
unsigned char *SearchString; /* Pointer to the string to search for */
|
|
unsigned char *NextLoadPtr; /* Offset at which to start loading
|
|
the next block, accounting for
|
|
bytes copied from the last block */
|
|
|
|
/* Check for the proper number of arguments */
|
|
if ( argc != 3 ) {
|
|
printf(“usage: search filename search-string\n”);
|
|
exit(1);
|
|
}
|
|
|
|
/* Try to open the file to be searched */
|
|
if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) {
|
|
printf(“Can’t open file: %s\n”, argv[1]);
|
|
exit(1);
|
|
}
|
|
/* Calculate the length of text to search for */
|
|
SearchString = argv[2];
|
|
SearchStringLength = strlen(SearchString);
|
|
/* Try to get memory in which to buffer the data */
|
|
if ( (WorkingBlock = malloc(BLOCK_SIZE)) == NULL ) {
|
|
printf(“Can’t get enough memory\n”);
|
|
exit(1);
|
|
}
|
|
|
|
/* Load the first block at the start of the buffer, and try to
|
|
fill the entire buffer */
|
|
NextLoadPtr = WorkingBlock;
|
|
NextLoadCount = BLOCK_SIZE;
|
|
Done = 0; /* Not done with search yet */
|
|
Found = 0; /* Assume we won’t find a match */
|
|
/* Search the file in BLOCK_SIZE chunks */
|
|
do {
|
|
/* Read in however many bytes are needed to fill out the block
|
|
(accounting for bytes copied over from the last block), or
|
|
the rest of the bytes in the file, whichever is less */
|
|
if ( (WorkingLength = read(Handle, NextLoadPtr,
|
|
NextLoadCount)) == -1 ) {
|
|
printf(“Error reading file %s\n”, argv[1]);
|
|
exit(1);
|
|
}
|
|
/* If we didn’t read all the bytes we requested, we’re done
|
|
after this block, whether we find a match or not */
|
|
if ( WorkingLength != NextLoadCount ) {
|
|
Done = 1;
|
|
}
|
|
|
|
/* Account for any bytes we copied from the end of the last
|
|
block in the total length of this block */
|
|
WorkingLength += NextLoadPtr - WorkingBlock;
|
|
/* Calculate the number of bytes in this block that could
|
|
possibly be the start of a matching sequence that lies
|
|
entirely in this block (sequences that run off the end of
|
|
the block will be transferred to the next block and found
|
|
when that block is searched)
|
|
*/
|
|
if ( (BlockSearchLength =
|
|
WorkingLength - SearchStringLength + 1) <= 0 ) {
|
|
Done = 1; /* Too few characters in this block for
|
|
there to be any possible matches, so this
|
|
is the final block and we’re done without
|
|
finding a match
|
|
*/
|
|
}
|
|
else {
|
|
/* Search this block */
|
|
if ( SearchForString(WorkingBlock, BlockSearchLength,
|
|
SearchString, SearchStringLength) ) {
|
|
Found = 1; /* We’ve found a match */
|
|
Done = 1;
|
|
}
|
|
else {
|
|
/* Copy any bytes from the end of the block that start
|
|
potentially-matching sequences that would run off
|
|
the end of the block over to the next block */
|
|
if ( SearchStringLength > 1 ) {
|
|
memcpy(WorkingBlock,
|
|
WorkingBlock+BLOCK_SIZE - SearchStringLength + 1,
|
|
SearchStringLength - 1);
|
|
}
|
|
/* Set up to load the next bytes from the file after the
|
|
bytes copied from the end of the current block */
|
|
NextLoadPtr = WorkingBlock + SearchStringLength - 1;
|
|
NextLoadCount = BLOCK_SIZE - SearchStringLength + 1;
|
|
}
|
|
}
|
|
} while ( !Done );
|
|
|
|
/* Report the results */
|
|
if ( Found ) {
|
|
printf(“String found\n”);
|
|
} else {
|
|
printf(“String not found\n”);
|
|
}
|
|
exit(Found); /* Return the found/not found status as the
|
|
DOS errorlevel */
|
|
}
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P><BR></P>
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="05-02.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="05-04.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
|
|
<hr width="90%" size="1" noshade>
|
|
<div align="center">
|
|
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book © 2001 Michael Abrash</font>
|
|
</div>
|
|
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
|
<!-- reference_subfoot = footer -->
|
|
<!-- reference_footer = subfoot -->
|
|
|
|
<!-- BEGIN SUB FOOTER -->
|
|
</BODY>
|
|
</HTML>
|
|
|
|
<!-- END FOOTER -->
|
|
|
|
|