Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert function to read from string instead of file in C

Tags:

c

scanf

I've been tasked with updating a function which currently reads in a configuration file from disk and populates a structure:

static int LoadFromFile(FILE *Stream, ConfigStructure *cs)
{
  int tempInt;

   ...

  if ( fscanf( Stream, "Version: %d\n",&tempInt) != 1 )
  {
    printf("Unable to read version number\n");
    return 0;
  }
  cs->Version = tempInt;
   ...

}

to one which allows us to bypass writing the configuration to disk and instead pass it directly in memory, roughly equivalent to this:

static int LoadFromString(char *Stream, ConfigStructure *cs)

A few things to note:

  • The current LoadFromFile function is incredibly dense and complex, reading dozens of versions of the config file in a backward compatible manner, which makes duplication of the overall logic quite a pain.
  • The functions that generate the config file and those that read it originate in totally different parts of the old system and therefore don't share any data structures so I can't pass those directly. I could potentially write a wrapper, but again, it would need to handle any structure passed in in a backwards compatible manner.
  • I'm tempted to just pass the file as is in as a string (as in the prototype above) and convert all the fscanf's to sscanf's but then I have to handle incrementing the pointer along (and potentially dealing with buffer overrun errors) manually.
  • This has to remain in C, so no C++ functionality like streams can help here

Am I missing a better option? Is there some way to create a FILE * that actually just points to a location in memory instead of on disk? Any pointers, suggestions or other help is greatly appreciated.

like image 453
Dusty Avatar asked Oct 24 '25 04:10

Dusty


1 Answers

If you can't pass structures and must pass the data as a string, then you should be able to tweak your function to read from a string instead of a file. If the function is as complicated as you describe, then converting fscanf->sscanf would possibly be the most straightforward way to go.

Here's an idea using your function prototype above. Read in the entire data string (without processing any of it) and store it in a local buffer. That way the code can have random access to the data as it can with a file and making buffer overruns easier to predict and avoid. Start by mallocing a reasonably-sized buffer, copy data into it, and realloc yourself more space as needed. Once you have a local copy of the entire data buffer, scan through it and extract whatever data you need.

Note that this might get tricky if '\0' characters are valid input. In that case, you would have to add additional logic to test if this was the end of the input string or just a zero byte (difficulty depending on the particular format of your data buffer).

like image 119
bta Avatar answered Oct 26 '25 18:10

bta



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!