patterncMinor
NULL-eating / elimination version of fgets() in C
Viewed 0 times
versionnullfgetseliminationeating
Problem
I've come up with the following routine to read data from a file stream, but I don't want any
It might of importance to note that this code is called by a Kernel driver, and MUST be fast. Speed is totally of the essence here, which is why this is all in one function, and uses calls like
NULLs in the stream to terminate the string early. This function will read in a "line", and allow it to be processed with normal C string functions. Does anyone see any inherent problems or potential bugs in this routine?char *my_fgets(char *Buf, int iMaxCount, FILE *fp)
{
// Handle basic failures.
if(!Buf) return NULL;
if(iMaxCount Buf) && *(p-1) != 0x0a && *p != NULL) *(--p) = 0x00;
// Free our work buffer, and return the new 'clean' data.
free(lbuf);
return Buf;
}It might of importance to note that this code is called by a Kernel driver, and MUST be fast. Speed is totally of the essence here, which is why this is all in one function, and uses calls like
fread() over fgets() to get a chunk of data in one shot. That might not matter in the final analysis, but I thought I would mention it.Solution
There's absolutely no need for an intermediate (dynamic) buffer. Everything you do can be done directly in the client buffer (
I don't see a reason for
The way you remove null chars is suboptimal. I'd keep count of null chars encountered, and shift non-null chars by that count, in a single loop. In any case, I'd factor removal code into a separate function (No Raw Loops rule strikes again).
Looking for a newline is better be done with a standard
That said, the main code condenses to
Buf).I don't see a reason for
fread-ing data. fgets works as good, and spares you from calling ftell and fseek.The way you remove null chars is suboptimal. I'd keep count of null chars encountered, and shift non-null chars by that count, in a single loop. In any case, I'd factor removal code into a separate function (No Raw Loops rule strikes again).
Looking for a newline is better be done with a standard
memchr().That said, the main code condenses to
char * fgets_and_remove_nulls(char * buf, size_t count, FILE * fp)
{
memset(buf, 0, size);
if(fgets(buf, size, fp) == NULL) return NULL;
char * end = memchr(buf, '\n', size);
if (end == NULL) end = buf + size;
remove_null_chars(buf, end);
return buf;
}Code Snippets
char * fgets_and_remove_nulls(char * buf, size_t count, FILE * fp)
{
memset(buf, 0, size);
if(fgets(buf, size, fp) == NULL) return NULL;
char * end = memchr(buf, '\n', size);
if (end == NULL) end = buf + size;
remove_null_chars(buf, end);
return buf;
}Context
StackExchange Code Review Q#61392, answer score: 3
Revisions (0)
No revisions yet.