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
@@ -0,0 +1,26 @@
1
+ #ifndef RBCZMQ_CONTEXT_H
2
+ #define RBCZMQ_CONTEXT_H
3
+
4
+ #define ZMQ_CONTEXT_DESTROYED 0x01
5
+
6
+ typedef struct {
7
+ zctx_t *ctx;
8
+ int flags;
9
+ } zmq_ctx_wrapper;
10
+
11
+ #define ZmqAssertContext(obj) ZmqAssertType(obj, rb_cZmqContext, "ZMQ::Context")
12
+ #define ZmqGetContext(obj) \
13
+ zmq_ctx_wrapper *ctx = NULL; \
14
+ ZmqAssertContext(obj); \
15
+ Data_Get_Struct(obj, zmq_ctx_wrapper, ctx); \
16
+ if (!ctx) rb_raise(rb_eTypeError, "uninitialized ZMQ context!"); \
17
+ if (ctx->flags & ZMQ_CONTEXT_DESTROYED) rb_raise(rb_eZmqError, "ZMQ::Context instance %p has been destroyed by the ZMQ framework", (void *)obj);
18
+
19
+ struct nogvl_socket_args {
20
+ zctx_t *ctx;
21
+ int type;
22
+ };
23
+
24
+ void _init_rb_czmq_context();
25
+
26
+ #endif
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+
3
+ require 'mkmf'
4
+ require 'pathname'
5
+
6
+ def sys(cmd, err_msg)
7
+ p cmd
8
+ system(cmd) || fail(err_msg)
9
+ end
10
+
11
+ def fail(msg)
12
+ STDERR.puts msg
13
+ exit(1)
14
+ end
15
+
16
+ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
17
+
18
+ # XXX fallbacks specific to Darwin for JRuby (does not set these values in RbConfig::CONFIG)
19
+ LIBEXT = RbConfig::CONFIG['LIBEXT'] || 'a'
20
+ DLEXT = RbConfig::CONFIG['DLEXT'] || 'bundle'
21
+
22
+ cwd = Pathname(File.expand_path(File.dirname(__FILE__)))
23
+ dst_path = cwd + 'dst'
24
+ libs_path = dst_path + 'lib'
25
+ vendor_path = cwd + '..'
26
+ zmq_path = vendor_path + 'zeromq'
27
+ czmq_path = vendor_path + 'czmq'
28
+ zmq_include_path = zmq_path + 'include'
29
+ czmq_include_path = czmq_path + 'include'
30
+
31
+ # Fail early if we don't meet the following dependencies.
32
+
33
+ # Present on OS X and BSD systems, package install required on Linux
34
+ fail("package uuid-dev required (apt-get install uuid-dev)") unless have_header('uuid/uuid.h')
35
+
36
+ # Courtesy of EventMachine and @tmm1
37
+ def check_libs libs = [], fatal = false
38
+ libs.all? { |lib| have_library(lib) || (abort("could not find library: #{lib}") if fatal) }
39
+ end
40
+
41
+ def check_heads heads = [], fatal = false
42
+ heads.all? { |head| have_header(head) || (abort("could not find header: #{head}") if fatal)}
43
+ end
44
+
45
+ case RUBY_PLATFORM
46
+ when /mswin32/, /mingw32/, /bccwin32/
47
+ check_heads(%w[windows.h winsock.h], true)
48
+ check_libs(%w[kernel32 rpcrt4 gdi32], true)
49
+
50
+ if GNU_CHAIN
51
+ CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++"
52
+ else
53
+ $defs.push "-EHs"
54
+ $defs.push "-GR"
55
+ end
56
+
57
+ when /solaris/
58
+ add_define 'OS_SOLARIS8'
59
+
60
+ if CONFIG['CC'] == 'cc' and `cc -flags 2>&1` =~ /Sun/ # detect SUNWspro compiler
61
+ # SUN CHAIN
62
+ add_define 'CC_SUNWspro'
63
+ $preload = ["\nCXX = CC"] # hack a CXX= line into the makefile
64
+ $CFLAGS = CONFIG['CFLAGS'] = "-KPIC"
65
+ CONFIG['CCDLFLAGS'] = "-KPIC"
66
+ CONFIG['LDSHARED'] = "$(CXX) -G -KPIC -lCstd"
67
+ else
68
+ # GNU CHAIN
69
+ # on Unix we need a g++ link, not gcc.
70
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
71
+ end
72
+
73
+ when /openbsd/
74
+ # OpenBSD branch contributed by Guillaume Sellier.
75
+
76
+ # on Unix we need a g++ link, not gcc. On OpenBSD, linking against libstdc++ have to be explicitly done for shared libs
77
+ CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++ -fPIC"
78
+ CONFIG['LDSHAREDXX'] = "$(CXX) -shared -lstdc++ -fPIC"
79
+
80
+ when /darwin/
81
+ # on Unix we need a g++ link, not gcc.
82
+ # Ff line contributed by Daniel Harple.
83
+ CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
84
+
85
+ when /aix/
86
+ CONFIG['LDSHARED'] = "$(CXX) -shared -Wl,-G -Wl,-brtl"
87
+
88
+ else
89
+ # on Unix we need a g++ link, not gcc.
90
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
91
+ end
92
+
93
+ # extract dependencies
94
+ unless File.directory?(zmq_path) && File.directory?(czmq_path)
95
+ fail "The 'tar' (creates and manipulates streaming archive files) utility is required to extract dependencies" if `which tar`.strip.empty?
96
+ Dir.chdir(vendor_path) do
97
+ sys "tar xvzf zeromq.tar.gz", "Could not extract the ZeroMQ archive!"
98
+ sys "tar xvzf czmq.tar.gz", "Could not extract the CZMQ archive!"
99
+ end
100
+ end
101
+
102
+ # build libzmq
103
+ lib = libs_path + "libzmq.#{LIBEXT}"
104
+ Dir.chdir zmq_path do
105
+ sys "./autogen.sh", "ZeroMQ autogen failed!" unless File.exist?(zmq_path + 'configure')
106
+ sys "./configure --prefix=#{dst_path} --without-documentation --enable-shared && make && make install", "ZeroMQ compile error!"
107
+ end unless File.exist?(lib)
108
+
109
+ # build libczmq
110
+ lib = libs_path + "libczmq.#{LIBEXT}"
111
+ Dir.chdir czmq_path do
112
+ sys "./autogen.sh", "CZMQ autogen failed!" unless File.exist?(czmq_path + 'configure')
113
+ sys "./configure LDFLAGS=-L#{libs_path} --prefix=#{dst_path} --with-libzmq=#{dst_path} --disable-shared && make all && make install", "CZMQ compile error!"
114
+ end unless File.exist?(lib)
115
+
116
+ dir_config('rbczmq')
117
+
118
+ have_func('rb_thread_blocking_region')
119
+
120
+ $INCFLAGS << " -I#{zmq_include_path}" if find_header("zmq.h", zmq_include_path)
121
+ $INCFLAGS << " -I#{czmq_include_path}" if find_header("czmq.h", czmq_include_path)
122
+
123
+ $LIBPATH << libs_path.to_s
124
+
125
+ # Special case to prevent Rubinius compile from linking system libzmq if present
126
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
127
+ CONFIG['LDSHARED'] = "#{CONFIG['LDSHARED']} -Wl,-rpath=#{libs_path.to_s}"
128
+ end
129
+
130
+ fail "Error compiling and linking libzmq" unless have_library("zmq")
131
+ fail "Error compiling and linking libczmq" unless have_library("czmq")
132
+
133
+ $defs << "-pedantic"
134
+
135
+ $CFLAGS << ' -Wall -funroll-loops'
136
+ $CFLAGS << ' -Wextra -O0 -ggdb3' if ENV['DEBUG']
137
+
138
+ create_makefile('rbczmq_ext')
@@ -0,0 +1,401 @@
1
+ #include <rbczmq_ext.h>
2
+ static VALUE intern_data;
3
+
4
+ /*
5
+ * :nodoc:
6
+ * Callback invoked by zframe_destroy in libczmq. We track all frames coerced to native objects in a symbol table
7
+ * to guard against a mismatch between allocated frames and the Ruby object space as zframe_destroy is invoked
8
+ * throughout libczmq (zmsg.c) where the Ruby GC can't easily track it. Ruby MRI Object finalizers are a real
9
+ * pita to deal with.
10
+ *
11
+ */
12
+ void rb_czmq_frame_freed(zframe_t *frame)
13
+ {
14
+ st_delete(frames_map, (st_data_t*)&frame, 0);
15
+ }
16
+
17
+ /*
18
+ * :nodoc:
19
+ * Coerce a zframe instance to a native Ruby object.
20
+ *
21
+ */
22
+ VALUE rb_czmq_alloc_frame(zframe_t *frame)
23
+ {
24
+ VALUE frame_obj;
25
+ ZmqRegisterFrame(frame);
26
+ frame_obj = Data_Wrap_Struct(rb_cZmqFrame, 0, rb_czmq_free_frame_gc, frame);
27
+ rb_obj_call_init(frame_obj, 0, NULL);
28
+ return frame_obj;
29
+ }
30
+
31
+ /*
32
+ * :nodoc:
33
+ * Free all resources for a frame - invoked by the lower level ZMQ::Frame#destroy as well as the GC callback. We also
34
+ * do a symbol table lookup here to ensure we don't double free a struct that's already been recycled from within
35
+ * libczmq.
36
+ *
37
+ */
38
+ void rb_czmq_free_frame(zframe_t *frame)
39
+ {
40
+ if (frame)
41
+ if (st_lookup(frames_map, (st_data_t)frame, 0)) zframe_destroy(&frame);
42
+ }
43
+
44
+ /*
45
+ * :nodoc:
46
+ * GC free callback
47
+ *
48
+ */
49
+ void rb_czmq_free_frame_gc(void *ptr)
50
+ {
51
+ zframe_t *frame = (zframe_t *)ptr;
52
+ rb_czmq_free_frame(frame);
53
+ }
54
+
55
+ /*
56
+ * call-seq:
57
+ * ZMQ::Frame.new => ZMQ::Frame
58
+ * ZMQ::Frame.new("data") => ZMQ::Frame
59
+ *
60
+ * Creates a new ZMQ::Frame instance. Can be initialized with or without data. A frame corresponds to one zmq_msg_t.
61
+ *
62
+ * === Examples
63
+ * ZMQ::Frame.new => ZMQ::Frame
64
+ * ZMQ::Frame.new("data") => ZMQ::Frame
65
+ *
66
+ */
67
+
68
+ static VALUE rb_czmq_frame_s_new(int argc, VALUE *argv, VALUE frame)
69
+ {
70
+ VALUE data;
71
+ errno = 0;
72
+ zframe_t *fr;
73
+ rb_scan_args(argc, argv, "01", &data);
74
+ if (NIL_P(data)) {
75
+ fr = zframe_new(NULL, 0);
76
+ } else {
77
+ Check_Type(data, T_STRING);
78
+ fr = zframe_new(RSTRING_PTR(data), (size_t)RSTRING_LEN(data));
79
+ }
80
+ if (fr == NULL) {
81
+ ZmqAssertSysError();
82
+ rb_memerror();
83
+ }
84
+ ZmqRegisterFrame(fr);
85
+ frame = Data_Wrap_Struct(rb_cZmqFrame, 0, rb_czmq_free_frame_gc, fr);
86
+ rb_obj_call_init(frame, 0, NULL);
87
+ return frame;
88
+ }
89
+
90
+ /*
91
+ * call-seq:
92
+ * frame.destroy => nil
93
+ *
94
+ * Explicitly destroys an allocated ZMQ::Frame instance. Useful for manual memory management, otherwise the GC
95
+ * will take the same action if a frame object is not reachable anymore on the next GC cycle. This is
96
+ * a lower level API.
97
+ *
98
+ * === Examples
99
+ * frame = ZMQ::Frame.new("data") => ZMQ::Frame
100
+ * frame.destroy => nil
101
+ *
102
+ */
103
+
104
+ static VALUE rb_czmq_frame_destroy(VALUE obj)
105
+ {
106
+ ZmqGetFrame(obj);
107
+ rb_czmq_free_frame(frame);
108
+ return Qnil;
109
+ }
110
+
111
+ /*
112
+ * call-seq:
113
+ * frame.size => Fixnum
114
+ *
115
+ * Returns the size of the frame.
116
+ *
117
+ * === Examples
118
+ * frame = ZMQ::Frame.new("data") => ZMQ::Frame
119
+ * frame.size => 4
120
+ *
121
+ */
122
+
123
+ static VALUE rb_czmq_frame_size(VALUE obj)
124
+ {
125
+ size_t size;
126
+ ZmqGetFrame(obj);
127
+ size = zframe_size(frame);
128
+ return LONG2FIX(size);
129
+ }
130
+
131
+ /*
132
+ * call-seq:
133
+ * frame.data => String
134
+ *
135
+ * Returns the data represented by the frame as a string.
136
+ *
137
+ * === Examples
138
+ * frame = ZMQ::Frame.new("data") => ZMQ::Frame
139
+ * frame.data => "data"
140
+ *
141
+ */
142
+
143
+ static VALUE rb_czmq_frame_data(VALUE obj)
144
+ {
145
+ size_t size;
146
+ ZmqGetFrame(obj);
147
+ size = zframe_size(frame);
148
+ return ZmqEncode(rb_str_new((char *)zframe_data(frame), (long)size));
149
+ }
150
+
151
+ /*
152
+ * call-seq:
153
+ * frame.to_s => String
154
+ *
155
+ * Returns a String representation of this frame.
156
+ *
157
+ * === Examples
158
+ * frame = ZMQ::Frame.new("data") => ZMQ::Frame
159
+ * frame.to_s => "data"
160
+ *
161
+ */
162
+
163
+ static VALUE rb_czmq_frame_to_s(VALUE obj)
164
+ {
165
+ return rb_funcall(obj, intern_data, 0, 0);
166
+ }
167
+
168
+ /*
169
+ * call-seq:
170
+ * frame.strhex => String
171
+ *
172
+ * Returns a printable hex representation of this frame
173
+ *
174
+ * === Examples
175
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
176
+ * frame.strhex => "6D657373616765"
177
+ *
178
+ */
179
+
180
+ static VALUE rb_czmq_frame_strhex(VALUE obj)
181
+ {
182
+ ZmqGetFrame(obj);
183
+ return rb_str_new2(zframe_strhex(frame));
184
+ }
185
+
186
+ /*
187
+ * call-seq:
188
+ * frame.dup => ZMQ::Frame
189
+ *
190
+ * Returns a copy of the current frame
191
+ *
192
+ * === Examples
193
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
194
+ * frame.dup => ZMQ::Frame
195
+ *
196
+ */
197
+
198
+ static VALUE rb_czmq_frame_dup(VALUE obj)
199
+ {
200
+ VALUE dup;
201
+ zframe_t *dup_fr = NULL;
202
+ errno = 0;
203
+ ZmqGetFrame(obj);
204
+ dup_fr = zframe_dup(frame);
205
+ if (dup_fr == NULL) {
206
+ ZmqAssertSysError();
207
+ rb_memerror();
208
+ }
209
+ ZmqRegisterFrame(dup_fr);
210
+ dup = Data_Wrap_Struct(rb_cZmqFrame, 0, rb_czmq_free_frame_gc, dup_fr);
211
+ rb_obj_call_init(dup, 0, NULL);
212
+ return dup;
213
+ }
214
+
215
+ /*
216
+ * call-seq:
217
+ * frame.data_equals?("data") => boolean
218
+ *
219
+ * Determines if the current frame's payload matches a given string
220
+ *
221
+ * === Examples
222
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
223
+ * frame.data_equals?("message") => true
224
+ *
225
+ */
226
+
227
+ static VALUE rb_czmq_frame_data_equals_p(VALUE obj, VALUE data)
228
+ {
229
+ ZmqGetFrame(obj);
230
+ Check_Type(data, T_STRING);
231
+ return (zframe_streq(frame, RSTRING_PTR(data)) == TRUE) ? Qtrue : Qfalse;
232
+ }
233
+
234
+ /*
235
+ * call-seq:
236
+ * frame.more? => boolean
237
+ *
238
+ * Determines if the current frame is part of a multipart message.
239
+ *
240
+ * === Examples
241
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
242
+ * frame.more? => false
243
+ *
244
+ */
245
+
246
+ static VALUE rb_czmq_frame_more_p(VALUE obj)
247
+ {
248
+ ZmqGetFrame(obj);
249
+ return (zframe_more(frame) == ZFRAME_MORE) ? Qtrue : Qfalse;
250
+ }
251
+
252
+ /*
253
+ * call-seq:
254
+ * frame.eql?(other) => boolean
255
+ *
256
+ * Determines if the current frame is equal to another (identical size and data).
257
+ *
258
+ * === Examples
259
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
260
+ * other_frame = ZMQ::Frame.new("other")
261
+ * frame.eql?(other_frame) => false
262
+ *
263
+ */
264
+
265
+ static VALUE rb_czmq_frame_eql_p(VALUE obj, VALUE other_frame)
266
+ {
267
+ zframe_t *other = NULL;
268
+ ZmqGetFrame(obj);
269
+ ZmqAssertFrame(other_frame);
270
+ Data_Get_Struct(other_frame, zframe_t, other);
271
+ if (!other) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!"); \
272
+ if (!(st_lookup(frames_map, (st_data_t)other, 0))) rb_raise(rb_eZmqError, "object %p has been destroyed by the ZMQ framework", (void *)other_frame);
273
+ return (zframe_eq(frame, other)) ? Qtrue : Qfalse;
274
+ }
275
+
276
+ /*
277
+ * call-seq:
278
+ * frame == other => boolean
279
+ *
280
+ * Determines if the current frame is equal to another (identical size and data).
281
+ *
282
+ * === Examples
283
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
284
+ * other_frame = ZMQ::Frame.new("other")
285
+ * frame == other_frame => false
286
+ * frame == frame => true
287
+ *
288
+ */
289
+
290
+ static VALUE rb_czmq_frame_equals(VALUE obj, VALUE other_frame)
291
+ {
292
+ if (obj == other_frame) return Qtrue;
293
+ return rb_czmq_frame_eql_p(obj, other_frame);
294
+ }
295
+
296
+ /*
297
+ * call-seq:
298
+ * frame <=> other => boolean
299
+ *
300
+ * Comparable support for ZMQ::Frame instances.
301
+ *
302
+ * === Examples
303
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
304
+ * other_frame = ZMQ::Frame.new("other")
305
+ * frame > other_frame => true
306
+ *
307
+ */
308
+
309
+ static VALUE rb_czmq_frame_cmp(VALUE obj, VALUE other_frame)
310
+ {
311
+ long diff;
312
+ zframe_t *other = NULL;
313
+ if (obj == other_frame) return INT2NUM(0);
314
+ ZmqGetFrame(obj);
315
+ ZmqAssertFrame(other_frame);
316
+ Data_Get_Struct(other_frame, zframe_t, other);
317
+ if (!other) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!"); \
318
+ if (!(st_lookup(frames_map, (st_data_t)other, 0))) rb_raise(rb_eZmqError, "object %p has been destroyed by the ZMQ framework", (void *)other_frame);
319
+ diff = (zframe_size(frame) - zframe_size(other));
320
+ if (diff == 0) return INT2NUM(0);
321
+ if (diff > 0) return INT2NUM(1);
322
+ return INT2NUM(-1);
323
+ }
324
+
325
+ /*
326
+ * call-seq:
327
+ * frame.print => nil
328
+ *
329
+ * Dumps out frame contents to stderr
330
+ *
331
+ * === Examples
332
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
333
+ * frame.print => nil
334
+ *
335
+ */
336
+
337
+ static VALUE rb_czmq_frame_print(int argc, VALUE *argv, VALUE obj)
338
+ {
339
+ VALUE prefix;
340
+ const char *print_prefix = NULL;
341
+ ZmqGetFrame(obj);
342
+ rb_scan_args(argc, argv, "01", &prefix);
343
+ if (NIL_P(prefix)) {
344
+ print_prefix = "";
345
+ } else {
346
+ Check_Type(prefix, T_STRING);
347
+ print_prefix = RSTRING_PTR(prefix);
348
+ }
349
+ zframe_print(frame, (char *)print_prefix);
350
+ return Qnil;
351
+ }
352
+
353
+ /*
354
+ * call-seq:
355
+ * frame.reset("new") => nil
356
+ *
357
+ * Sets new content for this frame
358
+ *
359
+ * === Examples
360
+ * frame = ZMQ::Frame.new("message") => ZMQ::Frame
361
+ * frame.reset("new") => nil
362
+ * frame.data => "new"
363
+ *
364
+ */
365
+
366
+ static VALUE rb_czmq_frame_reset(VALUE obj, VALUE data)
367
+ {
368
+ errno = 0;
369
+ ZmqGetFrame(obj);
370
+ Check_Type(data, T_STRING);
371
+ zframe_reset(frame, (char *)RSTRING_PTR(data), (size_t)RSTRING_LEN(data));
372
+ ZmqAssertSysError();
373
+ return Qnil;
374
+ }
375
+
376
+ void _init_rb_czmq_frame()
377
+ {
378
+ intern_data = rb_intern("data");
379
+
380
+ rb_cZmqFrame = rb_define_class_under(rb_mZmq, "Frame", rb_cObject);
381
+
382
+ rb_define_const(rb_cZmqFrame, "MORE", INT2NUM(ZFRAME_MORE));
383
+ rb_define_const(rb_cZmqFrame, "REUSE", INT2NUM(ZFRAME_REUSE));
384
+
385
+ rb_define_singleton_method(rb_cZmqFrame, "new", rb_czmq_frame_s_new, -1);
386
+ rb_define_method(rb_cZmqFrame, "destroy", rb_czmq_frame_destroy, 0);
387
+ rb_define_method(rb_cZmqFrame, "size", rb_czmq_frame_size, 0);
388
+ rb_define_method(rb_cZmqFrame, "dup", rb_czmq_frame_dup, 0);
389
+ rb_define_method(rb_cZmqFrame, "data", rb_czmq_frame_data, 0);
390
+ rb_define_method(rb_cZmqFrame, "to_s", rb_czmq_frame_to_s, 0);
391
+ rb_define_method(rb_cZmqFrame, "to_str", rb_czmq_frame_to_s, 0);
392
+ rb_define_method(rb_cZmqFrame, "strhex", rb_czmq_frame_strhex, 0);
393
+ rb_define_method(rb_cZmqFrame, "data_equals?", rb_czmq_frame_data_equals_p, 1);
394
+ rb_define_method(rb_cZmqFrame, "more?", rb_czmq_frame_more_p, 0);
395
+ rb_define_method(rb_cZmqFrame, "eql?", rb_czmq_frame_eql_p, 1);
396
+ rb_define_method(rb_cZmqFrame, "==", rb_czmq_frame_equals, 1);
397
+ rb_define_method(rb_cZmqFrame, "<=>", rb_czmq_frame_cmp, 1);
398
+ rb_define_method(rb_cZmqFrame, "print", rb_czmq_frame_print, -1);
399
+ rb_define_alias(rb_cZmqFrame, "dump", "print");
400
+ rb_define_method(rb_cZmqFrame, "reset", rb_czmq_frame_reset, 1);
401
+ }