mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-18 21:29:18 +02:00
140 lines
3.8 KiB
C
140 lines
3.8 KiB
C
/**
|
|
* 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);
|
|
}
|
|
}
|