Skip to main content

Lecture Notes: 12 Slice Demo

··2 mins
#include <stdio.h>
#include <sys/stat.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>


typedef struct slice {
    const char* ptr;
    int len;
} slice;

typedef struct scell {
    slice item;
    struct scell* next;
} scell;

slice
to_slice(const char* text)
{
    slice yy;
    yy.ptr = text;
    yy.len = strlen(text);
    return yy;
}

int
sleq(slice aa, slice bb)
{
    if (aa.len != bb.len) {
        return 0;
    }

    for (int ii = 0; ii < aa.len; ++ii) {
        if (aa.ptr[ii] != bb.ptr[ii]) {
            return 0;
        }
    }

    return 1;
}

scell*
scons(slice item, scell* next)
{
    scell* xs = malloc(sizeof(scell));
    xs->item = item;
    xs->next = next;
    return xs;
}

void
sfree(scell* xs)
{
    if (xs) {
        sfree(xs->next);
        free(xs);
    }
}

scell*
reverse1(scell* xs, scell* ys)
{
    if (xs == 0) {
        return ys;
    }

    scell* tmp = xs->next;
    xs->next = ys;
    return reverse1(tmp, xs);
}

scell*
reverse(scell* xs)
{
    return reverse1(xs, 0);
}

void
delete_slice(scell** xsp, slice word)
{
    scell* xs = *xsp;

    if (xs == 0) {
        return;
    }

    if (sleq(xs->item, word)) {
        *xsp = xs->next;
        xs->next = 0;
        sfree(xs);
    }

    delete_slice(&(xs->next), word);
}

void
delete_str(scell** xsp, const char* word)
{
    delete_slice(xsp, to_slice(word));
}

long
file_size(const char* path)
{
    struct stat sb; // stack allocated
    int rv = stat(path, &sb); // out parameter
    assert(rv != -1);
    
    // man stat
    // man 3type stat
    return sb.st_size; // dot field access
}

scell*
split_lines(const char* data, long size)
{
    scell* ys = 0;

    long start = 0;
    for (long ii = 0; ii < size; ++ii) {
        if (data[ii] == '\n') {
            slice sl;
            sl.ptr = data + start;
            sl.len = (int) ii - start;
            ys = scons(sl, ys);
            start = ii + 1;
        }
    }

    return reverse(ys);
}

void
print_words(scell* xs)
{
    for (; xs; xs = xs->next) {
        printf("%.*s\n", xs->item.len, xs->item.ptr);
    }
}

int
main(int argc, char* argv[])
{
    if (argc != 2) {
        fprintf(stderr, "expected input file.\n");
        return 1;
    }

    const char* path = argv[1];
    long sz = file_size(path);

    char* data = malloc(sz);

    FILE* fh = fopen(path, "r");
    assert(fh != 0);
    
    int count = 0;
    while (count < sz) {
        int rv = fread(data + count, 1, sz - count, fh);
        assert(fh != 0);
        count += rv;
    }

    fclose(fh);


    scell* lines = split_lines(data, sz);
    print_words(lines);

    delete_str(&lines, "exhumed");
    delete_str(&lines, "Romanov");
    delete_str(&lines, "teapot's"); // first item

    printf("\n\n");
    print_words(lines);

    sfree(lines);

    free(data);
    return 0;
}