1 //-------------------------------------------------------------------------
\r
3 // This file contains some DataFlex 3.2 Console Mode functions
\r
4 // to provide limited hashing algorithms. More advanced hashing
\r
5 // can be found in win32.inc.
\r
7 // This file is to be included in df32func.mk
\r
9 // Copyright (c) 2006-2009, glyn@8kb.co.uk
\r
11 // df32func/hash.inc
\r
12 //-------------------------------------------------------------------------
\r
14 //-------------------------------------------------------------------------
\r
16 //-------------------------------------------------------------------------
\r
18 // Produces an integer hash value for indexing into a DataFlex array.
\r
20 // This is a rather unaccomplished hash, but is specifically designed to produce
\r
21 // positive hashed values with a relatively low integer range (< 10,000,000)
\r
22 // in order to give a decent distribution and still fit into a DataFlex 3.2
\r
24 // It can without doubt be improved.
\r
26 // Note that whilst this hash may appear to preserve ascii order to some
\r
27 // degree this is an artifact rather than by design and cannot be relied on.
\r
28 function hash_for_df_arrays global string argv returns integer
\r
29 local integer l_iHash
\r
33 move (lowercase(trim(argv))) to l_sTmp
\r
35 if (l_sTmp <> "") begin
\r
36 // Start at the first character of the string and produce distributed starting points for integer hash values
\r
37 if (mid(l_sTmp,1,1)) in "1234567890" move (((ascii(mid(l_sTmp,1,1)))-47)*200000) to l_iHash //index at 1-10
\r
38 if (mid(l_sTmp,1,1)) in "abcdefghijklmnopqrstuvwxyz" move (((ascii(mid(l_sTmp,1,1)))-86)*200000) to l_iHash //index at 11-36
\r
39 if not (mid(l_sTmp,1,1)) in "1234567890abcdefghijklmnopqrstuvwxyz" move (37*200000) to l_iHash //index at 37+
\r
41 // Take the sum of the second, last and middle chars (upper and lowercase) in the string and add to the hash
\r
42 if (length(argv) > 1) calc (l_iHash + (ascii(mid(argv,1,2)))) to l_iHash
\r
43 if (length(argv) > 2) calc (l_iHash + (ascii(mid(argv,1,(length(argv)))))) to l_iHash
\r
44 if (length(argv) > 4) calc (l_iHash + (ascii(mid(argv,1,(length(argv)/2))))) to l_iHash
\r
46 // If the string is longer than 9 chars add the second last val * 100 to the hash
\r
47 if (length(argv) > 9) calc (l_iHash + (100*(ascii(mid(argv,1,(length(argv)-2)))))) to l_iHash
\r
49 // Add the length of the string onto the hash if shorter than 255 chars, else add 256.
\r
50 if (length(argv) > 255) calc (l_iHash + 256) to l_iHash
\r
51 else calc (l_iHash + length(argv)) to l_iHash
\r
57 function_return l_iHash
\r
60 // Chop up an integer hash that is out of the optimal DataFlex 3.2 array
\r
61 // size range and make it fit. This reduces the uniqueness of the hash but
\r
62 // unfortuantely is a necessary evil when using out of range hashes.
\r
63 function reduce_hash global integer argv returns integer
\r
64 local integer l_iHash
\r
66 // Make sure positive
\r
67 if (argv < 0) calc (argv*-1) to l_iHash
\r
68 else move argv to l_iHash
\r
70 // Unashamedly chop out the middle range
\r
71 if (length(string(l_iHash)) > 7) begin
\r
72 move (integer(left(string(l_iHash),3)+right(string(l_iHash), 3))) to l_iHash
\r
75 function_return l_iHash
\r
78 // Djb2 hashing from Dan Bernstein
\r
80 // The main info is here http://fr.wikipedia.org/wiki/Table_de_hachage#Fonction_de_Hachage
\r
82 // http://en.wikipedia.org/wiki/Daniel_J._Bernstein
\r
83 // http://cr.yp.to/djb.html
\r
84 // http://www.cse.yorku.ca/~oz/hash.html
\r
85 function hash_djb2 global string argv returns integer
\r
86 local integer l_iHash l_i
\r
88 move 5381 to l_iHash
\r
90 for l_i from 1 to (length(argv))
\r
91 move ((LShift(l_iHash,5) + l_iHash) + (ascii(mid(argv,1,L_i)))) to l_iHash
\r
94 function_return l_iHash
\r
97 // This is the SDBM hashing algorithm as used in berkeley DB
\r
99 // http://cpansearch.perl.org/src/RGARCIA/perl-5.10.0/ext/SDBM_File/sdbm/README
\r
100 // http://en.wikipedia.org/wiki/Dbm
\r
101 // http://en.wikipedia.org/wiki/Sleepycat_Software
\r
102 // http://en.wikipedia.org/wiki/Berkeley_DB
\r
103 function hash_sdbm global string argv returns integer
\r
104 local integer l_iHash l_i
\r
108 for l_i from 1 to (length(argv))
\r
109 move ((ascii(mid(argv,1,L_i))) + (LShift(l_iHash,6)) + (LShift(l_iHash,16)) - l_iHash) to l_iHash
\r
112 function_return l_iHash
\r
115 // Lazy hash, efficient for small fairly unique strings.
\r
116 function hash_lazy global string argv returns integer
\r
117 local integer l_iHash l_i
\r
121 for l_i from 1 to (length(argv))
\r
122 move (l_iHash + (ascii(mid(argv,1,L_i)))) to l_iHash
\r
125 function_return l_iHash
\r