Using bread to return a bstring

c, file-io

Solution

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.

Problem

- gcc 4.7.2 - c89 - `bstrlib.h` from Better String Library I 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.

Original source