File Coverage

Raw.xs
Criterion Covered Total %
statement 81 92 88.0
branch 32 76 42.1
condition n/a
subroutine n/a
pod n/a
total 113 168 67.2


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #include "ppport.h"
6              
7             #include
8             #include
9             #include
10             #include
11              
12             #ifndef MUTABLE_GV
13             #define MUTABLE_GV(p) ((GV *)MUTABLE_PTR(p))
14             #endif
15              
16             #define FEATURE_IPC 1
17             #define FEATURE_PGM 2
18             #define FEATURE_TIPC 3
19             #define FEATURE_NORM 4
20             #define FEATURE_CURVE 5
21             #define FEATURE_GSSAPI 6
22             #define FEATURE_DRAFT 7
23              
24             #include "const-c-constant.inc"
25             #include "const-c-error.inc"
26             #include "const-c-message_options.inc"
27             #include "const-c-message_properties.inc"
28             #include "const-c-socket_options.inc"
29              
30             typedef struct
31             {
32             void *context;
33             zmq_raw_mutex *mutex;
34             zmq_raw_timers *timers;
35             int reference_count;
36             } zmq_raw_context;
37              
38             typedef struct
39             {
40             int code;
41             SV *message;
42             const char *file;
43             unsigned int line;
44             } zmq_raw_error;
45              
46             typedef struct
47             {
48             void *socket;
49             void *context;
50             int type;
51             } zmq_raw_socket;
52              
53             typedef struct
54             {
55             void *poller;
56             zmq_raw_event_map *interested;
57             zmq_raw_event_map *events;
58             zmq_poller_event_t *poller_events;
59             int allocated;
60             int size;
61             } zmq_raw_poller;
62              
63             typedef struct
64             {
65             int dummy;
66             } zmq_raw_proxy;
67              
68             typedef struct my_cxt_t
69             {
70             zmq_raw_timers *timers;
71             zmq_raw_mutex *context_mutex;
72             } my_cxt_t;
73              
74 228           STATIC PerlIO *zmq_get_socket_io (SV *sv)
75             {
76 228 100         if (SvROK (sv))
77 227           sv = SvRV (sv);
78              
79 228 100         if (SvTYPE (sv) == SVt_PVGV)
80             {
81 2 50         if (isGV_with_GP (sv))
    50          
    0          
82             {
83 2           GV *gv = MUTABLE_GV (sv);
84 2 50         IO *io = GvIO (gv);
    50          
    0          
    50          
85 2 50         if (io)
86 2           return IoIFP (io);
87             }
88             }
89              
90 226           return NULL;
91             }
92              
93             #ifdef _WIN32
94             STATIC SOCKET zmq_get_native_socket (PerlIO *io)
95             {
96             return _get_osfhandle (PerlIO_fileno (io));
97             }
98             #else
99 2           STATIC int zmq_get_native_socket (PerlIO *io)
100             {
101 2           return PerlIO_fileno (io);
102             }
103             #endif
104              
105             STATIC MGVTBL null_mg_vtbl =
106             {
107             NULL, /* get */
108             NULL, /* set */
109             NULL, /* len */
110             NULL, /* clear */
111             NULL, /* free */
112             #if MGf_COPY
113             NULL, /* copy */
114             #endif /* MGf_COPY */
115             #if MGf_DUP
116             NULL, /* dup */
117             #endif /* MGf_DUP */
118             #if MGf_LOCAL
119             NULL, /* local */
120             #endif /* MGf_LOCAL */
121             };
122              
123              
124             #ifdef USE_ITHREADS
125             static int zmq_raw_ctx_dup (pTHX_ MAGIC *magic, CLONE_PARAMS *param)
126             {
127             zmq_raw_context *context = (zmq_raw_context *)magic->mg_ptr;
128             zmq_raw_mutex_lock (context->mutex);
129             ++context->reference_count;
130             zmq_raw_mutex_unlock (context->mutex);
131             return 0;
132             }
133             #endif
134              
135 74           STATIC void xs_object_magic_attach_struct_with_table (pTHX_ SV *sv, void *ptr, MGVTBL *table, int flags)
136             {
137 74           MAGIC *magic = sv_magicext (sv, NULL, PERL_MAGIC_ext, table, (const char *)ptr, 0);
138 74           magic->mg_flags |= flags;
139 74           }
140              
141 74           STATIC void xs_object_magic_attach_struct(pTHX_ SV *sv, void *ptr)
142             {
143 74           xs_object_magic_attach_struct_with_table (aTHX_ sv, ptr, &null_mg_vtbl, 0);
144 74           }
145              
146              
147 74           STATIC void *xs_object_magic_get_struct (pTHX_ SV *sv)
148             {
149 74           MAGIC *mg = NULL;
150              
151 74 50         if (SvTYPE (sv) >= SVt_PVMG)
152             {
153             MAGIC *tmp;
154              
155 148 100         for (tmp = SvMAGIC(sv); tmp;
156 74           tmp = tmp -> mg_moremagic) {
157 74 50         if ((tmp -> mg_type == PERL_MAGIC_ext) &&
    50          
158 74           (tmp -> mg_virtual == &null_mg_vtbl))
159 74           mg = tmp;
160             }
161             }
162              
163 74 50         return (mg) ? mg -> mg_ptr : NULL;
164             }
165              
166              
167             #define ZMQ_SV_TO_MAGIC(SV) \
168             xs_object_magic_get_struct(aTHX_ SvRV (SV))
169              
170             #define ZMQ_NEW_OBJ(rv, package, sv) \
171             STMT_START { \
172             (rv) = sv_setref_pv (newSV(0), package, sv); \
173             } STMT_END
174              
175             #ifdef USE_ITHREADS
176             #define ZMQ_NEW_REFCOUNTED_OBJ(rv, package, sv, dup) \
177             ZMQ_NEW_OBJ (rv, package, sv); \
178             STMT_START { \
179             STATIC MGVTBL __FILE__##__LINE__##_vtbl = \
180             { \
181             NULL, NULL, NULL, NULL, NULL, \
182             NULL, dup, NULL \
183             }; \
184             xs_object_magic_attach_struct_with_table (aTHX_ SvRV (rv), \
185             sv, &__FILE__##__LINE__##_vtbl, MGf_DUP); \
186             } STMT_END
187              
188             #else
189             #define ZMQ_NEW_REFCOUNTED_OBJ(rv, package, sv, dup) \
190             ZMQ_NEW_OBJ (rv, package, sv);
191             #endif
192              
193             #define ZMQ_NEW_OBJ_WITH_MAGIC(rv, package, sv, magic) \
194             STMT_START { \
195             (rv) = sv_setref_pv (newSV(0), package, sv); \
196             xs_object_magic_attach_struct (aTHX_ SvRV (rv), \
197             SvREFCNT_inc_NN (magic)); \
198             } STMT_END
199              
200              
201 14           STATIC const COP* zmq_closest_cop(pTHX_ const COP *cop, const OP *o, const OP *curop, bool opnext)
202             {
203             dVAR;
204              
205 14 50         if (!o || !curop || (
    50          
    50          
    0          
    50          
206 0 0         opnext ? o->op_next == curop && o->op_type != OP_SCOPE : o == curop
    0          
207             ))
208 14           return cop;
209              
210 0 0         if (o->op_flags & OPf_KIDS)
211             {
212             const OP *kid;
213              
214 0 0         for (kid = cUNOPo->op_first; kid; kid = OpSIBLING (kid))
    0          
215             {
216             const COP *new_cop;
217              
218 0 0         if (kid->op_type == OP_NULL && kid->op_targ == OP_NEXTSTATE)
    0          
219 0           cop = (const COP *)kid;
220              
221             /* Keep searching, and return when we've found something. */
222 0           new_cop = zmq_closest_cop (aTHX_ cop, kid, curop, opnext);
223 0 0         if (new_cop)
224 0           return new_cop;
225             }
226             }
227              
228 0           return NULL;
229             }
230              
231 14           STATIC zmq_raw_error *create_error_obj (int code, SV *message)
232             {
233             zmq_raw_error *e;
234             const COP *cop;
235              
236 14           Newxz (e, 1, zmq_raw_error);
237 14           e -> code = code;
238 14           e -> message = message;
239              
240 14 50         cop = zmq_closest_cop (aTHX_ PL_curcop, OpSIBLING(PL_curcop), PL_op, FALSE);
241 14 50         if (cop == NULL)
242 0           cop = PL_curcop;
243              
244 14 50         if (CopLINE (cop))
245             {
246 14 50         e -> file = CopFILE (cop);
247 14           e -> line = CopLINE (cop);
248             } else
249 0           e -> file = "unknown";
250              
251 14           return e;
252             }
253              
254 12           STATIC zmq_raw_error *create_error_obj_fmt (int code, const char *prefix, const char *pat, va_list *list)
255             {
256             zmq_raw_error *e;
257              
258 12           e = create_error_obj (code, newSVpv (prefix, 0));
259 12           sv_vcatpvf(e -> message, pat, list);
260              
261 12           return e;
262             }
263              
264 14           STATIC void __attribute__noreturn__ croak_error_obj (zmq_raw_error *e)
265             {
266 14           SV *res = NULL;
267 14           ZMQ_NEW_OBJ (res, "ZMQ::Raw::Error", e);
268 14           SvREFCNT_inc (e -> message);
269 14           croak_sv (res);
270             }
271              
272 12           STATIC void croak_usage (const char *pat, ...)
273             {
274             zmq_raw_error *e;
275             va_list list;
276              
277 12           va_start (list, pat);
278 12           e = create_error_obj_fmt (-1, "", pat, &list);
279 12           va_end (list);
280              
281 12           croak_error_obj (e);
282             }
283              
284 1803           STATIC void *zmq_sv_to_ptr (const char *type, SV *sv, const char *file, int line)
285             {
286 1803           SV *full_type = sv_2mortal (newSVpvf ("ZMQ::Raw::%s", type));
287              
288 1803 100         if (!(sv_isobject (sv) && sv_derived_from (sv, SvPV_nolen (full_type))))
    50          
    50          
289 1 50         croak_usage ("Argument is not of type %s @ (%s:%d)\n",
290 1           SvPV_nolen (full_type), file, line);
291              
292 1802 50         return INT2PTR (void *, SvIV ((SV *) SvRV (sv)));
293             }
294              
295             #define ZMQ_SV_TO_PTR(type, sv) \
296             zmq_sv_to_ptr(#type, sv, __FILE__, __LINE__)
297              
298             #define zmq_raw_check_error(error) \
299             STMT_START { \
300             if (error < 0) \
301             { \
302             zmq_raw_error *e; \
303             \
304             if (zmq_errno() == EINTR || zmq_errno() == EAGAIN) \
305             { \
306             int ctx = GIMME_V; \
307             if (ctx == G_ARRAY) \
308             { \
309             XSRETURN_EMPTY; \
310             } \
311             \
312             XSRETURN_UNDEF; \
313             } \
314             \
315             e = create_error_obj (zmq_errno(), NULL); \
316             if (SvTRUE(ERRSV)) \
317             e->message = newSVpv (SvPVbyte_nolen (ERRSV), 0); \
318             else \
319             e->message = newSVpvf ("%s (errno: %d) @ (%s:%d)\n", \
320             zmq_strerror (zmq_errno()), zmq_errno(), __FILE__, __LINE__); \
321             \
322             croak_error_obj (e); \
323             } \
324             } STMT_END
325              
326              
327             MODULE = ZMQ::Raw PACKAGE = ZMQ::Raw
328              
329             INCLUDE: const-xs-constant.inc
330              
331             void
332             has (package, option)
333             SV *package
334             int option
335              
336             PREINIT:
337 8           const char *f = NULL;
338              
339             CODE:
340 8           switch (option)
341             {
342             case FEATURE_IPC:
343 1           f = "ipc";
344 1           break;
345             case FEATURE_PGM:
346 1           f = "pgm";
347 1           break;
348             case FEATURE_TIPC:
349 1           f = "tipc";
350 1           break;
351             case FEATURE_NORM:
352 1           f = "norm";
353 1           break;
354             case FEATURE_CURVE:
355 1           f = "curve";
356 1           break;
357             case FEATURE_GSSAPI:
358 1           f = "gssapi";
359 1           break;
360             case FEATURE_DRAFT:
361 1           f = "draft";
362 1           break;
363             default:
364 1           croak_usage ("unknown option %d", option);
365             }
366              
367 7 100         if (zmq_has (f))
368 3           XSRETURN_YES;
369              
370 4           XSRETURN_NO;
371              
372             INCLUDE: xs/Context.xs
373             INCLUDE: xs/Curve.xs
374             INCLUDE: xs/Error.xs
375             INCLUDE: xs/Message.xs
376             INCLUDE: xs/Poller.xs
377             INCLUDE: xs/Proxy.xs
378             INCLUDE: xs/Socket.xs
379             INCLUDE: xs/Timer.xs
380             INCLUDE: xs/Z85.xs
381