Skip to content

Instantly share code, notes, and snippets.

@ibeauregard
Last active March 27, 2021 18:14
Show Gist options
  • Save ibeauregard/58b4032a6fbe576f3c955a2f0e015731 to your computer and use it in GitHub Desktop.
Save ibeauregard/58b4032a6fbe576f3c955a2f0e015731 to your computer and use it in GitHub Desktop.
readline (from a stream)
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#define READLINE_READ_SIZE 512
#define NEWLINE '\n'
typedef struct {
ushort offset;
ushort length;
char array[BUFSIZ];
} ReadBuffer;
ushort fill(ReadBuffer* buffer, int fd);
void reset_index(ReadBuffer* buffer);
ushort newline_index(ReadBuffer* buffer, int fd);
ushort scan_until_newline(const ReadBuffer* buffer, ushort i);
void add_newline(ReadBuffer* buffer, ushort i);
char* pop(ReadBuffer* buffer, ushort n);
void offset(ReadBuffer* buffer, ushort n);
char* my_readline(int fd)
{
static ReadBuffer buffer = {
.offset = 0,
.length = 0,
.array = {0}
};
if (!buffer.length && !fill(&buffer, fd))
{
return NULL;
}
return pop(&buffer, newline_index(&buffer, fd));
}
ushort fill(ReadBuffer* buffer, int fd)
{
reset_index(buffer);
ushort chars_read = read(fd, &buffer->array[buffer->length], READLINE_READ_SIZE);
if (chars_read == 0) return 0;
buffer->length += chars_read;
buffer->array[buffer->length] = 0;
return chars_read;
}
void reset_index(ReadBuffer* buffer)
{
ushort i;
for (i = 0; i < buffer->length; i++)
{
buffer->array[i] = buffer->array[i + buffer->offset];
}
buffer->offset = 0;
}
ushort newline_index(ReadBuffer* buffer, int fd)
{
ushort i = scan_until_newline(buffer, 0);
char last = buffer->array[buffer->offset + i];
while (last != NEWLINE)
{
if (!fill(buffer, fd))
{
add_newline(buffer, i);
break;
}
i = scan_until_newline(buffer, i);
last = buffer->array[buffer->offset + i];
}
return i;
}
ushort scan_until_newline(const ReadBuffer* buffer, ushort i)
{
const char* startingPoint = &buffer->array[buffer->offset];
for (; i < buffer->length && startingPoint[i] != NEWLINE; i++);
return i;
}
void add_newline(ReadBuffer* buffer, ushort i)
{
buffer->array[buffer->offset + i] = NEWLINE;
buffer->length++;
}
char* pop(ReadBuffer* buffer, ushort n)
{
char* line = malloc(n + 1);
const char* bufferArray = &buffer->array[buffer->offset];
ushort i;
for (i = 0; i < n; i++)
{
line[i] = bufferArray[i];
}
line[i] = 0;
offset(buffer, n + 1);
return line;
}
void offset(ReadBuffer* buffer, ushort n)
{
buffer->offset += n;
buffer->length -= n;
}
int main()
{
char* str;
int fd = open("file.txt", O_RDONLY);
while ((str = my_readline(fd)))
{
printf("%s\n", str);
free(str);
}
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment