Skip to content

Commit

Permalink
new memstream filehandle type
Browse files Browse the repository at this point in the history
  • Loading branch information
billhails committed Nov 9, 2024
1 parent 7343723 commit 9240c25
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 23 deletions.
3 changes: 3 additions & 0 deletions docs/generated/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ Support for declaring builtins

```mermaid
flowchart TD
BuiltInMemBufHash --entries--> entries
BuiltIn --name--> HashSymbol
BuiltIn --result--> TcType
BuiltIn --args--> BuiltInArgs
BuiltIn --implementation--> void_ptr
BuiltInImplementation --implementation--> void_ptr
BuiltInImplementation --nargs--> int
BuiltInMemBuf --buffer--> string
BuiltInMemBuf --size--> size
BuiltInArgs["BuiltInArgs[]"] --entries--> TcType
BuiltIns["BuiltIns[]"] --entries--> BuiltIn
```
Expand Down
24 changes: 24 additions & 0 deletions fn/ioutils.fn
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,27 @@ fn with_input_from(filename, handler) {
}
}
}

fn with_buffer(handler) {
switch (openmem()) {
(success(filehandle)) {
let data = some(handler(filehandle));
in
close(filehandle);
data;
}
(failure(errmsg)) {
print(errmsg);
nothing;
}
}
}

fn to_string(data) {
unsafe switch (with_buffer(fn (buf) {
fputv(buf, data);
fgets(buf);
})) {
(some(result)) { result }
}
}
86 changes: 77 additions & 9 deletions src/builtin_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ static void registerGets(BuiltIns *registry);
static void registerFGets(BuiltIns *registry);

static void registerOpen(BuiltIns *registry);
static void registerOpenMemstream(BuiltIns *registry);
static void registerClose(BuiltIns *registry);

static void registerOpenDir(BuiltIns *registry);
Expand All @@ -62,6 +63,21 @@ static void registerCloseDir(BuiltIns *registry);

static void registerFType(BuiltIns *registry);

static BuiltInMemBufHash *memBufs = NULL;

void markMemBufs() {
if (memBufs != NULL) {
markHashTable((HashTable *) memBufs);
}
}

static BuiltInMemBufHash *getMemBufs(void) {
if (memBufs == NULL) {
memBufs = newBuiltInMemBufHash();
}
return memBufs;
}

