File: XSBind.h

package info (click to toggle)
liblucy-perl 0.3.3-4
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 9,328 kB
  • ctags: 8,492
  • sloc: ansic: 80,468; perl: 7,080; yacc: 681; java: 174; lex: 96; makefile: 20
file content (340 lines) | stat: -rw-r--r-- 13,123 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* XSBind.h -- Functions to help bind Clownfish to Perl XS api.
 */

#ifndef H_CFISH_XSBIND
#define H_CFISH_XSBIND 1

#ifdef __cplusplus
extern "C" {
#endif

#include "charmony.h"
#include "Lucy/Object/Obj.h"
#include "Lucy/Object/ByteBuf.h"
#include "Lucy/Object/CharBuf.h"
#include "Lucy/Object/Err.h"
#include "Lucy/Object/Hash.h"
#include "Lucy/Object/Num.h"
#include "Lucy/Object/VArray.h"
#include "Lucy/Object/VTable.h"

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#define NEED_newRV_noinc_GLOBAL
#include "ppport.h"

/** Given either a class name or a perl object, manufacture a new Clownfish
 * object suitable for supplying to a cfish_Foo_init() function.
 */
cfish_Obj*
cfish_XSBind_new_blank_obj(SV *either_sv);

/** Test whether an SV is defined.  Handles "get" magic, unlike SvOK on its
 * own.
 */
static CHY_INLINE chy_bool_t
cfish_XSBind_sv_defined(SV *sv) {
    if (!sv || !SvANY(sv)) { return false; }
    if (SvGMAGICAL(sv)) { mg_get(sv); }
    return SvOK(sv);
}

/** If the SV contains a Clownfish object which passes an "isa" test against the
 * passed-in VTable, return a pointer to it.  If not, but
 * <code>allocation</code> is non-NULL and a ZombieCharBuf would satisfy the
 * "isa" test, stringify the SV, create a ZombieCharBuf using
 * <code>allocation</code>, assign the SV's string to it, and return that
 * instead.  If all else fails, throw an exception.
 */
cfish_Obj*
cfish_XSBind_sv_to_cfish_obj(SV *sv, cfish_VTable *vtable, void *allocation);

/** As XSBind_sv_to_cfish_obj above, but returns NULL instead of throwing an
 * exception.
 */
cfish_Obj*
cfish_XSBind_maybe_sv_to_cfish_obj(SV *sv, cfish_VTable *vtable,
                                   void *allocation);


/** Derive an SV from a Clownfish object.  If the Clownfish object is NULL, the SV
 * will be undef.
 *
 * The new SV has single refcount for which the caller must take
 * responsibility.
 */
static CHY_INLINE SV*
cfish_XSBind_cfish_obj_to_sv(cfish_Obj *obj) {
    return obj ? (SV*)Cfish_Obj_To_Host(obj) : newSV(0);
}

/** XSBind_cfish_obj_to_sv, with a cast.
 */
#define CFISH_OBJ_TO_SV(_obj) cfish_XSBind_cfish_obj_to_sv((cfish_Obj*)_obj)

/** As XSBind_cfish_obj_to_sv above, except decrements the object's refcount
 * after creating the SV. This is useful when the Clownfish expression creates a new
 * refcount, e.g.  a call to a constructor.
 */
static CHY_INLINE SV*
cfish_XSBind_cfish_obj_to_sv_noinc(cfish_Obj *obj) {
    SV *retval;
    if (obj) {
        retval = (SV*)Cfish_Obj_To_Host(obj);
        Cfish_Obj_Dec_RefCount(obj);
    }
    else {
        retval = newSV(0);
    }
    return retval;
}

/** XSBind_cfish_obj_to_sv_noinc, with a cast.
 */
#define CFISH_OBJ_TO_SV_NOINC(_obj) \
    cfish_XSBind_cfish_obj_to_sv_noinc((cfish_Obj*)_obj)

/** Deep conversion of Clownfish objects to Perl objects -- CharBufs to UTF-8
 * SVs, ByteBufs to SVs, VArrays to Perl array refs, Hashes to Perl hashrefs,
 * and any other object to a Perl object wrapping the Clownfish Obj.
 */
SV*
cfish_XSBind_cfish_to_perl(cfish_Obj *obj);

/** Deep conversion of Perl data structures to Clownfish objects -- Perl hash
 * to Hash, Perl array to VArray, Clownfish objects stripped of their
 * wrappers, and everything else stringified and turned to a CharBuf.
 */
cfish_Obj*
cfish_XSBind_perl_to_cfish(SV *sv);

/** Convert a ByteBuf into a new string SV.
 */
SV*
cfish_XSBind_bb_to_sv(const cfish_ByteBuf *bb);

/** Convert a CharBuf into a new UTF-8 string SV.
 */
SV*
cfish_XSBind_cb_to_sv(const cfish_CharBuf *cb);

/** Turn on overloading for the supplied Perl object and its class.
 */
void
cfish_XSBind_enable_overload(void *pobj);

/** Process hash-style params passed to an XS subroutine.  The varargs must be
 * a NULL-terminated series of ALLOT_ macros.
 *
 *     cfish_XSBind_allot_params(stack, start, num_stack_elems,
 *         "Lucy::Search::TermQuery::new_PARAMS",
 *          ALLOT_OBJ(&field, "field", 5, LUCY_CHARBUF, true, alloca(cfish_ZCB_size()),
 *          ALLOT_OBJ(&term, "term", 4, LUCY_CHARBUF, true, alloca(cfish_ZCB_size()),
 *          NULL);
 *
 * The following ALLOT_ macros are available for primitive types:
 *
 *     ALLOT_I8(ptr, key, keylen, required)
 *     ALLOT_I16(ptr, key, keylen, required)
 *     ALLOT_I32(ptr, key, keylen, required)
 *     ALLOT_I64(ptr, key, keylen, required)
 *     ALLOT_U8(ptr, key, keylen, required)
 *     ALLOT_U16(ptr, key, keylen, required)
 *     ALLOT_U32(ptr, key, keylen, required)
 *     ALLOT_U64(ptr, key, keylen, required)
 *     ALLOT_BOOL(ptr, key, keylen, required)
 *     ALLOT_CHAR(ptr, key, keylen, required)
 *     ALLOT_SHORT(ptr, key, keylen, required)
 *     ALLOT_INT(ptr, key, keylen, required)
 *     ALLOT_LONG(ptr, key, keylen, required)
 *     ALLOT_SIZE_T(ptr, key, keylen, required)
 *     ALLOT_F32(ptr, key, keylen, required)
 *     ALLOT_F64(ptr, key, keylen, required)
 *
 * The four arguments to these ALLOT_ macros have the following meanings:
 *
 *     ptr -- A pointer to the variable to be extracted.
 *     key -- The name of the parameter as a C string.
 *     keylen -- The length of the parameter name in bytes.
 *     required -- A boolean indicating whether the parameter is required.
 *
 * If a required parameter is not present, allot_params() will immediately
 * cease processing of parameters, set Err_error and return false.
 *
 * Use the following macro if a Clownfish object is desired:
 *
 *     ALLOT_OBJ(ptr, key, keylen, required, vtable, allocation)
 *
 * The "vtable" argument must be the VTable corresponding to the class of the
 * desired object.  The "allocation" argument must be a blob of memory
 * allocated on the stack sufficient to hold a ZombieCharBuf.  (Use
 * cfish_ZCB_size() to find the allocation size.)
 *
 * To extract a Perl scalar, use the following ALLOT_ macro:
 *
 *     ALLOT_SV(ptr, key, keylen, required)
 *
 * @param stack The Perl stack.
 * @param start Where on the Perl stack to start looking for params.  For
 * methods, this would typically be 1; for functions, most likely 0.
 * @param num_stack_elems The number of arguments passed to the Perl function
 * (generally, the XS variable "items").
 * @param params_hash_name The name of a package global hash.  Any param
 * labels which are not present in this hash will trigger an exception.
 * @return true on success, false on failure (sets Err_error).
 */
chy_bool_t
cfish_XSBind_allot_params(SV** stack, int32_t start,
                          int32_t num_stack_elems,
                          char* params_hash_name, ...);

#define XSBIND_WANT_I8       0x1
#define XSBIND_WANT_I16      0x2
#define XSBIND_WANT_I32      0x3
#define XSBIND_WANT_I64      0x4
#define XSBIND_WANT_U8       0x5
#define XSBIND_WANT_U16      0x6
#define XSBIND_WANT_U32      0x7
#define XSBIND_WANT_U64      0x8
#define XSBIND_WANT_BOOL     0x9
#define XSBIND_WANT_F32      0xA
#define XSBIND_WANT_F64      0xB
#define XSBIND_WANT_OBJ      0xC
#define XSBIND_WANT_SV       0xD

#if (CHY_SIZEOF_CHAR == 1)
  #define XSBIND_WANT_CHAR XSBIND_WANT_I8
#else
  #error "Can't build unless sizeof(char) == 1"
#endif

#if (CHY_SIZEOF_SHORT == 2)
  #define XSBIND_WANT_SHORT XSBIND_WANT_I16
#else
  #error "Can't build unless sizeof(short) == 2"
#endif

#if (CHY_SIZEOF_INT == 4)
  #define XSBIND_WANT_INT XSBIND_WANT_I32
#else // sizeof(int) == 8
  #define XSBIND_WANT_INT XSBIND_WANT_I64
#endif

#if (CHY_SIZEOF_LONG == 4)
  #define XSBIND_WANT_LONG XSBIND_WANT_I32
#else // sizeof(long) == 8
  #define XSBIND_WANT_LONG XSBIND_WANT_I64
#endif

#if (CHY_SIZEOF_SIZE_T == 4)
  #define XSBIND_WANT_SIZE_T XSBIND_WANT_U32
#else // sizeof(long) == 8
  #define XSBIND_WANT_SIZE_T XSBIND_WANT_U64
#endif

#define XSBIND_ALLOT_I8(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_I8, NULL, NULL
#define XSBIND_ALLOT_I16(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_I16, NULL, NULL
#define XSBIND_ALLOT_I32(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_I32, NULL, NULL
#define XSBIND_ALLOT_I64(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_I64, NULL, NULL
#define XSBIND_ALLOT_U8(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_U8, NULL, NULL
#define XSBIND_ALLOT_U16(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_U16, NULL, NULL
#define XSBIND_ALLOT_U32(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_U32, NULL, NULL
#define XSBIND_ALLOT_U64(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_U64, NULL, NULL
#define XSBIND_ALLOT_BOOL(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_BOOL, NULL, NULL
#define XSBIND_ALLOT_CHAR(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_CHAR, NULL, NULL
#define XSBIND_ALLOT_SHORT(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_SHORT, NULL, NULL
#define XSBIND_ALLOT_INT(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_INT, NULL, NULL
#define XSBIND_ALLOT_LONG(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_LONG, NULL, NULL
#define XSBIND_ALLOT_SIZE_T(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_SIZE_T, NULL, NULL
#define XSBIND_ALLOT_F32(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_F32, NULL, NULL
#define XSBIND_ALLOT_F64(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_F64, NULL, NULL
#define XSBIND_ALLOT_OBJ(ptr, key, keylen, required, vtable, allocation) \
    ptr, key, keylen, required, XSBIND_WANT_OBJ, vtable, allocation
#define XSBIND_ALLOT_SV(ptr, key, keylen, required) \
    ptr, key, keylen, required, XSBIND_WANT_SV, NULL, NULL

/* Define short names for most of the symbols in this file.  Note that these
 * short names are ALWAYS in effect, since they are only used for Perl and we
 * can be confident they don't conflict with anything.  (It's prudent to use
 * full symbols nevertheless in case someone else defines e.g. a function
 * named "XSBind_sv_defined".)
 */
#define XSBind_new_blank_obj           cfish_XSBind_new_blank_obj
#define XSBind_sv_defined              cfish_XSBind_sv_defined
#define XSBind_sv_to_cfish_obj         cfish_XSBind_sv_to_cfish_obj
#define XSBind_maybe_sv_to_cfish_obj   cfish_XSBind_maybe_sv_to_cfish_obj
#define XSBind_cfish_obj_to_sv         cfish_XSBind_cfish_obj_to_sv
#define XSBind_cfish_obj_to_sv_noinc   cfish_XSBind_cfish_obj_to_sv_noinc
#define XSBind_cfish_to_perl           cfish_XSBind_cfish_to_perl
#define XSBind_perl_to_cfish           cfish_XSBind_perl_to_cfish
#define XSBind_bb_to_sv                cfish_XSBind_bb_to_sv
#define XSBind_cb_to_sv                cfish_XSBind_cb_to_sv
#define XSBind_enable_overload         cfish_XSBind_enable_overload
#define XSBind_allot_params            cfish_XSBind_allot_params
#define ALLOT_I8                       XSBIND_ALLOT_I8
#define ALLOT_I16                      XSBIND_ALLOT_I16
#define ALLOT_I32                      XSBIND_ALLOT_I32
#define ALLOT_I64                      XSBIND_ALLOT_I64
#define ALLOT_U8                       XSBIND_ALLOT_U8
#define ALLOT_U16                      XSBIND_ALLOT_U16
#define ALLOT_U32                      XSBIND_ALLOT_U32
#define ALLOT_U64                      XSBIND_ALLOT_U64
#define ALLOT_BOOL                     XSBIND_ALLOT_BOOL
#define ALLOT_CHAR                     XSBIND_ALLOT_CHAR
#define ALLOT_SHORT                    XSBIND_ALLOT_SHORT
#define ALLOT_INT                      XSBIND_ALLOT_INT
#define ALLOT_LONG                     XSBIND_ALLOT_LONG
#define ALLOT_SIZE_T                   XSBIND_ALLOT_SIZE_T
#define ALLOT_F32                      XSBIND_ALLOT_F32
#define ALLOT_F64                      XSBIND_ALLOT_F64
#define ALLOT_OBJ                      XSBIND_ALLOT_OBJ
#define ALLOT_SV                       XSBIND_ALLOT_SV

/* Strip the prefix from some common ClownFish symbols where we know there's
 * no conflict with Perl.  It's a little inconsistent to do this rather than
 * leave all symbols at full size, but the succinctness is worth it.
 */
#define THROW            CFISH_THROW
#define WARN             CFISH_WARN

#ifdef __cplusplus
}
#endif

#endif // H_CFISH_XSBIND