bstrlib.h from Better String LibraryI am maintaining someone's code that looks like this:
FILE *db_fp = NULL;
bstring data = NULL;
db_fp = db_open(DB_FILE, "r");
LOG_CHECK(db_fp == NULL, "Failed to open database: %s", DB_FILE);
data = bread((bNread)fread, db_fp);
LOG_CHECK(data == NULL, "Failed to read from db file: %s", DB_FILE);
db_close(db_fp);
return data;
I am having a little trouble understanding the following line:
data = bread((bNread)fread, db_fp);
What I can guess, is that it is fetching a bstream from the following file pointer and returning a bstring. However, I am wondering about bread and fread.
bread contains 2 arguments, A function pointer (bNread) and the file pointer. But I am not sure I understand how it works.
The declaration for bread() in the Better String Library documentation is:
typedef size_t (*bNread)(void *buff, size_t elsize, size_t nelem, void *parm);
extern bstring bread(bNread readPtr, void *parm);
Therefore, bread() is a function that takes a pointer to a function as an argument. The bNread type is used to specify the type of function. The fread() function is close enough to pass muster when cast — the match isn't exact because it expects a FILE * for its fourth argument and a true function of the type pointed at by a bNread expects a void *. The second argument to bread is the value to be passed as the fourth argument to the function pointed to by the bNread.
So, in the code you're maintaining:
data = bread((bNread)fread, db_fp);
The Better String Library function is called with fread() as the I/O function, cast to the correct type to quell an otherwise justified compiler warning about a mismatch in types, plus the file stream that should be used for reading.
The implementation of the bread() function uses the function pointer and the stream pointer whenever it needs to do I/O in order to read a string. That is, as KerrekB also explained, the code
might write something like:
char buffer[256];
size_t nbytes = (*readPtr)(buffer, sizeof(char), sizeof(buffer), parm);
or (equivalently):
size_t nbytes = readPtr(buffer, sizeof(char), sizeof(buffer), parm);
(If you learned C long enough ago, the first was the only way to invoke functions through pointers to functions; since the C89 standard was produced, the second has been available and is probably used more widely these days.) There are a number of tricks that the implementation must worry about, but the basic function call would be somewhat similar. The code could use I/O functions other than fread(), though the interface to the function must be similar.
Pointers to functions are powerful, but are arcane until you've used them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With