是否有GNU getline接口的替代实现?

dmc*_*kee 11 c licensing getline

我目前正在进行的实验使用的软件库具有复杂的源历史记录,并且没有明确定义的许可证.合理化事物并在固定许可下发布将是一项相当大的工作.

它也打算运行一个随机的unixish平台,只有我们支持的一些libc有GNU getline,但现在代码期望它.

有没有人知道在限制较少的许可下可以重新实现GNUgetline语义?

编辑::我问,因为谷歌没有帮助,我想尽可能避免写一个(这可能是一个有趣的练习,但它不能最好地利用我的时间.)

更具体地说,有问题的界面是:

ssize_t getline (char **lineptr, size_t *n, FILE *stream);
Run Code Online (Sandbox Code Playgroud)

Wil*_*ung 16

我很困惑.

我查看了链接,阅读说明,这是一个很好的实用程序.

但是,你是说你根本无法将此功能重写为规范吗?规范似乎很清楚,

这里:

/* This code is public domain -- Will Hartung 4/9/09 */
#include <stdio.h>
#include <stdlib.h>

size_t getline(char **lineptr, size_t *n, FILE *stream) {
    char *bufptr = NULL;
    char *p = bufptr;
    size_t size;
    int c;

    if (lineptr == NULL) {
        return -1;
    }
    if (stream == NULL) {
        return -1;
    }
    if (n == NULL) {
        return -1;
    }
    bufptr = *lineptr;
    size = *n;

    c = fgetc(stream);
    if (c == EOF) {
        return -1;
    }
    if (bufptr == NULL) {
        bufptr = malloc(128);
        if (bufptr == NULL) {
            return -1;
        }
        size = 128;
    }
    p = bufptr;
    while(c != EOF) {
        if ((p - bufptr) > (size - 1)) {
            size = size + 128;
            bufptr = realloc(bufptr, size);
            if (bufptr == NULL) {
                return -1;
            }
        }
        *p++ = c;
        if (c == '\n') {
            break;
        }
        c = fgetc(stream);
    }

    *p++ = '\0';
    *lineptr = bufptr;
    *n = size;

    return p - bufptr - 1;
}

int main(int argc, char** args) {
    char *buf = NULL; /*malloc(10);*/
    int bufSize = 0; /*10;*/

    printf("%d\n", bufSize);
    int charsRead =  getline(&buf, &bufSize, stdin);

    printf("'%s'", buf);
    printf("%d\n", bufSize);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

15分钟,我10年没写过C. 它稍微破坏了getline契约,因为它只检查lineptr是否为NULL,而不是NULL和n == 0.如果你愿意,可以修复它.(另一个案例对我来说没有多大意义,我猜你可以在这种情况下返回-1.)

将'\n'替换为变量以实现"getdelim".

人们还在写代码吗?

  • 这适用于短字符串,但在重新分配后可能会失败.bufptr可能获得一个新地址,p需要保持相同的相对偏移量.在我的测试中(使用MinGW),realloc可能会使用相同的指针返回几次(如果该位置有足够的内存)或者可能在第一次重新分配时返回一个新地址.新地址可以靠近内存或远离地址,也可以在第一个地址之前和之后.IE它可以使pa随机数.要修复,请输入"offset = p - bufptr;" 在while EOF行下,"p = bufptr + offset;" 在if NULL块之后. (10认同)
  • ***注意@Todd指出,这个'getline`实现是非常破坏的***.***不要在任何地方使用***. (4认同)
  • 你不能在`size_t`中返回-1.如果出现问题,这将失败. (2认同)

Ant*_*ala 7

Will Hartung编写的代码存在一个非常严重的问题。realloc将最有可能释放旧块并分配一个新块,但是p代码中的指针将继续指向原始块。这个试图通过使用数组索引来解决这个问题。它还尝试更紧密地复制标准POSIX逻辑。

/* 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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdint.h>

// 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;
}
Run Code Online (Sandbox Code Playgroud)

可以通过一次锁定流并使用-的等效项来提高平台的性能getc_unlocked(3)-但这些未在C中标准化;如果您使用的是POSIX版本,那么您可能已经拥有getline(3)了。

  • @user 在 *Windows* 你可以使用 [_lock_file](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/lock-file?view=vs-2019) 和 [_getc_nolock ](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getc-nolock-getwc-nolock?view=vs-2019) (2认同)

Geo*_*ler 5

使用 NetBSD 的这些可移植版本:getdelim()getline()

这些来自 pkgsrc 中的 libnbcompat,并且在每个文件的顶部都有一个 BSD 许可证。您需要两者,因为 getline() 调用 getdelim()。获取两个文件的最新版本。请参阅每个文件顶部的 BSD 许可证。修改文件以适合您的程序:您可能需要在其中一个头文件中声明 getline() 和 getdelim(),并修改这两个文件以包含您的头而不是 nbcompat 头。

这个版本的 getdelim() 是可移植的,因为它调用了 fgetc()。相比之下,来自 libc(如 BSD libc 或 musl libc)的 getdelim() 可能会使用该 libc 的私有特性,因此它无法跨平台工作。

POSIX 2008 指定 getline() 之后的几年里,更多的 Unixish 平台添加了 getline() 函数。getline() 很少丢失,但它仍然可以在旧平台上发生。一些人尝试在旧平台(如 PowerPC Mac OS X)上引导 NetBSD pkgsrc,因此他们希望 libnbcompat 提供缺少的 POSIX 函数,如 getline()。