Skip to content

Commit

Permalink
Implemented simple (read-only) (ungetc-able) string-stream
Browse files Browse the repository at this point in the history
Refactored the stream interface and implemented a simple
stringstream. Now have working filestream and stringstream. Next up is
make eval read "(repl)" from stringstream.
  • Loading branch information
jbf committed Sep 13, 2011
1 parent 190df1c commit 7320e6f
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -23,3 +23,4 @@ TAGS
/src/vm/cpp_vm.d
/src/vm/test/test_context.d
/tlisp
/test/test_stringstream
33 changes: 33 additions & 0 deletions src/ast-walker/filestream.c
@@ -0,0 +1,33 @@
#include "filestream.h"

int filestream_getc(STREAM *stream);
int filestream_ungetc(int ch, STREAM *stream);
int filestream_flush(STREAM *stream);
int filestream_close(STREAM *stream);

int make_filestream(STREAM *stream, FILE *f) {
stream->payload = f;
stream->fgetc_fun = filestream_getc;
stream->ungetc_fun = filestream_ungetc;
stream->flush_fun = filestream_flush;
stream->close_fun = filestream_close;
return 1;
}

int filestream_getc(STREAM *stream) {
return fgetc((FILE *)stream->payload);
}

int filestream_ungetc(int ch, STREAM *stream) {
return ungetc(ch, (FILE *)stream->payload);
}

int filestream_flush(STREAM *stream) {
return fflush((FILE *)stream->payload);
}

int filestream_close(STREAM *stream) {
FILE *f = (FILE *)stream->payload;
stream->payload = NULL;
return fclose(f);
}
9 changes: 9 additions & 0 deletions src/ast-walker/filestream.h
@@ -0,0 +1,9 @@
#ifndef _FILESTREAM_H
#define _FILESTREAM_H 1

#include <stdio.h>
#include "t_stream.h"

int make_filestream(STREAM *stream, FILE *f);

#endif /* _FILESTREAM_H */
5 changes: 5 additions & 0 deletions src/ast-walker/memory.c
Expand Up @@ -33,6 +33,11 @@ void *malloc_or_bail(size_t bytes) {
return tmp;
}

/* Off-heap free. */
void free_malloced(void *ptr) {
free(ptr);
}

