ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/vendor/apache/subversion/dist/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c
Revision: 9264
Committed: Mon Feb 20 02:37:02 2017 UTC (7 years, 2 months ago) by laffer1
Content type: text/plain
File size: 59140 byte(s)
Log Message:
subversion 1.8.10

File Contents

# Content
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 }