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
@@ -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
+ }