/* On-heap malloc that only returns if it succeeds */
void *mem_sys_safe_alloc(size_t bytes) {
void *t;
Expand Down
1 change: 1 addition & 0 deletions src/ast-walker/memory.h
Expand Up @@ -5,6 +5,7 @@

void *mem_sys_safe_alloc(size_t bytes);
void *malloc_or_bail(size_t bytes);
void free_malloced(void *ptr);
void *u8_new(size_t bytes);

#define new(type) ((type *)mem_sys_safe_alloc(sizeof(type)/sizeof(char)))
Expand Down
71 changes: 71 additions & 0 deletions src/ast-walker/stringstream.c
@@ -0,0 +1,71 @@
#include "stringstream.h"

#include <string.h>
#include <stdio.h>

#include "memory.h"

int stringstream_getc(STREAM *stream);
int stringstream_ungetc(int ch, STREAM *stream);
int stringstream_flush(STREAM *stream);
int stringstream_close(STREAM *stream);

typedef struct string_info {
char *str;
size_t len;
size_t index;
} string_info;

int make_stringstream(STREAM *stream, const char *str, size_t size) {
char *target;
string_info *s = new_malloc(string_info);

/* This will at most trigger a read overflow + pagefault. Sweet */
if(strlen(str) >= size) { /* str + '\0' must fit in size */
memset(stream, 0, sizeof(STREAM)/sizeof(char));
return 0;
} else if (size < 1) {
memset(stream, 0, sizeof(STREAM)/sizeof(char));
return 0;
}

target = malloc_or_bail(size);
strcpy(target, str); // we got here, len(target) >= len(str + 1)
s->len = size-1;
s->index = 0;
s->str = target;

stream->payload = s;

stream->fgetc_fun = stringstream_getc;
stream->ungetc_fun = stringstream_ungetc;
stream->flush_fun = stringstream_flush;
stream->close_fun = stringstream_close;
return 1;
}

int stringstream_getc(STREAM *stream) {
string_info *s = (string_info *)stream->payload;
if (s->index >= s->len)
return EOF;
return (int)((unsigned char)*(s->str + s->index++));
}

int stringstream_ungetc(int ch, STREAM *stream) {
string_info *s = (string_info *)stream->payload;
if (s->index <= 0)
return EOF;

*(s->str + --(s->index)) = (char)ch;
return ch;
}

int stringstream_flush(STREAM *stream) {
return 1;
}

int stringstream_close(STREAM *stream) {
free_malloced(((string_info *)stream->payload)->str);
free_malloced(stream->payload);
return 1;
}
10 changes: 10 additions & 0 deletions src/ast-walker/stringstream.h
@@ -0,0 +1,10 @@
#ifndef _STRINGSTREAM_H
#define _STRINGSTREAM_H 1

#include <stdlib.h>

#include "t_stream.h"

int make_stringstream(STREAM *stream, const char *str, size_t size);

#endif /* _STRINGSTREAM_H */
31 changes: 0 additions & 31 deletions src/ast-walker/t_stream.c
@@ -1,9 +1,5 @@
#include "t_stream.h"

int filestream_getc(STREAM *stream);
int filestream_ungetc(int ch, STREAM *stream);
int filestream_flush(STREAM *stream);
int filestream_close(STREAM *stream);

int stream_getc(STREAM *stream) {
return (stream->fgetc_fun)(stream);
Expand All @@ -20,30 +16,3 @@ int stream_flush(STREAM *stream) {
int stream_close(STREAM *stream) {
return (stream->close_fun)(stream);
}

STREAM *make_filestream(STREAM *stream, FILE *f) {
stream->payload = f;
stream->fgetc_fun = filestream_getc;
stream->ungetc_fun = filestream_ungetc;
stream->flush_fun = filestream_flush;
stream->close_fun = filestream_close;
return stream;
}

int filestream_getc(STREAM *stream) {
return fgetc((FILE *)stream->payload);
}

int filestream_ungetc(int ch, STREAM *stream) {
return ungetc(ch, (FILE *)stream->payload);
}

int filestream_flush(STREAM *stream) {
return fflush((FILE *)stream->payload);
}

int filestream_close(STREAM *stream) {
FILE *f = (FILE *)stream->payload;
stream->payload = NULL;
return fclose(f);
}
3 changes: 0 additions & 3 deletions src/ast-walker/t_stream.h
Expand Up @@ -14,7 +14,4 @@ int stream_ungetc(int ch, STREAM *stream);
int stream_flush(STREAM *stream);
int stream_close(STREAM *stream);

#include <stdio.h>
STREAM *make_filestream(STREAM *stream, FILE *f);

#endif /* _T_STREAM_H */
1 change: 1 addition & 0 deletions src/ast-walker/token.c
Expand Up @@ -5,6 +5,7 @@
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "errors.h"

Expand Down
47 changes: 47 additions & 0 deletions test/test_stringstream.c
@@ -0,0 +1,47 @@
#include "../src/ast-walker/stringstream.c"
#include "../src/ast-walker/memory.h"
#include "../src/ast-walker/memory.c"
#include "../src/ast-walker/t_stream.h"
#include "../src/ast-walker/t_stream.c"

#include <string.h>

int main(void) {
STREAM s;
const char *tmp = "hej pa dig";
int ch, i;

make_stringstream(&s, tmp, strlen(tmp)+1);

while((ch = stream_getc(&s)) != EOF)
putchar(ch);

printf("END\n");
stream_close(&s);

printf("%s\n", tmp);

make_stringstream(&s, tmp, strlen(tmp)+1);
for (i = 0; i < 4; i++)
ch = stream_getc(&s);

stream_ungetc('.', &s);
stream_ungetc('J', &s);
stream_ungetc('O', &s);
stream_ungetc('H', &s);

ch = stream_ungetc('2', &s);
if (ch != EOF) {
printf("Should get EOF\n");
} else {
printf("All ok, got EOF\n");
}

printf("UNCHANGED: %s\n", tmp);

while((ch = stream_getc(&s)) != EOF)
putchar(ch);
printf("END\n");

stream_close(&s);
}

0 comments on commit 7320e6f

Please sign in to comment.