1 |
/* |
2 |
* swigutil_pl.c: utility functions for the SWIG Perl bindings |
3 |
* |
4 |
* ==================================================================== |
5 |
* Licensed to the Apache Software Foundation (ASF) under one |
6 |
* or more contributor license agreements. See the NOTICE file |
7 |
* distributed with this work for additional information |
8 |
* regarding copyright ownership. The ASF licenses this file |
9 |
* to you under the Apache License, Version 2.0 (the |
10 |
* "License"); you may not use this file except in compliance |
11 |
* with the License. You may obtain a copy of the License at |
12 |
* |
13 |
* http://www.apache.org/licenses/LICENSE-2.0 |
14 |
* |
15 |
* Unless required by applicable law or agreed to in writing, |
16 |
* software distributed under the License is distributed on an |
17 |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
18 |
* KIND, either express or implied. See the License for the |
19 |
* specific language governing permissions and limitations |
20 |
* under the License. |
21 |
* ==================================================================== |
22 |
*/ |
23 |
|
24 |
#include <apr.h> |
25 |
#include <apr_general.h> |
26 |
#include <apr_portable.h> |
27 |
|
28 |
#include <EXTERN.h> |
29 |
#include <perl.h> |
30 |
#include <XSUB.h> |
31 |
|
32 |
/* Perl defines a _ macro, but SVN uses it for translations. |
33 |
* So undefine _ after including the Perl headers. */ |
34 |
#undef _ |
35 |
|
36 |
#include <stdarg.h> |
37 |
#ifdef WIN32 |
38 |
#include <io.h> |
39 |
#endif |
40 |
|
41 |
#include "svn_hash.h" |
42 |
#include "svn_pools.h" |
43 |
#include "svn_opt.h" |
44 |
#include "svn_time.h" |
45 |
#include "svn_private_config.h" |
46 |
|
47 |
#include "swig_perl_external_runtime.swg" |
48 |
|
49 |
#include "swigutil_pl.h" |
50 |
|
51 |
/* cache SWIG_TypeQuery results in a perl hash */ |
52 |
static HV *type_cache = NULL; |
53 |
|
54 |
#define _SWIG_TYPE(name) _swig_perl_type_query(name, 0) |
55 |
#define POOLINFO _SWIG_TYPE("apr_pool_t *") |
56 |
|
57 |
static swig_type_info *_swig_perl_type_query(const char *typename, U32 klen) |
58 |
{ |
59 |
SV **type_info; |
60 |
swig_type_info *tinfo; |
61 |
|
62 |
if (!type_cache) |
63 |
type_cache = newHV(); |
64 |
|
65 |
if (klen == 0) |
66 |
klen = strlen(typename); |
67 |
|
68 |
if ((type_info = hv_fetch(type_cache, typename, klen, 0))) |
69 |
return (swig_type_info *) (SvIV(*type_info)); |
70 |
|
71 |
tinfo = SWIG_TypeQuery(typename); |
72 |
hv_store(type_cache, typename, klen, newSViv((IV)tinfo), 0); |
73 |
|
74 |
return tinfo; |
75 |
} |
76 |
|
77 |
/* element convertors for perl -> c */ |
78 |
typedef void *(*pl_element_converter_t)(SV *value, void *ctx, |
79 |
apr_pool_t *pool); |
80 |
|
81 |
static void *convert_pl_string(SV *value, void *dummy, apr_pool_t *pool) |
82 |
{ |
83 |
void **result = apr_palloc(pool, sizeof(void *)); |
84 |
*result = SvPV_nolen(value); |
85 |
return *result; |
86 |
} |
87 |
|
88 |
static void *convert_pl_obj(SV *value, swig_type_info *tinfo, |
89 |
apr_pool_t *pool) |
90 |
{ |
91 |
void **result = apr_palloc(pool, sizeof(void *)); |
92 |
if (SWIG_ConvertPtr(value, result, tinfo, 0) < 0) { |
93 |
croak("unable to convert from swig object"); |
94 |
} |
95 |
return *result; |
96 |
} |
97 |
|
98 |
static void *convert_pl_revnum_t(SV *value, void *dummy, apr_pool_t *pool) |
99 |
{ |
100 |
svn_revnum_t *result = apr_palloc(pool, sizeof(svn_revnum_t)); |
101 |
*result = SvIV(value); |
102 |
return (void *)result; |
103 |
} |
104 |
|
105 |
static void *convert_pl_svn_string_t(SV *value, void *dummy, apr_pool_t *pool) |
106 |
{ |
107 |
svn_string_t *result = apr_palloc(pool, sizeof(svn_string_t)); |
108 |
/* just the in typemap for svn_string_t */ |
109 |
result->data = SvPV(value, result->len); |
110 |
return (void *)result; |
111 |
} |
112 |
|
113 |
/* Convert a revision range and return a svn_opt_revision_range_t*. |
114 |
* Value can be: |
115 |
* - a _p_svn_opt_revision_range_t object |
116 |
* - a reference to a two-element array, [start, end], |
117 |
* where start and end is anything accepted by svn_swig_pl_set_revision |
118 |
* If value is not acceptable and *(svn_boolean_t *)ctx is FALSE, |
119 |
* convert_pl_revision_range returns NULL, otherwise it croak()s. |
120 |
*/ |
121 |
static void *convert_pl_revision_range(SV *value, void *ctx, apr_pool_t *pool) |
122 |
{ |
123 |
svn_boolean_t croak_on_error = *(svn_boolean_t *)ctx; |
124 |
|
125 |
if (sv_isobject(value) && sv_derived_from(value, "_p_svn_opt_revision_range_t")) { |
126 |
svn_opt_revision_range_t *range; |
127 |
/* this will assign to range */ |
128 |
SWIG_ConvertPtr(value, (void **)&range, _SWIG_TYPE("svn_opt_revision_range_t *"), 0); |
129 |
return range; |
130 |
} |
131 |
|
132 |
if (SvROK(value) |
133 |
&& SvTYPE(SvRV(value)) == SVt_PVAV |
134 |
&& av_len((AV *)SvRV(value)) == 1) { |
135 |
/* value is a two-element ARRAY */ |
136 |
AV* array = (AV *)SvRV(value); |
137 |
svn_opt_revision_t temp_start, temp_end; |
138 |
svn_opt_revision_t *start, *end; |
139 |
svn_opt_revision_range_t *range; |
140 |
|
141 |
/* Note: Due to how svn_swig_pl_set_revision works, |
142 |
* either the passed in svn_opt_revision_t is modified |
143 |
* (and the original pointer returned) or a different pointer |
144 |
* is returned. svn_swig_pl_set_revision may return NULL |
145 |
* only if croak_on_error is FALSE. |
146 |
*/ |
147 |
start = svn_swig_pl_set_revision(&temp_start, |
148 |
*av_fetch(array, 0, 0), croak_on_error); |
149 |
if (start == NULL) |
150 |
return NULL; |
151 |
end = svn_swig_pl_set_revision(&temp_end, |
152 |
*av_fetch(array, 1, 0), croak_on_error); |
153 |
if (end == NULL) |
154 |
return NULL; |
155 |
|
156 |
/* allocate a new range and copy in start and end fields */ |
157 |
range = apr_palloc(pool, sizeof(*range)); |
158 |
range->start = *start; |
159 |
range->end = *end; |
160 |
return range; |
161 |
} |
162 |
|
163 |
if (croak_on_error) |
164 |
croak("unknown revision range: " |
165 |
"must be an array of length 2 whose elements are acceptable " |
166 |
"as opt_revision_t or a _p_svn_opt_revision_range_t object"); |
167 |
return NULL; |
168 |
} |
169 |
|
170 |
/* perl -> c hash convertors */ |
171 |
static apr_hash_t *svn_swig_pl_to_hash(SV *source, |
172 |
pl_element_converter_t cv, |
173 |
void *ctx, apr_pool_t *pool) |
174 |
{ |
175 |
apr_hash_t *hash; |
176 |
HV *h; |
177 |
char *key; |
178 |
I32 cnt, retlen; |
179 |
|
180 |
if (!(source && SvROK(source) && SvTYPE(SvRV(source)) == SVt_PVHV)) { |
181 |
return NULL; |
182 |
} |
183 |
|
184 |
hash = apr_hash_make(pool); |
185 |
h = (HV *)SvRV(source); |
186 |
cnt = hv_iterinit(h); |
187 |
while (cnt--) { |
188 |
SV* item = hv_iternextsv(h, &key, &retlen); |
189 |
void *val = cv(item, ctx, pool); |
190 |
svn_hash_sets(hash, apr_pstrmemdup(pool, key, retlen), val); |
191 |
} |
192 |
|
193 |
return hash; |
194 |
} |
195 |
|
196 |
apr_hash_t *svn_swig_pl_objs_to_hash(SV *source, swig_type_info *tinfo, |
197 |
apr_pool_t *pool) |
198 |
{ |
199 |
|
200 |
return svn_swig_pl_to_hash(source, (pl_element_converter_t)convert_pl_obj, |
201 |
tinfo, pool); |
202 |
} |
203 |
|
204 |
apr_hash_t *svn_swig_pl_strings_to_hash(SV *source, apr_pool_t *pool) |
205 |
{ |
206 |
|
207 |
return svn_swig_pl_to_hash(source, convert_pl_string, NULL, pool); |
208 |
} |
209 |
|
210 |
|
211 |
apr_hash_t *svn_swig_pl_objs_to_hash_by_name(SV *source, |
212 |
const char *typename, |
213 |
apr_pool_t *pool) |
214 |
{ |
215 |
swig_type_info *tinfo = _SWIG_TYPE(typename); |
216 |
return svn_swig_pl_objs_to_hash(source, tinfo, pool); |
217 |
} |
218 |
|
219 |
apr_hash_t *svn_swig_pl_objs_to_hash_of_revnum_t(SV *source, |
220 |
apr_pool_t *pool) |
221 |
{ |
222 |
|
223 |
return svn_swig_pl_to_hash(source, |
224 |
(pl_element_converter_t)convert_pl_revnum_t, |
225 |
NULL, pool); |
226 |
} |
227 |
|
228 |
apr_hash_t *svn_swig_pl_hash_to_prophash(SV *source, apr_pool_t *pool) |
229 |
{ |
230 |
return svn_swig_pl_to_hash(source, convert_pl_svn_string_t, NULL, pool); |
231 |
} |
232 |
|
233 |
/* perl -> c array convertors */ |
234 |
static const |
235 |
apr_array_header_t *svn_swig_pl_to_array(SV *source, |
236 |
pl_element_converter_t cv, |
237 |
void *ctx, apr_pool_t *pool) |
238 |
{ |
239 |
int targlen; |
240 |
apr_array_header_t *temp; |
241 |
AV* array; |
242 |
|
243 |
if (SvROK(source) && SvTYPE(SvRV(source)) == SVt_PVAV) { |
244 |
array = (AV *)SvRV(source); |
245 |
targlen = av_len(array) + 1; |
246 |
temp = apr_array_make(pool, targlen, sizeof(const char *)); |
247 |
temp->nelts = targlen; |
248 |
|
249 |
while (targlen--) { |
250 |
/* more error handling here */ |
251 |
SV **item = av_fetch(array, targlen, 0); |
252 |
APR_ARRAY_IDX(temp, targlen, const char *) = cv(*item, ctx, pool); |
253 |
} |
254 |
} else if (SvOK(source)) { |
255 |
targlen = 1; |
256 |
temp = apr_array_make(pool, targlen, sizeof(const char *)); |
257 |
temp->nelts = targlen; |
258 |
APR_ARRAY_IDX(temp, 0, const char *) = cv(source, ctx, pool); |
259 |
} else { |
260 |
croak("Must pass a single value or an array reference"); |
261 |
} |
262 |
|
263 |
return temp; |
264 |
} |
265 |
|
266 |
const apr_array_header_t *svn_swig_pl_strings_to_array(SV *source, |
267 |
apr_pool_t *pool) |
268 |
{ |
269 |
return svn_swig_pl_to_array(source, convert_pl_string, NULL, pool); |
270 |
} |
271 |
|
272 |
const apr_array_header_t *svn_swig_pl_objs_to_array(SV *source, |
273 |
swig_type_info *tinfo, |
274 |
apr_pool_t *pool) |
275 |
{ |
276 |
return svn_swig_pl_to_array(source, |
277 |
(pl_element_converter_t)convert_pl_obj, |
278 |
tinfo, pool); |
279 |
} |
280 |
|
281 |
/* Convert a single revision range or an array of revisions ranges |
282 |
* Note: We can't simply use svn_swig_pl_to_array() as is, since |
283 |
* it immediatley checks whether source is an array reference and then |
284 |
* proceeds to treat this as the "array of ..." case. But a revision range |
285 |
* may be specified as a (two-element) array. Hence we first try to |
286 |
* convert source as a single revision range. Failing that and if it's |
287 |
* an array we then call svn_swig_pl_to_array(). Otherwise we croak(). |
288 |
*/ |
289 |
const apr_array_header_t *svn_swig_pl_array_to_apr_array_revision_range( |
290 |
SV *source, apr_pool_t *pool) |
291 |
{ |
292 |
svn_boolean_t croak_on_error = FALSE; |
293 |
svn_opt_revision_range_t *range; |
294 |
|
295 |
if (range = convert_pl_revision_range(source, &croak_on_error, pool)) { |
296 |
apr_array_header_t *temp = apr_array_make(pool, 1, |
297 |
sizeof(svn_opt_revision_range_t *)); |
298 |
temp->nelts = 1; |
299 |
APR_ARRAY_IDX(temp, 0, svn_opt_revision_range_t *) = range; |
300 |
return temp; |
301 |
} |
302 |
|
303 |
if (SvROK(source) && SvTYPE(SvRV(source)) == SVt_PVAV) { |
304 |
croak_on_error = TRUE; |
305 |
return svn_swig_pl_to_array(source, convert_pl_revision_range, |
306 |
&croak_on_error, pool); |
307 |
} |
308 |
|
309 |
croak("must pass a single revision range or a reference to an array of revision ranges"); |
310 |
|
311 |
/* This return is actually unreachable because of the croak above, |
312 |
* however, Visual Studio's compiler doesn't like if all paths don't have |
313 |
* a return and errors out otherwise. */ |
314 |
return NULL; |
315 |
} |
316 |
|
317 |
/* element convertors for c -> perl */ |
318 |
typedef SV *(*element_converter_t)(void *value, void *ctx); |
319 |
|
320 |
static SV *convert_string(const char *value, void *dummy) |
321 |
{ |
322 |
SV *obj = sv_2mortal(newSVpv(value, 0)); |
323 |
return obj; |
324 |
} |
325 |
|
326 |
static SV *convert_svn_string_t(svn_string_t *value, void *dummy) |
327 |
{ |
328 |
SV *obj = sv_2mortal(newSVpv(value->data, value->len)); |
329 |
return obj; |
330 |
} |
331 |
|
332 |
static SV *convert_to_swig_type(void *ptr, swig_type_info *tinfo) |
333 |
{ |
334 |
SV *obj = sv_newmortal(); |
335 |
SWIG_MakePtr(obj, ptr, tinfo, 0); |
336 |
return obj; |
337 |
} |
338 |
|
339 |
static SV *convert_int(int value, void *dummy) |
340 |
{ |
341 |
return sv_2mortal(newSViv(value)); |
342 |
} |
343 |
|
344 |
static SV *convert_svn_revnum_t(svn_revnum_t revnum, void *dummy) |
345 |
{ |
346 |
return sv_2mortal(newSViv((long int)revnum)); |
347 |
|
348 |
} |
349 |
|
350 |
/* c -> perl hash convertors */ |
351 |
static SV *convert_hash(apr_hash_t *hash, element_converter_t converter_func, |
352 |
void *ctx) |
353 |
{ |
354 |
apr_hash_index_t *hi; |
355 |
HV *hv; |
356 |
|
357 |
hv = newHV(); |
358 |
for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi)) { |
359 |
const char *key; |
360 |
void *val; |
361 |
int klen; |
362 |
SV *obj; |
363 |
|
364 |
apr_hash_this(hi, (void *)&key, NULL, &val); |
365 |
klen = strlen(key); |
366 |
|
367 |
obj = converter_func(val, ctx); |
368 |
hv_store(hv, (const char *)key, klen, obj, 0); |
369 |
SvREFCNT_inc(obj); |
370 |
} |
371 |
|
372 |
return sv_2mortal(newRV_noinc((SV*)hv)); |
373 |
} |
374 |
|
375 |
SV *svn_swig_pl_prophash_to_hash(apr_hash_t *hash) |
376 |
{ |
377 |
return convert_hash(hash, (element_converter_t)convert_svn_string_t, |
378 |
NULL); |
379 |
} |
380 |
|
381 |
SV *svn_swig_pl_convert_hash(apr_hash_t *hash, swig_type_info *tinfo) |
382 |
{ |
383 |
return convert_hash(hash, (element_converter_t)convert_to_swig_type, |
384 |
tinfo); |
385 |
} |
386 |
|
387 |
/* c -> perl array convertors */ |
388 |
static SV *convert_array(const apr_array_header_t *array, |
389 |
element_converter_t converter_func, void *ctx) |
390 |
{ |
391 |
AV *list = newAV(); |
392 |
int i; |
393 |
|
394 |
for (i = 0; i < array->nelts; ++i) { |
395 |
void *element = APR_ARRAY_IDX(array, i, void *); |
396 |
SV *item = converter_func(element, ctx); |
397 |
av_push(list, item); |
398 |
SvREFCNT_inc(item); |
399 |
} |
400 |
return sv_2mortal(newRV_noinc((SV*)list)); |
401 |
} |
402 |
|
403 |
SV *svn_swig_pl_array_to_list(const apr_array_header_t *array) |
404 |
{ |
405 |
return convert_array(array, (element_converter_t)convert_string, NULL); |
406 |
} |
407 |
|
408 |
/* Formerly used by pre-1.0 APIs. Now unused |
409 |
SV *svn_swig_pl_ints_to_list(const apr_array_header_t *array) |
410 |
{ |
411 |
return convert_array (array, (element_converter_t)convert_int, NULL); |
412 |
} |
413 |
*/ |
414 |
|
415 |
SV *svn_swig_pl_convert_array(const apr_array_header_t *array, |
416 |
swig_type_info *tinfo) |
417 |
{ |
418 |
return convert_array(array, (element_converter_t)convert_to_swig_type, |
419 |
tinfo); |
420 |
} |
421 |
|
422 |
SV *svn_swig_pl_revnums_to_list(const apr_array_header_t *array) |
423 |
{ |
424 |
return convert_array(array, (element_converter_t)convert_svn_revnum_t, |
425 |
NULL); |
426 |
} |
427 |
|
428 |
/* perl -> c svn_opt_revision_t conversion */ |
429 |
svn_opt_revision_t *svn_swig_pl_set_revision(svn_opt_revision_t *rev, |
430 |
SV *source, |
431 |
svn_boolean_t croak_on_error) |
432 |
{ |
433 |
#define maybe_croak(argv) do { if (croak_on_error) croak argv; \ |
434 |
else return NULL; } while (0) |
435 |
|
436 |
if (source == NULL || source == &PL_sv_undef || !SvOK(source)) { |
437 |
rev->kind = svn_opt_revision_unspecified; |
438 |
} |
439 |
else if (sv_isobject(source) && sv_derived_from(source, "_p_svn_opt_revision_t")) { |
440 |
/* this will assign to rev */ |
441 |
SWIG_ConvertPtr(source, (void **)&rev, _SWIG_TYPE("svn_opt_revision_t *"), 0); |
442 |
} |
443 |
else if (looks_like_number(source)) { |
444 |
rev->kind = svn_opt_revision_number; |
445 |
rev->value.number = SvIV(source); |
446 |
} |
447 |
else if (SvPOK(source)) { |
448 |
char *input = SvPV_nolen(source); |
449 |
if (svn_cstring_casecmp(input, "BASE") == 0) |
450 |
rev->kind = svn_opt_revision_base; |
451 |
else if (svn_cstring_casecmp(input, "HEAD") == 0) |
452 |
rev->kind = svn_opt_revision_head; |
453 |
else if (svn_cstring_casecmp(input, "WORKING") == 0) |
454 |
rev->kind = svn_opt_revision_working; |
455 |
else if (svn_cstring_casecmp(input, "COMMITTED") == 0) |
456 |
rev->kind = svn_opt_revision_committed; |
457 |
else if (svn_cstring_casecmp(input, "PREV") == 0) |
458 |
rev->kind = svn_opt_revision_previous; |
459 |
else if (*input == '{') { |
460 |
svn_boolean_t matched; |
461 |
apr_time_t tm; |
462 |
svn_error_t *err; |
463 |
|
464 |
char *end = strchr(input,'}'); |
465 |
if (!end) |
466 |
maybe_croak(("unknown opt_revision_t string \"%s\": " |
467 |
"missing closing brace for \"{DATE}\"", input)); |
468 |
*end = '\0'; |
469 |
err = svn_parse_date (&matched, &tm, input + 1, apr_time_now(), |
470 |
svn_swig_pl_make_pool ((SV *)NULL)); |
471 |
if (err) { |
472 |
svn_error_clear (err); |
473 |
maybe_croak(("unknown opt_revision_t string \"{%s}\": " |
474 |
"internal svn_parse_date error", input + 1)); |
475 |
} |
476 |
if (!matched) |
477 |
maybe_croak(("unknown opt_revision_t string \"{%s}\": " |
478 |
"svn_parse_date failed to parse it", input + 1)); |
479 |
|
480 |
rev->kind = svn_opt_revision_date; |
481 |
rev->value.date = tm; |
482 |
} else |
483 |
maybe_croak(("unknown opt_revision_t string \"%s\": must be one of " |
484 |
"\"BASE\", \"HEAD\", \"WORKING\", \"COMMITTED\", " |
485 |
"\"PREV\" or a \"{DATE}\"", input)); |
486 |
} else |
487 |
maybe_croak(("unknown opt_revision_t type: must be undef, a number, " |
488 |
"a string (one of \"BASE\", \"HEAD\", \"WORKING\", " |
489 |
"\"COMMITTED\", \"PREV\" or a \"{DATE}\") " |
490 |
"or a _p_svn_opt_revision_t object")); |
491 |
|
492 |
return rev; |
493 |
#undef maybe_croak |
494 |
} |
495 |
|
496 |
/* put the va_arg in stack and invoke caller_func with func. |
497 |
fmt: |
498 |
* O: perl object |
499 |
* i: apr_int32_t |
500 |
* u: apr_uint32_t |
501 |
* L: apr_int64_t |
502 |
* U: apr_uint64_t |
503 |
* s: string |
504 |
* S: swigtype |
505 |
* r: svn_revnum_t |
506 |
* b: svn_boolean_t |
507 |
* t: svn_string_t |
508 |
* z: apr_size_t |
509 |
|
510 |
Please do not add C types here. Add a new format code if needed. |
511 |
Using the underlying C types and not the APR or SVN types can break |
512 |
things if these data types change in the future or on platforms which |
513 |
use different types. |
514 |
|
515 |
put returned value in result if result is not NULL |
516 |
*/ |
517 |
|
518 |
svn_error_t *svn_swig_pl_callback_thunk(perl_func_invoker_t caller_func, |
519 |
void *func, |
520 |
SV **result, |
521 |
const char *fmt, ...) |
522 |
{ |
523 |
const char *fp = fmt; |
524 |
va_list ap; |
525 |
int count; |
526 |
I32 call_flags = result ? G_SCALAR : (G_VOID & G_DISCARD); |
527 |
|
528 |
dSP ; |
529 |
ENTER ; |
530 |
SAVETMPS ; |
531 |
|
532 |
PUSHMARK(SP) ; |
533 |
|
534 |
va_start(ap, fmt); |
535 |
while (*fp) { |
536 |
char *c; |
537 |
void *o; |
538 |
SV *obj; |
539 |
swig_type_info *t; |
540 |
svn_string_t *str; |
541 |
|
542 |
switch (*fp++) { |
543 |
case 'O': |
544 |
XPUSHs(va_arg(ap, SV *)); |
545 |
break; |
546 |
case 'S': /* swig object */ |
547 |
o = va_arg(ap, void *); |
548 |
t = va_arg(ap, swig_type_info *); |
549 |
|
550 |
obj = sv_newmortal(); |
551 |
SWIG_MakePtr(obj, o, t, 0); |
552 |
XPUSHs(obj); |
553 |
break; |
554 |
|
555 |
case 's': /* string */ |
556 |
c = va_arg(ap, char *); |
557 |
XPUSHs(c ? sv_2mortal(newSVpv(c, 0)) : &PL_sv_undef); |
558 |
break; |
559 |
|
560 |
case 'i': /* apr_int32_t */ |
561 |
XPUSHs(sv_2mortal(newSViv(va_arg(ap, apr_int32_t)))); |
562 |
break; |
563 |
|
564 |
case 'u': /* apr_uint32_t */ |
565 |
XPUSHs(sv_2mortal(newSViv(va_arg(ap, apr_uint32_t)))); |
566 |
break; |
567 |
|
568 |
case 'r': /* svn_revnum_t */ |
569 |
XPUSHs(sv_2mortal(newSViv(va_arg(ap, svn_revnum_t)))); |
570 |
break; |
571 |
|
572 |
case 'b': /* svn_boolean_t */ |
573 |
XPUSHs(sv_2mortal(newSViv(va_arg(ap, svn_boolean_t)))); |
574 |
break; |
575 |
|
576 |
case 't': /* svn_string_t */ |
577 |
str = va_arg(ap, svn_string_t *); |
578 |
XPUSHs(str ? sv_2mortal(newSVpv(str->data, str->len)) |
579 |
: &PL_sv_undef); |
580 |
break; |
581 |
|
582 |
case 'L': /* apr_int64_t */ |
583 |
/* Pass into perl as a string because some implementations may |
584 |
* not be able to handle a 64-bit int. If it's too long to |
585 |
* fit in Perl's interal IV size then perl will only make |
586 |
* it available as a string. If not then perl will convert |
587 |
* it to an IV for us. So this handles the problem gracefully */ |
588 |
c = malloc(30); |
589 |
snprintf(c,30,"%" APR_INT64_T_FMT,va_arg(ap, apr_int64_t)); |
590 |
XPUSHs(sv_2mortal(newSVpv(c, 0))); |
591 |
free(c); |
592 |
break; |
593 |
|
594 |
case 'U': /* apr_uint64_t */ |
595 |
c = malloc(30); |
596 |
snprintf(c,30,"%" APR_UINT64_T_FMT,va_arg(ap, apr_uint64_t)); |
597 |
XPUSHs(sv_2mortal(newSVpv(c, 0))); |
598 |
free(c); |
599 |
break; |
600 |
|
601 |
case 'z': /* apr_size_t */ |
602 |
if (sizeof(apr_size_t) >= 8) |
603 |
{ |
604 |
c = malloc(30); |
605 |
snprintf(c,30,"%" APR_SIZE_T_FMT,va_arg(ap, apr_size_t)); |
606 |
XPUSHs(sv_2mortal(newSVpv(c, 0))); |
607 |
free(c); |
608 |
} |
609 |
else |
610 |
{ |
611 |
XPUSHs(sv_2mortal(newSViv(va_arg(ap, apr_size_t)))); |
612 |
} |
613 |
break; |
614 |
} |
615 |
} |
616 |
|
617 |
va_end(ap); |
618 |
|
619 |
PUTBACK; |
620 |
switch (caller_func) { |
621 |
case CALL_SV: |
622 |
count = call_sv(func, call_flags ); |
623 |
break; |
624 |
case CALL_METHOD: |
625 |
count = call_method(func, call_flags ); |
626 |
break; |
627 |
default: |
628 |
croak("unkonwn calling type"); |
629 |
break; |
630 |
} |
631 |
SPAGAIN ; |
632 |
|
633 |
if (((call_flags & G_SCALAR) && count != 1) || |
634 |
((call_flags & G_VOID) && count != 0)) |
635 |
croak("Wrong number of returns"); |
636 |
|
637 |
if (result) { |
638 |
*result = POPs; |
639 |
SvREFCNT_inc(*result); |
640 |
} |
641 |
|
642 |
PUTBACK; |
643 |
FREETMPS ; |
644 |
LEAVE ; |
645 |
|
646 |
return SVN_NO_ERROR; |
647 |
} |
648 |
|
649 |
/*** Editor Wrapping ***/ |
650 |
|
651 |
/* this could be more perlish */ |
652 |
typedef struct item_baton { |
653 |
SV *editor; /* the editor handling the callbacks */ |
654 |
SV *baton; /* the dir/file baton (or NULL for edit baton) */ |
655 |
} item_baton; |
656 |
|
657 |
static item_baton * make_baton(apr_pool_t *pool, |
658 |
SV *editor, SV *baton) |
659 |
{ |
660 |
item_baton *newb = apr_palloc(pool, sizeof(*newb)); |
661 |
|
662 |
newb->editor = editor; |
663 |
newb->baton = baton; |
664 |
|
665 |
return newb; |
666 |
} |
667 |
|
668 |
static svn_error_t * close_baton(void *baton, const char *method, apr_pool_t *pool) |
669 |
{ |
670 |
item_baton *ib = baton; |
671 |
|
672 |
if (ib->baton) { |
673 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
674 |
(void *)method, NULL, |
675 |
"OOS", ib->editor, ib->baton, |
676 |
pool, POOLINFO)); |
677 |
SvREFCNT_dec(ib->baton); |
678 |
} |
679 |
else { |
680 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
681 |
(void *)method, NULL, |
682 |
"OS", ib->editor, pool, POOLINFO)); |
683 |
} |
684 |
|
685 |
return SVN_NO_ERROR; |
686 |
} |
687 |
|
688 |
static svn_error_t * thunk_set_target_revision(void *edit_baton, |
689 |
svn_revnum_t target_revision, |
690 |
apr_pool_t *pool) |
691 |
{ |
692 |
item_baton *ib = edit_baton; |
693 |
|
694 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
695 |
(void *)"set_target_revision", NULL, |
696 |
"Or", ib->editor, target_revision)); |
697 |
|
698 |
return SVN_NO_ERROR; |
699 |
} |
700 |
|
701 |
static svn_error_t * thunk_open_root(void *edit_baton, |
702 |
svn_revnum_t base_revision, |
703 |
apr_pool_t *dir_pool, |
704 |
void **root_baton) |
705 |
{ |
706 |
item_baton *ib = edit_baton; |
707 |
SV *result; |
708 |
|
709 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
710 |
(void *)"open_root", &result, |
711 |
"OrS", ib->editor, base_revision, |
712 |
dir_pool, POOLINFO)); |
713 |
|
714 |
*root_baton = make_baton(dir_pool, ib->editor, result); |
715 |
return SVN_NO_ERROR; |
716 |
} |
717 |
|
718 |
static svn_error_t * thunk_delete_entry(const char *path, |
719 |
svn_revnum_t revision, |
720 |
void *parent_baton, |
721 |
apr_pool_t *pool) |
722 |
{ |
723 |
item_baton *ib = parent_baton; |
724 |
|
725 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
726 |
(void *)"delete_entry", NULL, |
727 |
"OsrOS", ib->editor, path, revision, |
728 |
ib->baton, pool, POOLINFO)); |
729 |
return SVN_NO_ERROR; |
730 |
} |
731 |
|
732 |
static svn_error_t * thunk_add_directory(const char *path, |
733 |
void *parent_baton, |
734 |
const char *copyfrom_path, |
735 |
svn_revnum_t copyfrom_revision, |
736 |
apr_pool_t *dir_pool, |
737 |
void **child_baton) |
738 |
{ |
739 |
item_baton *ib = parent_baton; |
740 |
SV *result; |
741 |
|
742 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
743 |
(void *)"add_directory", &result, |
744 |
"OsOsrS", ib->editor, path, ib->baton, |
745 |
copyfrom_path, copyfrom_revision, |
746 |
dir_pool, POOLINFO)); |
747 |
*child_baton = make_baton(dir_pool, ib->editor, result); |
748 |
return SVN_NO_ERROR; |
749 |
} |
750 |
|
751 |
static svn_error_t * thunk_open_directory(const char *path, |
752 |
void *parent_baton, |
753 |
svn_revnum_t base_revision, |
754 |
apr_pool_t *dir_pool, |
755 |
void **child_baton) |
756 |
{ |
757 |
item_baton *ib = parent_baton; |
758 |
SV *result; |
759 |
|
760 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
761 |
(void *)"open_directory", &result, |
762 |
"OsOrS", ib->editor, path, ib->baton, |
763 |
base_revision, dir_pool, POOLINFO)); |
764 |
|
765 |
*child_baton = make_baton(dir_pool, ib->editor, result); |
766 |
|
767 |
return SVN_NO_ERROR; |
768 |
} |
769 |
|
770 |
static svn_error_t * thunk_change_dir_prop(void *dir_baton, |
771 |
const char *name, |
772 |
const svn_string_t *value, |
773 |
apr_pool_t *pool) |
774 |
{ |
775 |
item_baton *ib = dir_baton; |
776 |
|
777 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
778 |
(void *)"change_dir_prop", NULL, |
779 |
"OOstS", ib->editor, ib->baton, name, |
780 |
value, pool, POOLINFO)); |
781 |
|
782 |
return SVN_NO_ERROR; |
783 |
} |
784 |
|
785 |
static svn_error_t * thunk_close_directory(void *dir_baton, |
786 |
apr_pool_t *pool) |
787 |
{ |
788 |
return close_baton(dir_baton, "close_directory", pool); |
789 |
} |
790 |
|
791 |
static svn_error_t * thunk_absent_directory(const char *path, |
792 |
void *parent_baton, |
793 |
apr_pool_t *pool) |
794 |
{ |
795 |
item_baton *ib = parent_baton; |
796 |
|
797 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
798 |
(void *)"absent_directory", NULL, |
799 |
"OsOS", ib->editor, path, ib->baton, |
800 |
pool, POOLINFO)); |
801 |
|
802 |
return SVN_NO_ERROR; |
803 |
} |
804 |
|
805 |
static svn_error_t * thunk_add_file(const char *path, |
806 |
void *parent_baton, |
807 |
const char *copyfrom_path, |
808 |
svn_revnum_t copyfrom_revision, |
809 |
apr_pool_t *file_pool, |
810 |
void **file_baton) |
811 |
{ |
812 |
item_baton *ib = parent_baton; |
813 |
SV *result; |
814 |
|
815 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
816 |
(void *)"add_file", &result, |
817 |
"OsOsrS", ib->editor, path, ib->baton, |
818 |
copyfrom_path, copyfrom_revision, |
819 |
file_pool, POOLINFO)); |
820 |
|
821 |
*file_baton = make_baton(file_pool, ib->editor, result); |
822 |
return SVN_NO_ERROR; |
823 |
} |
824 |
|
825 |
static svn_error_t * thunk_open_file(const char *path, |
826 |
void *parent_baton, |
827 |
svn_revnum_t base_revision, |
828 |
apr_pool_t *file_pool, |
829 |
void **file_baton) |
830 |
{ |
831 |
item_baton *ib = parent_baton; |
832 |
SV *result; |
833 |
|
834 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
835 |
(void *)"open_file", &result, |
836 |
"OsOrS", ib->editor, path, ib->baton, |
837 |
base_revision, file_pool, POOLINFO)); |
838 |
|
839 |
*file_baton = make_baton(file_pool, ib->editor, result); |
840 |
return SVN_NO_ERROR; |
841 |
} |
842 |
|
843 |
static svn_error_t * thunk_window_handler(svn_txdelta_window_t *window, |
844 |
void *baton) |
845 |
{ |
846 |
SV *handler = baton; |
847 |
|
848 |
if (window == NULL) { |
849 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_SV, |
850 |
handler, NULL, "O", |
851 |
&PL_sv_undef)); |
852 |
SvREFCNT_dec(handler); |
853 |
} |
854 |
else { |
855 |
swig_type_info *tinfo = _SWIG_TYPE("svn_txdelta_window_t *"); |
856 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_SV, handler, |
857 |
NULL, "S", window, tinfo)); |
858 |
} |
859 |
|
860 |
return SVN_NO_ERROR; |
861 |
} |
862 |
|
863 |
static svn_error_t * |
864 |
thunk_apply_textdelta(void *file_baton, |
865 |
const char *base_checksum, |
866 |
apr_pool_t *pool, |
867 |
svn_txdelta_window_handler_t *handler, |
868 |
void **h_baton) |
869 |
{ |
870 |
item_baton *ib = file_baton; |
871 |
SV *result; |
872 |
|
873 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
874 |
(void *)"apply_textdelta", &result, |
875 |
"OOsS", ib->editor, ib->baton, |
876 |
base_checksum, pool, POOLINFO)); |
877 |
if (SvOK(result)) { |
878 |
if (SvROK(result) && SvTYPE(SvRV(result)) == SVt_PVAV) { |
879 |
swig_type_info *handler_info = |
880 |
_SWIG_TYPE("svn_txdelta_window_handler_t"); |
881 |
swig_type_info *void_info = _SWIG_TYPE("void *"); |
882 |
AV *array = (AV *)SvRV(result); |
883 |
|
884 |
if (SWIG_ConvertPtr(*av_fetch(array, 0, 0), |
885 |
(void **)handler, handler_info,0) < 0) { |
886 |
croak("Unable to convert from SWIG Type"); |
887 |
} |
888 |
if (SWIG_ConvertPtr(*av_fetch(array, 1, 0), |
889 |
h_baton, void_info,0) < 0) { |
890 |
croak("Unable to convert from SWIG Type "); |
891 |
} |
892 |
SvREFCNT_dec(result); |
893 |
} |
894 |
else { |
895 |
*handler = thunk_window_handler; |
896 |
*h_baton = result; |
897 |
} |
898 |
} |
899 |
else { |
900 |
*handler = svn_delta_noop_window_handler; |
901 |
*h_baton = NULL; |
902 |
} |
903 |
|
904 |
return SVN_NO_ERROR; |
905 |
} |
906 |
|
907 |
static svn_error_t * thunk_change_file_prop(void *file_baton, |
908 |
const char *name, |
909 |
const svn_string_t *value, |
910 |
apr_pool_t *pool) |
911 |
{ |
912 |
item_baton *ib = file_baton; |
913 |
|
914 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
915 |
(void *)"change_file_prop", NULL, |
916 |
"OOstS", ib->editor, ib->baton, name, |
917 |
value, pool, POOLINFO)); |
918 |
|
919 |
return SVN_NO_ERROR; |
920 |
} |
921 |
|
922 |
static svn_error_t * thunk_close_file(void *file_baton, |
923 |
const char *text_checksum, |
924 |
apr_pool_t *pool) |
925 |
{ |
926 |
item_baton *ib = file_baton; |
927 |
|
928 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
929 |
(void *)"close_file", NULL, "OOsS", |
930 |
ib->editor, ib->baton, text_checksum, |
931 |
pool, POOLINFO)); |
932 |
|
933 |
SvREFCNT_dec(ib->baton); |
934 |
|
935 |
return SVN_NO_ERROR; |
936 |
} |
937 |
|
938 |
static svn_error_t * thunk_absent_file(const char *path, |
939 |
void *parent_baton, |
940 |
apr_pool_t *pool) |
941 |
{ |
942 |
item_baton *ib = parent_baton; |
943 |
|
944 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD, |
945 |
(void *)"absent_file", NULL, |
946 |
"OsOS", ib->editor, path, ib->baton, |
947 |
pool, POOLINFO)); |
948 |
|
949 |
return SVN_NO_ERROR; |
950 |
} |
951 |
|
952 |
static svn_error_t * thunk_close_edit(void *edit_baton, |
953 |
apr_pool_t *pool) |
954 |
{ |
955 |
return close_baton(edit_baton, "close_edit", pool); |
956 |
} |
957 |
|
958 |
static svn_error_t * thunk_abort_edit(void *edit_baton, |
959 |
apr_pool_t *pool) |
960 |
{ |
961 |
return close_baton(edit_baton, "abort_edit", pool); |
962 |
} |
963 |
|
964 |
|
965 |
void |
966 |
svn_delta_wrap_window_handler(svn_txdelta_window_handler_t *handler, |
967 |
void **h_baton, |
968 |
SV *callback, |
969 |
apr_pool_t *pool) |
970 |
{ |
971 |
*handler = thunk_window_handler; |
972 |
*h_baton = callback; |
973 |
SvREFCNT_inc(callback); |
974 |
svn_swig_pl_hold_ref_in_pool(pool, callback); |
975 |
} |
976 |
|
977 |
void svn_delta_make_editor(svn_delta_editor_t **editor, |
978 |
void **edit_baton, |
979 |
SV *perl_editor, |
980 |
apr_pool_t *pool) |
981 |
{ |
982 |
svn_delta_editor_t *thunk_editor = svn_delta_default_editor(pool); |
983 |
|
984 |
thunk_editor->set_target_revision = thunk_set_target_revision; |
985 |
thunk_editor->open_root = thunk_open_root; |
986 |
thunk_editor->delete_entry = thunk_delete_entry; |
987 |
thunk_editor->add_directory = thunk_add_directory; |
988 |
thunk_editor->open_directory = thunk_open_directory; |
989 |
thunk_editor->change_dir_prop = thunk_change_dir_prop; |
990 |
thunk_editor->close_directory = thunk_close_directory; |
991 |
thunk_editor->absent_directory = thunk_absent_directory; |
992 |
thunk_editor->add_file = thunk_add_file; |
993 |
thunk_editor->open_file = thunk_open_file; |
994 |
thunk_editor->apply_textdelta = thunk_apply_textdelta; |
995 |
thunk_editor->change_file_prop = thunk_change_file_prop; |
996 |
thunk_editor->close_file = thunk_close_file; |
997 |
thunk_editor->absent_file = thunk_absent_file; |
998 |
thunk_editor->close_edit = thunk_close_edit; |
999 |
thunk_editor->abort_edit = thunk_abort_edit; |
1000 |
|
1001 |
*editor = thunk_editor; |
1002 |
*edit_baton = make_baton(pool, perl_editor, NULL); |
1003 |
svn_swig_pl_hold_ref_in_pool(pool, perl_editor); |
1004 |
} |
1005 |
|
1006 |
svn_error_t *svn_swig_pl_thunk_log_receiver(void *baton, |
1007 |
apr_hash_t *changed_paths, |
1008 |
svn_revnum_t rev, |
1009 |
const char *author, |
1010 |
const char *date, |
1011 |
const char *msg, |
1012 |
apr_pool_t *pool) |
1013 |
{ |
1014 |
SV *receiver = baton; |
1015 |
swig_type_info *tinfo = _SWIG_TYPE("svn_log_changed_path_t *"); |
1016 |
|
1017 |
if (!SvOK(receiver)) |
1018 |
return SVN_NO_ERROR; |
1019 |
|
1020 |
svn_swig_pl_callback_thunk(CALL_SV, |
1021 |
receiver, NULL, |
1022 |
"OrsssS", (changed_paths) ? |
1023 |
svn_swig_pl_convert_hash(changed_paths, tinfo) |
1024 |
: &PL_sv_undef, |
1025 |
rev, author, date, msg, pool, POOLINFO); |
1026 |
|
1027 |
return SVN_NO_ERROR; |
1028 |
} |
1029 |
|
1030 |
svn_error_t *svn_swig_pl_thunk_log_entry_receiver(void *baton, |
1031 |
svn_log_entry_t *log_entry, |
1032 |
apr_pool_t *pool) |
1033 |
{ |
1034 |
SV *receiver = baton; |
1035 |
|
1036 |
if (!SvOK(receiver)) |
1037 |
return SVN_NO_ERROR; |
1038 |
|
1039 |
svn_swig_pl_callback_thunk(CALL_SV, |
1040 |
receiver, NULL, |
1041 |
"SS", |
1042 |
log_entry, _SWIG_TYPE("svn_log_entry_t *"), |
1043 |
pool, POOLINFO); |
1044 |
|
1045 |
return SVN_NO_ERROR; |
1046 |
} |
1047 |
|
1048 |
svn_error_t * svn_swig_pl_thunk_client_diff_summarize_func( |
1049 |
const svn_client_diff_summarize_t *diff, |
1050 |
void *baton, |
1051 |
apr_pool_t *pool) |
1052 |
{ |
1053 |
SV *func = baton; |
1054 |
|
1055 |
if(!SvOK(func)) |
1056 |
return SVN_NO_ERROR; |
1057 |
|
1058 |
svn_swig_pl_callback_thunk(CALL_SV, |
1059 |
func, NULL, |
1060 |
"SS", diff, |
1061 |
_SWIG_TYPE("svn_client_diff_summarize_t *"), |
1062 |
pool, POOLINFO); |
1063 |
|
1064 |
return SVN_NO_ERROR; |
1065 |
} |
1066 |
|
1067 |
svn_error_t *svn_swig_pl_thunk_history_func(void *baton, |
1068 |
const char *path, |
1069 |
svn_revnum_t revision, |
1070 |
apr_pool_t *pool) |
1071 |
{ |
1072 |
SV *func = baton; |
1073 |
|
1074 |
if (!SvOK(func)) |
1075 |
return SVN_NO_ERROR; |
1076 |
|
1077 |
svn_swig_pl_callback_thunk(CALL_SV, |
1078 |
func, NULL, |
1079 |
"srS", path, revision, pool, POOLINFO); |
1080 |
|
1081 |
return SVN_NO_ERROR; |
1082 |
} |
1083 |
|
1084 |
svn_error_t *svn_swig_pl_thunk_authz_func(svn_boolean_t *allowed, |
1085 |
svn_fs_root_t *root, |
1086 |
const char *path, |
1087 |
void *baton, |
1088 |
apr_pool_t *pool) |
1089 |
{ |
1090 |
SV *func = baton, *result; |
1091 |
|
1092 |
if (!SvOK(func)) |
1093 |
return SVN_NO_ERROR; |
1094 |
|
1095 |
svn_swig_pl_callback_thunk(CALL_SV, |
1096 |
func, &result, |
1097 |
"SsS", root, _SWIG_TYPE("svn_fs_root_t *"), |
1098 |
path, pool, POOLINFO); |
1099 |
|
1100 |
*allowed = SvIV(result); |
1101 |
SvREFCNT_dec(result); |
1102 |
|
1103 |
return SVN_NO_ERROR; |
1104 |
} |
1105 |
|
1106 |
svn_error_t *svn_swig_pl_thunk_commit_callback(svn_revnum_t new_revision, |
1107 |
const char *date, |
1108 |
const char *author, |
1109 |
void *baton) |
1110 |
{ |
1111 |
if (!SvOK((SV *)baton)) |
1112 |
return SVN_NO_ERROR; |
1113 |
|
1114 |
svn_swig_pl_callback_thunk(CALL_SV, baton, NULL, |
1115 |
"rss", new_revision, date, author); |
1116 |
|
1117 |
return SVN_NO_ERROR; |
1118 |
} |
1119 |
|
1120 |
svn_error_t *svn_swig_pl_thunk_commit_callback2(const svn_commit_info_t *commit_info, |
1121 |
void *baton, |
1122 |
apr_pool_t *pool) |
1123 |
{ |
1124 |
if (!SvOK((SV *)baton)) |
1125 |
return SVN_NO_ERROR; |
1126 |
|
1127 |
svn_swig_pl_callback_thunk(CALL_SV, baton, NULL, |
1128 |
"SS", |
1129 |
commit_info, _SWIG_TYPE("svn_commit_info_t *"), |
1130 |
pool, POOLINFO); |
1131 |
|
1132 |
return SVN_NO_ERROR; |
1133 |
} |
1134 |
|
1135 |
|
1136 |
/* Wrap RA */ |
1137 |
|
1138 |
static svn_error_t * thunk_open_tmp_file(apr_file_t **fp, |
1139 |
void *callback_baton, |
1140 |
apr_pool_t *pool) |
1141 |
{ |
1142 |
SV *result; |
1143 |
swig_type_info *tinfo = _SWIG_TYPE("apr_file_t *"); |
1144 |
|
1145 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"open_tmp_file", |
1146 |
&result, "OS", callback_baton, pool, POOLINFO); |
1147 |
|
1148 |
if (SWIG_ConvertPtr(result, (void *)fp, tinfo,0) < 0) { |
1149 |
croak("Unable to convert from SWIG Type"); |
1150 |
} |
1151 |
|
1152 |
SvREFCNT_dec(result); |
1153 |
return SVN_NO_ERROR; |
1154 |
} |
1155 |
|
1156 |
svn_error_t *thunk_get_wc_prop(void *baton, |
1157 |
const char *relpath, |
1158 |
const char *name, |
1159 |
const svn_string_t **value, |
1160 |
apr_pool_t *pool) |
1161 |
{ |
1162 |
SV *result; |
1163 |
char *data; |
1164 |
STRLEN len; |
1165 |
|
1166 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"get_wc_prop", |
1167 |
&result, "OssS", baton, relpath, name, |
1168 |
pool, POOLINFO); |
1169 |
|
1170 |
/* this is svn_string_t * typemap in */ |
1171 |
if (!SvOK(result) || result == &PL_sv_undef) { |
1172 |
*value = NULL; |
1173 |
} |
1174 |
else if (SvPOK(result)) { |
1175 |
data = SvPV(result, len); |
1176 |
*value = svn_string_ncreate(data, len, pool); |
1177 |
} |
1178 |
else { |
1179 |
SvREFCNT_dec(result); |
1180 |
croak("not a string"); |
1181 |
} |
1182 |
|
1183 |
SvREFCNT_dec(result); |
1184 |
return SVN_NO_ERROR; |
1185 |
} |
1186 |
|
1187 |
|
1188 |
svn_error_t *svn_ra_make_callbacks(svn_ra_callbacks_t **cb, |
1189 |
void **c_baton, |
1190 |
SV *perl_callbacks, |
1191 |
apr_pool_t *pool) |
1192 |
{ |
1193 |
SV *auth_baton; |
1194 |
|
1195 |
*cb = apr_pcalloc(pool, sizeof(**cb)); |
1196 |
|
1197 |
(*cb)->open_tmp_file = thunk_open_tmp_file; |
1198 |
(*cb)->get_wc_prop = thunk_get_wc_prop; |
1199 |
(*cb)->set_wc_prop = NULL; |
1200 |
(*cb)->push_wc_prop = NULL; |
1201 |
(*cb)->invalidate_wc_props = NULL; |
1202 |
auth_baton = *hv_fetch((HV *)SvRV(perl_callbacks), "auth", 4, 0); |
1203 |
|
1204 |
if (SWIG_ConvertPtr(auth_baton, |
1205 |
(void **)&(*cb)->auth_baton, _SWIG_TYPE("svn_auth_baton_t *"),0) < 0) { |
1206 |
croak("Unable to convert from SWIG Type"); |
1207 |
} |
1208 |
*c_baton = perl_callbacks; |
1209 |
svn_swig_pl_hold_ref_in_pool(pool, perl_callbacks); |
1210 |
return SVN_NO_ERROR; |
1211 |
} |
1212 |
|
1213 |
svn_error_t *svn_swig_pl_thunk_gnome_keyring_unlock_prompt(char **keyring_password, |
1214 |
const char *keyring_name, |
1215 |
void *baton, |
1216 |
apr_pool_t *pool) |
1217 |
{ |
1218 |
SV *result; |
1219 |
STRLEN len; |
1220 |
/* The baton is the actual prompt function passed from perl, so we |
1221 |
* call that one and process the result. */ |
1222 |
svn_swig_pl_callback_thunk(CALL_SV, |
1223 |
baton, &result, |
1224 |
"sS", keyring_name, |
1225 |
pool, POOLINFO); |
1226 |
if (!SvOK(result) || result == &PL_sv_undef) { |
1227 |
*keyring_password = NULL; |
1228 |
} |
1229 |
else if (SvPOK(result)) { |
1230 |
*keyring_password = apr_pstrdup(pool, SvPV(result, len)); |
1231 |
} |
1232 |
else { |
1233 |
SvREFCNT_dec(result); |
1234 |
croak("not a string"); |
1235 |
} |
1236 |
|
1237 |
SvREFCNT_dec(result); |
1238 |
return SVN_NO_ERROR; |
1239 |
} |
1240 |
|
1241 |
svn_error_t *svn_swig_pl_thunk_simple_prompt(svn_auth_cred_simple_t **cred, |
1242 |
void *baton, |
1243 |
const char *realm, |
1244 |
const char *username, |
1245 |
svn_boolean_t may_save, |
1246 |
apr_pool_t *pool) |
1247 |
{ |
1248 |
/* Be nice and allocate the memory for the cred structure before passing it |
1249 |
* off to the perl space */ |
1250 |
*cred = apr_pcalloc(pool, sizeof(**cred)); |
1251 |
if (!*cred) { |
1252 |
croak("Could not allocate memory for cred structure"); |
1253 |
} |
1254 |
svn_swig_pl_callback_thunk(CALL_SV, |
1255 |
baton, NULL, |
1256 |
"SssbS", *cred, _SWIG_TYPE("svn_auth_cred_simple_t *"), |
1257 |
realm, username, may_save, pool, POOLINFO); |
1258 |
|
1259 |
return SVN_NO_ERROR; |
1260 |
} |
1261 |
|
1262 |
svn_error_t *svn_swig_pl_thunk_username_prompt(svn_auth_cred_username_t **cred, |
1263 |
void *baton, |
1264 |
const char *realm, |
1265 |
svn_boolean_t may_save, |
1266 |
apr_pool_t *pool) |
1267 |
{ |
1268 |
/* Be nice and allocate the memory for the cred structure before passing it |
1269 |
* off to the perl space */ |
1270 |
*cred = apr_pcalloc(pool, sizeof(**cred)); |
1271 |
if (!*cred) { |
1272 |
croak("Could not allocate memory for cred structure"); |
1273 |
} |
1274 |
svn_swig_pl_callback_thunk(CALL_SV, |
1275 |
baton, NULL, |
1276 |
"SsbS", *cred, _SWIG_TYPE("svn_auth_cred_username_t *"), |
1277 |
realm, may_save, pool, POOLINFO); |
1278 |
|
1279 |
return SVN_NO_ERROR; |
1280 |
} |
1281 |
|
1282 |
svn_error_t *svn_swig_pl_thunk_ssl_server_trust_prompt( |
1283 |
svn_auth_cred_ssl_server_trust_t **cred, |
1284 |
void *baton, |
1285 |
const char *realm, |
1286 |
apr_uint32_t failures, |
1287 |
const svn_auth_ssl_server_cert_info_t *cert_info, |
1288 |
svn_boolean_t may_save, |
1289 |
apr_pool_t *pool) |
1290 |
{ |
1291 |
/* Be nice and allocate the memory for the cred structure before passing it |
1292 |
* off to the perl space */ |
1293 |
*cred = apr_pcalloc(pool, sizeof(**cred)); |
1294 |
if (!*cred) { |
1295 |
croak("Could not allocate memory for cred structure"); |
1296 |
} |
1297 |
svn_swig_pl_callback_thunk(CALL_SV, |
1298 |
baton, NULL, |
1299 |
"SsiSbS", *cred, _SWIG_TYPE("svn_auth_cred_ssl_server_trust_t *"), |
1300 |
realm, failures, |
1301 |
cert_info, _SWIG_TYPE("svn_auth_ssl_server_cert_info_t *"), |
1302 |
may_save, pool, POOLINFO); |
1303 |
|
1304 |
/* Allow the perl callback to indicate failure by setting all vars to 0 |
1305 |
* or by simply doing nothing. While still allowing them to indicate |
1306 |
* failure by setting the cred strucutre's pointer to 0 via $$cred = 0 */ |
1307 |
if (*cred) { |
1308 |
if ((*cred)->may_save == 0 && (*cred)->accepted_failures == 0) { |
1309 |
*cred = NULL; |
1310 |
} |
1311 |
} |
1312 |
|
1313 |
return SVN_NO_ERROR; |
1314 |
} |
1315 |
|
1316 |
svn_error_t *svn_swig_pl_thunk_ssl_client_cert_prompt( |
1317 |
svn_auth_cred_ssl_client_cert_t **cred, |
1318 |
void *baton, |
1319 |
const char * realm, |
1320 |
svn_boolean_t may_save, |
1321 |
apr_pool_t *pool) |
1322 |
{ |
1323 |
/* Be nice and allocate the memory for the cred structure before passing it |
1324 |
* off to the perl space */ |
1325 |
*cred = apr_pcalloc(pool, sizeof(**cred)); |
1326 |
if (!*cred) { |
1327 |
croak("Could not allocate memory for cred structure"); |
1328 |
} |
1329 |
svn_swig_pl_callback_thunk(CALL_SV, |
1330 |
baton, NULL, |
1331 |
"SsbS", *cred, _SWIG_TYPE("svn_auth_cred_ssl_client_cert_t *"), |
1332 |
realm, may_save, pool, POOLINFO); |
1333 |
|
1334 |
return SVN_NO_ERROR; |
1335 |
} |
1336 |
|
1337 |
svn_error_t *svn_swig_pl_thunk_ssl_client_cert_pw_prompt( |
1338 |
svn_auth_cred_ssl_client_cert_pw_t **cred, |
1339 |
void *baton, |
1340 |
const char *realm, |
1341 |
svn_boolean_t may_save, |
1342 |
apr_pool_t *pool) |
1343 |
{ |
1344 |
/* Be nice and allocate the memory for the cred structure before passing it |
1345 |
* off to the perl space */ |
1346 |
*cred = apr_pcalloc(pool, sizeof(**cred)); |
1347 |
if (!*cred) { |
1348 |
croak("Could not allocate memory for cred structure"); |
1349 |
} |
1350 |
svn_swig_pl_callback_thunk(CALL_SV, |
1351 |
baton, NULL, |
1352 |
"SsbS", *cred, _SWIG_TYPE("svn_auth_cred_ssl_client_cert_pw_t *"), |
1353 |
realm, may_save, pool, POOLINFO); |
1354 |
|
1355 |
return SVN_NO_ERROR; |
1356 |
} |
1357 |
|
1358 |
/* Thunked version of svn_wc_notify_func_t callback type */ |
1359 |
void svn_swig_pl_notify_func(void * baton, |
1360 |
const char *path, |
1361 |
svn_wc_notify_action_t action, |
1362 |
svn_node_kind_t kind, |
1363 |
const char *mime_type, |
1364 |
svn_wc_notify_state_t content_state, |
1365 |
svn_wc_notify_state_t prop_state, |
1366 |
svn_revnum_t revision) |
1367 |
{ |
1368 |
if (!SvOK((SV *)baton)) { |
1369 |
return; |
1370 |
} |
1371 |
|
1372 |
svn_swig_pl_callback_thunk(CALL_SV, |
1373 |
baton, NULL, |
1374 |
"siisiir", path, action, kind, mime_type, |
1375 |
content_state, prop_state, revision); |
1376 |
|
1377 |
} |
1378 |
|
1379 |
/* Thunked version of svn_client_get_commit_log3_t callback type. */ |
1380 |
svn_error_t *svn_swig_pl_get_commit_log_func(const char **log_msg, |
1381 |
const char **tmp_file, |
1382 |
const apr_array_header_t * |
1383 |
commit_items, |
1384 |
void *baton, |
1385 |
apr_pool_t *pool) |
1386 |
{ |
1387 |
SV *result; |
1388 |
svn_error_t *ret_val = SVN_NO_ERROR; |
1389 |
SV *log_msg_sv; |
1390 |
SV *tmp_file_sv; |
1391 |
SV *commit_items_sv; |
1392 |
|
1393 |
if (!SvOK((SV *)baton)) { |
1394 |
*log_msg = apr_pstrdup(pool, ""); |
1395 |
*tmp_file = NULL; |
1396 |
return SVN_NO_ERROR; |
1397 |
} |
1398 |
|
1399 |
log_msg_sv = newRV_noinc(sv_newmortal()); |
1400 |
tmp_file_sv = newRV_noinc(sv_newmortal()); |
1401 |
commit_items_sv = svn_swig_pl_convert_array |
1402 |
(commit_items, _SWIG_TYPE("svn_client_commit_item3_t *")); |
1403 |
|
1404 |
svn_swig_pl_callback_thunk(CALL_SV, |
1405 |
baton, &result, |
1406 |
"OOOS", log_msg_sv, tmp_file_sv, |
1407 |
commit_items_sv, pool, POOLINFO); |
1408 |
|
1409 |
if (!SvOK(SvRV(log_msg_sv))) { |
1410 |
/* client returned undef to us */ |
1411 |
*log_msg = NULL; |
1412 |
} else if (SvPOK(SvRV(log_msg_sv))) { |
1413 |
/* client returned string so get the string and then duplicate |
1414 |
* it using pool memory */ |
1415 |
*log_msg = apr_pstrdup(pool, SvPV_nolen(SvRV(log_msg_sv))); |
1416 |
} else { |
1417 |
croak("Invalid value in log_msg reference, must be undef or a string"); |
1418 |
} |
1419 |
|
1420 |
if (!SvOK(SvRV(tmp_file_sv))) { |
1421 |
*tmp_file = NULL; |
1422 |
} else if (SvPOK(SvRV(tmp_file_sv))) { |
1423 |
*tmp_file = apr_pstrdup(pool, SvPV_nolen(SvRV(tmp_file_sv))); |
1424 |
} else { |
1425 |
croak("Invalid value in tmp_file reference, " |
1426 |
"must be undef or a string"); |
1427 |
} |
1428 |
|
1429 |
if (sv_derived_from(result, "_p_svn_error_t")) { |
1430 |
swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *"); |
1431 |
if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) { |
1432 |
SvREFCNT_dec(result); |
1433 |
croak("Unable to convert from SWIG Type"); |
1434 |
} |
1435 |
} |
1436 |
|
1437 |
SvREFCNT_dec(result); |
1438 |
return ret_val; |
1439 |
} |
1440 |
|
1441 |
/* Thunked version of svn_client_info_t callback type. */ |
1442 |
svn_error_t *svn_swig_pl_info_receiver(void *baton, |
1443 |
const char *path, |
1444 |
const svn_info_t *info, |
1445 |
apr_pool_t *pool) |
1446 |
{ |
1447 |
SV *result; |
1448 |
svn_error_t *ret_val; |
1449 |
swig_type_info *infoinfo = _SWIG_TYPE("svn_info_t *"); |
1450 |
|
1451 |
if (!SvOK((SV *)baton)) |
1452 |
return SVN_NO_ERROR; |
1453 |
|
1454 |
svn_swig_pl_callback_thunk(CALL_SV, baton, &result, "sSS", path, info, |
1455 |
infoinfo, pool, POOLINFO); |
1456 |
|
1457 |
if (sv_derived_from(result, "_p_svn_error_t")) { |
1458 |
swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *"); |
1459 |
if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) { |
1460 |
SvREFCNT_dec(result); |
1461 |
croak("Unable to convert from SWIG Type"); |
1462 |
} |
1463 |
} |
1464 |
else |
1465 |
ret_val = SVN_NO_ERROR; |
1466 |
|
1467 |
SvREFCNT_dec(result); |
1468 |
return ret_val; |
1469 |
} |
1470 |
|
1471 |
|
1472 |
/* Thunked version of svn_wc_cancel_func_t callback type. */ |
1473 |
svn_error_t *svn_swig_pl_cancel_func(void *cancel_baton) { |
1474 |
SV *result; |
1475 |
svn_error_t *ret_val; |
1476 |
|
1477 |
if (!SvOK((SV *)cancel_baton)) { |
1478 |
return SVN_NO_ERROR; |
1479 |
} |
1480 |
svn_swig_pl_callback_thunk(CALL_SV, cancel_baton, &result, ""); |
1481 |
|
1482 |
if (sv_derived_from(result,"_p_svn_error_t")) { |
1483 |
swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *"); |
1484 |
if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) { |
1485 |
SvREFCNT_dec(result); |
1486 |
croak("Unable to convert from SWIG Type"); |
1487 |
} |
1488 |
} else if (SvIOK(result) && SvIV(result)) { |
1489 |
ret_val = svn_error_create(SVN_ERR_CANCELLED, NULL, |
1490 |
"By cancel callback"); |
1491 |
} else if (SvTRUE(result) && SvPOK(result)) { |
1492 |
ret_val = svn_error_create(SVN_ERR_CANCELLED, NULL, |
1493 |
SvPV_nolen(result)); |
1494 |
} else { |
1495 |
ret_val = SVN_NO_ERROR; |
1496 |
} |
1497 |
SvREFCNT_dec(result); |
1498 |
return ret_val; |
1499 |
} |
1500 |
|
1501 |
/* Thunked version of svn_wc_status_func_t callback type. */ |
1502 |
void svn_swig_pl_status_func(void *baton, |
1503 |
const char *path, |
1504 |
svn_wc_status_t *status) |
1505 |
{ |
1506 |
swig_type_info *statusinfo = _SWIG_TYPE("svn_wc_status_t *"); |
1507 |
|
1508 |
if (!SvOK((SV *)baton)) { |
1509 |
return; |
1510 |
} |
1511 |
|
1512 |
svn_swig_pl_callback_thunk(CALL_SV, baton, NULL, "sS", |
1513 |
path, status, statusinfo); |
1514 |
|
1515 |
} |
1516 |
|
1517 |
/* Thunked version of svn_wc_status_func2_t callback type. */ |
1518 |
void svn_swig_pl_status_func2(void *baton, |
1519 |
const char *path, |
1520 |
svn_wc_status2_t *status) |
1521 |
{ |
1522 |
swig_type_info *statusinfo = _SWIG_TYPE("svn_wc_status2 _t *"); |
1523 |
|
1524 |
if (!SvOK((SV *)baton)) { |
1525 |
return; |
1526 |
} |
1527 |
|
1528 |
svn_swig_pl_callback_thunk(CALL_SV, baton, NULL, "sS", |
1529 |
path, status, statusinfo); |
1530 |
|
1531 |
} |
1532 |
|
1533 |
/* Thunked version of svn_wc_status_func3_t callback type. */ |
1534 |
svn_error_t *svn_swig_pl_status_func3(void *baton, |
1535 |
const char *path, |
1536 |
svn_wc_status2_t *status, |
1537 |
apr_pool_t *pool) |
1538 |
{ |
1539 |
SV *result; |
1540 |
svn_error_t *ret_val = SVN_NO_ERROR; |
1541 |
|
1542 |
swig_type_info *statusinfo = _SWIG_TYPE("svn_wc_status2 _t *"); |
1543 |
|
1544 |
if (!SvOK((SV *)baton)) { |
1545 |
return ret_val; |
1546 |
} |
1547 |
|
1548 |
svn_swig_pl_callback_thunk(CALL_SV, baton, &result, "sSS", |
1549 |
path, status, statusinfo, |
1550 |
pool, POOLINFO); |
1551 |
|
1552 |
if (sv_derived_from(result, "_p_svn_error_t")) { |
1553 |
swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *"); |
1554 |
if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) { |
1555 |
SvREFCNT_dec(result); |
1556 |
croak("Unable to convert from SWIG Type"); |
1557 |
} |
1558 |
} |
1559 |
|
1560 |
SvREFCNT_dec(result); |
1561 |
return ret_val; |
1562 |
} |
1563 |
|
1564 |
|
1565 |
/* Thunked version of svn_client_blame_receiver_t callback type. */ |
1566 |
svn_error_t *svn_swig_pl_blame_func(void *baton, |
1567 |
apr_int64_t line_no, |
1568 |
svn_revnum_t revision, |
1569 |
const char *author, |
1570 |
const char *date, |
1571 |
const char *line, |
1572 |
apr_pool_t *pool) |
1573 |
{ |
1574 |
SV *result; |
1575 |
svn_error_t *ret_val = SVN_NO_ERROR; |
1576 |
|
1577 |
svn_swig_pl_callback_thunk(CALL_SV, baton, &result, "LrsssS", |
1578 |
line_no, revision, author, date, line, |
1579 |
pool, POOLINFO); |
1580 |
|
1581 |
if (sv_derived_from(result, "_p_svn_error_t")) { |
1582 |
swig_type_info *errorinfo = _SWIG_TYPE("svn_error_t *"); |
1583 |
if (SWIG_ConvertPtr(result, (void *)&ret_val, errorinfo, 0) < 0) { |
1584 |
SvREFCNT_dec(result); |
1585 |
croak("Unable to convert from SWIG Type"); |
1586 |
} |
1587 |
} |
1588 |
|
1589 |
SvREFCNT_dec(result); |
1590 |
return ret_val; |
1591 |
} |
1592 |
|
1593 |
/* Thunked config enumerator */ |
1594 |
svn_boolean_t svn_swig_pl_thunk_config_enumerator(const char *name, const char *value, void *baton) |
1595 |
{ |
1596 |
SV *result; |
1597 |
if (!SvOK((SV *)baton)) |
1598 |
return 0; |
1599 |
|
1600 |
svn_swig_pl_callback_thunk(CALL_SV, baton, &result, |
1601 |
"ss", name, value); |
1602 |
|
1603 |
return SvOK(result); |
1604 |
} |
1605 |
|
1606 |
|
1607 |
/* default pool support */ |
1608 |
|
1609 |
#if defined(SVN_AVOID_CIRCULAR_LINKAGE_AT_ALL_COSTS_HACK) |
1610 |
static svn_swig_pl_get_current_pool_t svn_swig_pl_get_current_pool = NULL; |
1611 |
static svn_swig_pl_set_current_pool_t svn_swig_pl_set_current_pool = NULL; |
1612 |
|
1613 |
void svn_swig_pl_bind_current_pool_fns(svn_swig_pl_get_current_pool_t get, |
1614 |
svn_swig_pl_set_current_pool_t set) |
1615 |
{ |
1616 |
svn_swig_pl_get_current_pool = get; |
1617 |
svn_swig_pl_set_current_pool = set; |
1618 |
} |
1619 |
#else |
1620 |
apr_pool_t *svn_swig_pl_get_current_pool(void); |
1621 |
void svn_swig_pl_set_current_pool(apr_pool_t *pool); |
1622 |
#endif |
1623 |
|
1624 |
|
1625 |
apr_pool_t *svn_swig_pl_make_pool(SV *obj) |
1626 |
{ |
1627 |
apr_pool_t *pool; |
1628 |
|
1629 |
if (obj && sv_isobject(obj)) { |
1630 |
if (sv_derived_from(obj, "SVN::Pool")) { |
1631 |
obj = SvRV(obj); |
1632 |
} |
1633 |
if (sv_derived_from(obj, "_p_apr_pool_t")) { |
1634 |
SWIG_ConvertPtr(obj, (void **)&pool, POOLINFO, 0); |
1635 |
return pool; |
1636 |
} |
1637 |
} |
1638 |
|
1639 |
if (!svn_swig_pl_get_current_pool()) |
1640 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"new_default", |
1641 |
&obj, "s", "SVN::Pool"); |
1642 |
|
1643 |
return svn_swig_pl_get_current_pool(); |
1644 |
} |
1645 |
|
1646 |
/* stream interpolability with io::handle */ |
1647 |
|
1648 |
typedef struct io_baton_t { |
1649 |
SV *obj; |
1650 |
IO *io; |
1651 |
} io_baton_t; |
1652 |
|
1653 |
static svn_error_t *io_handle_read(void *baton, |
1654 |
char *buffer, |
1655 |
apr_size_t *len) |
1656 |
{ |
1657 |
io_baton_t *io = baton; |
1658 |
MAGIC *mg; |
1659 |
|
1660 |
if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) { |
1661 |
SV *ret; |
1662 |
SV *buf = sv_newmortal(); |
1663 |
|
1664 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"READ", &ret, "OOz", |
1665 |
SvTIED_obj((SV*)io->io, mg), |
1666 |
buf, *len); |
1667 |
*len = SvIV(ret); |
1668 |
SvREFCNT_dec(ret); |
1669 |
memmove(buffer, SvPV_nolen(buf), *len); |
1670 |
} |
1671 |
else |
1672 |
*len = PerlIO_read(IoIFP(io->io), buffer, *len); |
1673 |
return SVN_NO_ERROR; |
1674 |
} |
1675 |
|
1676 |
static svn_error_t *io_handle_write(void *baton, |
1677 |
const char *data, |
1678 |
apr_size_t *len) |
1679 |
{ |
1680 |
io_baton_t *io = baton; |
1681 |
MAGIC *mg; |
1682 |
|
1683 |
if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) { |
1684 |
SV *ret, *pv; |
1685 |
pv = sv_2mortal(newSVpvn(data, *len)); |
1686 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"WRITE", &ret, "OOz", |
1687 |
SvTIED_obj((SV*)io->io, mg), pv, *len); |
1688 |
*len = SvIV(ret); |
1689 |
SvREFCNT_dec(ret); |
1690 |
} |
1691 |
else |
1692 |
*len = PerlIO_write(IoIFP(io->io), data, *len); |
1693 |
return SVN_NO_ERROR; |
1694 |
} |
1695 |
|
1696 |
static svn_error_t *io_handle_close(void *baton) |
1697 |
{ |
1698 |
io_baton_t *io = baton; |
1699 |
MAGIC *mg; |
1700 |
|
1701 |
if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) { |
1702 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"CLOSE", NULL, "O", |
1703 |
SvTIED_obj((SV*)io->io, mg)); |
1704 |
} |
1705 |
else { |
1706 |
PerlIO_close(IoIFP(io->io)); |
1707 |
} |
1708 |
|
1709 |
return SVN_NO_ERROR; |
1710 |
} |
1711 |
|
1712 |
static apr_status_t io_handle_cleanup(void *baton) |
1713 |
{ |
1714 |
io_baton_t *io = baton; |
1715 |
SvREFCNT_dec(io->obj); |
1716 |
return APR_SUCCESS; |
1717 |
} |
1718 |
|
1719 |
svn_error_t *svn_swig_pl_make_stream(svn_stream_t **stream, SV *obj) |
1720 |
{ |
1721 |
IO *io; |
1722 |
|
1723 |
if (!SvOK(obj)) { |
1724 |
*stream = NULL; |
1725 |
return SVN_NO_ERROR; |
1726 |
} |
1727 |
|
1728 |
if (obj && sv_isobject(obj)) { |
1729 |
int simple_type = 1; |
1730 |
if (sv_derived_from(obj, "SVN::Stream")) |
1731 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"svn_stream", |
1732 |
&obj, "O", obj); |
1733 |
else if (!sv_derived_from(obj, "_p_svn_stream_t")) |
1734 |
simple_type = 0; |
1735 |
|
1736 |
if (simple_type) { |
1737 |
SWIG_ConvertPtr(obj, (void **)stream, _SWIG_TYPE("svn_stream_t *"), 0); |
1738 |
return SVN_NO_ERROR; |
1739 |
} |
1740 |
} |
1741 |
|
1742 |
if (obj && SvROK(obj) && SvTYPE(SvRV(obj)) == SVt_PVGV && |
1743 |
(io = GvIO(SvRV(obj)))) { |
1744 |
apr_pool_t *pool = svn_swig_pl_get_current_pool(); |
1745 |
io_baton_t *iob = apr_palloc(pool, sizeof(io_baton_t)); |
1746 |
SvREFCNT_inc(obj); |
1747 |
iob->obj = obj; |
1748 |
iob->io = io; |
1749 |
*stream = svn_stream_create(iob, pool); |
1750 |
svn_stream_set_read(*stream, io_handle_read); |
1751 |
svn_stream_set_write(*stream, io_handle_write); |
1752 |
svn_stream_set_close(*stream, io_handle_close); |
1753 |
apr_pool_cleanup_register(pool, iob, io_handle_cleanup, |
1754 |
io_handle_cleanup); |
1755 |
|
1756 |
} |
1757 |
else |
1758 |
croak("unknown type for svn_stream_t"); |
1759 |
|
1760 |
return SVN_NO_ERROR; |
1761 |
} |
1762 |
|
1763 |
svn_error_t *svn_swig_pl_ra_lock_callback( |
1764 |
void *baton, |
1765 |
const char *path, |
1766 |
svn_boolean_t do_lock, |
1767 |
const svn_lock_t *lock, |
1768 |
svn_error_t *ra_err, |
1769 |
apr_pool_t *pool) |
1770 |
{ |
1771 |
if (!SvOK((SV *)baton)) |
1772 |
return SVN_NO_ERROR; |
1773 |
|
1774 |
SVN_ERR(svn_swig_pl_callback_thunk(CALL_SV, baton, NULL, "sbSSS", |
1775 |
path, do_lock, |
1776 |
lock, _SWIG_TYPE("svn_lock_t *"), |
1777 |
ra_err, _SWIG_TYPE("svn_error_t *"), |
1778 |
pool, POOLINFO)); |
1779 |
return SVN_NO_ERROR; |
1780 |
} |
1781 |
|
1782 |
SV *svn_swig_pl_from_stream(svn_stream_t *stream) |
1783 |
{ |
1784 |
SV *ret; |
1785 |
|
1786 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"new", &ret, "sS", |
1787 |
"SVN::Stream", stream, _SWIG_TYPE("svn_stream_t *")); |
1788 |
|
1789 |
return sv_2mortal(ret); |
1790 |
} |
1791 |
|
1792 |
apr_file_t *svn_swig_pl_make_file(SV *file, apr_pool_t *pool) |
1793 |
{ |
1794 |
apr_file_t *apr_file = NULL; |
1795 |
|
1796 |
if (!SvOK(file) || file == &PL_sv_undef) |
1797 |
return NULL; |
1798 |
|
1799 |
if (SvPOKp(file)) { |
1800 |
apr_file_open(&apr_file, SvPV_nolen(file), |
1801 |
APR_CREATE | APR_READ | APR_WRITE, |
1802 |
APR_OS_DEFAULT, |
1803 |
pool); |
1804 |
} else if (SvROK(file) && SvTYPE(SvRV(file)) == SVt_PVGV) { |
1805 |
apr_status_t status; |
1806 |
#ifdef WIN32 |
1807 |
apr_os_file_t osfile = (apr_os_file_t) |
1808 |
_get_osfhandle(PerlIO_fileno(IoIFP(sv_2io(file)))); |
1809 |
#else |
1810 |
apr_os_file_t osfile = PerlIO_fileno(IoIFP(sv_2io(file))); |
1811 |
#endif |
1812 |
status = apr_os_file_put(&apr_file, &osfile, |
1813 |
O_CREAT | O_WRONLY, pool); |
1814 |
if (status) |
1815 |
return NULL; |
1816 |
} |
1817 |
return apr_file; |
1818 |
} |
1819 |
|
1820 |
static apr_status_t cleanup_refcnt(void *data) |
1821 |
{ |
1822 |
SV *sv = data; |
1823 |
SvREFCNT_dec(sv); |
1824 |
return APR_SUCCESS; |
1825 |
} |
1826 |
|
1827 |
void svn_swig_pl_hold_ref_in_pool(apr_pool_t *pool, SV *sv) |
1828 |
{ |
1829 |
SvREFCNT_inc(sv); |
1830 |
apr_pool_cleanup_register(pool, sv, cleanup_refcnt, apr_pool_cleanup_null); |
1831 |
} |
1832 |
|
1833 |
SV *svn_swig_pl_from_md5(unsigned char *digest) |
1834 |
{ |
1835 |
SV *ret; |
1836 |
|
1837 |
svn_swig_pl_callback_thunk(CALL_METHOD, (void *)"new", &ret, "sS", |
1838 |
"SVN::MD5", digest, |
1839 |
_SWIG_TYPE("unsigned char *")); |
1840 |
|
1841 |
return sv_2mortal(ret); |
1842 |
} |