Are there alternate implementations of GNU getline interface?

后端 未结 5 1214
醉酒成梦
醉酒成梦 2020-11-28 09:48

The experiment I am currently working uses a software base with a complicated source history and no well defined license. It would be a considerable amount of work to ration

5条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-28 10:01

    The code by Will Hartung suffers from a very serious problem. realloc will most probably free the old block and allocate a new one, but the p pointer within the code will continue to point to the original. This one tries to fix that by using array indexing instead. It also tries to more closely replicate the standard POSIX logic.

    /* The original code is public domain -- Will Hartung 4/9/09 */
    /* Modifications, public domain as well, by Antti Haapala, 11/10/17
       - Switched to getc on 5/23/19 */
    
    #include 
    #include 
    #include 
    #include 
    
    // if typedef doesn't exist (msvc, blah)
    typedef intptr_t ssize_t;
    
    ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
        size_t pos;
        int c;
    
        if (lineptr == NULL || stream == NULL || n == NULL) {
            errno = EINVAL;
            return -1;
        }
    
        c = getc(stream);
        if (c == EOF) {
            return -1;
        }
    
        if (*lineptr == NULL) {
            *lineptr = malloc(128);
            if (*lineptr == NULL) {
                return -1;
            }
            *n = 128;
        }
    
        pos = 0;
        while(c != EOF) {
            if (pos + 1 >= *n) {
                size_t new_size = *n + (*n >> 2);
                if (new_size < 128) {
                    new_size = 128;
                }
                char *new_ptr = realloc(*lineptr, new_size);
                if (new_ptr == NULL) {
                    return -1;
                }
                *n = new_size;
                *lineptr = new_ptr;
            }
    
            ((unsigned char *)(*lineptr))[pos ++] = c;
            if (c == '\n') {
                break;
            }
            c = getc(stream);
        }
    
        (*lineptr)[pos] = '\0';
        return pos;
    }
    

    The performance can be increased for a platform by locking the stream once and using the equivalent of getc_unlocked(3) - but these are not standardized in C; and if you're using the POSIX version, then you probably will have getline(3) already.

提交回复
热议问题