rbczmq 0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }