Posted: Tue May 02, 2006 7:09 pm
				
				Yes, this would work too... I'll test it. Until now, netmaesto's idea is working exremely well, the scanner is working. I gotta test the efficacity too.
			http://www.purebasic.com
https://www.purebasic.fr/english/
Code: Select all
EnableExplicit
Macro strL(val)
  Str(val)
EndMacro
Structure UDT_keyInfo
  key.l
  ptr.l
EndStructure
; ===========================================================================
; PART 1 : Preparation. Not required in the main prog.
;   Assumes speed not critical, builds the list
;   This would be done each time a virus definition was added.
Global NewList keys.UDT_keyInfo()                ; To hold the key/ptr info
Global itemCount.l                               ; To count the info
Global memBank.l
Global fileSz.l
Global rawFile.s
rawFile = "C:\100\pb400\PROJECTS\DataBase\rawViralKeys.dta"
RandomSeed(1)
; Substitute this for something reading key/pointer information from the real file.
; Assumptions are:
;   The offset of each "record" in the real file is known.
;   A fixed length key using a part of the record is feasible.
;   Duplication is allowed. If none, so much the better!
Procedure populateRawList()                      ; Pretend we're reading these in
  Protected offSet.l                             ;   from a file. Key is used here
  For offSet = 1 To 52000                        ;   is just a long. Substitute for
    AddElement(keys())                           ;   whatever you will use. IMO, if
    keys()\key = Random($7FFFFFFF)               ;   using strings of 8 or less, then
    keys()\ptr = offSet                          ;   treat as quads or longs.
    itemCount + 1
  Next                                           ; Once keys are listed, sort them
  SortStructuredList(keys(),0,OffsetOf(UDT_keyInfo\key),#PB_Sort_Long)
EndProcedure
populateRawList()                                ; Build our lookup list
CreateFile(0,rawFile)                            ; Write our list to file
WriteLong(0,itemCount)                           ; First bytes are a count of items
ForEach keys()
  WriteLong(0,keys()\key)
  WriteLong(0,keys()\ptr)
Next
CloseFile(0)
; ===========================================================================
; PART 2 - Used to lookup in the main prog
;    Uses a binary search, overhead is:
;       max 16 (plus adjusting) hits for  32k - 1 items
;       max 32 (plus adjusting) hits for  64k - 1 items
;       max 64 (plus adjusting) hits for 128k - 1 items
;    etc.
fileSz = FileSize(rawFile)                       ; Load our sorted list
memBank.l = AllocateMemory(fileSz-4)             ; Not a lot of error checking :)
ReadFile(0,rawFile)
itemCount = ReadLong(0)
ReadData(0,memBank,fileSz)
CloseFile(0)
; This will (should) always find the first key that is >= to the search key,
;    with one exception:
;      If the key being searched is greater than the highest key in list,
;      the last key in the list is return and will be < than search key
     
Procedure binaryFindKey(key.l)                   ; Find the first key >= to search key
  Protected stepper.l                            ; Used to zone in on the target
  Protected offset.l                             ; The position, in items, we seek
  Protected *lookHere.UDT_keyInfo                ; Floated on the memory bank
  stepper = 1                                    ; Start our stepper at binary one
  While stepper < itemCount / 2                  ; Get as close to the middle as we
    stepper << 1                                 ;   can, using two's complement
  Wend
  If stepper >= itemCount                        ; If we just missed (got the end)
    stepper >> 1                                 ;   halve the stepper
  EndIf
  offset = stepper                               ; Set our offset (in items or elements)
  While stepper > 0                              ; Keep looking until we exhaust the stepper
    *lookHere = memBank + (offset - 1) * SizeOf(UDT_keyInfo)
    stepper >> 1                                 ; After getting offset, shrink the stepper
    If *lookHere\key = key                       ; Cf we got the key
      Break                                      ; Paydirt!
    ElseIf *lookHere\key > key                   ; Otherwise, if we are too deep into the
      offset - stepper                           ;   list, backtrack
    Else                                         ; Or if we are not deep enough,
      offset + stepper                           ;   then advance
      While offset > itemCount                   ;   But make sure we stay in bounds
        stepper << 1
        offset - stepper                         ; Potential crash/infinite loop here?
      Wend                                       ;  (** Note to me, check this **)
    EndIf
  Wend
  While *lookHere\key >= key And *lookHere > memBank
    *lookHere - SizeOf(UDT_keyInfo)              ; Tidy up, get to a lesser value
  Wend
  While *lookHere\key < key And *lookHere < memBank + (itemCount * SizeOf(UDT_keyInfo)) - SizeOf(UDT_keyInfo)
    *lookHere + SizeOf(UDT_keyInfo)              ; Stop at first > value or end of list
  Wend
  ProcedureReturn *lookHere
EndProcedure
Define *res.UDT_keyInfo
Define search.l
Define timer.l
timer=ElapsedMilliseconds()
search = 1234567                                 ; Some key to find
*res = binaryFindKey(search)                     ; Get result
Debug StrL(ElapsedMilliseconds()-timer)+" ms, got "+StrL(*res\key)+" for "+StrL(search)
If *res\key <> search
  Debug "NO MATCH"
Else                                             ; If duplicate keys exist, this is the 1st
  While *res\key = search And *res < memBank + (itemCount * SizeOf(UDT_keyInfo)) - SizeOf(UDT_keyInfo)
    ; Fetch the extended information
    ; If this is the one we want
    ;   Break
    ; otherwise
    *res + SizeOf(UDT_keyInfo)
  Wend
EndIf
FreeMemory(memBank)Code: Select all
#TableSize = 52000
Global Dim search.s(#TableSize)
Procedure.s CreateKey()
  Protected OutKey.s="", KeyPos.l, KeyEnd.l
  KeyEnd = 30+Random(30)
  For KeyPos=1 To KeyEnd
    OutKey + RSet(Hex(Random($FF)),2,"0")
  Next
  ProcedureReturn OutKey
EndProcedure
Procedure DummyTable()
  Protected TablePos.l
  For TablePos = 0 To #TableSize
    search(TablePos) = CreateKey()
  Next
  SortArray(search(),2) 
EndProcedure
Procedure.l FindKeyFast(KeyToFind.s)
  Protected KeyLo.l,KeyHi.l,KeyPos.l,DebugCount.l=0
  KeyLo=0
  KeyHi=#TableSize
  Repeat
    KeyPos = (KeyLo+KeyHi)>>1
    ;DebugCount+1
    ;Debug Str(DebugCount)+": "+Str(KeyLo)+" | "+Str(KeyPos)+" | "+Str(KeyHi)
    If search(KeyPos)=KeyToFind
      ProcedureReturn KeyPos
    ElseIf search(KeyPos)>KeyToFind
      KeyHi=KeyPos
    Else
      KeyLo=KeyPos
    EndIf
  ForEver
EndProcedure
Procedure.l FindKeySlow(base.s)
  For t = 0 To #TableSize
    If search.s(t) = base.s
      ProcedureReturn t
    EndIf
  Next t 
EndProcedure
Procedure TestIt()
  base.s = search(Random(#TableSize))
  QueryPerformanceCounter_(@Cntr1)
  Debug FindKeySlow(base)
  QueryPerformanceCounter_(@Cntr2)
  Debug FindKeyFast(base)
  QueryPerformanceCounter_(@Cntr3)
  Debug Str((Cntr2-Cntr1)/(Cntr3-Cntr2))+" times faster..."
  Debug "-------"
EndProcedure
DummyTable()
For x=1 To 10
  TestIt()
Next sverson
 sverson .
.