]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /** |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | ||
20 | #include <ruby.h> | |
21 | #include <constants.h> | |
22 | #include <bytes.h> | |
23 | #include <macros.h> | |
24 | ||
25 | ID buf_ivar_id; | |
26 | ID index_ivar_id; | |
27 | ||
28 | ID slice_method_id; | |
29 | ||
30 | int GARBAGE_BUFFER_SIZE; | |
31 | ||
32 | #define GET_BUF(self) rb_ivar_get(self, buf_ivar_id) | |
33 | ||
34 | VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str); | |
35 | VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value); | |
36 | VALUE rb_thrift_memory_buffer_read_byte(VALUE self); | |
37 | VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value); | |
38 | ||
39 | VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str) { | |
40 | VALUE buf = GET_BUF(self); | |
41 | str = force_binary_encoding(str); | |
42 | rb_str_buf_cat(buf, StringValuePtr(str), RSTRING_LEN(str)); | |
43 | return Qnil; | |
44 | } | |
45 | ||
46 | VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value) { | |
47 | int length = FIX2INT(length_value); | |
48 | ||
49 | VALUE index_value = rb_ivar_get(self, index_ivar_id); | |
50 | int index = FIX2INT(index_value); | |
51 | ||
52 | VALUE buf = GET_BUF(self); | |
53 | VALUE data = rb_funcall(buf, slice_method_id, 2, index_value, length_value); | |
54 | ||
55 | index += length; | |
56 | if (index > RSTRING_LEN(buf)) { | |
57 | index = RSTRING_LEN(buf); | |
58 | } | |
59 | if (index >= GARBAGE_BUFFER_SIZE) { | |
60 | rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); | |
61 | index = 0; | |
62 | } | |
63 | rb_ivar_set(self, index_ivar_id, INT2FIX(index)); | |
64 | ||
65 | if (RSTRING_LEN(data) < length) { | |
66 | rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); | |
67 | } | |
68 | ||
69 | return data; | |
70 | } | |
71 | ||
72 | VALUE rb_thrift_memory_buffer_read_byte(VALUE self) { | |
73 | VALUE index_value = rb_ivar_get(self, index_ivar_id); | |
74 | int index = FIX2INT(index_value); | |
75 | ||
76 | VALUE buf = GET_BUF(self); | |
77 | if (index >= RSTRING_LEN(buf)) { | |
78 | rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); | |
79 | } | |
80 | char byte = RSTRING_PTR(buf)[index++]; | |
81 | ||
82 | if (index >= GARBAGE_BUFFER_SIZE) { | |
83 | rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); | |
84 | index = 0; | |
85 | } | |
86 | rb_ivar_set(self, index_ivar_id, INT2FIX(index)); | |
87 | ||
88 | int result = (int) byte; | |
89 | return INT2FIX(result); | |
90 | } | |
91 | ||
92 | VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value) { | |
93 | int i = 0; | |
94 | int size = FIX2INT(size_value); | |
95 | int index; | |
96 | VALUE buf = GET_BUF(self); | |
97 | ||
98 | index = FIX2INT(rb_ivar_get(self, index_ivar_id)); | |
99 | while (i < size) { | |
100 | if (index >= RSTRING_LEN(buf)) { | |
101 | rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); | |
102 | } | |
103 | char byte = RSTRING_PTR(buf)[index++]; | |
104 | ||
105 | if (i >= RSTRING_LEN(buffer_value)) { | |
106 | rb_raise(rb_eIndexError, "index %d out of string", i); | |
107 | } | |
108 | ((char*)RSTRING_PTR(buffer_value))[i] = byte; | |
109 | i++; | |
110 | } | |
111 | ||
112 | if (index >= GARBAGE_BUFFER_SIZE) { | |
113 | rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); | |
114 | index = 0; | |
115 | } | |
116 | rb_ivar_set(self, index_ivar_id, INT2FIX(index)); | |
117 | ||
118 | return INT2FIX(i); | |
119 | } | |
120 | ||
121 | void Init_memory_buffer() { | |
122 | VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBufferTransport")); | |
123 | rb_define_method(thrift_memory_buffer_class, "write", rb_thrift_memory_buffer_write, 1); | |
124 | rb_define_method(thrift_memory_buffer_class, "read", rb_thrift_memory_buffer_read, 1); | |
125 | rb_define_method(thrift_memory_buffer_class, "read_byte", rb_thrift_memory_buffer_read_byte, 0); | |
126 | rb_define_method(thrift_memory_buffer_class, "read_into_buffer", rb_thrift_memory_buffer_read_into_buffer, 2); | |
127 | ||
128 | buf_ivar_id = rb_intern("@buf"); | |
129 | index_ivar_id = rb_intern("@index"); | |
130 | ||
131 | slice_method_id = rb_intern("slice"); | |
132 | ||
133 | GARBAGE_BUFFER_SIZE = FIX2INT(rb_const_get(thrift_memory_buffer_class, rb_intern("GARBAGE_BUFFER_SIZE"))); | |
134 | } |