2 ; this is a simple map used primarily for the source cache
\r
8 free_space_length dd ?
\r
19 ; in: cl = number of hash bits
\r
20 ; out: ebx - new map
\r
25 lea ecx,[sizeof.Map+ebx*4]
\r
30 mov [ebx+Map.hash_mask],eax
\r
31 lea edi,[ebx+sizeof.Map]
\r
36 mov [ebx+Map.linked_blocks],eax
\r
40 mov [ebx+Map.free_space],eax
\r
41 mov [ebx+Map.free_space_length],1000h-10h
\r
46 ; preserves: esi, edi
\r
48 mov ebx,[ebx+Map.linked_blocks]
\r
52 jz string_map_destroyed
\r
57 string_map_destroyed:
\r
64 ; ecx = string length, zero for ASCIIZ string
\r
67 ; cf set when no entry found
\r
68 ; preserves: ebx, [esi], edi
\r
69 ; note: when entry is found, esi is replaced with pointer to the same string in persistent storage
\r
75 mov eax,[eax+MapEntry.value]
\r
79 and edx,[ebx+Map.hash_mask]
\r
80 mov eax,[ebx+sizeof.Map+edx*4]
\r
83 cmp [eax+MapEntry.name_length],ecx
\r
86 mov edi,[eax+MapEntry.name]
\r
88 jz not_this_map_entry
\r
92 jne not_this_map_entry
\r
101 mov eax,[eax+MapEntry.next_entry]
\r
112 ; ecx = string length, zero for ASCIIZ string
\r
114 ; preserves: ebx, [esi], edi
\r
116 ; esi is replaced with pointer to the same string in persistent storage,
\r
117 ; an ASCIIZ string is a key with length including the terminating zero
\r
118 ; and when it is put into persistent storage, final zero is copied as well
\r
123 call find_map_entry
\r
124 jnc put_value_into_map_entry
\r
125 mov eax,[ebx+sizeof.Map+edx*4]
\r
126 find_free_map_entry:
\r
127 cmp [eax+MapEntry.name],0
\r
130 mov eax,[eax+MapEntry.next_entry]
\r
132 jnz find_free_map_entry
\r
133 call allocate_map_entry
\r
134 mov [edx+MapEntry.next_entry],eax
\r
137 call allocate_map_entry
\r
138 mov [ebx+sizeof.Map+edx*4],eax
\r
140 mov [eax+MapEntry.next_entry],0
\r
142 mov [eax+MapEntry.name_length],ecx
\r
146 mov [eax+MapEntry.name],esi
\r
147 put_value_into_map_entry:
\r
148 pop [eax+MapEntry.value]
\r
150 allocate_map_entry:
\r
151 mov eax,[ebx+Map.free_space]
\r
152 add [ebx+Map.free_space],sizeof.MapEntry
\r
153 sub [ebx+Map.free_space_length],sizeof.MapEntry
\r
154 jc map_out_of_free_space
\r
156 map_out_of_free_space:
\r
161 xchg [ebx+Map.linked_blocks],edx
\r
164 mov [ebx+Map.free_space],eax
\r
165 mov [ebx+Map.free_space_length],1000h-10h
\r
167 jmp allocate_map_entry
\r
173 ; ecx = string length, zero for ASCIIZ string
\r
174 ; preserves: ebx, [esi], edi
\r
177 jz not_found_in_map
\r
178 call find_map_entry
\r
179 jc not_found_in_map
\r
180 mov dword [eax+MapEntry.name],0
\r
183 iterate_through_map:
\r
186 ; edi - callback function
\r
190 ; ecx = string length
\r
192 mov ecx,[ebx+Map.hash_mask]
\r
195 iterate_through_hash_table:
\r
197 iterate_through_bucket:
\r
200 push ebx ecx edx edi
\r
201 mov eax,[edx+MapEntry.value]
\r
202 mov esi,[edx+MapEntry.name]
\r
203 mov ecx,[edx+MapEntry.name_length]
\r
205 pop edi edx ecx ebx
\r
206 mov edx,[edx+MapEntry.next_entry]
\r
207 jmp iterate_through_bucket
\r
210 loop iterate_through_hash_table
\r
214 ; in: esi - string, ecx = string length, zero for ASCIIZ string
\r
215 ; out: ecx = string length, edx = 32-bit hash
\r
216 ; preserves: ebx, esi, edi
\r
224 loop hash_known_length
\r