Category : Files from Magazines
Archive   : DDJ0990.ZIP
Filename : CAMPISE.ASC
by Leon Campise
[LISTING ONE]
FUNCTION FASTSRCH% (BuffFile%, RecLen%, KeyLoc%, KeyVal$, StartRec%,
LastRec%, FoundRecs%())
CONST physbufflen% = 10000
DIM FarBuff(Dum%) AS STRING * physbufflen '* string buffer in the far heap
MaxFound% = UBOUND(FoundRecs%) '* can only find as many as array will hold
NumMatches% = 0 '* initialize the number of matches found
IF KeyLoc% = RecLen% THEN '* if key is the last byte in the record:
CompByte% = 0 : LastByte% = -1 '* modulo position to check will be 0
ELSE '* and when calculating record number
CompByte%=KeyLoc% : LastByte%=0 '* of the matching record,
'* 1 must be subtracted
END IF
RecsPerRead% = physbufflen \ RecLen%
'* calc. the # of records scanned with each disk read
BuffLen% = RecsPerRead% * RecLen%
'* the actual number of bytes in the buffer being used
CurRec% = StartRec% '* initialize CurRec
DO '* OUTER LOOP * This loop executes for each disk read
BuffByte& = ((CurRec% - 1&) * RecLen%) + 1 '* first byte in next buffer
GET BuffFile%, BuffByte&, FarBuff(0) '* perform the actual disk i/o
Match% = 0 '* initialize match to false
IF CurRec% + RecsPerRead% - 1 > LastRec% THEN '* when the last disk
BuffLen% = (LastRec% - CurRec% + 1) * RecLen% '* read goes past the
END IF '* number of records
'* to search, shorten
'* the number of bytes
'* in buffer to scan
DO '* MIDDLE LOOP * Loops for each match found in this buffer
DO '* INNER LOOP * Loops for each "false" match
Match% = INSTR(Match% + 1, FarBuff(0), KeyVal$)
Match% > BuffLen% THEN Match% = 0
'* if match was past valid data, ignore the match
IF Match% = 0 THEN EXIT DO '* no more matches in this buffer
LOOP WHILE Match% MOD RecLen% <> CompByte%
'* keep searching if the match was in the wrong position
IF Match% > 0 AND NumMatches% < MaxFound% THEN
'* if a match and the array isn't full
NumMatches% = NumMatches% + 1
'* add into the array of found records
FoundRecs%(NumMatches%) = _
((Match% + LastByte%) \ RecLen%) + CurRec%
'* CALCULATE THE ACTUAL RECORD NUMBER *
END IF
LOOP UNTIL Match% = 0 '* no more matches in this buffer, exit loop
CurRec% = CurRec% + RecsPerRead% '* calc. first record of next buffer
LOOP UNTIL CurRec% > LastRec% '* if 1st rec. of next buffer is > number
'* of recs to search then were finished
FASTSRCH% = NumMatches% '* set return value = number of matches
END FUNCTION
[LISTING TWO]
DECLARE FUNCTION InstrASM% (BYVAL BuffSeg%, BYVAL BuffOff%, BYVAL BuffLen%,_
BYVAL KeySeg%, BYVAL KeyOff%, BYVAL KeyLen%, BYVAL RecLen%)
FUNCTION InstrR% (StRec%, Buff() AS STRING * 10000, KeyVal$, RecLen%,
KeyPos%) STATIC
KeyLen% = LEN(KeyVal$) '* Get the length of the key
StartingOffs% = ((StRec% - 1) * RecLen%) + KeyPos% - 1
'* Calculate the 1st byte to search
BuffLen% = LEN(Buff(0)) - StartingOffs% '* Calculate # of bytes to search
BuffSeg% = SSEG(Buff(0)) '* Locate the buffer's segment
BuffOff% = SADD(Buff(0)) + StartingOffs% '* and offset.
KeySeg% = SSEG(KeyVal$) '* Locate the key's segment
KeyOff% = SADD(KeyVal$) '* and offset.
FoundPos% = InstrASM%(BuffSeg%, BuffOff%, BuffLen%, _
KeySeg%, KeyOff%, KeyLen%, RecLen%) '* Perform a search
IF FoundPos% = 0 THEN '* If no match,
InstrR% = 0 '* set the record number to 0
ELSE '* otherwise calculate the record number
InstrR% = (FoundPos% + StartingOffs% + RecLen% - 1) \ RecLen%
END IF
END FUNCTION
[LISTING THREE]
.MODEL MEDIUM, BASIC
.CODE
INSTRASM PROC FAR USES DS SI DI, BuffSeg,BuffStartAdd,BuffLen,KeySeg,\
KeyAddr,KeyLen,RecLen
PUSHF
MOV BX,BuffSeg ; Move the Buffer Segment
MOV ES, BX ; into the EXTRA SEGMENT REGISTER
MOV BX,KeySeg ; Move the Key String Segment
MOV DS,BX ; into the DATA SEGMENT REGISTER
MOV AX,RecLen ; Move the Record Length to AX
MOV DX,BuffLen ; Move the Length of the Buffer to DX
MOV BX,BuffStartAdd ; Move Buffer Starting Address to BX
ADD DX,BX ; Add Buffer Offset(BX) to Buffer Length(DX)
SUB DX,1 ; and subtract 1 for End of Buffer Address
CLD ; Clear the direction flag
FinishedYet:
CMP BX,DX ; Next Record Address>End Of Buffer Address?
JA NoMoreBuff ; if so, quit.
MOV DI,BX ; Move Next Record Address to Dest. Index
MOV SI,KeyAddr ; Move Key Address to Source Index
MOV CX,KeyLen ; Move Key Length to CX as REPE counter
REPE CMPSB ; Compare strings and if equal
JE Match ; go to Match (* can use JA or JB to alter *)
ADD BX,AX ; Add Record Length(AX) to Next Record Address
JMP FinishedYet ; Loop back and continue checking for a match
NoMoreBuff:
XOR AX,AX ; Set AX to 0 for return in function value
JMP TheEnd ; Go to end
Match:
MOV AX,BX ; Move Current Record Offset to AX for return
SUB AX,BuffStartAdd ; Subtract Starting Address of Buffer and
ADD AX,1 ; add 1 to get actual offset w/i Buffer
TheEnd:
POPF
RET
INSTRASM ENDP
END
[Example 1: Scanning a file without FASTSRCH]
OPEN "TRANSACT.DAT" FOR RANDOM AS #1 LEN = LEN(T)
FOR I% = 1 TO NumRecs%
GET #1, I%, T
IF KeyVal$ = T.CustNum THEN CALL Print1Rec(T)
NEXT
[Example 2: Scanning a file using FASTSRCH]
DIM FoundRecs%(MaxToFind%)
OPEN "TRANSACT.DAT" FOR BINARY AS #1
NumFound% = FASTSRCH(1, LEN(T), 7, KeyVal$, 1, LastRec%, FoundRecs%())
CLOSE #1
OPEN "TRANSACT.DAT" FOR RANDOM AS #1 LEN = LEN(T)
FOR I% = 1 TO NumFound%
GET #1, FoundRecs%(I%), T
CALL Print1Rec(T)
NEXT
[Example 3: Implementing InstrR]
(a)
Match% = InstrR(Match% + 1, FarBuff(), KeyVal$, RecLen%, KeyPos%)
IF Match% > BuffLen% then Match% = 0
(b)
FoundRecs%(NumMatches%) = Match% + CurRec% - 1
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/