2 * swigutil_pl.c: utility functions for the SWIG Perl bindings
4 * ====================================================================
5 * Copyright (c) 2000-2006 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
29 #include <apr_general.h>
30 #include <apr_portable.h>
32 #include "svn_pools.h"
34 #include "svn_private_config.h"
36 #include "swig_perl_external_runtime.swg"
38 #include "swigutil_pl.h"
40 /* cache SWIG_TypeQuery results in a perl hash */
41 static HV
*type_cache
= NULL
;
43 #define _SWIG_TYPE(name) _swig_perl_type_query(name, 0)
44 #define POOLINFO _SWIG_TYPE("apr_pool_t *")
46 static swig_type_info
*_swig_perl_type_query(const char *typename
, U32 klen
)
49 swig_type_info
*tinfo
;
55 klen
= strlen(typename
);
57 if ((type_info
= hv_fetch(type_cache
, typename
, klen
, 0)))
58 return (swig_type_info
*) (SvIV(*type_info
));
60 tinfo
= SWIG_TypeQuery(typename
);
61 hv_store(type_cache
, typename
, klen
, newSViv((IV
)tinfo
), 0);
66 /* element convertors for perl -> c */
67 typedef void *(*pl_element_converter_t
)(SV
*value
, void *ctx
,
70 static void *convert_pl_string(SV
*value
, void *dummy
, apr_pool_t
*pool
)
72 void **result
= apr_palloc(pool
, sizeof(void *));
73 *result
= SvPV_nolen(value
);
77 static void *convert_pl_obj(SV
*value
, swig_type_info
*tinfo
,
80 void **result
= apr_palloc(pool
, sizeof(void *));
81 if (SWIG_ConvertPtr(value
, result
, tinfo
, 0) < 0) {
82 croak("unable to convert from swig object");
87 /* perl -> c hash convertors */
88 static apr_hash_t
*svn_swig_pl_to_hash(SV
*source
,
89 pl_element_converter_t cv
,
90 void *ctx
, apr_pool_t
*pool
)
97 if (!(source
&& SvROK(source
) && SvTYPE(SvRV(source
)) == SVt_PVHV
)) {
101 hash
= apr_hash_make(pool
);
102 h
= (HV
*)SvRV(source
);
103 cnt
= hv_iterinit(h
);
105 SV
* item
= hv_iternextsv(h
, &key
, &retlen
);
106 void *val
= cv(item
, ctx
, pool
);
107 apr_hash_set(hash
, key
, APR_HASH_KEY_STRING
, val
);
113 apr_hash_t
*svn_swig_pl_objs_to_hash(SV
*source
, swig_type_info
*tinfo
,
117 return svn_swig_pl_to_hash(source
, (pl_element_converter_t
)convert_pl_obj
,
121 apr_hash_t
*svn_swig_pl_strings_to_hash(SV
*source
, apr_pool_t
*pool
)
124 return svn_swig_pl_to_hash(source
, convert_pl_string
, NULL
, pool
);
128 apr_hash_t
*svn_swig_pl_objs_to_hash_by_name(SV
*source
,
129 const char *typename
,
132 swig_type_info
*tinfo
= _SWIG_TYPE(typename
);
133 return svn_swig_pl_objs_to_hash(source
, tinfo
, pool
);
136 /* perl -> c array convertors */
138 apr_array_header_t
*svn_swig_pl_to_array(SV
*source
,
139 pl_element_converter_t cv
,
140 void *ctx
, apr_pool_t
*pool
)
143 apr_array_header_t
*temp
;
146 if (SvROK(source
) && SvTYPE(SvRV(source
)) == SVt_PVAV
) {
147 array
= (AV
*)SvRV(source
);
148 targlen
= av_len(array
) + 1;
149 temp
= apr_array_make(pool
, targlen
, sizeof(const char *));
150 temp
->nelts
= targlen
;
153 /* more error handling here */
154 SV
**item
= av_fetch(array
, targlen
, 0);
155 APR_ARRAY_IDX(temp
, targlen
, const char *) = cv(*item
, ctx
, pool
);
157 } else if (SvOK(source
)) {
159 temp
= apr_array_make(pool
, targlen
, sizeof(const char *));
160 temp
->nelts
= targlen
;
161 APR_ARRAY_IDX(temp
, 0, const char *) = cv(source
, ctx
, pool
);
163 croak("Must pass a single value or an array reference");
169 const apr_array_header_t
*svn_swig_pl_strings_to_array(SV
*source
,
172 return svn_swig_pl_to_array(source
, convert_pl_string
, NULL
, pool
);
175 const apr_array_header_t
*svn_swig_pl_objs_to_array(SV
*source
,
176 swig_type_info
*tinfo
,
179 return svn_swig_pl_to_array(source
,
180 (pl_element_converter_t
)convert_pl_obj
,
184 /* element convertors for c -> perl */
185 typedef SV
*(*element_converter_t
)(void *value
, void *ctx
);
187 static SV
*convert_string(const char *value
, void *dummy
)
189 SV
*obj
= sv_2mortal(newSVpv(value
, 0));
193 static SV
*convert_svn_string_t(svn_string_t
*value
, void *dummy
)
195 SV
*obj
= sv_2mortal(newSVpv(value
->data
, value
->len
));
199 static SV
*convert_to_swig_type(void *ptr
, swig_type_info
*tinfo
)
201 SV
*obj
= sv_newmortal();
202 SWIG_MakePtr(obj
, ptr
, tinfo
, 0);
206 static SV
*convert_int(int value
, void *dummy
)
208 return sv_2mortal(newSViv(value
));
211 /* c -> perl hash convertors */
212 static SV
*convert_hash(apr_hash_t
*hash
, element_converter_t converter_func
,
215 apr_hash_index_t
*hi
;
219 for (hi
= apr_hash_first(NULL
, hash
); hi
; hi
= apr_hash_next(hi
)) {
225 apr_hash_this(hi
, (void *)&key
, NULL
, &val
);
228 obj
= converter_func(val
, ctx
);
229 hv_store(hv
, (const char *)key
, klen
, obj
, 0);
233 return sv_2mortal(newRV_noinc((SV
*)hv
));
236 SV
*svn_swig_pl_prophash_to_hash(apr_hash_t
*hash
)
238 return convert_hash(hash
, (element_converter_t
)convert_svn_string_t
,
242 SV
*svn_swig_pl_convert_hash(apr_hash_t
*hash
, swig_type_info
*tinfo
)
244 return convert_hash(hash
, (element_converter_t
)convert_to_swig_type
,
248 /* c -> perl array convertors */
249 static SV
*convert_array(const apr_array_header_t
*array
,
250 element_converter_t converter_func
, void *ctx
)
255 for (i
= 0; i
< array
->nelts
; ++i
) {
256 void *element
= APR_ARRAY_IDX(array
, i
, void *);
257 SV
*item
= converter_func(element
, ctx
);
261 return sv_2mortal(newRV_noinc((SV
*)list
));
264 SV
*svn_swig_pl_array_to_list(const apr_array_header_t
*array
)
266 return convert_array(array
, (element_converter_t
)convert_string
, NULL
);
269 /* Formerly used by pre-1.0 APIs. Now unused
270 SV *svn_swig_pl_ints_to_list(const apr_array_header_t *array)
272 return convert_array (array, (element_converter_t)convert_int, NULL);
276 SV
*svn_swig_pl_convert_array(const apr_array_header_t
*array
,
277 swig_type_info
*tinfo
)
279 return convert_array(array
, (element_converter_t
)convert_to_swig_type
,
283 /* put the va_arg in stack and invoke caller_func with func.
297 Please do not add C types here. Add a new format code if needed.
298 Using the underlying C types and not the APR or SVN types can break
299 things if these data types change in the future or on platforms which
302 put returned value in result if result is not NULL
305 svn_error_t
*svn_swig_pl_callback_thunk(perl_func_invoker_t caller_func
,
308 const char *fmt
, ...)
310 const char *fp
= fmt
;
313 I32 call_flags
= result
? G_SCALAR
: (G_VOID
& G_DISCARD
);
331 XPUSHs(va_arg(ap
, SV
*));
333 case 'S': /* swig object */
334 o
= va_arg(ap
, void *);
335 t
= va_arg(ap
, swig_type_info
*);
337 obj
= sv_newmortal();
338 SWIG_MakePtr(obj
, o
, t
, 0);
342 case 's': /* string */
343 c
= va_arg(ap
, char *);
344 XPUSHs(c
? sv_2mortal(newSVpv(c
, 0)) : &PL_sv_undef
);
347 case 'i': /* apr_int32_t */
348 XPUSHs(sv_2mortal(newSViv(va_arg(ap
, apr_int32_t
))));
351 case 'u': /* apr_uint32_t */
352 XPUSHs(sv_2mortal(newSViv(va_arg(ap
, apr_uint32_t
))));
355 case 'r': /* svn_revnum_t */
356 XPUSHs(sv_2mortal(newSViv(va_arg(ap
, svn_revnum_t
))));
359 case 'b': /* svn_boolean_t */
360 XPUSHs(sv_2mortal(newSViv(va_arg(ap
, svn_boolean_t
))));
363 case 't': /* svn_string_t */
364 str
= va_arg(ap
, svn_string_t
*);
365 XPUSHs(str
? sv_2mortal(newSVpv(str
->data
, str
->len
))
369 case 'L': /* apr_int64_t */
370 /* Pass into perl as a string because some implementations may
371 * not be able to handle a 64-bit int. If it's too long to
372 * fit in Perl's interal IV size then perl will only make
373 * it available as a string. If not then perl will convert
374 * it to an IV for us. So this handles the problem gracefully */
376 snprintf(c
,30,"%" APR_INT64_T_FMT
,va_arg(ap
, apr_int64_t
));
377 XPUSHs(sv_2mortal(newSVpv(c
, 0)));
381 case 'U': /* apr_uint64_t */
383 snprintf(c
,30,"%" APR_UINT64_T_FMT
,va_arg(ap
, apr_uint64_t
));
384 XPUSHs(sv_2mortal(newSVpv(c
, 0)));
388 case 'z': /* apr_size_t */
389 if (sizeof(apr_size_t
) >= 8)
392 snprintf(c
,30,"%" APR_SIZE_T_FMT
,va_arg(ap
, apr_size_t
));
393 XPUSHs(sv_2mortal(newSVpv(c
, 0)));
398 XPUSHs(sv_2mortal(newSViv(va_arg(ap
, apr_size_t
))));
407 switch (caller_func
) {
409 count
= call_sv(func
, call_flags
);
412 count
= call_method(func
, call_flags
);
415 croak("unkonwn calling type");
420 if (((call_flags
& G_SCALAR
) && count
!= 1) ||
421 ((call_flags
& G_VOID
) && count
!= 0))
422 croak("Wrong number of returns");
426 SvREFCNT_inc(*result
);
436 /*** Editor Wrapping ***/
438 /* this could be more perlish */
440 SV
*editor
; /* the editor handling the callbacks */
441 SV
*baton
; /* the dir/file baton (or NULL for edit baton) */
444 static item_baton
* make_baton(apr_pool_t
*pool
,
445 SV
*editor
, SV
*baton
)
447 item_baton
*newb
= apr_palloc(pool
, sizeof(*newb
));
449 newb
->editor
= editor
;
455 static svn_error_t
* close_baton(void *baton
, const char *method
, apr_pool_t
*pool
)
457 item_baton
*ib
= baton
;
460 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
461 (void *)method
, NULL
,
462 "OOS", ib
->editor
, ib
->baton
,
464 SvREFCNT_dec(ib
->baton
);
467 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
468 (void *)method
, NULL
,
469 "OS", ib
->editor
, pool
, POOLINFO
));
475 static svn_error_t
* thunk_set_target_revision(void *edit_baton
,
476 svn_revnum_t target_revision
,
479 item_baton
*ib
= edit_baton
;
481 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
482 (void *)"set_target_revision", NULL
,
483 "Or", ib
->editor
, target_revision
));
488 static svn_error_t
* thunk_open_root(void *edit_baton
,
489 svn_revnum_t base_revision
,
490 apr_pool_t
*dir_pool
,
493 item_baton
*ib
= edit_baton
;
496 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
497 (void *)"open_root", &result
,
498 "OrS", ib
->editor
, base_revision
,
499 dir_pool
, POOLINFO
));
501 *root_baton
= make_baton(dir_pool
, ib
->editor
, result
);
505 static svn_error_t
* thunk_delete_entry(const char *path
,
506 svn_revnum_t revision
,
510 item_baton
*ib
= parent_baton
;
512 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
513 (void *)"delete_entry", NULL
,
514 "OsrOS", ib
->editor
, path
, revision
,
515 ib
->baton
, pool
, POOLINFO
));
519 static svn_error_t
* thunk_add_directory(const char *path
,
521 const char *copyfrom_path
,
522 svn_revnum_t copyfrom_revision
,
523 apr_pool_t
*dir_pool
,
526 item_baton
*ib
= parent_baton
;
529 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
530 (void *)"add_directory", &result
,
531 "OsOsrS", ib
->editor
, path
, ib
->baton
,
532 copyfrom_path
, copyfrom_revision
,
533 dir_pool
, POOLINFO
));
534 *child_baton
= make_baton(dir_pool
, ib
->editor
, result
);
538 static svn_error_t
* thunk_open_directory(const char *path
,
540 svn_revnum_t base_revision
,
541 apr_pool_t
*dir_pool
,
544 item_baton
*ib
= parent_baton
;
547 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
548 (void *)"open_directory", &result
,
549 "OsOrS", ib
->editor
, path
, ib
->baton
,
550 base_revision
, dir_pool
, POOLINFO
));
552 *child_baton
= make_baton(dir_pool
, ib
->editor
, result
);
557 static svn_error_t
* thunk_change_dir_prop(void *dir_baton
,
559 const svn_string_t
*value
,
562 item_baton
*ib
= dir_baton
;
564 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
565 (void *)"change_dir_prop", NULL
,
566 "OOstS", ib
->editor
, ib
->baton
, name
,
567 value
, pool
, POOLINFO
));
572 static svn_error_t
* thunk_close_directory(void *dir_baton
,
575 return close_baton(dir_baton
, "close_directory", pool
);
578 static svn_error_t
* thunk_absent_directory(const char *path
,
582 item_baton
*ib
= parent_baton
;
584 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
585 (void *)"absent_directory", NULL
,
586 "OsOS", ib
->editor
, path
, ib
->baton
,
592 static svn_error_t
* thunk_add_file(const char *path
,
594 const char *copyfrom_path
,
595 svn_revnum_t copyfrom_revision
,
596 apr_pool_t
*file_pool
,
599 item_baton
*ib
= parent_baton
;
602 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
603 (void *)"add_file", &result
,
604 "OsOsrS", ib
->editor
, path
, ib
->baton
,
605 copyfrom_path
, copyfrom_revision
,
606 file_pool
, POOLINFO
));
608 *file_baton
= make_baton(file_pool
, ib
->editor
, result
);
612 static svn_error_t
* thunk_open_file(const char *path
,
614 svn_revnum_t base_revision
,
615 apr_pool_t
*file_pool
,
618 item_baton
*ib
= parent_baton
;
621 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
622 (void *)"open_file", &result
,
623 "OsOrS", ib
->editor
, path
, ib
->baton
,
624 base_revision
, file_pool
, POOLINFO
));
626 *file_baton
= make_baton(file_pool
, ib
->editor
, result
);
630 static svn_error_t
* thunk_window_handler(svn_txdelta_window_t
*window
,
635 if (window
== NULL
) {
636 SVN_ERR(svn_swig_pl_callback_thunk(CALL_SV
,
639 SvREFCNT_dec(handler
);
642 swig_type_info
*tinfo
= _SWIG_TYPE("svn_txdelta_window_t *");
643 SVN_ERR(svn_swig_pl_callback_thunk(CALL_SV
, handler
,
644 NULL
, "S", window
, tinfo
));
651 thunk_apply_textdelta(void *file_baton
,
652 const char *base_checksum
,
654 svn_txdelta_window_handler_t
*handler
,
657 item_baton
*ib
= file_baton
;
660 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
661 (void *)"apply_textdelta", &result
,
662 "OOsS", ib
->editor
, ib
->baton
,
663 base_checksum
, pool
, POOLINFO
));
665 if (SvROK(result
) && SvTYPE(SvRV(result
)) == SVt_PVAV
) {
666 swig_type_info
*handler_info
=
667 _SWIG_TYPE("svn_txdelta_window_handler_t");
668 swig_type_info
*void_info
= _SWIG_TYPE("void *");
669 AV
*array
= (AV
*)SvRV(result
);
671 if (SWIG_ConvertPtr(*av_fetch(array
, 0, 0),
672 (void **)handler
, handler_info
,0) < 0) {
673 croak("Unable to convert from SWIG Type");
675 if (SWIG_ConvertPtr(*av_fetch(array
, 1, 0),
676 h_baton
, void_info
,0) < 0) {
677 croak("Unable to convert from SWIG Type ");
679 SvREFCNT_dec(result
);
682 *handler
= thunk_window_handler
;
687 *handler
= svn_delta_noop_window_handler
;
694 static svn_error_t
* thunk_change_file_prop(void *file_baton
,
696 const svn_string_t
*value
,
699 item_baton
*ib
= file_baton
;
701 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
702 (void *)"change_file_prop", NULL
,
703 "OOstS", ib
->editor
, ib
->baton
, name
,
704 value
, pool
, POOLINFO
));
709 static svn_error_t
* thunk_close_file(void *file_baton
,
710 const char *text_checksum
,
713 item_baton
*ib
= file_baton
;
715 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
716 (void *)"close_file", NULL
, "OOsS",
717 ib
->editor
, ib
->baton
, text_checksum
,
720 SvREFCNT_dec(ib
->baton
);
725 static svn_error_t
* thunk_absent_file(const char *path
,
729 item_baton
*ib
= parent_baton
;
731 SVN_ERR(svn_swig_pl_callback_thunk(CALL_METHOD
,
732 (void *)"absent_file", NULL
,
733 "OsOS", ib
->editor
, path
, ib
->baton
,
739 static svn_error_t
* thunk_close_edit(void *edit_baton
,
742 return close_baton(edit_baton
, "close_edit", pool
);
745 static svn_error_t
* thunk_abort_edit(void *edit_baton
,
748 return close_baton(edit_baton
, "abort_edit", pool
);
753 svn_delta_wrap_window_handler(svn_txdelta_window_handler_t
*handler
,
758 *handler
= thunk_window_handler
;
760 SvREFCNT_inc(callback
);
761 svn_swig_pl_hold_ref_in_pool(pool
, callback
);
764 void svn_delta_make_editor(svn_delta_editor_t
**editor
,
769 svn_delta_editor_t
*thunk_editor
= svn_delta_default_editor(pool
);
771 thunk_editor
->set_target_revision
= thunk_set_target_revision
;
772 thunk_editor
->open_root
= thunk_open_root
;
773 thunk_editor
->delete_entry
= thunk_delete_entry
;
774 thunk_editor
->add_directory
= thunk_add_directory
;
775 thunk_editor
->open_directory
= thunk_open_directory
;
776 thunk_editor
->change_dir_prop
= thunk_change_dir_prop
;
777 thunk_editor
->close_directory
= thunk_close_directory
;
778 thunk_editor
->absent_directory
= thunk_absent_directory
;
779 thunk_editor
->add_file
= thunk_add_file
;
780 thunk_editor
->open_file
= thunk_open_file
;
781 thunk_editor
->apply_textdelta
= thunk_apply_textdelta
;
782 thunk_editor
->change_file_prop
= thunk_change_file_prop
;
783 thunk_editor
->close_file
= thunk_close_file
;
784 thunk_editor
->absent_file
= thunk_absent_file
;
785 thunk_editor
->close_edit
= thunk_close_edit
;
786 thunk_editor
->abort_edit
= thunk_abort_edit
;
788 *editor
= thunk_editor
;
789 *edit_baton
= make_baton(pool
, perl_editor
, NULL
);
790 svn_swig_pl_hold_ref_in_pool(pool
, perl_editor
);
793 svn_error_t
*svn_swig_pl_thunk_log_receiver(void *baton
,
794 apr_hash_t
*changed_paths
,
801 SV
*receiver
= baton
;
802 swig_type_info
*tinfo
= _SWIG_TYPE("svn_log_changed_path_t *");
807 svn_swig_pl_callback_thunk(CALL_SV
,
809 "OrsssS", (changed_paths
) ?
810 svn_swig_pl_convert_hash(changed_paths
, tinfo
)
812 rev
, author
, date
, msg
, pool
, POOLINFO
);
817 svn_error_t
*svn_swig_pl_thunk_history_func(void *baton
,
819 svn_revnum_t revision
,
827 svn_swig_pl_callback_thunk(CALL_SV
,
829 "srS", path
, revision
, pool
, POOLINFO
);
834 svn_error_t
*svn_swig_pl_thunk_authz_func(svn_boolean_t
*allowed
,
840 SV
*func
= baton
, *result
;
845 svn_swig_pl_callback_thunk(CALL_SV
,
847 "SsS", root
, _SWIG_TYPE("svn_fs_root_t *"),
848 path
, pool
, POOLINFO
);
850 *allowed
= SvIV(result
);
851 SvREFCNT_dec(result
);
856 svn_error_t
*svn_swig_pl_thunk_commit_callback(svn_revnum_t new_revision
,
861 if (!SvOK((SV
*)baton
))
864 svn_swig_pl_callback_thunk(CALL_SV
, baton
, NULL
,
865 "rss", new_revision
, date
, author
);
872 static svn_error_t
* thunk_open_tmp_file(apr_file_t
**fp
,
873 void *callback_baton
,
877 swig_type_info
*tinfo
= _SWIG_TYPE("apr_file_t *");
879 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"open_tmp_file",
880 &result
, "OS", callback_baton
, pool
, POOLINFO
);
882 if (SWIG_ConvertPtr(result
, (void *)fp
, tinfo
,0) < 0) {
883 croak("Unable to convert from SWIG Type");
886 SvREFCNT_dec(result
);
890 svn_error_t
*thunk_get_wc_prop(void *baton
,
893 const svn_string_t
**value
,
900 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"get_wc_prop",
901 &result
, "OssS", baton
, relpath
, name
,
904 /* this is svn_string_t * typemap in */
905 if (!SvOK(result
) || result
== &PL_sv_undef
) {
908 else if (SvPOK(result
)) {
909 data
= SvPV(result
, len
);
910 *value
= svn_string_ncreate(data
, len
, pool
);
913 SvREFCNT_dec(result
);
914 croak("not a string");
917 SvREFCNT_dec(result
);
922 svn_error_t
*svn_ra_make_callbacks(svn_ra_callbacks_t
**cb
,
929 *cb
= apr_pcalloc(pool
, sizeof(**cb
));
931 (*cb
)->open_tmp_file
= thunk_open_tmp_file
;
932 (*cb
)->get_wc_prop
= thunk_get_wc_prop
;
933 (*cb
)->set_wc_prop
= NULL
;
934 (*cb
)->push_wc_prop
= NULL
;
935 (*cb
)->invalidate_wc_props
= NULL
;
936 auth_baton
= *hv_fetch((HV
*)SvRV(perl_callbacks
), "auth", 4, 0);
938 if (SWIG_ConvertPtr(auth_baton
,
939 (void **)&(*cb
)->auth_baton
, _SWIG_TYPE("svn_auth_baton_t *"),0) < 0) {
940 croak("Unable to convert from SWIG Type");
942 *c_baton
= perl_callbacks
;
943 svn_swig_pl_hold_ref_in_pool(pool
, perl_callbacks
);
947 svn_error_t
*svn_swig_pl_thunk_simple_prompt(svn_auth_cred_simple_t
**cred
,
950 const char *username
,
951 svn_boolean_t may_save
,
954 /* Be nice and allocate the memory for the cred structure before passing it
955 * off to the perl space */
956 *cred
= apr_pcalloc(pool
, sizeof(**cred
));
958 croak("Could not allocate memory for cred structure");
960 svn_swig_pl_callback_thunk(CALL_SV
,
962 "SssbS", *cred
, _SWIG_TYPE("svn_auth_cred_simple_t *"),
963 realm
, username
, may_save
, pool
, POOLINFO
);
968 svn_error_t
*svn_swig_pl_thunk_username_prompt(svn_auth_cred_username_t
**cred
,
971 svn_boolean_t may_save
,
974 /* Be nice and allocate the memory for the cred structure before passing it
975 * off to the perl space */
976 *cred
= apr_pcalloc(pool
, sizeof(**cred
));
978 croak("Could not allocate memory for cred structure");
980 svn_swig_pl_callback_thunk(CALL_SV
,
982 "SsbS", *cred
, _SWIG_TYPE("svn_auth_cred_username_t *"),
983 realm
, may_save
, pool
, POOLINFO
);
988 svn_error_t
*svn_swig_pl_thunk_ssl_server_trust_prompt(
989 svn_auth_cred_ssl_server_trust_t
**cred
,
992 apr_uint32_t failures
,
993 const svn_auth_ssl_server_cert_info_t
*cert_info
,
994 svn_boolean_t may_save
,
997 /* Be nice and allocate the memory for the cred structure before passing it
998 * off to the perl space */
999 *cred
= apr_pcalloc(pool
, sizeof(**cred
));
1001 croak("Could not allocate memory for cred structure");
1003 svn_swig_pl_callback_thunk(CALL_SV
,
1005 "SsiSbS", *cred
, _SWIG_TYPE("svn_auth_cred_ssl_server_trust_t *"),
1007 cert_info
, _SWIG_TYPE("svn_auth_ssl_server_cert_info_t *"),
1008 may_save
, pool
, POOLINFO
);
1010 /* Allow the perl callback to indicate failure by setting all vars to 0
1011 * or by simply doing nothing. While still allowing them to indicate
1012 * failure by setting the cred strucutre's pointer to 0 via $$cred = 0 */
1014 if ((*cred
)->may_save
== 0 && (*cred
)->accepted_failures
== 0) {
1019 return SVN_NO_ERROR
;
1022 svn_error_t
*svn_swig_pl_thunk_ssl_client_cert_prompt(
1023 svn_auth_cred_ssl_client_cert_t
**cred
,
1026 svn_boolean_t may_save
,
1029 /* Be nice and allocate the memory for the cred structure before passing it
1030 * off to the perl space */
1031 *cred
= apr_pcalloc(pool
, sizeof(**cred
));
1033 croak("Could not allocate memory for cred structure");
1035 svn_swig_pl_callback_thunk(CALL_SV
,
1037 "SsbS", *cred
, _SWIG_TYPE("svn_auth_cred_ssl_client_cert_t *"),
1038 realm
, may_save
, pool
, POOLINFO
);
1040 return SVN_NO_ERROR
;
1043 svn_error_t
*svn_swig_pl_thunk_ssl_client_cert_pw_prompt(
1044 svn_auth_cred_ssl_client_cert_pw_t
**cred
,
1047 svn_boolean_t may_save
,
1050 /* Be nice and allocate the memory for the cred structure before passing it
1051 * off to the perl space */
1052 *cred
= apr_pcalloc(pool
, sizeof(**cred
));
1054 croak("Could not allocate memory for cred structure");
1056 svn_swig_pl_callback_thunk(CALL_SV
,
1058 "SsbS", *cred
, _SWIG_TYPE("svn_auth_cred_ssl_client_cert_pw_t *"),
1059 realm
, may_save
, pool
, POOLINFO
);
1061 return SVN_NO_ERROR
;
1064 /* Thunked version of svn_wc_notify_func_t callback type */
1065 void svn_swig_pl_notify_func(void * baton
,
1067 svn_wc_notify_action_t action
,
1068 svn_node_kind_t kind
,
1069 const char *mime_type
,
1070 svn_wc_notify_state_t content_state
,
1071 svn_wc_notify_state_t prop_state
,
1072 svn_revnum_t revision
)
1074 if (!SvOK((SV
*)baton
)) {
1078 svn_swig_pl_callback_thunk(CALL_SV
,
1080 "siisiir", path
, action
, kind
, mime_type
,
1081 content_state
, prop_state
, revision
);
1085 /* Thunked version of svn_client_get_commit_log3_t callback type. */
1086 svn_error_t
*svn_swig_pl_get_commit_log_func(const char **log_msg
,
1087 const char **tmp_file
,
1088 const apr_array_header_t
*
1094 svn_error_t
*ret_val
= SVN_NO_ERROR
;
1097 SV
*commit_items_sv
;
1099 if (!SvOK((SV
*)baton
)) {
1100 *log_msg
= apr_pstrdup(pool
, "");
1102 return SVN_NO_ERROR
;
1105 log_msg_sv
= newRV_noinc(sv_newmortal());
1106 tmp_file_sv
= newRV_noinc(sv_newmortal());
1107 commit_items_sv
= svn_swig_pl_convert_array
1108 (commit_items
, _SWIG_TYPE("svn_client_commit_item3_t *"));
1110 svn_swig_pl_callback_thunk(CALL_SV
,
1112 "OOOS", log_msg_sv
, tmp_file_sv
,
1113 commit_items_sv
, pool
, POOLINFO
);
1115 if (!SvOK(SvRV(log_msg_sv
))) {
1116 /* client returned undef to us */
1118 } else if (SvPOK(SvRV(log_msg_sv
))) {
1119 /* client returned string so get the string and then duplicate
1120 * it using pool memory */
1121 *log_msg
= apr_pstrdup(pool
, SvPV_nolen(SvRV(log_msg_sv
)));
1123 croak("Invalid value in log_msg reference, must be undef or a string");
1126 if (!SvOK(SvRV(tmp_file_sv
))) {
1128 } else if (SvPOK(SvRV(tmp_file_sv
))) {
1129 *tmp_file
= apr_pstrdup(pool
, SvPV_nolen(SvRV(tmp_file_sv
)));
1131 croak("Invalid value in tmp_file reference, "
1132 "must be undef or a string");
1135 if (sv_derived_from(result
, "_p_svn_error_t")) {
1136 swig_type_info
*errorinfo
= _SWIG_TYPE("svn_error_t *");
1137 if (SWIG_ConvertPtr(result
, (void *)&ret_val
, errorinfo
, 0) < 0) {
1138 SvREFCNT_dec(result
);
1139 croak("Unable to convert from SWIG Type");
1143 SvREFCNT_dec(result
);
1147 /* Thunked version of svn_client_info_t callback type. */
1148 svn_error_t
*svn_swig_pl_info_receiver(void *baton
,
1150 const svn_info_t
*info
,
1154 svn_error_t
*ret_val
;
1155 swig_type_info
*infoinfo
= _SWIG_TYPE("svn_info_t *");
1157 if (!SvOK((SV
*)baton
))
1158 return SVN_NO_ERROR
;
1160 svn_swig_pl_callback_thunk(CALL_SV
, baton
, &result
, "sSS", path
, info
,
1161 infoinfo
, pool
, POOLINFO
);
1163 if (sv_derived_from(result
, "_p_svn_error_t")) {
1164 swig_type_info
*errorinfo
= _SWIG_TYPE("svn_error_t *");
1165 if (SWIG_ConvertPtr(result
, (void *)&ret_val
, errorinfo
, 0) < 0) {
1166 SvREFCNT_dec(result
);
1167 croak("Unable to convert from SWIG Type");
1171 ret_val
= SVN_NO_ERROR
;
1173 SvREFCNT_dec(result
);
1178 /* Thunked version of svn_wc_cancel_func_t callback type. */
1179 svn_error_t
*svn_swig_pl_cancel_func(void *cancel_baton
) {
1181 svn_error_t
*ret_val
;
1183 if (!SvOK((SV
*)cancel_baton
)) {
1184 return SVN_NO_ERROR
;
1186 svn_swig_pl_callback_thunk(CALL_SV
, cancel_baton
, &result
, "");
1188 if (sv_derived_from(result
,"_p_svn_error_t")) {
1189 swig_type_info
*errorinfo
= _SWIG_TYPE("svn_error_t *");
1190 if (SWIG_ConvertPtr(result
, (void *)&ret_val
, errorinfo
, 0) < 0) {
1191 SvREFCNT_dec(result
);
1192 croak("Unable to convert from SWIG Type");
1194 } else if (SvIOK(result
) && SvIV(result
)) {
1195 ret_val
= svn_error_create(SVN_ERR_CANCELLED
, NULL
,
1196 "By cancel callback");
1197 } else if (SvTRUE(result
) && SvPOK(result
)) {
1198 ret_val
= svn_error_create(SVN_ERR_CANCELLED
, NULL
,
1199 SvPV_nolen(result
));
1201 ret_val
= SVN_NO_ERROR
;
1203 SvREFCNT_dec(result
);
1207 /* Thunked version of svn_wc_status_func_t callback type. */
1208 void svn_swig_pl_status_func(void *baton
,
1210 svn_wc_status_t
*status
)
1212 swig_type_info
*statusinfo
= _SWIG_TYPE("svn_wc_status_t *");
1214 if (!SvOK((SV
*)baton
)) {
1218 svn_swig_pl_callback_thunk(CALL_SV
, baton
, NULL
, "sS",
1219 path
, status
, statusinfo
);
1223 /* Thunked version of svn_client_blame_receiver_t callback type. */
1224 svn_error_t
*svn_swig_pl_blame_func(void *baton
,
1225 apr_int64_t line_no
,
1226 svn_revnum_t revision
,
1233 svn_error_t
*ret_val
= SVN_NO_ERROR
;
1235 svn_swig_pl_callback_thunk(CALL_SV
, baton
, &result
, "LrsssS",
1236 line_no
, revision
, author
, date
, line
,
1239 if (sv_derived_from(result
, "_p_svn_error_t")) {
1240 swig_type_info
*errorinfo
= _SWIG_TYPE("svn_error_t *");
1241 if (SWIG_ConvertPtr(result
, (void *)&ret_val
, errorinfo
, 0) < 0) {
1242 SvREFCNT_dec(result
);
1243 croak("Unable to convert from SWIG Type");
1247 SvREFCNT_dec(result
);
1251 /* Thunked config enumerator */
1252 svn_boolean_t
svn_swig_pl_thunk_config_enumerator(const char *name
, const char *value
, void *baton
)
1255 if (!SvOK((SV
*)baton
))
1258 svn_swig_pl_callback_thunk(CALL_SV
, baton
, &result
,
1261 return SvOK(result
);
1265 /* default pool support */
1267 #if defined(SVN_AVOID_CIRCULAR_LINKAGE_AT_ALL_COSTS_HACK)
1268 static svn_swig_pl_get_current_pool_t svn_swig_pl_get_current_pool
= NULL
;
1269 static svn_swig_pl_set_current_pool_t svn_swig_pl_set_current_pool
= NULL
;
1271 void svn_swig_pl_bind_current_pool_fns(svn_swig_pl_get_current_pool_t get
,
1272 svn_swig_pl_set_current_pool_t set
)
1274 svn_swig_pl_get_current_pool
= get
;
1275 svn_swig_pl_set_current_pool
= set
;
1278 apr_pool_t
*svn_swig_pl_get_current_pool(void);
1279 void svn_swig_pl_set_current_pool(apr_pool_t
*pool
);
1283 apr_pool_t
*svn_swig_pl_make_pool(SV
*obj
)
1287 if (obj
&& sv_isobject(obj
)) {
1288 if (sv_derived_from(obj
, "SVN::Pool")) {
1291 if (sv_derived_from(obj
, "_p_apr_pool_t")) {
1292 SWIG_ConvertPtr(obj
, (void **)&pool
, POOLINFO
, 0);
1297 if (!svn_swig_pl_get_current_pool())
1298 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"new_default",
1299 &obj
, "s", "SVN::Pool");
1301 return svn_swig_pl_get_current_pool();
1304 /* stream interpolability with io::handle */
1311 static svn_error_t
*io_handle_read(void *baton
,
1315 io_baton_t
*io
= baton
;
1318 if ((mg
= SvTIED_mg((SV
*)io
->io
, PERL_MAGIC_tiedscalar
))) {
1320 SV
*buf
= sv_newmortal();
1322 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"READ", &ret
, "OOz",
1323 SvTIED_obj((SV
*)io
->io
, mg
),
1327 memmove(buffer
, SvPV_nolen(buf
), *len
);
1330 *len
= PerlIO_read(IoIFP(io
->io
), buffer
, *len
);
1331 return SVN_NO_ERROR
;
1334 static svn_error_t
*io_handle_write(void *baton
,
1338 io_baton_t
*io
= baton
;
1341 if ((mg
= SvTIED_mg((SV
*)io
->io
, PERL_MAGIC_tiedscalar
))) {
1343 pv
= sv_2mortal(newSVpvn(data
, *len
));
1344 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"WRITE", &ret
, "OOz",
1345 SvTIED_obj((SV
*)io
->io
, mg
), pv
, *len
);
1350 *len
= PerlIO_write(IoIFP(io
->io
), data
, *len
);
1351 return SVN_NO_ERROR
;
1354 static svn_error_t
*io_handle_close(void *baton
)
1356 io_baton_t
*io
= baton
;
1359 if ((mg
= SvTIED_mg((SV
*)io
->io
, PERL_MAGIC_tiedscalar
))) {
1360 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"CLOSE", NULL
, "O",
1361 SvTIED_obj((SV
*)io
->io
, mg
));
1364 PerlIO_close(IoIFP(io
->io
));
1367 return SVN_NO_ERROR
;
1370 static apr_status_t
io_handle_cleanup(void *baton
)
1372 io_baton_t
*io
= baton
;
1373 SvREFCNT_dec(io
->obj
);
1377 svn_error_t
*svn_swig_pl_make_stream(svn_stream_t
**stream
, SV
*obj
)
1380 int simple_type
= 1;
1384 return SVN_NO_ERROR
;
1387 if (obj
&& sv_isobject(obj
)) {
1388 if (sv_derived_from(obj
, "SVN::Stream"))
1389 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"svn_stream",
1391 else if (!sv_derived_from(obj
, "_p_svn_stream_t"))
1395 SWIG_ConvertPtr(obj
, (void **)stream
, _SWIG_TYPE("svn_stream_t *"), 0);
1396 return SVN_NO_ERROR
;
1400 if (obj
&& SvROK(obj
) && SvTYPE(SvRV(obj
)) == SVt_PVGV
&&
1401 (io
= GvIO(SvRV(obj
)))) {
1402 apr_pool_t
*pool
= svn_swig_pl_get_current_pool();
1403 io_baton_t
*iob
= apr_palloc(pool
, sizeof(io_baton_t
));
1407 *stream
= svn_stream_create(iob
, pool
);
1408 svn_stream_set_read(*stream
, io_handle_read
);
1409 svn_stream_set_write(*stream
, io_handle_write
);
1410 svn_stream_set_close(*stream
, io_handle_close
);
1411 apr_pool_cleanup_register(pool
, iob
, io_handle_cleanup
,
1416 croak("unknown type for svn_stream_t");
1418 return SVN_NO_ERROR
;
1421 SV
*svn_swig_pl_from_stream(svn_stream_t
*stream
)
1425 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"new", &ret
, "sS",
1426 "SVN::Stream", stream
, _SWIG_TYPE("svn_stream_t *"));
1428 return sv_2mortal(ret
);
1431 apr_file_t
*svn_swig_pl_make_file(SV
*file
, apr_pool_t
*pool
)
1433 apr_file_t
*apr_file
= NULL
;
1435 if (!SvOK(file
) || file
== &PL_sv_undef
)
1439 apr_file_open(&apr_file
, SvPV_nolen(file
),
1440 APR_CREATE
| APR_READ
| APR_WRITE
,
1443 } else if (SvROK(file
) && SvTYPE(SvRV(file
)) == SVt_PVGV
) {
1444 apr_status_t status
;
1446 apr_os_file_t osfile
= (apr_os_file_t
)
1447 _get_osfhandle(PerlIO_fileno(IoIFP(sv_2io(file
))));
1449 apr_os_file_t osfile
= PerlIO_fileno(IoIFP(sv_2io(file
)));
1451 status
= apr_os_file_put(&apr_file
, &osfile
,
1452 O_CREAT
| O_WRONLY
, pool
);
1459 static apr_status_t
cleanup_refcnt(void *data
)
1466 void svn_swig_pl_hold_ref_in_pool(apr_pool_t
*pool
, SV
*sv
)
1469 apr_pool_cleanup_register(pool
, sv
, cleanup_refcnt
, apr_pool_cleanup_null
);
1472 SV
*svn_swig_pl_from_md5(unsigned char *digest
)
1476 svn_swig_pl_callback_thunk(CALL_METHOD
, (void *)"new", &ret
, "sS",
1478 _SWIG_TYPE("unsigned char *"));
1480 return sv_2mortal(ret
);