Skip to content

Instantly share code, notes, and snippets.

@chmike
Last active February 26, 2020 15:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chmike/eb436c661754fd5c7b69a5248354354a to your computer and use it in GitHub Desktop.
Save chmike/eb436c661754fd5c7b69a5248354354a to your computer and use it in GitHub Desktop.
getline using fd
// getlinefd reads a full line from fd into *lineptr. Initialize *lineptr to NULL and *n to 0.
// getlinefd will store the line into *lineptr which is is a buffer that will grow as needed.
// The buffer size is stored in *n. The line ends '\0' and with a '\n'when present.
// getlinefd returns the number of characters read, or -1 in case of error or if the end of file is reached.
ssize_t getlinefd(char **lineptr, size_t *n, int fd) {
static char buf[10];
static size_t len = 0;
const size_t blen = sizeof(buf);
if (lineptr == NULL || n == NULL) {
errno = EINVAL;
return -1;
}
if (*lineptr == NULL)
len = 0;
for (size_t i = 0; i < len; i++) {
if (buf[i] == '\n') {
i++;
if (i+1 > *n)
*lineptr = realloc(*lineptr, *n = i+1);
strncpy(*lineptr, buf, i);
(*lineptr)[i] = '\0';
len = blen-i;
memmove(buf, buf+i, len);
return i;
}
}
size_t l = 0;
while (1) {
ssize_t r = read(fd, buf+len, blen-len);
if (r < 0)
return -1;
len += r;
if (len == 0) {
if (l != 0) {
(*lineptr)[l] = '\0';
return l;
}
if (*lineptr != NULL)
(*lineptr)[0] = '\0';
return -1;
}
for (size_t i = 0; i < len; i++) {
if (buf[i] == '\n') {
i++;
if (l+i+1 > *n)
*lineptr = realloc(*lineptr, *n = l+i+1);
strncpy(*lineptr+l, buf, i);
l += i;
(*lineptr)[l] = '\0';
len = blen-i;
memmove(buf, buf+i, len);
return l;
}
}
if (l+len+1 > *n)
*lineptr = realloc(*lineptr, *n = l+len+1);
strncpy(*lineptr+l, buf, len);
l += len;
len = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment