<h1>Tech Notes</h1><h2>STAZ Munger - The ultimate search routine</h2><p>There comes a time in every programmers life when he starts to ask questions about things. Things like: "Why am I growing hair in certain places?" and "How do I search a large handle of text?"</p>
<p>I'll do my best to deal with both of those questions here, starting with grabbing your large handle and helping you look at it. Do that now. Grab your handle. Have you given it a name? We suggest doing that. It is a good programming practice to pre-dimension all of your variables. I'll call mine 'h'. That can be short for handle. (Or hair.)</p>
<pre>
dim h as handle
</pre>
<p>The next step, and it is an easy one, is to put your handle into a munger. In this case, we use the stazMunger. I like it because it's fast. We're talking a search routine that can zip through hundreds of files in a tenth of a second. And what is even more important is that the search is not case sensitive! If you search for "your HAIR" it will find "your hair". (I told you at the outset that we would deal with both questions. I have now fulfilled my obligation.)</p>
<p>Without further ado, the fastest, meanest, coolest, search function to ever toggle the bits of a Macintosh computer. I give you, <i>stazMunger!</i></p>
<pre>
register on
local fn stazMunger(ptrIn as ptr , start as long , limit as long, @txtPtr as ^str255)
register off
dim as long p, theEnd, x, lgth, searchByte, lastByte
dim as ptr txt
lgth = txtPtr.0`` - 1
theEnd = ptrIn + limit - lgth
p = ptrIn + start
txt = txtPtr + 1
searchByte = gFBLowerChar(txt.0``)
lastByte = gFBLowerChar(|txt + lgth|)
while p < theend
long if gfblowerchar(|p|) == searchByte
long if gFBLowerChar(|p + lgth|) == lastByte
x = lgth - 1
while x > 0
if gFBLowerChar(|txt + x|) != gFBLowerChar(|p + x|) then exit while
x --
wend
if x <= 0 then p -= ptrIn : exit fn ' Found
end if
end if
p ++
wend
p = -1 ' Not Found
end fn = p
</pre>
<p>Calling the function is not a big deal. You can grab the handle from anywhere. In the following little function, I fill a handle with the contents of a file, then call stazMunger using the handle. Because stazMunger does not move memory, you do not need to lock the handle. My sample function reads a file given only a file spec as a parameter.</p>
<pre>
local fn readTextFile(fsIn as ^fsSpec)
dim h as handle
dim lgth as long
dim fs as fsSpec
BlockMove fsIn,@fs, sizeOf(fsSpec)
open "I",#1,@fs
lgth = lof(1,1)
h = fn NewHandle(lgth)
long if h
HLock(h)
read file #1, [h], lgth
HUnLock(h)
end if
close #1
end fn = h
</pre>
<p>The next step is to feed the handle to stazMunger and ask for a search string.</p>
<p>When the job is complete, 'offset' will either equal an offet into the handle 'h' or it will equal -1 to indicate that the search string was not found. Cool, huh?</p>
<p>p.s. My thanks to Jay Reeve for his many speed-ups and improvements in this routine.</p>