binyo 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/ext/binyo/binyo-error-internal.h +38 -0
- data/ext/binyo/binyo-error.h +41 -0
- data/ext/binyo/binyo-io-buffer.h +54 -0
- data/ext/binyo/binyo-io.h +131 -0
- data/ext/binyo/binyo-mem.h +44 -0
- data/ext/binyo/binyo-missing.h +36 -0
- data/ext/binyo/binyo.c +96 -0
- data/ext/binyo/binyo.h +75 -0
- data/ext/binyo/byte.c +116 -0
- data/ext/binyo/byte.h +39 -0
- data/ext/binyo/bytelist.c +223 -0
- data/ext/binyo/bytelist.h +45 -0
- data/ext/binyo/error.c +202 -0
- data/ext/binyo/extconf.h +5 -0
- data/ext/binyo/extconf.rb +73 -0
- data/ext/binyo/io.c +324 -0
- data/ext/binyo/io_buffer.c +143 -0
- data/ext/binyo/io_in_bytes.c +196 -0
- data/ext/binyo/io_in_cache.c +144 -0
- data/ext/binyo/io_in_fd.c +166 -0
- data/ext/binyo/io_in_generic.c +182 -0
- data/ext/binyo/io_in_seq.c +187 -0
- data/ext/binyo/io_out_bytes.c +120 -0
- data/ext/binyo/io_out_fd.c +110 -0
- data/ext/binyo/io_out_generic.c +125 -0
- data/lib/binyo.rb +32 -0
- data/lib/binyo.so +0 -0
- data/test/hex.rb +135 -0
- data/test/scratch.rb +33 -0
- metadata +77 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
/*
|
2
|
+
* binyo - Fast binary IO for Ruby
|
3
|
+
*
|
4
|
+
* Copyright (c) 2012-2013
|
5
|
+
* Martin Bosslet <martin.bosslet@gmail.com>
|
6
|
+
* All rights reserved.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
* a copy of this software and associated documentation files (the
|
10
|
+
* "Software"), to deal in the Software without restriction, including
|
11
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
* the following conditions:
|
15
|
+
*
|
16
|
+
* The above copyright notice and this permission notice shall be
|
17
|
+
* included in all copies or substantial portions of the Software.
|
18
|
+
*
|
19
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
22
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
23
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
24
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
25
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
#if !defined(_BYTELIST_H_)
|
29
|
+
#define _BYTELIST_H_
|
30
|
+
|
31
|
+
extern VALUE cBinyoByteList;
|
32
|
+
|
33
|
+
struct binyo_bytelist_st;
|
34
|
+
typedef struct binyo_bytelist_st binyo_bytelist;
|
35
|
+
|
36
|
+
binyo_bytelist * binyo_bytelist_new_size(size_t size);
|
37
|
+
binyo_bytelist * binyo_bytelist_new_size_default(size_t size, uint8_t default_value);
|
38
|
+
binyo_bytelist * binyo_bytelist_new_bytes(uint8_t *bytes, size_t len);
|
39
|
+
void binyo_bytelist_free(binyo_bytelist *bytelist);
|
40
|
+
|
41
|
+
void Init_binyo_bytelist(void);
|
42
|
+
|
43
|
+
#endif /* _BYTELIST_H_ */
|
44
|
+
|
45
|
+
|
data/ext/binyo/error.c
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
/*
|
2
|
+
* binyo - Fast binary IO for Ruby
|
3
|
+
*
|
4
|
+
* Copyright (c) 2012-2013
|
5
|
+
* Martin Bosslet <martin.bosslet@gmail.com>
|
6
|
+
* All rights reserved.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
* a copy of this software and associated documentation files (the
|
10
|
+
* "Software"), to deal in the Software without restriction, including
|
11
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
* the following conditions:
|
15
|
+
*
|
16
|
+
* The above copyright notice and this permission notice shall be
|
17
|
+
* included in all copies or substantial portions of the Software.
|
18
|
+
*
|
19
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
22
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
23
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
24
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
25
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
#include "binyo.h"
|
29
|
+
#include <stdarg.h>
|
30
|
+
|
31
|
+
typedef struct binyo_err_stack_elem_st binyo_err_stack_elem;
|
32
|
+
|
33
|
+
typedef struct binyo_err_stack_st {
|
34
|
+
int count;
|
35
|
+
binyo_err_stack_elem *head;
|
36
|
+
} binyo_err_stack;
|
37
|
+
|
38
|
+
struct binyo_err_stack_elem_st {
|
39
|
+
char *message;
|
40
|
+
size_t len;
|
41
|
+
binyo_err_stack_elem *prev;
|
42
|
+
};
|
43
|
+
|
44
|
+
static binyo_err_stack err_stack = { 0 };
|
45
|
+
|
46
|
+
#define int_err_stack_empty() (err_stack.count == 0)
|
47
|
+
|
48
|
+
static void
|
49
|
+
int_err_stack_push(char *message, size_t len)
|
50
|
+
{
|
51
|
+
binyo_err_stack_elem *elem;
|
52
|
+
|
53
|
+
elem = ALLOC(binyo_err_stack_elem);
|
54
|
+
elem->message = message;
|
55
|
+
elem->len = len;
|
56
|
+
elem->prev = err_stack.head;
|
57
|
+
err_stack.head = elem;
|
58
|
+
err_stack.count++;
|
59
|
+
}
|
60
|
+
|
61
|
+
static char *
|
62
|
+
int_err_stack_pop()
|
63
|
+
{
|
64
|
+
char *message;
|
65
|
+
binyo_err_stack_elem *head = err_stack.head;
|
66
|
+
|
67
|
+
if (!head) return NULL;
|
68
|
+
|
69
|
+
err_stack.head = head->prev;
|
70
|
+
message = head->message;
|
71
|
+
xfree(head);
|
72
|
+
err_stack.count--;
|
73
|
+
return message;
|
74
|
+
}
|
75
|
+
|
76
|
+
int
|
77
|
+
binyo_has_errors(void)
|
78
|
+
{
|
79
|
+
return !int_err_stack_empty();
|
80
|
+
}
|
81
|
+
|
82
|
+
int
|
83
|
+
binyo_error_message(char *buf, int buf_len)
|
84
|
+
{
|
85
|
+
binyo_err_stack_elem *head = err_stack.head;
|
86
|
+
int len = 0;
|
87
|
+
|
88
|
+
while (head) {
|
89
|
+
int cur_len;
|
90
|
+
char *message = head->message;
|
91
|
+
cur_len = snprintf(buf + len, buf_len, "%s%s", (len ? ": " : ""), message);
|
92
|
+
if (cur_len > 0)
|
93
|
+
len += cur_len;
|
94
|
+
head = head->prev;
|
95
|
+
}
|
96
|
+
|
97
|
+
return len;
|
98
|
+
}
|
99
|
+
|
100
|
+
void
|
101
|
+
binyo_error_add(const char *format, ...)
|
102
|
+
{
|
103
|
+
char *buf;
|
104
|
+
int len = 0;
|
105
|
+
va_list args;
|
106
|
+
|
107
|
+
va_start(args, format);
|
108
|
+
buf = ALLOC_N(char, BUFSIZ);
|
109
|
+
if ((len = vsnprintf(buf, BUFSIZ, format, args)) < 0) return;
|
110
|
+
int_err_stack_push(buf, len);
|
111
|
+
va_end(args);
|
112
|
+
}
|
113
|
+
|
114
|
+
static int
|
115
|
+
int_error_msg_create(char *buf, int len, const char *format, va_list args)
|
116
|
+
{
|
117
|
+
int l;
|
118
|
+
|
119
|
+
if ((l = vsnprintf(buf, len, format, args)) < 0) {
|
120
|
+
return -1;
|
121
|
+
}
|
122
|
+
|
123
|
+
while (!int_err_stack_empty()) {
|
124
|
+
int cur_len;
|
125
|
+
char *message = int_err_stack_pop();
|
126
|
+
cur_len = snprintf(buf + l, len, "%s%s", (l ? ": " : ""), message);
|
127
|
+
xfree(message);
|
128
|
+
if (cur_len > 0)
|
129
|
+
l += cur_len;
|
130
|
+
}
|
131
|
+
|
132
|
+
return l;
|
133
|
+
}
|
134
|
+
|
135
|
+
|
136
|
+
static VALUE
|
137
|
+
int_error_create(VALUE exception_class, const char *format, va_list args)
|
138
|
+
{
|
139
|
+
char buf[BUFSIZ];
|
140
|
+
int len = 0;
|
141
|
+
|
142
|
+
if ((len = int_error_msg_create(buf, BUFSIZ, format, args)) < 0) {
|
143
|
+
return rb_funcall(exception_class, rb_intern("new"), 0);
|
144
|
+
}
|
145
|
+
|
146
|
+
return rb_exc_new(exception_class, buf, len);
|
147
|
+
}
|
148
|
+
|
149
|
+
static VALUE
|
150
|
+
int_error_enhance(VALUE exception_class, VALUE active_exc, const char *format, va_list args)
|
151
|
+
{
|
152
|
+
char buf[BUFSIZ];
|
153
|
+
int len;
|
154
|
+
VALUE orig_msg;
|
155
|
+
long orig_len;
|
156
|
+
const char *active_name = rb_class2name(CLASS_OF(active_exc));
|
157
|
+
size_t active_name_len = strlen(active_name);
|
158
|
+
|
159
|
+
if ((len = int_error_msg_create(buf, BUFSIZ, format, args)) < 0) {
|
160
|
+
return active_exc;
|
161
|
+
}
|
162
|
+
|
163
|
+
orig_msg = rb_funcall(active_exc, rb_intern("message"), 0);
|
164
|
+
StringValueCStr(orig_msg);
|
165
|
+
orig_len = RSTRING_LEN(orig_msg);
|
166
|
+
if (len <= BUFSIZ - ( (int) active_name_len ) - orig_len - 4) {
|
167
|
+
strcat(buf, ": ");
|
168
|
+
strcat(buf, active_name);
|
169
|
+
strcat(buf, ": ");
|
170
|
+
strcat(buf, RSTRING_PTR(orig_msg));
|
171
|
+
len += active_name_len + orig_len + 4;
|
172
|
+
}
|
173
|
+
|
174
|
+
return rb_exc_new(exception_class, buf, len);
|
175
|
+
}
|
176
|
+
|
177
|
+
void
|
178
|
+
binyo_error_raise(VALUE exception_class, const char *format, ...)
|
179
|
+
{
|
180
|
+
VALUE exc;
|
181
|
+
VALUE active_exc;
|
182
|
+
va_list args;
|
183
|
+
|
184
|
+
va_start(args, format);
|
185
|
+
active_exc = rb_errinfo();
|
186
|
+
if (NIL_P(active_exc)) {
|
187
|
+
exc = int_error_create(exception_class, format, args);
|
188
|
+
} else {
|
189
|
+
exc = int_error_enhance(exception_class, active_exc, format, args);
|
190
|
+
}
|
191
|
+
va_end(args);
|
192
|
+
rb_exc_raise(exc);
|
193
|
+
}
|
194
|
+
|
195
|
+
void
|
196
|
+
binyo_error_clear(void)
|
197
|
+
{
|
198
|
+
while (!int_err_stack_empty()) {
|
199
|
+
xfree(int_err_stack_pop());
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
data/ext/binyo/extconf.h
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= Info
|
4
|
+
|
5
|
+
binyo - Fast binary IO for Ruby
|
6
|
+
|
7
|
+
Copyright (C) 2012-2013
|
8
|
+
Martin Bosslet <martin.bosslet@gmail.com>
|
9
|
+
All rights reserved.
|
10
|
+
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
12
|
+
a copy of this software and associated documentation files (the
|
13
|
+
"Software"), to deal in the Software without restriction, including
|
14
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
15
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
16
|
+
permit persons to whom the Software is furnished to do so, subject to
|
17
|
+
the following conditions:
|
18
|
+
|
19
|
+
The above copyright notice and this permission notice shall be
|
20
|
+
included in all copies or substantial portions of the Software.
|
21
|
+
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
23
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
24
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
25
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
26
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
27
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
28
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
29
|
+
|
30
|
+
=end
|
31
|
+
|
32
|
+
require 'mkmf'
|
33
|
+
|
34
|
+
dir_config('profiler')
|
35
|
+
|
36
|
+
message "=== binyo - Fast binary IO for Ruby ===\n"
|
37
|
+
|
38
|
+
arg = ARGV.shift
|
39
|
+
if arg
|
40
|
+
if arg.include? "-g"
|
41
|
+
debug = true
|
42
|
+
elsif arg.include? "-p"
|
43
|
+
profiler = true
|
44
|
+
unless have_library("profiler", "ProfilerStart")
|
45
|
+
message "'libprofiler' could not be found.\n"
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if CONFIG['GCC'] == 'yes'
|
52
|
+
if debug
|
53
|
+
flags = "--coverage -g3 -fprofile-arcs -ftest-coverage"
|
54
|
+
message "!! set #{flags} for coverage !!"
|
55
|
+
$CFLAGS += " #{flags}"
|
56
|
+
$DLDFLAGS += " #{flags}"
|
57
|
+
$LIBS += " -lgcov"
|
58
|
+
end
|
59
|
+
if profiler
|
60
|
+
message "Linking to profiler library\n"
|
61
|
+
pkg_config('profiler')
|
62
|
+
$LIBS += " -lprofiler"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
message "=== Checking Ruby features ===\n"
|
67
|
+
|
68
|
+
have_header("ruby/io.h")
|
69
|
+
have_func("rb_io_check_byte_readable")
|
70
|
+
|
71
|
+
create_header
|
72
|
+
create_makefile("binyo")
|
73
|
+
message "Done.\n"
|
data/ext/binyo/io.c
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
/*
|
2
|
+
* binyo - Fast binary IO for Ruby
|
3
|
+
*
|
4
|
+
* Copyright (c) 2012-2013
|
5
|
+
* Martin Bosslet <martin.bosslet@gmail.com>
|
6
|
+
* All rights reserved.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
* a copy of this software and associated documentation files (the
|
10
|
+
* "Software"), to deal in the Software without restriction, including
|
11
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
* the following conditions:
|
15
|
+
*
|
16
|
+
* The above copyright notice and this permission notice shall be
|
17
|
+
* included in all copies or substantial portions of the Software.
|
18
|
+
*
|
19
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
22
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
23
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
24
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
25
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
#include "binyo.h"
|
29
|
+
|
30
|
+
#define int_check_stream(io) if (!(io) || !(io)->methods) \
|
31
|
+
rb_raise(eBinyoError, "Stream not initialized properly")
|
32
|
+
|
33
|
+
#define int_check_stream_has(io, m) if (!(io) || !(io)->methods || !(io)->methods->m) \
|
34
|
+
rb_raise(eBinyoError, "Stream not initialized properly")
|
35
|
+
|
36
|
+
VALUE sBinyo_ID_SEEK_CUR, sBinyo_ID_SEEK_SET, sBinyo_ID_SEEK_END;
|
37
|
+
ID sBinyo_ID_READ, sBinyo_ID_SEEK, sBinyo_ID_WRITE, sBinyo_ID_CLOSE;
|
38
|
+
|
39
|
+
void
|
40
|
+
binyo_add_io_error(void)
|
41
|
+
{
|
42
|
+
int err = binyo_last_sys_error();
|
43
|
+
binyo_error_add("Error stream IO: %d", err);
|
44
|
+
}
|
45
|
+
|
46
|
+
/* instream */
|
47
|
+
|
48
|
+
static int
|
49
|
+
int_read_all(binyo_instream *in, VALUE vbuf, VALUE *out)
|
50
|
+
{
|
51
|
+
uint8_t *buf;
|
52
|
+
ssize_t r;
|
53
|
+
|
54
|
+
buf = ALLOC_N(uint8_t, BINYO_IO_BUF_SIZE);
|
55
|
+
|
56
|
+
while ((r = binyo_instream_read(in, buf, BINYO_IO_BUF_SIZE)) >= 0) {
|
57
|
+
rb_str_buf_cat(vbuf, (const char *) buf, r);
|
58
|
+
}
|
59
|
+
|
60
|
+
xfree(buf);
|
61
|
+
if (r == BINYO_ERR) return BINYO_ERR;
|
62
|
+
*out = vbuf;
|
63
|
+
return BINYO_OK;
|
64
|
+
}
|
65
|
+
|
66
|
+
static int
|
67
|
+
int_rb_read_generic(binyo_instream *in, VALUE vlen, VALUE vbuf, VALUE *out)
|
68
|
+
{
|
69
|
+
long len;
|
70
|
+
size_t tlen;
|
71
|
+
ssize_t r;
|
72
|
+
uint8_t *buf;
|
73
|
+
|
74
|
+
if (NIL_P(vbuf)) {
|
75
|
+
vbuf = rb_str_new2("");
|
76
|
+
rb_enc_associate(vbuf, rb_ascii8bit_encoding());
|
77
|
+
}
|
78
|
+
|
79
|
+
if (NIL_P(vlen))
|
80
|
+
return int_read_all(in, vbuf, out);
|
81
|
+
|
82
|
+
len = NUM2LONG(vlen);
|
83
|
+
if (len < 0) {
|
84
|
+
binyo_error_add("Negative length given");
|
85
|
+
return BINYO_ERR;
|
86
|
+
}
|
87
|
+
if ((size_t) len > SIZE_MAX) {
|
88
|
+
binyo_error_add("Size too large: %ld", len);
|
89
|
+
return BINYO_ERR;
|
90
|
+
}
|
91
|
+
|
92
|
+
tlen = (size_t) len;
|
93
|
+
if (len == 0) {
|
94
|
+
rb_str_resize(vbuf, 0);
|
95
|
+
*out = vbuf;
|
96
|
+
return BINYO_OK;
|
97
|
+
}
|
98
|
+
|
99
|
+
buf = ALLOC_N(uint8_t, tlen);
|
100
|
+
r = binyo_instream_read(in, buf, tlen);
|
101
|
+
|
102
|
+
if (r == BINYO_ERR) {
|
103
|
+
binyo_error_add("Error while reading from stream");
|
104
|
+
xfree(buf);
|
105
|
+
return BINYO_ERR;
|
106
|
+
}
|
107
|
+
else if (r == BINYO_IO_EOF) {
|
108
|
+
xfree(buf);
|
109
|
+
rb_str_resize(vbuf, 0);
|
110
|
+
*out = Qnil;
|
111
|
+
return BINYO_OK;
|
112
|
+
}
|
113
|
+
else {
|
114
|
+
rb_str_buf_cat(vbuf, (const char *)buf, r);
|
115
|
+
xfree(buf);
|
116
|
+
*out = vbuf;
|
117
|
+
return BINYO_OK;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
int
|
122
|
+
binyo_instream_rb_read(binyo_instream *in, VALUE vlen, VALUE vbuf, VALUE *out)
|
123
|
+
{
|
124
|
+
int_check_stream(in);
|
125
|
+
|
126
|
+
if (in->methods->rb_read) {
|
127
|
+
return in->methods->rb_read(in, vlen, vbuf, out);
|
128
|
+
}
|
129
|
+
else {
|
130
|
+
return int_rb_read_generic(in, vlen, vbuf, out);
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
ssize_t
|
135
|
+
binyo_instream_read(binyo_instream *in, uint8_t *buf, size_t len)
|
136
|
+
{
|
137
|
+
int_check_stream_has(in, read);
|
138
|
+
|
139
|
+
if (len > SSIZE_MAX) {
|
140
|
+
binyo_error_add("Size too large: %ld", len);
|
141
|
+
return BINYO_ERR;
|
142
|
+
}
|
143
|
+
return in->methods->read(in, buf, len);
|
144
|
+
}
|
145
|
+
|
146
|
+
static ssize_t
|
147
|
+
int_gets_generic(binyo_instream *in, char *line, size_t len)
|
148
|
+
{
|
149
|
+
ssize_t ret = 0, r = 0;
|
150
|
+
char *p = line;
|
151
|
+
char *end = line + len;
|
152
|
+
|
153
|
+
if (!line) return BINYO_ERR;
|
154
|
+
|
155
|
+
while (p < end) {
|
156
|
+
if ((r = in->methods->read(in, (uint8_t *) p, 1)) < 0)
|
157
|
+
break;
|
158
|
+
if (r == 1) {
|
159
|
+
if (*p == '\n')
|
160
|
+
break;
|
161
|
+
p++;
|
162
|
+
ret++;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
if (r == BINYO_ERR) return BINYO_ERR;
|
167
|
+
if (ret == 0 && r == BINYO_IO_EOF) return BINYO_IO_EOF;
|
168
|
+
|
169
|
+
/* normalize CRLF */
|
170
|
+
if (*p == '\n' && *(p - 1) == '\r')
|
171
|
+
ret--;
|
172
|
+
|
173
|
+
return ret;
|
174
|
+
}
|
175
|
+
|
176
|
+
ssize_t
|
177
|
+
binyo_instream_gets(binyo_instream *in, char *line, size_t len)
|
178
|
+
{
|
179
|
+
int_check_stream(in);
|
180
|
+
if (len > SSIZE_MAX) {
|
181
|
+
binyo_error_add("Size too large: %ld", len);
|
182
|
+
return BINYO_ERR;
|
183
|
+
}
|
184
|
+
if (in->methods->gets) {
|
185
|
+
return in->methods->gets(in, line, len);
|
186
|
+
}
|
187
|
+
else {
|
188
|
+
return int_gets_generic(in, line, len);
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
int
|
193
|
+
binyo_instream_seek(binyo_instream *in, off_t offset, int whence)
|
194
|
+
{
|
195
|
+
int_check_stream_has(in, seek);
|
196
|
+
return in->methods->seek(in, offset, whence);
|
197
|
+
}
|
198
|
+
|
199
|
+
void
|
200
|
+
binyo_instream_mark(binyo_instream *in)
|
201
|
+
{
|
202
|
+
int_check_stream(in);
|
203
|
+
if (in->methods->mark)
|
204
|
+
in->methods->mark(in);
|
205
|
+
}
|
206
|
+
|
207
|
+
void
|
208
|
+
binyo_instream_free(binyo_instream *in)
|
209
|
+
{
|
210
|
+
int_check_stream(in);
|
211
|
+
if (in->methods->free)
|
212
|
+
in->methods->free(in);
|
213
|
+
xfree(in);
|
214
|
+
}
|
215
|
+
|
216
|
+
static binyo_instream *
|
217
|
+
int_instream_common_new(VALUE value)
|
218
|
+
{
|
219
|
+
int type;
|
220
|
+
|
221
|
+
type = TYPE(value);
|
222
|
+
|
223
|
+
if (type == T_STRING) {
|
224
|
+
return binyo_instream_new_bytes((uint8_t *)RSTRING_PTR(value), RSTRING_LEN(value));
|
225
|
+
}
|
226
|
+
else {
|
227
|
+
if (type == T_FILE) {
|
228
|
+
return binyo_instream_new_fd_io(value);
|
229
|
+
}
|
230
|
+
else if (rb_respond_to(value, sBinyo_ID_READ)) {
|
231
|
+
return binyo_instream_new_io_generic(value);
|
232
|
+
}
|
233
|
+
}
|
234
|
+
return NULL;
|
235
|
+
}
|
236
|
+
|
237
|
+
binyo_instream *
|
238
|
+
binyo_instream_new_value(VALUE value)
|
239
|
+
{
|
240
|
+
return int_instream_common_new(value);
|
241
|
+
}
|
242
|
+
|
243
|
+
/* end instream */
|
244
|
+
|
245
|
+
/* outstream */
|
246
|
+
|
247
|
+
ssize_t
|
248
|
+
binyo_outstream_write(binyo_outstream *out, uint8_t *buf, size_t len)
|
249
|
+
{
|
250
|
+
int_check_stream_has(out, write);
|
251
|
+
if (len > SSIZE_MAX) {
|
252
|
+
binyo_error_add("Size too large: %ld", len);
|
253
|
+
return BINYO_ERR;
|
254
|
+
}
|
255
|
+
return out->methods->write(out, buf, len);
|
256
|
+
}
|
257
|
+
|
258
|
+
int
|
259
|
+
binyo_outstream_rb_write(binyo_outstream *out, VALUE vbuf, VALUE *ret)
|
260
|
+
{
|
261
|
+
int_check_stream(out);
|
262
|
+
|
263
|
+
if (out->methods->rb_write) {
|
264
|
+
return out->methods->rb_write(out, vbuf, ret);
|
265
|
+
}
|
266
|
+
else {
|
267
|
+
ssize_t w;
|
268
|
+
w = binyo_outstream_write(out, (uint8_t *) RSTRING_PTR(vbuf), RSTRING_LEN(vbuf));
|
269
|
+
if (w == BINYO_ERR) {
|
270
|
+
binyo_error_add("Error while writing to stream");
|
271
|
+
return BINYO_ERR;
|
272
|
+
}
|
273
|
+
*ret = LONG2NUM(w);
|
274
|
+
return BINYO_OK;
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
278
|
+
void
|
279
|
+
binyo_outstream_mark(binyo_outstream *out)
|
280
|
+
{
|
281
|
+
int_check_stream(out);
|
282
|
+
if (out->methods->mark)
|
283
|
+
out->methods->mark(out);
|
284
|
+
}
|
285
|
+
|
286
|
+
void
|
287
|
+
binyo_outstream_free(binyo_outstream *out)
|
288
|
+
{
|
289
|
+
int_check_stream(out);
|
290
|
+
if (out->methods->free)
|
291
|
+
out->methods->free(out);
|
292
|
+
xfree(out);
|
293
|
+
}
|
294
|
+
|
295
|
+
binyo_outstream *
|
296
|
+
binyo_outstream_new_value(VALUE value)
|
297
|
+
{
|
298
|
+
int type;
|
299
|
+
|
300
|
+
type = TYPE(value);
|
301
|
+
|
302
|
+
if (type == T_FILE)
|
303
|
+
return binyo_outstream_new_fd_io(value);
|
304
|
+
if (rb_respond_to(value, sBinyo_ID_WRITE))
|
305
|
+
return binyo_outstream_new_io_generic(value);
|
306
|
+
binyo_error_add("Value cannot be converted into a stream");
|
307
|
+
return NULL;
|
308
|
+
}
|
309
|
+
|
310
|
+
/* end outstream */
|
311
|
+
|
312
|
+
void
|
313
|
+
Init_binyo_io(void)
|
314
|
+
{
|
315
|
+
sBinyo_ID_SEEK = rb_intern("seek");
|
316
|
+
sBinyo_ID_READ = rb_intern("read");
|
317
|
+
sBinyo_ID_WRITE = rb_intern("write");
|
318
|
+
sBinyo_ID_CLOSE = rb_intern("close");
|
319
|
+
|
320
|
+
sBinyo_ID_SEEK_CUR = rb_const_get(rb_cIO, rb_intern("SEEK_CUR"));
|
321
|
+
sBinyo_ID_SEEK_SET = rb_const_get(rb_cIO, rb_intern("SEEK_SET"));
|
322
|
+
sBinyo_ID_SEEK_END = rb_const_get(rb_cIO, rb_intern("SEEK_END"));
|
323
|
+
}
|
324
|
+
|