void registerIO(BuiltIns *registry) {
registerPutc(registry);
registerFPutc(registry);
Expand All @@ -76,6 +92,7 @@ void registerIO(BuiltIns *registry) {
registerGets(registry);
registerFGets(registry);
registerOpen(registry);
registerOpenMemstream(registry);
registerClose(registry);
registerOpenDir(registry);
registerReadDir(registry);
Expand Down Expand Up @@ -157,12 +174,25 @@ static Value builtin_puts(Vec *args) {
#define IO_MODE_WRITE 1
#define IO_MODE_APPEND 2

static HashSymbol *fileHandleToKey(FILE *file) {
static char buf[128];
sprintf(buf, "%p", file);
return newSymbol(buf);
}

static void opaque_io_close(Opaque *data) {
if (data == NULL) return;
if (data->data == NULL) return;
DEBUG("closing io %p", data->data);
fclose(data->data);
HashSymbol *key = fileHandleToKey(data->data);
BuiltInMemBuf *memBuf = NULL;
if (getBuiltInMemBufHash(getMemBufs(), key, &memBuf)) {
if (memBuf->buffer != NULL) {
free(memBuf->buffer);
memBuf->buffer = NULL;
}
}
data->data = NULL;
}

Expand Down Expand Up @@ -204,6 +234,21 @@ static Value builtin_open(Vec *args) {
return result;
}

static Value builtin_open_memstream(Vec *args __attribute__((unused))) {
BuiltInMemBuf *memBuf = newBuiltInMemBuf();
int save = PROTECT(memBuf);
FILE *file = open_memstream(&memBuf->buffer, &memBuf->size);
BuiltInMemBufHash *memBufs = getMemBufs();
HashSymbol *key = fileHandleToKey(file);
setBuiltInMemBufHash(memBufs, key, memBuf);
Opaque *wrapper = newOpaque(file, opaque_io_close, NULL);
Value opaque = value_Opaque(wrapper);
protectValue(opaque);
Value result = makeTryResult(1, opaque);
UNPROTECT(save);
return result;
}

static Value builtin_opendir(Vec *args) {
char *dirname = listToUtf8(args->entries[0]);
DIR *dir = opendir(dirname);
Expand Down Expand Up @@ -364,7 +409,7 @@ void fputValue(FILE *fh, Value x) {
fputVec(fh, x.val.vec);
break;
default:
cant_happen("unrecognised value type in fputValue");
cant_happen("unrecognised value type %s", valueTypeName(x.type));
}
}

Expand All @@ -390,13 +435,24 @@ void putVec(Vec *x) {
static Value private_fgets(FILE *fh) {
ByteArray *bytes = newByteArray();
int save = PROTECT(bytes);
int c;
while ((c = fgetc(fh)) != EOF) {
if (c == '\n') break;
if (c == 0) break;
pushByteArray(bytes, (Byte) c);
HashSymbol *key = fileHandleToKey(fh);
BuiltInMemBuf *buf = NULL;
if (getBuiltInMemBufHash(getMemBufs(), key, &buf)) {
fflush(fh);
if (buf->buffer == NULL) {
cant_happen("fgets on null memstream");
}
char *b = buf->buffer;
do { pushByteArray(bytes, (Byte) *b); } while (*(b++));
} else {
int c;
while ((c = fgetc(fh)) != EOF) {
if (c == '\n') break;
if (c == 0) break;
pushByteArray(bytes, (Byte) c);
}
pushByteArray(bytes, 0);
}
pushByteArray(bytes, 0);
Value string = utf8ToList((char *) bytes->entries);
UNPROTECT(save);
return string;
Expand Down Expand Up @@ -441,8 +497,8 @@ static Value builtin_fputv(Vec *args) {
if (data == NULL || data->data == NULL) {
cant_happen("fput on closed file handle");
}
fputValue((FILE *) data->data, args->entries[0]);
return args->entries[0];
fputValue((FILE *) data->data, args->entries[1]);
return args->entries[1];
}

static TcType *pushFileArg(BuiltInArgs *args) {
Expand Down Expand Up @@ -572,6 +628,18 @@ static void registerOpen(BuiltIns *registry) {
UNPROTECT(save);
}

// try(string, opaque(file))
static void registerOpenMemstream(BuiltIns *registry) {
BuiltInArgs *args = newBuiltInArgs();
int save = PROTECT(args);
TcType *stringType = makeStringType();
PROTECT(stringType);
TcType *tryFileType = makeTryFileType(stringType);
PROTECT(tryFileType);
pushNewBuiltIn(registry, "openmem", tryFileType, args, (void *)builtin_open_memstream);
UNPROTECT(save);
}

// string -> try(string, opaque(dir))
static void registerOpenDir(BuiltIns *registry) {
BuiltInArgs *args = newBuiltInArgs();
Expand Down
1 change: 1 addition & 0 deletions src/builtin_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# include <stdio.h>
# include "builtins.h"

void markMemBufs(void);
void registerIO(BuiltIns *registry);
void putValue(Value x);
void fputValue(FILE *fh, Value x);
Expand Down
8 changes: 8 additions & 0 deletions src/builtins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ structs:
implementation: void_ptr
nargs: int

BuiltInMemBuf:
buffer: string=NULL
size: size=0

hashes:
BuiltInMemBufHash:
entries: BuiltInMemBuf

arrays:
BuiltInArgs:
dimension: 1
Expand Down
2 changes: 2 additions & 0 deletions src/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "symbol.h"
#include "arithmetic.h"
#include "opaque.h"
#include "builtin_io.h"

static int bytesAllocated = 0;
static int nextGC = 0;
Expand Down Expand Up @@ -381,6 +382,7 @@ static void mark() {
markProtected();
markArithmetic();
markNamespaces();
markMemBufs();
#ifdef DEBUG_LOG_GC
eprintf("starting markVarTable\n");
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/primitives.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,7 @@ file:
printf: "%p"
valued: true

size:
cname: size_t
printf: "%zu"
valued: true
14 changes: 0 additions & 14 deletions tests/fn/test_hygiene.fn

This file was deleted.

4 changes: 4 additions & 0 deletions tests/fn/test_tostring.fn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
let
link "ioutils.fn" as io;
in
assert(io.to_string(1234 + 5i) == "(1234+5i)")

0 comments on commit 9240c25

Please sign in to comment.