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);
getline is a POSIX function, and Windows isn't POSIX, so it doesn't have some POSIX C functions available. You'll need to roll your own. Or use one that has already been written.
First, getline() is not in the C standard library, but is a POSIX 2008 extension. Normally, it will be available with a POSIX-compatible compiler, as the macros _POSIX_C_SOURCE will be defined with the appropriate values.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With