rbczmq 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -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')
|
data/ext/rbczmq/frame.c
ADDED
@@ -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
|
+
}
|