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.
Files changed (101) hide show
  1. data/.gitignore +23 -0
  2. data/.travis.yml +19 -0
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +19 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +247 -0
  7. data/Rakefile +67 -0
  8. data/examples/loop.rb +109 -0
  9. data/examples/poller.rb +37 -0
  10. data/examples/pub_sub.rb +101 -0
  11. data/examples/push_pull.rb +104 -0
  12. data/examples/req_rep.rb +100 -0
  13. data/ext/czmq.tar.gz +0 -0
  14. data/ext/rbczmq/context.c +280 -0
  15. data/ext/rbczmq/context.h +26 -0
  16. data/ext/rbczmq/extconf.rb +138 -0
  17. data/ext/rbczmq/frame.c +401 -0
  18. data/ext/rbczmq/frame.h +24 -0
  19. data/ext/rbczmq/jruby.h +22 -0
  20. data/ext/rbczmq/loop.c +413 -0
  21. data/ext/rbczmq/loop.h +24 -0
  22. data/ext/rbczmq/message.c +620 -0
  23. data/ext/rbczmq/message.h +24 -0
  24. data/ext/rbczmq/poller.c +308 -0
  25. data/ext/rbczmq/poller.h +29 -0
  26. data/ext/rbczmq/pollitem.c +251 -0
  27. data/ext/rbczmq/pollitem.h +25 -0
  28. data/ext/rbczmq/rbczmq_ext.c +198 -0
  29. data/ext/rbczmq/rbczmq_ext.h +94 -0
  30. data/ext/rbczmq/rbczmq_prelude.h +22 -0
  31. data/ext/rbczmq/rubinius.h +24 -0
  32. data/ext/rbczmq/ruby18.h +43 -0
  33. data/ext/rbczmq/ruby19.h +15 -0
  34. data/ext/rbczmq/socket.c +1570 -0
  35. data/ext/rbczmq/socket.h +136 -0
  36. data/ext/rbczmq/timer.c +110 -0
  37. data/ext/rbczmq/timer.h +23 -0
  38. data/ext/zeromq.tar.gz +0 -0
  39. data/lib/rbczmq.rb +3 -0
  40. data/lib/zmq.rb +77 -0
  41. data/lib/zmq/context.rb +50 -0
  42. data/lib/zmq/default_handler.rb +16 -0
  43. data/lib/zmq/frame.rb +11 -0
  44. data/lib/zmq/handler.rb +76 -0
  45. data/lib/zmq/loop.rb +131 -0
  46. data/lib/zmq/message.rb +9 -0
  47. data/lib/zmq/poller.rb +22 -0
  48. data/lib/zmq/pollitem.rb +31 -0
  49. data/lib/zmq/socket.rb +125 -0
  50. data/lib/zmq/socket/dealer.rb +33 -0
  51. data/lib/zmq/socket/pair.rb +39 -0
  52. data/lib/zmq/socket/pub.rb +30 -0
  53. data/lib/zmq/socket/pull.rb +29 -0
  54. data/lib/zmq/socket/push.rb +32 -0
  55. data/lib/zmq/socket/rep.rb +37 -0
  56. data/lib/zmq/socket/req.rb +37 -0
  57. data/lib/zmq/socket/router.rb +38 -0
  58. data/lib/zmq/socket/sub.rb +27 -0
  59. data/lib/zmq/timer.rb +12 -0
  60. data/lib/zmq/version.rb +5 -0
  61. data/perf/pair.rb +7 -0
  62. data/perf/pair/local.rb +22 -0
  63. data/perf/pair/remote.rb +25 -0
  64. data/perf/pub_sub.rb +7 -0
  65. data/perf/pub_sub/local.rb +22 -0
  66. data/perf/pub_sub/remote.rb +25 -0
  67. data/perf/push_pull.rb +7 -0
  68. data/perf/push_pull/local.rb +21 -0
  69. data/perf/push_pull/remote.rb +25 -0
  70. data/perf/req_rep.rb +7 -0
  71. data/perf/req_rep/local.rb +35 -0
  72. data/perf/req_rep/remote.rb +28 -0
  73. data/perf/runner.rb +142 -0
  74. data/rbczmq.gemspec +22 -0
  75. data/test/helper.rb +21 -0
  76. data/test/socket/test_dealer_socket.rb +14 -0
  77. data/test/socket/test_pair_socket.rb +24 -0
  78. data/test/socket/test_pair_sockets.rb +74 -0
  79. data/test/socket/test_pub_socket.rb +17 -0
  80. data/test/socket/test_pub_sub_sockets.rb +87 -0
  81. data/test/socket/test_pull_socket.rb +17 -0
  82. data/test/socket/test_push_pull_sockets.rb +81 -0
  83. data/test/socket/test_push_socket.rb +17 -0
  84. data/test/socket/test_rep_socket.rb +25 -0
  85. data/test/socket/test_req_rep_sockets.rb +42 -0
  86. data/test/socket/test_req_socket.rb +27 -0
  87. data/test/socket/test_router_socket.rb +14 -0
  88. data/test/socket/test_routing.rb +66 -0
  89. data/test/socket/test_sub_socket.rb +17 -0
  90. data/test/test_context.rb +86 -0
  91. data/test/test_frame.rb +78 -0
  92. data/test/test_handler.rb +28 -0
  93. data/test/test_loop.rb +252 -0
  94. data/test/test_message.rb +201 -0
  95. data/test/test_poller.rb +154 -0
  96. data/test/test_pollitem.rb +78 -0
  97. data/test/test_socket.rb +403 -0
  98. data/test/test_threading.rb +34 -0
  99. data/test/test_timer.rb +37 -0
  100. data/test/test_zmq.rb +62 -0
  101. 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
+ }