I am modifying a parser I've inherited which currently only reads from FILE* via read. It now has the requirement of being able to pull data from char* constants as well so inline text inside C strings can be parsed.
I've looked at providing a simple interface to both in the form of "readers" so you can provide a file reader and a char reader from which the parser can grab characters. For example:
// Inputs
const char *str = "stringToParse";
FILE *f = fopen(...);
// Creating a reader. Each reader stores a function ptr to a destructor
// which closes the file if required and an internal state object.
Reader *r = FileReader(f);
// -or-
Reader *r = CharReader(str);
// Start parsing ---------------------------
// Inside the parser, repeated calls to:
int error = ReadBytes(&buf /* target buf */, &nRead /* n read out */, maxBytes /* max to read */);
// End parsing -----------------------------
CloseReader(&r); // calls destructor, free's state, self
I'd like to keep this really simple. Are there any obvious other ways to achieve this using less infrastructure that I have missed?
Note: I have simplified this considerably from what is there to highlight the programming interface concerns. It actually uses wchar_t internally and a mush of encoding stuff and is a bit of a rat's nest which I will untangle at the same time.
Thanks to everyone who answered. The cleanest answer is to use fmemopen. I've provided a full example below:
#include <stdio.h>
#include <string.h>
void dump(FILE *f) {
char c;
while ((c = fgetc(f)) != EOF)
putchar(c);
}
int main(int argc, char *argv[]) {
/* open string */
const char str[] = "Hello string!\n";
FILE *fstr = fmemopen(&str, strlen(str), "r");
/* open file */
FILE *ffile = fopen("hello.file", "r");
/* dump each to stdout */
dump(ffile);
dump(fstr);
/* clean up */
fclose(ffile);
fclose(fstr);
}