Reputation: 678
I wish to get strings from the buffer of raw bytes in the memory, will work well?
static int in = 0;
void *loadFile (FILE *fp)
{
fseek (fp, 0L, SEEK_END);
size_t size = ftell (fp);
fseek (fp, 0L, SEEK_SET);
char *buf = malloc (sizeof(char) * size);
if (!buf)
return NULL;
if (fread (buf, sizeof(char), size, fp) != size) {
free (buf);
return NULL;
}
return buf;
}
char *getString (void *buf)
{
char *l_buf = buf;
int i, j, num;
char *string = NULL;
for (i = in; l_buf[i] == '\n' || l_buf[i] == '\r'; i++);
for (j = i; l_buf[j] != '\n' && l_buf[j] != '\r'; j++);
num = j - i;
string = malloc (sizeof(char) * (num + 1));
if (!string)
return NULL;
in = j;
strncpy (string, &l_buf[i], num);
string[num] = '\0';
return string;
}
Upvotes: 0
Views: 2119
Reputation: 7477
I believe there is at least one problem with the solution as proposed and that is there is no check to ensure you don't run off the end of the memory buffer in getString(). So one way to avoid this in your read code would be to add an explicit NULL to the end of the buffer like so
char *buf = malloc (sizeof(char) * (size + 1));
if (!buf)
return NULL;
if (fread (buf, sizeof(char), size, fp) != size) {
free (buf);
return NULL;
}
buf[size] = `\0`;
And then in your string extraction function add the a NULL check to the line termination tests, something like this:
for (i = in; l_buf[i] != '\0' && (l_buf[i] == '\n' || l_buf[i] == '\r'); i++);
if (l_buf[i] == '\0') {
/* Never saw the start of a line before the buffer ran out */
return NULL;
}
for (j = i; l_buf[i] != '\0' && l_buf[j] != '\n' && l_buf[j] != '\r'; j++);
if (i == j) {
return NULL;
}
There is another potential problem but as you didn't say whether you were running on UNIX or Windows or cared about portability here I can't be sure. The proposed code doesn't deal with line terminations that include both `\r' and '\n'.
I would also suggest to make the function re-entrant by replacing the global start position index with a parameter like so:
char *getString (void *buf, int *in) { ...
Then just update that pointer in getString() like so:
*in = j;
Upvotes: 1
Reputation: 967
All references to buf[i]
should be l_buf[i]
. buf[i] is indexing from a void pointer (not what you want), but l_buf [i] is indexing from a char pointer.
Upvotes: 1