rbczmq 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/.gitignore +23 -0
- data/.travis.yml +19 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +19 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +247 -0
- data/Rakefile +67 -0
- data/examples/loop.rb +109 -0
- data/examples/poller.rb +37 -0
- data/examples/pub_sub.rb +101 -0
- data/examples/push_pull.rb +104 -0
- data/examples/req_rep.rb +100 -0
- data/ext/czmq.tar.gz +0 -0
- data/ext/rbczmq/context.c +280 -0
- data/ext/rbczmq/context.h +26 -0
- data/ext/rbczmq/extconf.rb +138 -0
- data/ext/rbczmq/frame.c +401 -0
- data/ext/rbczmq/frame.h +24 -0
- data/ext/rbczmq/jruby.h +22 -0
- data/ext/rbczmq/loop.c +413 -0
- data/ext/rbczmq/loop.h +24 -0
- data/ext/rbczmq/message.c +620 -0
- data/ext/rbczmq/message.h +24 -0
- data/ext/rbczmq/poller.c +308 -0
- data/ext/rbczmq/poller.h +29 -0
- data/ext/rbczmq/pollitem.c +251 -0
- data/ext/rbczmq/pollitem.h +25 -0
- data/ext/rbczmq/rbczmq_ext.c +198 -0
- data/ext/rbczmq/rbczmq_ext.h +94 -0
- data/ext/rbczmq/rbczmq_prelude.h +22 -0
- data/ext/rbczmq/rubinius.h +24 -0
- data/ext/rbczmq/ruby18.h +43 -0
- data/ext/rbczmq/ruby19.h +15 -0
- data/ext/rbczmq/socket.c +1570 -0
- data/ext/rbczmq/socket.h +136 -0
- data/ext/rbczmq/timer.c +110 -0
- data/ext/rbczmq/timer.h +23 -0
- data/ext/zeromq.tar.gz +0 -0
- data/lib/rbczmq.rb +3 -0
- data/lib/zmq.rb +77 -0
- data/lib/zmq/context.rb +50 -0
- data/lib/zmq/default_handler.rb +16 -0
- data/lib/zmq/frame.rb +11 -0
- data/lib/zmq/handler.rb +76 -0
- data/lib/zmq/loop.rb +131 -0
- data/lib/zmq/message.rb +9 -0
- data/lib/zmq/poller.rb +22 -0
- data/lib/zmq/pollitem.rb +31 -0
- data/lib/zmq/socket.rb +125 -0
- data/lib/zmq/socket/dealer.rb +33 -0
- data/lib/zmq/socket/pair.rb +39 -0
- data/lib/zmq/socket/pub.rb +30 -0
- data/lib/zmq/socket/pull.rb +29 -0
- data/lib/zmq/socket/push.rb +32 -0
- data/lib/zmq/socket/rep.rb +37 -0
- data/lib/zmq/socket/req.rb +37 -0
- data/lib/zmq/socket/router.rb +38 -0
- data/lib/zmq/socket/sub.rb +27 -0
- data/lib/zmq/timer.rb +12 -0
- data/lib/zmq/version.rb +5 -0
- data/perf/pair.rb +7 -0
- data/perf/pair/local.rb +22 -0
- data/perf/pair/remote.rb +25 -0
- data/perf/pub_sub.rb +7 -0
- data/perf/pub_sub/local.rb +22 -0
- data/perf/pub_sub/remote.rb +25 -0
- data/perf/push_pull.rb +7 -0
- data/perf/push_pull/local.rb +21 -0
- data/perf/push_pull/remote.rb +25 -0
- data/perf/req_rep.rb +7 -0
- data/perf/req_rep/local.rb +35 -0
- data/perf/req_rep/remote.rb +28 -0
- data/perf/runner.rb +142 -0
- data/rbczmq.gemspec +22 -0
- data/test/helper.rb +21 -0
- data/test/socket/test_dealer_socket.rb +14 -0
- data/test/socket/test_pair_socket.rb +24 -0
- data/test/socket/test_pair_sockets.rb +74 -0
- data/test/socket/test_pub_socket.rb +17 -0
- data/test/socket/test_pub_sub_sockets.rb +87 -0
- data/test/socket/test_pull_socket.rb +17 -0
- data/test/socket/test_push_pull_sockets.rb +81 -0
- data/test/socket/test_push_socket.rb +17 -0
- data/test/socket/test_rep_socket.rb +25 -0
- data/test/socket/test_req_rep_sockets.rb +42 -0
- data/test/socket/test_req_socket.rb +27 -0
- data/test/socket/test_router_socket.rb +14 -0
- data/test/socket/test_routing.rb +66 -0
- data/test/socket/test_sub_socket.rb +17 -0
- data/test/test_context.rb +86 -0
- data/test/test_frame.rb +78 -0
- data/test/test_handler.rb +28 -0
- data/test/test_loop.rb +252 -0
- data/test/test_message.rb +201 -0
- data/test/test_poller.rb +154 -0
- data/test/test_pollitem.rb +78 -0
- data/test/test_socket.rb +403 -0
- data/test/test_threading.rb +34 -0
- data/test/test_timer.rb +37 -0
- data/test/test_zmq.rb +62 -0
- metadata +208 -0
data/ext/rbczmq/loop.h
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#ifndef RBCZMQ_LOOP_H
|
2
|
+
#define RBCZMQ_LOOP_H
|
3
|
+
|
4
|
+
#define ZMQ_LOOP_DESTROYED 0x01
|
5
|
+
|
6
|
+
typedef struct {
|
7
|
+
zloop_t *loop;
|
8
|
+
int flags;
|
9
|
+
Bool verbose;
|
10
|
+
Bool running;
|
11
|
+
} zmq_loop_wrapper;
|
12
|
+
|
13
|
+
#define ZmqAssertLoop(obj) ZmqAssertType(obj, rb_cZmqLoop, "ZMQ::Loop")
|
14
|
+
#define ZmqGetLoop(obj) \
|
15
|
+
zmq_loop_wrapper *loop = NULL; \
|
16
|
+
ZmqAssertLoop(obj); \
|
17
|
+
Data_Get_Struct(obj, zmq_loop_wrapper, loop); \
|
18
|
+
if (!loop) rb_raise(rb_eTypeError, "uninitialized ZMQ loop!"); \
|
19
|
+
if (loop->flags & ZMQ_LOOP_DESTROYED) rb_raise(rb_eZmqError, "ZMQ::Loop instance %p has been destroyed by the ZMQ framework", (void *)obj);
|
20
|
+
|
21
|
+
VALUE rb_czmq_pollitem_set_verbose(VALUE obj, VALUE level);
|
22
|
+
void _init_rb_czmq_loop();
|
23
|
+
|
24
|
+
#endif
|
@@ -0,0 +1,620 @@
|
|
1
|
+
#include <rbczmq_ext.h>
|
2
|
+
|
3
|
+
/*
|
4
|
+
* :nodoc:
|
5
|
+
* Free all resources for a message - invoked by the lower level ZMQ::Message#destroy as well as the GC callback.
|
6
|
+
*
|
7
|
+
*/
|
8
|
+
void rb_czmq_free_message(zmq_message_wrapper *message)
|
9
|
+
{
|
10
|
+
errno = 0;
|
11
|
+
zmsg_destroy(&message->message);
|
12
|
+
message->message = NULL;
|
13
|
+
message->flags |= ZMQ_MESSAGE_DESTROYED;
|
14
|
+
}
|
15
|
+
|
16
|
+
/*
|
17
|
+
* :nodoc:
|
18
|
+
* GC free callback
|
19
|
+
*
|
20
|
+
*/
|
21
|
+
static void rb_czmq_free_message_gc(void *ptr)
|
22
|
+
{
|
23
|
+
zmq_message_wrapper *msg = (zmq_message_wrapper *)ptr;
|
24
|
+
if (msg) {
|
25
|
+
if (msg->message != NULL && !(msg->flags & ZMQ_MESSAGE_DESTROYED)) rb_czmq_free_message(msg);
|
26
|
+
xfree(msg);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
/*
|
31
|
+
* :nodoc:
|
32
|
+
* Coerce a zmsg instance to a native Ruby object.
|
33
|
+
*
|
34
|
+
*/
|
35
|
+
VALUE rb_czmq_alloc_message(zmsg_t *message)
|
36
|
+
{
|
37
|
+
VALUE message_obj;
|
38
|
+
zmq_message_wrapper *m = NULL;
|
39
|
+
errno = 0;
|
40
|
+
message_obj = Data_Make_Struct(rb_cZmqMessage, zmq_message_wrapper, 0, rb_czmq_free_message_gc, m);
|
41
|
+
m->message = message;
|
42
|
+
ZmqAssertObjOnAlloc(m->message, m);
|
43
|
+
m->flags = 0;
|
44
|
+
rb_obj_call_init(message_obj, 0, NULL);
|
45
|
+
return message_obj;
|
46
|
+
}
|
47
|
+
|
48
|
+
/*
|
49
|
+
* call-seq:
|
50
|
+
* ZMQ::Message.new => ZMQ::Message
|
51
|
+
*
|
52
|
+
* Creates an empty ZMQ::Message instance.
|
53
|
+
*
|
54
|
+
* === Examples
|
55
|
+
* ZMQ::Message.new => ZMQ::Message
|
56
|
+
*
|
57
|
+
*/
|
58
|
+
|
59
|
+
static VALUE rb_czmq_message_new(VALUE message)
|
60
|
+
{
|
61
|
+
zmq_message_wrapper *msg = NULL;
|
62
|
+
errno = 0;
|
63
|
+
message = Data_Make_Struct(rb_cZmqMessage, zmq_message_wrapper, 0, rb_czmq_free_message_gc, msg);
|
64
|
+
msg->message = zmsg_new();
|
65
|
+
ZmqAssertObjOnAlloc(msg->message, msg);
|
66
|
+
msg->flags = 0;
|
67
|
+
rb_obj_call_init(message, 0, NULL);
|
68
|
+
return message;
|
69
|
+
}
|
70
|
+
|
71
|
+
/*
|
72
|
+
* call-seq:
|
73
|
+
* msg.size => Fixnum
|
74
|
+
*
|
75
|
+
* Returns the size of a given ZMQ::Message instance - the number of frames.
|
76
|
+
*
|
77
|
+
* === Examples
|
78
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
79
|
+
* msg.size => 0
|
80
|
+
* msg.pushstr "frame" => true
|
81
|
+
* msg.size => 1
|
82
|
+
*
|
83
|
+
*/
|
84
|
+
|
85
|
+
static VALUE rb_czmq_message_size(VALUE obj)
|
86
|
+
{
|
87
|
+
ZmqGetMessage(obj);
|
88
|
+
return INT2NUM(zmsg_size(message->message));
|
89
|
+
}
|
90
|
+
|
91
|
+
/*
|
92
|
+
* call-seq:
|
93
|
+
* msg.content_size => Fixnum
|
94
|
+
*
|
95
|
+
* Returns the content size of a given ZMQ::Message instance - the sum of each frame's length.
|
96
|
+
*
|
97
|
+
* === Examples
|
98
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
99
|
+
* msg.content_size => 0
|
100
|
+
* msg.pushstr "frame" => true
|
101
|
+
* msg.content_size => 5
|
102
|
+
*
|
103
|
+
*/
|
104
|
+
|
105
|
+
static VALUE rb_czmq_message_content_size(VALUE obj)
|
106
|
+
{
|
107
|
+
ZmqGetMessage(obj);
|
108
|
+
return INT2NUM(zmsg_content_size(message->message));
|
109
|
+
}
|
110
|
+
|
111
|
+
/*
|
112
|
+
* call-seq:
|
113
|
+
* msg.push(frame) => Boolean
|
114
|
+
*
|
115
|
+
* Push frame to the front of the message, before all other frames. Message takes ownership of the frame and will
|
116
|
+
* destroy it when message is sent.
|
117
|
+
*
|
118
|
+
* === Examples
|
119
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
120
|
+
* msg.push ZMQ::Frame(test) => true
|
121
|
+
* msg.size => 1
|
122
|
+
*
|
123
|
+
*/
|
124
|
+
|
125
|
+
static VALUE rb_czmq_message_push(VALUE obj, VALUE frame_obj)
|
126
|
+
{
|
127
|
+
int rc = 0;
|
128
|
+
errno = 0;
|
129
|
+
ZmqGetMessage(obj);
|
130
|
+
ZmqGetFrame(frame_obj);
|
131
|
+
rc = zmsg_push(message->message, frame);
|
132
|
+
ZmqAssert(rc);
|
133
|
+
rb_czmq_frame_freed(frame);
|
134
|
+
return Qtrue;
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* call-seq:
|
139
|
+
* msg.add(frame) => Boolean
|
140
|
+
*
|
141
|
+
* Add frame to the end of the message, after all other frames. Message takes ownership of the frame and will
|
142
|
+
* destroy it when message is sent.
|
143
|
+
*
|
144
|
+
* === Examples
|
145
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
146
|
+
* msg.add ZMQ::Frame(test) => true
|
147
|
+
* msg.size => 1
|
148
|
+
*
|
149
|
+
*/
|
150
|
+
|
151
|
+
static VALUE rb_czmq_message_add(VALUE obj, VALUE frame_obj)
|
152
|
+
{
|
153
|
+
int rc = 0;
|
154
|
+
errno = 0;
|
155
|
+
ZmqGetMessage(obj);
|
156
|
+
ZmqGetFrame(frame_obj);
|
157
|
+
rc = zmsg_add(message->message, frame);
|
158
|
+
ZmqAssert(rc);
|
159
|
+
rb_czmq_frame_freed(frame);
|
160
|
+
return Qtrue;
|
161
|
+
}
|
162
|
+
|
163
|
+
/*
|
164
|
+
* call-seq:
|
165
|
+
* msg.pop => ZMQ::Frame or nil
|
166
|
+
*
|
167
|
+
* Remove first frame from message, if any. Returns a ZMQ::Frame instance or nil. Caller now owns the frame.
|
168
|
+
*
|
169
|
+
* === Examples
|
170
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
171
|
+
* msg.pushstr "test" => true
|
172
|
+
* msg.pop => ZMQ::Frame
|
173
|
+
* msg.size => 1
|
174
|
+
* msg.pop => nil
|
175
|
+
*
|
176
|
+
*/
|
177
|
+
|
178
|
+
static VALUE rb_czmq_message_pop(VALUE obj)
|
179
|
+
{
|
180
|
+
zframe_t *frame = NULL;
|
181
|
+
ZmqGetMessage(obj);
|
182
|
+
frame = zmsg_pop(message->message);
|
183
|
+
if (frame == NULL) return Qnil;
|
184
|
+
return rb_czmq_alloc_frame(frame);
|
185
|
+
}
|
186
|
+
|
187
|
+
/*
|
188
|
+
* call-seq:
|
189
|
+
* msg.print => nil
|
190
|
+
*
|
191
|
+
* Dumps the first 10 frames of the message to stderr for debugging.
|
192
|
+
*
|
193
|
+
* === Examples
|
194
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
195
|
+
* msg.pushstr "test" => true
|
196
|
+
* msg.print => nil
|
197
|
+
*
|
198
|
+
*/
|
199
|
+
|
200
|
+
static VALUE rb_czmq_message_print(VALUE obj)
|
201
|
+
{
|
202
|
+
ZmqGetMessage(obj);
|
203
|
+
zmsg_dump(message->message);
|
204
|
+
return Qnil;
|
205
|
+
}
|
206
|
+
|
207
|
+
/*
|
208
|
+
* call-seq:
|
209
|
+
* msg.first => ZMQ::Frame or nil
|
210
|
+
*
|
211
|
+
* Resets the cursor to the first message frame, if any.
|
212
|
+
*
|
213
|
+
* === Examples
|
214
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
215
|
+
* msg.pushstr "test" => true
|
216
|
+
* msg.first => ZMQ::Frame
|
217
|
+
* msg.first => nil
|
218
|
+
*
|
219
|
+
*/
|
220
|
+
|
221
|
+
static VALUE rb_czmq_message_first(VALUE obj)
|
222
|
+
{
|
223
|
+
zframe_t *frame = NULL;
|
224
|
+
ZmqGetMessage(obj);
|
225
|
+
frame = zmsg_first(message->message);
|
226
|
+
if (frame == NULL) return Qnil;
|
227
|
+
return rb_czmq_alloc_frame(zframe_dup(frame));
|
228
|
+
}
|
229
|
+
|
230
|
+
/*
|
231
|
+
* call-seq:
|
232
|
+
* msg.next => ZMQ::Frame or nil
|
233
|
+
*
|
234
|
+
* Returns the next message frame or nil if there aren't anymore. Advances the frames cursor and can thus be used for
|
235
|
+
* iteration.
|
236
|
+
*
|
237
|
+
* === Examples
|
238
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
239
|
+
* msg.pushstr "test" => true
|
240
|
+
* msg.next => ZMQ::Frame
|
241
|
+
* msg.next => nil
|
242
|
+
*
|
243
|
+
*/
|
244
|
+
|
245
|
+
static VALUE rb_czmq_message_next(VALUE obj)
|
246
|
+
{
|
247
|
+
zframe_t *frame = NULL;
|
248
|
+
ZmqGetMessage(obj);
|
249
|
+
frame = zmsg_next(message->message);
|
250
|
+
if (frame == NULL) return Qnil;
|
251
|
+
return rb_czmq_alloc_frame(zframe_dup(frame));
|
252
|
+
}
|
253
|
+
|
254
|
+
/*
|
255
|
+
* call-seq:
|
256
|
+
* msg.last => ZMQ::Frame or nil
|
257
|
+
*
|
258
|
+
* Resets the cursor to the last message frame, if any.
|
259
|
+
*
|
260
|
+
* === Examples
|
261
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
262
|
+
* msg.pushstr "test" => true
|
263
|
+
* msg.last => ZMQ::Frame
|
264
|
+
* msg.last => nil
|
265
|
+
*
|
266
|
+
*/
|
267
|
+
|
268
|
+
static VALUE rb_czmq_message_last(VALUE obj)
|
269
|
+
{
|
270
|
+
zframe_t *frame = NULL;
|
271
|
+
ZmqGetMessage(obj);
|
272
|
+
frame = zmsg_last(message->message);
|
273
|
+
if (frame == NULL) return Qnil;
|
274
|
+
return rb_czmq_alloc_frame(zframe_dup(frame));
|
275
|
+
}
|
276
|
+
|
277
|
+
/*
|
278
|
+
* call-seq:
|
279
|
+
* msg.remove(frame) => nil
|
280
|
+
*
|
281
|
+
* Removes the given frame from the message's frame list if present. Does not destroy the frame itself.
|
282
|
+
*
|
283
|
+
* === Examples
|
284
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
285
|
+
* frame = ZMQ::Frame("test") => ZMQ::Frame
|
286
|
+
* msg.push(frame) => true
|
287
|
+
* msg.size => 1
|
288
|
+
* msg.remove(frame) => nil
|
289
|
+
* msg.size => 0
|
290
|
+
*
|
291
|
+
*/
|
292
|
+
|
293
|
+
static VALUE rb_czmq_message_remove(VALUE obj, VALUE frame_obj)
|
294
|
+
{
|
295
|
+
ZmqGetMessage(obj);
|
296
|
+
zframe_t *frame = NULL;
|
297
|
+
ZmqAssertFrame(frame_obj);
|
298
|
+
Data_Get_Struct(frame_obj, zframe_t, frame);
|
299
|
+
zmsg_remove(message->message, frame);
|
300
|
+
return Qnil;
|
301
|
+
}
|
302
|
+
|
303
|
+
/*
|
304
|
+
* call-seq:
|
305
|
+
* msg.pushstr(frame) => Boolean
|
306
|
+
*
|
307
|
+
* Push a string as a new frame to the front of the message, before all other frames.
|
308
|
+
*
|
309
|
+
* === Examples
|
310
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
311
|
+
* msg.pushstr "test" => true
|
312
|
+
*
|
313
|
+
*/
|
314
|
+
|
315
|
+
static VALUE rb_czmq_message_pushstr(VALUE obj, VALUE str)
|
316
|
+
{
|
317
|
+
int rc = 0;
|
318
|
+
errno = 0;
|
319
|
+
ZmqGetMessage(obj);
|
320
|
+
Check_Type(str, T_STRING);
|
321
|
+
rc = zmsg_pushstr(message->message, StringValueCStr(str));
|
322
|
+
ZmqAssert(rc);
|
323
|
+
return Qtrue;
|
324
|
+
}
|
325
|
+
|
326
|
+
/*
|
327
|
+
* call-seq:
|
328
|
+
* msg.addstr(frame) => Boolean
|
329
|
+
*
|
330
|
+
* Push a string as a new frame to the end of the message, after all other frames.
|
331
|
+
*
|
332
|
+
* === Examples
|
333
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
334
|
+
* msg.addstr "test" => true
|
335
|
+
*
|
336
|
+
*/
|
337
|
+
|
338
|
+
static VALUE rb_czmq_message_addstr(VALUE obj, VALUE str)
|
339
|
+
{
|
340
|
+
int rc = 0;
|
341
|
+
errno = 0;
|
342
|
+
ZmqGetMessage(obj);
|
343
|
+
Check_Type(str, T_STRING);
|
344
|
+
rc = zmsg_addstr(message->message, StringValueCStr(str));
|
345
|
+
ZmqAssert(rc);
|
346
|
+
return Qtrue;
|
347
|
+
}
|
348
|
+
|
349
|
+
/*
|
350
|
+
* call-seq:
|
351
|
+
* msg.popstr => String or nil
|
352
|
+
*
|
353
|
+
* Pop frame off front of message, return as a new string.
|
354
|
+
*
|
355
|
+
* === Examples
|
356
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
357
|
+
* msg.addstr "test" => true
|
358
|
+
* msg.popstr => "test"
|
359
|
+
*
|
360
|
+
*/
|
361
|
+
|
362
|
+
static VALUE rb_czmq_message_popstr(VALUE obj)
|
363
|
+
{
|
364
|
+
char *str = NULL;
|
365
|
+
ZmqGetMessage(obj);
|
366
|
+
str = zmsg_popstr(message->message);
|
367
|
+
if (str == NULL) return Qnil;
|
368
|
+
return rb_str_new2(str);
|
369
|
+
}
|
370
|
+
|
371
|
+
/*
|
372
|
+
* call-seq:
|
373
|
+
* msg.wrap(frame) => nil
|
374
|
+
*
|
375
|
+
* Push frame plus empty frame to front of message, before the first frame. Message takes ownership of frame, will
|
376
|
+
* destroy it when message is sent.
|
377
|
+
*
|
378
|
+
* === Examples
|
379
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
380
|
+
* msg.wrap ZMQ::Frame("test") => nil
|
381
|
+
* msg.size => 2
|
382
|
+
*
|
383
|
+
*/
|
384
|
+
|
385
|
+
static VALUE rb_czmq_message_wrap(VALUE obj, VALUE frame_obj)
|
386
|
+
{
|
387
|
+
errno = 0;
|
388
|
+
ZmqGetMessage(obj);
|
389
|
+
ZmqGetFrame(frame_obj);
|
390
|
+
zmsg_wrap(message->message, frame);
|
391
|
+
rb_czmq_frame_freed(frame);
|
392
|
+
return Qnil;
|
393
|
+
}
|
394
|
+
|
395
|
+
/*
|
396
|
+
* call-seq:
|
397
|
+
* msg.unwrap => ZMQ::Frame or nil
|
398
|
+
*
|
399
|
+
* Pop frame off front of message, caller now owns frame. If next frame is empty, pops and destroys that empty frame.
|
400
|
+
*
|
401
|
+
* === Examples
|
402
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
403
|
+
* frame = ZMQ::Frame("test") => ZMQ::Frame
|
404
|
+
* msg.wrap ZMQ::Frame("test") => nil
|
405
|
+
* msg.size => 2
|
406
|
+
* msg.unwrap => frame
|
407
|
+
* msg.size => 0
|
408
|
+
*
|
409
|
+
*/
|
410
|
+
|
411
|
+
static VALUE rb_czmq_message_unwrap(VALUE obj)
|
412
|
+
{
|
413
|
+
zframe_t *frame = NULL;
|
414
|
+
ZmqGetMessage(obj);
|
415
|
+
frame = zmsg_unwrap(message->message);
|
416
|
+
if (frame == NULL) return Qnil;
|
417
|
+
return rb_czmq_alloc_frame(frame);
|
418
|
+
}
|
419
|
+
|
420
|
+
/*
|
421
|
+
* call-seq:
|
422
|
+
* msg.dup => ZMQ::Message
|
423
|
+
*
|
424
|
+
* Creates a copy of this message
|
425
|
+
*
|
426
|
+
* === Examples
|
427
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
428
|
+
* msg.dup => ZMQ::Message
|
429
|
+
*
|
430
|
+
*/
|
431
|
+
|
432
|
+
static VALUE rb_czmq_message_dup(VALUE obj)
|
433
|
+
{
|
434
|
+
VALUE dup;
|
435
|
+
zmq_message_wrapper *dup_msg = NULL;
|
436
|
+
errno = 0;
|
437
|
+
ZmqGetMessage(obj);
|
438
|
+
dup = Data_Make_Struct(rb_cZmqMessage, zmq_message_wrapper, 0, rb_czmq_free_message_gc, dup_msg);
|
439
|
+
dup_msg->message = zmsg_dup(message->message);
|
440
|
+
ZmqAssertObjOnAlloc(dup_msg->message, dup_msg);
|
441
|
+
dup_msg->flags = message->flags;
|
442
|
+
rb_obj_call_init(dup, 0, NULL);
|
443
|
+
return dup;
|
444
|
+
}
|
445
|
+
|
446
|
+
/*
|
447
|
+
* call-seq:
|
448
|
+
* msg.destroy => nil
|
449
|
+
*
|
450
|
+
* Destroys a ZMQ::Message instance and all the frames it contains. Useful for manual memory management, otherwise the GC
|
451
|
+
* will take the same action if a message object is not reachable anymore on the next GC cycle. This is
|
452
|
+
* a lower level API.
|
453
|
+
*
|
454
|
+
* === Examples
|
455
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
456
|
+
* msg.destroy => nil
|
457
|
+
*
|
458
|
+
*/
|
459
|
+
|
460
|
+
static VALUE rb_czmq_message_destroy(VALUE obj)
|
461
|
+
{
|
462
|
+
ZmqGetMessage(obj);
|
463
|
+
rb_czmq_free_message(message);
|
464
|
+
return Qnil;
|
465
|
+
}
|
466
|
+
|
467
|
+
/*
|
468
|
+
* call-seq:
|
469
|
+
* msg.encode => string
|
470
|
+
*
|
471
|
+
* Encodes the message to a new buffer.
|
472
|
+
*
|
473
|
+
* === Examples
|
474
|
+
* msg = ZMQ::Message.new => ZMQ::Message
|
475
|
+
* msg.pushstr "body"
|
476
|
+
* msg.pushstr "header"
|
477
|
+
* msg.encode => "\006header\004body"
|
478
|
+
*
|
479
|
+
*/
|
480
|
+
|
481
|
+
static VALUE rb_czmq_message_encode(VALUE obj)
|
482
|
+
{
|
483
|
+
byte *buff;
|
484
|
+
size_t buff_size;
|
485
|
+
ZmqGetMessage(obj);
|
486
|
+
buff_size = zmsg_encode(message->message, &buff);
|
487
|
+
return rb_str_new((char *)buff, buff_size);
|
488
|
+
}
|
489
|
+
|
490
|
+
/*
|
491
|
+
* call-seq:
|
492
|
+
* ZMQ::Message.decode("\006header\004body") => ZMQ::Message
|
493
|
+
*
|
494
|
+
* Decode a buffer into a new message. Returns nil if the buffer is not properly formatted.
|
495
|
+
*
|
496
|
+
* === Examples
|
497
|
+
* msg = ZMQ::Message.decode("\006header\004body")
|
498
|
+
* msg.popstr => "header"
|
499
|
+
* msg.popstr => "body"
|
500
|
+
*
|
501
|
+
*/
|
502
|
+
|
503
|
+
static VALUE rb_czmq_message_s_decode(ZMQ_UNUSED VALUE obj, VALUE buffer)
|
504
|
+
{
|
505
|
+
zmsg_t * m = NULL;
|
506
|
+
Check_Type(buffer, T_STRING);
|
507
|
+
m = zmsg_decode((byte *)StringValueCStr(buffer), RSTRING_LEN(buffer));
|
508
|
+
if (m == NULL) return Qnil;
|
509
|
+
return rb_czmq_alloc_message(m);
|
510
|
+
}
|
511
|
+
|
512
|
+
/*
|
513
|
+
* call-seq:
|
514
|
+
* msg.eql?(other) => boolean
|
515
|
+
*
|
516
|
+
* Determines if a message equals another. True if size, content size and serialized representation is equal.
|
517
|
+
*
|
518
|
+
* === Examples
|
519
|
+
* msg = ZMQ::Message("header", "body")
|
520
|
+
* other = ZMQ::Message("header", "body")
|
521
|
+
* msg.eql?(other) => true
|
522
|
+
*
|
523
|
+
*/
|
524
|
+
|
525
|
+
static VALUE rb_czmq_message_eql_p(VALUE obj, VALUE other_message)
|
526
|
+
{
|
527
|
+
zmq_message_wrapper *other = NULL;
|
528
|
+
byte *buff = NULL;
|
529
|
+
size_t buff_size;
|
530
|
+
byte *other_buff = NULL;
|
531
|
+
size_t other_buff_size;
|
532
|
+
ZmqGetMessage(obj);
|
533
|
+
ZmqAssertMessage(other_message);
|
534
|
+
Data_Get_Struct(other_message, zmq_message_wrapper, other);
|
535
|
+
if (!other) rb_raise(rb_eTypeError, "uninitialized ZMQ message!");
|
536
|
+
|
537
|
+
if (zmsg_size(message->message) != zmsg_size(other->message)) return Qfalse;
|
538
|
+
if (zmsg_content_size(message->message) != zmsg_content_size(other->message)) return Qfalse;
|
539
|
+
|
540
|
+
buff_size = zmsg_encode(message->message, &buff);
|
541
|
+
other_buff_size = zmsg_encode(other->message, &other_buff);
|
542
|
+
if (buff_size != other_buff_size) return Qfalse;
|
543
|
+
if (strncmp((const char*)buff, (const char*)other_buff, buff_size) != 0) return Qfalse;
|
544
|
+
return Qtrue;
|
545
|
+
}
|
546
|
+
|
547
|
+
/*
|
548
|
+
* call-seq:
|
549
|
+
* msg == other => boolean
|
550
|
+
*
|
551
|
+
* Determines if a message equals another. True if size, content size and serialized representation is equal.
|
552
|
+
*
|
553
|
+
* === Examples
|
554
|
+
* msg = ZMQ::Message("header", "body")
|
555
|
+
* other = ZMQ::Message("header", "body")
|
556
|
+
* msg == other => true
|
557
|
+
*
|
558
|
+
*/
|
559
|
+
|
560
|
+
static VALUE rb_czmq_message_equals(VALUE obj, VALUE other_message)
|
561
|
+
{
|
562
|
+
if (obj == other_message) return Qtrue;
|
563
|
+
return rb_czmq_message_eql_p(obj, other_message);
|
564
|
+
}
|
565
|
+
|
566
|
+
/*
|
567
|
+
* call-seq:
|
568
|
+
* msg.to_a => Array
|
569
|
+
*
|
570
|
+
* Returns an Array of all frames this message is composed of.
|
571
|
+
*
|
572
|
+
* === Examples
|
573
|
+
* ZMQ::Message.new.to_a => []
|
574
|
+
* msg = ZMQ::Message("header", "body") => ZMQ::Message
|
575
|
+
* msg.to_a => [ZMQ::Frame("header"), ZMQ::Frame("body")]
|
576
|
+
*
|
577
|
+
*/
|
578
|
+
|
579
|
+
static VALUE rb_czmq_message_to_a(VALUE obj)
|
580
|
+
{
|
581
|
+
VALUE ary;
|
582
|
+
ZmqGetMessage(obj);
|
583
|
+
ary = rb_ary_new2(zmsg_size(message->message));
|
584
|
+
zframe_t *frame = zmsg_first(message->message);
|
585
|
+
while (frame) {
|
586
|
+
rb_ary_push(ary, rb_czmq_alloc_frame(zframe_dup(frame)));
|
587
|
+
frame = zmsg_next(message->message);
|
588
|
+
}
|
589
|
+
return ary;
|
590
|
+
}
|
591
|
+
|
592
|
+
void _init_rb_czmq_message()
|
593
|
+
{
|
594
|
+
rb_cZmqMessage = rb_define_class_under(rb_mZmq, "Message", rb_cObject);
|
595
|
+
|
596
|
+
rb_define_singleton_method(rb_cZmqMessage, "decode", rb_czmq_message_s_decode, 1);
|
597
|
+
|
598
|
+
rb_define_alloc_func(rb_cZmqMessage, rb_czmq_message_new);
|
599
|
+
rb_define_method(rb_cZmqMessage, "size", rb_czmq_message_size, 0);
|
600
|
+
rb_define_method(rb_cZmqMessage, "content_size", rb_czmq_message_content_size, 0);
|
601
|
+
rb_define_method(rb_cZmqMessage, "push", rb_czmq_message_push, 1);
|
602
|
+
rb_define_method(rb_cZmqMessage, "pop", rb_czmq_message_pop, 0);
|
603
|
+
rb_define_method(rb_cZmqMessage, "add", rb_czmq_message_add, 1);
|
604
|
+
rb_define_method(rb_cZmqMessage, "wrap", rb_czmq_message_wrap, 1);
|
605
|
+
rb_define_method(rb_cZmqMessage, "unwrap", rb_czmq_message_unwrap, 0);
|
606
|
+
rb_define_method(rb_cZmqMessage, "print", rb_czmq_message_print, 0);
|
607
|
+
rb_define_method(rb_cZmqMessage, "first", rb_czmq_message_first, 0);
|
608
|
+
rb_define_method(rb_cZmqMessage, "next", rb_czmq_message_next, 0);
|
609
|
+
rb_define_method(rb_cZmqMessage, "last", rb_czmq_message_last, 0);
|
610
|
+
rb_define_method(rb_cZmqMessage, "remove", rb_czmq_message_remove, 1);
|
611
|
+
rb_define_method(rb_cZmqMessage, "pushstr", rb_czmq_message_pushstr, 1);
|
612
|
+
rb_define_method(rb_cZmqMessage, "popstr", rb_czmq_message_popstr, 0);
|
613
|
+
rb_define_method(rb_cZmqMessage, "addstr", rb_czmq_message_addstr, 1);
|
614
|
+
rb_define_method(rb_cZmqMessage, "dup", rb_czmq_message_dup, 0);
|
615
|
+
rb_define_method(rb_cZmqMessage, "destroy", rb_czmq_message_destroy, 0);
|
616
|
+
rb_define_method(rb_cZmqMessage, "encode", rb_czmq_message_encode, 0);
|
617
|
+
rb_define_method(rb_cZmqMessage, "eql?", rb_czmq_message_equals, 1);
|
618
|
+
rb_define_method(rb_cZmqMessage, "==", rb_czmq_message_equals, 1);
|
619
|
+
rb_define_method(rb_cZmqMessage, "to_a", rb_czmq_message_to_a, 0);
|
620
|
+
}
|