]> gitweb.factorcode.org Git - factor.git/blob - native/fd.c
i/o refactoring continues
[factor.git] / native / fd.c
1 #include "factor.h"
2
3 void init_io(void)
4 {
5         env.user[STDIN_ENV]  = tag_object(port(0));
6         env.user[STDOUT_ENV] = tag_object(port(1));
7         env.user[STDERR_ENV] = tag_object(port(2));
8 }
9
10 bool can_read_line(PORT* port)
11 {
12         return false;
13 }
14
15 void primitive_can_read_line(void)
16 {
17         PORT* port = untag_port(dpop());
18         dpush(tag_boolean(can_read_line(port)));
19 }
20
21 /* Return true if something was read */
22 bool read_step(PORT* port)
23 {
24         FIXNUM amount = read(port->fd,
25                 port->buffer + 1,
26                 port->buffer->capacity * 2);
27
28         if(amount == -1)
29         {
30                 if(errno != EAGAIN)
31                         io_error(port,__FUNCTION__);
32                 return false;
33         }
34         else
35         {
36                 port->buf_fill = (amount < 0 ? 0 : amount);
37                 port->buf_pos = 0;
38                 return true;
39         }
40 }
41
42 bool read_line_step(PORT* port)
43 {
44         int i;
45         char ch;
46
47         SBUF* line = untag_sbuf(port->line);
48
49         for(i = port->buf_pos; i < port->buf_fill; i++)
50         {
51                 ch = bget((CELL)port->buffer + sizeof(STRING) + i);
52                 if(ch == '\n')
53                 {
54                         port->buf_pos = i + 1;
55                         return true;
56                 }
57                 else
58                         set_sbuf_nth(line,line->top,ch);
59         }
60
61         port->buf_pos = port->buf_fill;
62
63         /* We've reached the end of the above loop, without seeing a newline
64         or EOF, so read again */
65         return false;
66 }
67
68 void primitive_read_line_fd_8(void)
69 {
70         PORT* port = untag_port(dpeek());
71         drepl(port->line);
72         port->line = F;
73
74 }
75
76 /* Return true if write was done */
77 bool write_step(PORT* port)
78 {
79         char* chars = (char*)port->buffer + sizeof(STRING);
80
81         FIXNUM amount = write(port->fd,chars + port->buf_pos,
82                 port->buf_fill - port->buf_pos);
83
84         if(amount == -1)
85         {
86                 if(errno != EAGAIN)
87                         io_error(port,__FUNCTION__);
88                 return false;
89         }
90         else
91         {
92                 port->buf_pos += amount;
93                 return true;
94         }
95 }
96
97 bool can_write(PORT* port, FIXNUM len)
98 {
99         CELL buf_capacity;
100
101         switch(port->buf_mode)
102         {
103         case B_NONE:
104                 return true;
105         case B_READ_LINE:
106                 return false;
107         case B_WRITE:
108                 buf_capacity = port->buffer->capacity * CHARS;
109                 /* Is the string longer than the buffer? */
110                 if(port->buf_fill == 0 && len > buf_capacity)
111                 {
112                         /* Increase the buffer to fit the string */
113                         port->buffer = allot_string(len / CHARS + 1);
114                         return true;
115                 }
116                 else
117                         return (port->buf_fill + len <= buf_capacity);
118         default:
119                 critical_error("Bad buf_mode",port->buf_mode);
120                 return false;
121         }
122 }
123
124 void primitive_can_write(void)
125 {
126         PORT* port = untag_port(dpop());
127         FIXNUM len = to_fixnum(dpop());
128         dpush(tag_boolean(can_write(port,len)));
129 }
130
131 void write_fd_char_8(PORT* port, FIXNUM ch)
132 {
133         char c = (char)ch;
134
135         if(!can_write(port,1))
136                 io_error(port,__FUNCTION__);
137
138         init_buffer(port,B_WRITE);
139
140         bput((CELL)port->buffer + sizeof(STRING) + port->buf_fill,c);
141         port->buf_fill++;
142 }
143
144 void write_fd_string_8(PORT* port, STRING* str)
145 {
146         char* c_str;
147
148         /* Note this ensures the buffer is large enough to fit the string */
149         if(!can_write(port,str->capacity))
150                 io_error(port,__FUNCTION__);
151
152         init_buffer(port,B_WRITE);
153
154         c_str = to_c_string(str);
155
156         /* Append string to buffer */
157         memcpy((void*)((CELL)port->buffer + sizeof(STRING)
158                 + port->buf_fill),c_str,str->capacity);
159
160         port->buf_fill += str->capacity;
161 }
162
163 void primitive_write_fd_8(void)
164 {
165         PORT* port = untag_port(dpop());
166
167         CELL text = dpop();
168         CELL type = type_of(text);
169
170         switch(type)
171         {
172         case FIXNUM_TYPE:
173         case BIGNUM_TYPE:
174                 write_fd_char_8(port,to_fixnum(text));
175                 break;
176         case STRING_TYPE:
177                 write_fd_string_8(port,untag_string(text));
178                 break;
179         default:
180                 type_error(STRING_TYPE,text);
181                 break;
182         }
183 }
184
185 void primitive_close_fd(void)
186 {
187         /* This does not flush. */
188         PORT* port = untag_port(dpop());
189         close(port->fd);
190 }
191
192 void io_error(PORT* port, const char* func)
193 {
194         STRING* function = from_c_string(func);
195         STRING* error = from_c_string(strerror(errno));
196
197         CONS* c = cons(tag_object(function),tag_cons(
198                 cons(tag_object(error),F)));
199
200         general_error(ERROR_IO,tag_cons(c));
201 }