Permalink
Browse files

Implemented simple (read-only) (ungetc-able) string-stream

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...
1 parent 190df1c commit 7320e6fa3a5b25b2339efc03a8fddb40bb7abb5e @jbf committed Sep 13, 2011
View
@@ -23,3 +23,4 @@ TAGS
/src/vm/cpp_vm.d
/src/vm/test/test_context.d
/tlisp
+/test/test_stringstream
@@ -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);
+}
@@ -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 */
View
@@ -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;
View
@@ -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)))
@@ -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;
+}
@@ -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 */
View
@@ -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);
@@ -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);
-}
@@ -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 */
View
@@ -5,6 +5,7 @@
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
#include "errors.h"
View
@@ -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.