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

发布于 2024-07-16 15:11:34 字数 511 浏览 5 评论 0原文

我目前正在进行的实验使用的软件基础具有复杂的源历史记录并且没有明确定义的许可证。 合理化事情并在固定许可证下发布将需要大量的工作。

它还旨在运行一个随机的 unixish 平台,并且只有我们支持的一些 libc 具有 GNU getline,但现在代码期望它。

有谁知道 GNU getline 的重新实现 语义可以在限制较少的许可下使用吗?

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

更具体地说,有问题的接口是:

ssize_t getline (char **lineptr, size_t *n, FILE *stream);

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 rationalize things and release under a fixed license.

It is also intended to run a a random unixish platform, and only some of the libc's we support have GNU getline, but right now the code expects it.

Does anyone know of a re-implementation of the GNU getline semantics that is available under a less restrictive license?

Edit:: I ask because Google didn't help, and I'd like to avoid writing one if possible (it might be a fun exercise, but it can't be the best use of my time.)

To be more specific, the interface in question is:

ssize_t getline (char **lineptr, size_t *n, FILE *stream);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

多像笑话 2024-07-23 15:11:35

使用 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()。

Use these portable versions from NetBSD: getdelim() and getline()

These come from libnbcompat in pkgsrc, and have a BSD license at the top of each file. You need both because getline() calls getdelim(). Fetch the latest versions of both files. See the BSD license at the top of each file. Modify the files to fit into your program: you might need to declare getline() and getdelim() in one of your header files, and modify both files to include your header instead of the nbcompat headers.

This version of getdelim() is portable because it calls fgetc(). For contrast, a getdelim() from a libc (like BSD libc or musl libc) would probably use private features of that libc, so it would not work across platforms.

In the years since POSIX 2008 specified getline(), more Unixish platforms have added the getline() function. It is rare that getline() is missing, but it can still happen on old platforms. A few people try to bootstrap NetBSD pkgsrc on old platforms (like PowerPC Mac OS X), so they want libnbcompat to provide missing POSIX functions like getline().

无声情话 2024-07-23 15:11:35

如果您正在为 BSD 进行编译,请使用 fgetln
反而

If you are compiling for BSD use fgetln
instead

活泼老夫 2024-07-23 15:11:35

尝试使用 fgets() 而不是 getline()。 我在 Linux 中使用 getline(),它运行良好,直到我迁移到 Windows。 Visual Studio 无法识别 getline()。 因此,我将字符指针替换为字符,将 EOF 替换为 NULL。 见下图:

#define CHARCOUNT 1000

之前:

char *line = (char*) malloc(CHARCOUNT);
size_t size;
FILE *fp = fopen(file, "r");
while(getline(&line, &size, fp) != -1) {
   ...
}
free(line);

之后:

char line[CHARCOUNT];
while(fgets(line, CHARCOUNT, fp) != NULL) {
   ...
}

Try using fgets() instead of getline(). I was using getline() in Linux and it was working well until I migrated to Windows. The Visual studio did not recognize getline(). So, I replace the character pointer with character, and EOF with NULL. See below:

#define CHARCOUNT 1000

Before:

char *line = (char*) malloc(CHARCOUNT);
size_t size;
FILE *fp = fopen(file, "r");
while(getline(&line, &size, fp) != -1) {
   ...
}
free(line);

After:

char line[CHARCOUNT];
while(fgets(line, CHARCOUNT, fp) != NULL) {
   ...
}
意中人 2024-07-23 15:11:35

这里没有错误的更好答案:

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 = bufptr + (size - 128);
            }
            *p++ = c;
            if (c == '\n')
            {
                break;
            }
            c = fgetc(stream);
        }
    
        *p++ = '\0';
        *lineptr = bufptr;
        *n = size;
    
        return p - bufptr - 1;
    }

Better Answer with no Bug Here:

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 = bufptr + (size - 128);
            }
            *p++ = c;
            if (c == '\n')
            {
                break;
            }
            c = fgetc(stream);
        }
    
        *p++ = '\0';
        *lineptr = bufptr;
        *n = size;
    
        return p - bufptr - 1;
    }
吲‖鸣 2024-07-23 15:11:34

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;
}

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

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 <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;
}

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.

魔法少女 2024-07-23 15:11:34

我很困惑。

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

但是,您是说您根本无法将此函数重写为规范吗? 规范看起来很清楚,

这里:

/* 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;
}

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

将 '\n' 替换为变量以实现“getdelim”。

人们还写代码吗?

I'm puzzled.

I looked at the link, read the description, and this is a fine utility.

But, are you saying you simply can't rewrite this function to spec? The spec seems quite clear,

Here:

/* 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;
}

15 minutes, and I haven't written C in 10 years. It minorly breaks the getline contract in that it only checks if the lineptr is NULL, rather than NULL and n == 0. You can fix that if you like. (The other case didn't make a whole lot of sense to me, I guess you could return -1 in that case.)

Replace the '\n' with a variable to implement "getdelim".

Do people still write code any more?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文