@@ -212,26 +212,19 @@ native deleteproperty(id = 0, const name[] = "", value = cellmin);
212212 */
213213native bool: existproperty (id = 0 , const name[] = " " , value = cellmin);
214214
215- /* */ native __packpubvar (dest[], const source[], maxlength = sizeof (dest)) = strpack ;
215+ /* */ native __unpackpubvar (dest[], const source[], maxlength = sizeof (dest)) = strunpack ;
216216
217217static stock __findpubvar (const __name[])
218218{
219219 // Scans the AMX header to find a public variable and returns the address of the entry, or `0`
220220 // if there isn't one. Can't use `static` here because we rely on the string being all `\0`s.
221- new __packed [64 char ], __offset = 0 ;
221+ new __unpacked [64 ], __offset = 0 ;
222222 const __cellbytes = cellbits / charbits;
223223 // In 32-bit scripts this is `64`, but in 64-bit scripts it is only `96`. Part of the header
224224 // entry is always 32-bit, regardless of the cell bit width. We need it in bytes.
225225 const __defsize = __cellbytes + 4 ;
226- // Convert the normal input string to a C string, via a packed string. Pack it, then reverse
227- // every individual cell to get the correct final memory layout.
228- __packpubvar (__packed, __name);
229- // All cells have trailing nulls, so this can only be true when all bytes are non-zero because
230- // the top byte is non-zero.
231- while ((__packed[__offset] = swapchars (__packed[__offset])) > (cellmax >>> (charbits - 1 )))
232- {
233- ++ __offset;
234- }
226+ // Ensure the input is unpacked for easier (to code) comparisons.
227+ __unpackpubvar (__unpacked, __name);
235228 new __start, __end;
236229 // Now we start doing assembly magic to dig through the AMX header itself.
237230 // Get the offset from the start of the file to the start of the data segment (DAT).
@@ -258,12 +251,11 @@ static stock __findpubvar(const __name[])
258251 # emit ADD
259252 # emit ADD .C __cellbytes
260253 # emit STOR .S .pri __end
261- // Loop through the
254+ // Loop through the list of public variables and compare their names.
262255 new __s0, __s1, __s2;
263256 // This could be made a binary search, but it would complicate the code a lot, and isn't worth
264- // it given how rare public variables are. In fact, amx_assembly doesn't even bother with
265- // comparing four bytes at once and just loads and compares single characters instead, which is
266- // an option... It would simplify the code even more.
257+ // it given how rare public variables are. I actually wrote a more complex version that could
258+ // compare two packed C strings, but shorter is better here.
267259 while (__start != __end)
268260 {
269261 // Load the pointer.
@@ -278,26 +270,17 @@ static stock __findpubvar(const __name[])
278270 {
279271 # emit LREF .S .pri __s0
280272 # emit STOR .S .pri __s2
281- if (__packed[__s1] == __s2)
282- {
283- __s0 += __cellbytes;
284- ++ __s1;
285- continue ;
286- }
287- // They are different, but this could be because of junk data loaded from after the end
288- // of the pubvar name in the AMX. We need to determine whether the `NULL` comes first.
289- __s1 = __packed[__s1];
290- while (__s1 && (__s1 & 0x FF ) == (__s2 & 0x FF ))
273+ if (__unpacked[__s1] != __s2 & 0x FF )
291274 {
292- __s1 > >>= 8 ;
293- __s2 > >>= 8 ;
275+ break ;
294276 }
295- if (( __s1 & 0x FF ) || (__s2 & 0x FF ) )
277+ if (__unpacked[ __s1] == ' \0 ' )
296278 {
297- break ;
279+ // The end of the string.
280+ return __start - __cellbytes;
298281 }
299- // Enough matches.
300- return __start - __cellbytes ;
282+ ++ __s0;
283+ ++ __s1 ;
301284 }
302285 // This wasn't a match. Try the next one.
303286 __start += __defsize;
0 commit comments