954,479 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?

_getdelim() for MS-Windows compilers

By Melvin on Jan 23rd, 2010 1:23 pm

The idea for this came from another thread in the C++ forum that wanted to duplicate the _getdelim() function that is supported by GNU compilers g++. I made one major change in that this version does not allocate new memory every time it is called, which is grossly inefficient. Instead, this function only allocates new memory if the pointer to pointer passed to _getdelim() is NULL. If not NULL then it assumes the calling program has allocated the memory. The function might expand the size of the line buffer if the number of characters read exceeds the length of the line buffer.

I also removed the goto statements that are in the original GNU function and the ancient K&R style function parameter declarations.

This code snippet uses only standard C functions -- nothing compiler-specific, so it most likely will compile with any 32-bit or 64-bit compiler.

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#pragma warning(disable: 4996)

/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
  (and null-terminate it). *LINEPTR is a pointer returned from malloc (or
   NULL), pointing to *N characters of space.  It is realloc'd as
   necessary.  Returns the number of characters read (not including the
   null terminator), or -1 on error or EOF.  */
static __inline void __set_errno(unsigned int no)
{
    errno = no;
}

size_t __getdelim (char** lineptr, size_t* n, int terminator,FILE* stream)
{
    const size_t BLOCKSIZE = 255;
    int c;
    size_t len = 0;
    size_t linesize = 0;
    int newalloc = 0;
    if( lineptr == NULL || stream == NULL || n == NULL)
    {
        _set_errno(EINVAL);
        return -1;
    }
    linesize = BLOCKSIZE;
    if( *lineptr == NULL)
    {
        // allocate new memory if required
        *lineptr = malloc(BLOCKSIZE);
        *n = BLOCKSIZE;
        newalloc = 1;
    }
    else
        linesize = *n;
    while( (c = fgetc(stream)) != EOF && c != terminator)
    {
        // make sure we have enough room for the new character
        // If not, then streatch it out a bit.
        if( (len+1) == linesize)
        {
            linesize += BLOCKSIZE;
            *n = linesize;
            *lineptr = realloc(*lineptr, linesize);
        }
        (*lineptr)[len++] = c;
    }
    if( len == 0 && c != terminator) // check for blank lines
    {
        _set_errno(EINVAL);
        if( newalloc )
        {
            free(*lineptr);
            *lineptr = NULL;
        }
        else
            (*lineptr)[0] = 0; // truncate the string
        return -1;
    }
    (*lineptr)[len] = 0; // null-terminate the string
       
    return len;
}

int main()
{
    unsigned int n = 255;
    char* lineptr = malloc(n);
    FILE* fp = fopen("test3.c", "r");
    if( fp != NULL)
    {
        while(__getdelim(&lineptr, &n, '\n', fp) != -1 )
        {
            printf("%s\n", lineptr);
        }
        free(lineptr);
        lineptr = NULL;
        fclose(fp);
    }

}

:icon_eek: There are no checks against failed memory allocations.

mitrmkar
Posting Virtuoso
1,809 posts since Nov 2007
Reputation Points: 1,105
Solved Threads: 395
 

I might suggest removing the leading underscores -- that's the implementor's namespace.

Dave Sinkula
long time no c
Team Colleague
5,058 posts since Apr 2004
Reputation Points: 2,780
Solved Threads: 314
 

>>There are no checks against failed memory allocations.
Because its not really necessary on today's computers with lots and lots of memory, unless of course memory has been corrupt. I haven't seen malloc() return NULL since the days of 16-bit MS-DOS or Win95. If the computer doesn't have enough memory for malloc() then there are many many more problems to worry about.

>>I might suggest removing the leading underscores -- that's the implementor's namespace.

Agree -- its also a common way to indicate that a function is part of a library (*.lib or *.a)

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: