forked from justinethier/cyclone
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mstreams.c
140 lines (130 loc) · 3.77 KB
/
mstreams.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**
* Cyclone Scheme
* https://github.com/justinethier/cyclone
*
* Copyright (c) 2014-2016, Justin Ethier
* All rights reserved.
*
* This file contains platform-specific code for memory streams.
*/
#include "cyclone/types.h"
#include "cyclone/runtime.h"
#include <errno.h>
/* These macros are hardcoded here to support functions in this module. */
#define closcall1(td, clo, buf) \
if (obj_is_not_closure(clo)) { \
Cyc_apply(td, clo, 1, buf ); \
} else { \
((clo)->fn)(td, clo, 1, buf); \
;\
}
#define return_closcall1(td, clo,a1) { \
char top; \
object buf[1]; buf[0] = a1;\
if (stack_overflow(&top, (((gc_thread_data *)data)->stack_limit))) { \
GC(td, clo, buf, 1); \
return; \
} else {\
closcall1(td, (closure) (clo), buf); \
return;\
} \
}
int Cyc_have_mstreams()
{
#if CYC_HAVE_FMEMOPEN && CYC_HAVE_OPEN_MEMSTREAM
return 1;
#else
return 0;
#endif
}
object Cyc_heap_alloc_port(void *data, port_type * p);
port_type *Cyc_io_open_input_string(void *data, object str)
{
// Allocate port on the heap so the location of mem_buf does not change
port_type *p;
make_input_port(sp, NULL, CYC_IO_BUF_LEN);
Cyc_check_str(data, str);
p = (port_type *) Cyc_heap_alloc_port(data, &sp);
errno = 0;
#if CYC_HAVE_FMEMOPEN
p->str_bv_in_mem_buf = malloc(sizeof(char) * (string_len(str) + 1));
p->str_bv_in_mem_buf_len = string_len(str);
memcpy(p->str_bv_in_mem_buf, string_str(str), string_len(str));
p->fp = fmemopen(p->str_bv_in_mem_buf, string_len(str), "r");
#endif
if (p->fp == NULL) {
Cyc_rt_raise2(data, "Unable to open input memory stream",
obj_int2obj(errno));
}
return p;
}
port_type *Cyc_io_open_input_bytevector(void *data, object bv)
{
// Allocate port on the heap so the location of mem_buf does not change
port_type *p;
make_input_port(sp, NULL, CYC_IO_BUF_LEN);
Cyc_check_bvec(data, bv);
p = (port_type *) Cyc_heap_alloc_port(data, &sp);
errno = 0;
#if CYC_HAVE_FMEMOPEN
p->str_bv_in_mem_buf = malloc(sizeof(char) * ((bytevector) bv)->len);
p->str_bv_in_mem_buf_len = ((bytevector) bv)->len;
memcpy(p->str_bv_in_mem_buf, ((bytevector) bv)->data, ((bytevector) bv)->len);
p->fp = fmemopen(p->str_bv_in_mem_buf, ((bytevector) bv)->len, "r");
#endif
if (p->fp == NULL) {
Cyc_rt_raise2(data, "Unable to open input memory stream",
obj_int2obj(errno));
}
return p;
}
port_type *Cyc_io_open_output_string(void *data)
{
// Allocate port on the heap so the location of mem_buf does not change
port_type *p;
make_port(sp, NULL, 0);
p = (port_type *) Cyc_heap_alloc_port(data, &sp);
errno = 0;
#if CYC_HAVE_OPEN_MEMSTREAM
p->fp = open_memstream(&(p->str_bv_in_mem_buf), &(p->str_bv_in_mem_buf_len));
#endif
if (p->fp == NULL) {
Cyc_rt_raise2(data, "Unable to open output memory stream",
obj_int2obj(errno));
}
return p;
}
void Cyc_io_get_output_string(void *data, object cont, object port)
{
port_type *p = (port_type *) port;
Cyc_check_port(data, port);
if (p->fp) {
fflush(p->fp);
}
if (p->str_bv_in_mem_buf == NULL) {
Cyc_rt_raise2(data, "Not an in-memory port", port);
}
{
make_string_with_len(s, p->str_bv_in_mem_buf, p->str_bv_in_mem_buf_len);
s.num_cp = Cyc_utf8_count_code_points((uint8_t *) string_str(&s));
return_closcall1(data, cont, &s);
}
}
void Cyc_io_get_output_bytevector(void *data, object cont, object port)
{
port_type *p = (port_type *) port;
Cyc_check_port(data, port);
if (p->fp) {
fflush(p->fp);
}
if (p->str_bv_in_mem_buf == NULL) {
Cyc_rt_raise2(data, "Not an in-memory port", port);
}
{
object bv;
alloc_bytevector(data, bv, p->str_bv_in_mem_buf_len);
memcpy(((bytevector) bv)->data, p->str_bv_in_mem_buf,
p->str_bv_in_mem_buf_len);
return_closcall1(data, cont, bv);
}
}