unqlite binary read test is inconsistent

May 20, 2008
463
2
Here are two BTMs, create.btm to create the binary key and read.btm to read it.
Code:
C:\>ver

TCC  23.00.21 x64   Windows 10 [Version 10.0.17134.112]
Code:
CREATE.BTM
@echo off
setlocal
set key=btest

unqlite /db:"test.db" /rwc

set size=%@random[10,100]

REM Handle off by one poke error with @inc
set bhandle=%@balloc[%@inc[%size]]

set result=%@bpokestr[%bhandle,0,a,%@repeat[x,%size]]
unqlite /kvb %key %bhandle %size

set result=%@bfree[%bhandle]

unqlite /c
echo Binary key '%key' created of size %size
Code:
READ.BTM
@echo off
setlocal
set db=test.db
set key=btest

set result=%@unqopen[rwc,%db]

REM Size unknown - let unqreadb expand buffer
set bhandle=%@balloc[1]
set result=%@unqreadb[%db,%key,%bhandle]
set size=%@bsize[%bhandle]
set value=%@bpeekstr[%bhandle,0,a,%size]
set result=%@bfree[%bhandle]
set result=%@unqclose[%db]

echo Binary key '%key' read of size %size
echo Value: %value
The create seems to always work okay. Every once in a while, the read will have the same size. But, usually, the read will either be of a different/larger size with some junk chars at the end or TCC will close. When I put pauses between the steps, it seems the issue may be with bsize, though the handle is valid.
 

rconn

Administrator
Staff member
May 14, 2008
11,931
133
There are a couple of things wrong with this example.

First, don't use @BPEEKSTR to read binary values. For example, it will not work as you expect if there are any embedded nulls in the binary blob. And if you try read 20 bytes from a 10 byte "string", you're going to get 10 bytes of garbage tacked onto the end of the string.

Second, the reason it fails (most of the time) is because of your @balloc. Allocating 1 byte guarantees that not only will the memory buffer have to be reallocated, it will also almost always be moved -- and then your bhandle value is going to be wrong for all subsequent functions.

Dealing with the pointer change is a bit tricky. What I've done for 23.0.22 is check if the pointer changed, then look through the environment for the old value and change it. But that only works if you've saved he @balloc result to an environment variable.

If you had allocated a larger value to @balloc, it probably would have been able to reallocate it (if necessary) without having to move it. If you don't have ANY idea how big the binary record is going to be, just allocate a few K. You've got terabytes of virtual memory; quibbling over 1 byte vs. 16K bytes is utterly irrelevant.
 
May 20, 2008
463
2
It's difficult to know undocumented intentions. The help for @BPEEKSTR says it is to 'Read a string from a binary buffer' and now you say don't. Thanks for adding some clarification here in the forum. I wish more of that were documented in the help. When I work with TCC, I don't default to thinking in C/C++. Maybe I need to change that.