From: rich Date: Sat, 18 Oct 2003 12:36:09 +0000 (+0000) Subject: Support HVs. X-Git-Url: http://git.annexia.org/?a=commitdiff_plain;h=3099885336bf959064b00e4205e11e4e5d68e7d5;p=perl4caml.git Support HVs. --- diff --git a/perl.ml b/perl.ml index da811c0..95ad3e5 100644 --- a/perl.ml +++ b/perl.ml @@ -1,12 +1,13 @@ (* Interface to Perl from OCaml. * Copyright (C) 2003 Merjis Ltd. - * $Id: perl.ml,v 1.7 2003-10-16 08:54:56 rich Exp $ + * $Id: perl.ml,v 1.8 2003-10-18 12:36:09 rich Exp $ *) type t type sv type av +type hv exception Perl_failure of string @@ -78,6 +79,7 @@ let string_of_sv_t = function external deref : sv -> sv = "perl4caml_deref" external deref_array : sv -> av = "perl4caml_deref_array" +external deref_hash : sv -> hv = "perl4caml_deref_hash" external av_empty : unit -> av = "perl4caml_av_empty" external av_of_sv_list : sv list -> av = "perl4caml_av_of_sv_list" @@ -99,8 +101,27 @@ let av_map f av = done; List.rev !list +let list_of_av av = + let list = ref [] in + for i = 0 to av_length av - 1 do + list := av_get av i :: !list + done; + List.rev !list + +let av_of_string_list strs = + av_of_sv_list (List.map sv_of_string strs) + +external hv_empty : unit -> hv = "perl4caml_hv_empty" +external hv_set : hv -> string -> sv -> unit = "perl4caml_hv_set" +external hv_get : hv -> string -> sv = "perl4caml_hv_get" +external hv_exists : hv -> string -> bool = "perl4caml_hv_exists" +external hv_delete : hv -> string -> unit = "perl4caml_hv_delete" +external hv_clear : hv -> unit = "perl4caml_hv_clear" +external hv_undef : hv -> unit = "perl4caml_hv_undef" + external get_sv : ?create:bool -> string -> sv = "perl4caml_get_sv" external get_av : ?create:bool -> string -> av = "perl4caml_get_av" +external get_hv : ?create:bool -> string -> hv = "perl4caml_get_hv" external call : ?sv:sv -> ?fn:string -> sv list -> sv = "perl4caml_call" diff --git a/perl.mli b/perl.mli index 73270d2..ef8dea0 100644 --- a/perl.mli +++ b/perl.mli @@ -2,7 +2,7 @@ * * Copyright (C) 2003 Merjis Ltd. * - * $Id: perl.mli,v 1.8 2003-10-16 13:41:06 rich Exp $ + * $Id: perl.mli,v 1.9 2003-10-18 12:36:09 rich Exp $ *) type t @@ -14,10 +14,8 @@ type sv type av (** Perl array value. *) -(* type hv (** Perl hash value. *) -*) exception Perl_failure of string (** [die] in Perl code is translated automatically into this exception. *) @@ -148,13 +146,11 @@ val deref_array : sv -> av * array [AV]. If the input is not a reference to an array, throws * [Invalid_arg]. *) -(* val deref_hash : sv -> hv (** The input is a reference to a hash. This returns the underlying * hash [HV]. If the input is not a reference to a hash, throws * [Invalid_arg]. *) -*) val av_empty : unit -> av (** Create an empty [AV] (array). *) @@ -187,6 +183,25 @@ val av_extend : av -> int -> unit val av_map : (sv -> 'a) -> av -> 'a list (** Map a function over the elements in the [AV], return a list of the * results. *) +val list_of_av : av -> sv list +(** Convert an [AV] into a simple list of [SV]s. *) +val av_of_string_list : string list -> av +(** Build an [AV] from a list of strings. *) + +val hv_empty : unit -> hv +(** Create an empty [HV] (hash). *) +val hv_set : hv -> string -> sv -> unit +(** Store the given [SV] in the named key in the hash. *) +val hv_get : hv -> string -> sv +(** Return the [SV] at the key in the hash. Throws [Not_found] if no key. *) +val hv_exists : hv -> string -> bool +(** Return true if the hash contains the given key. Same as Perl [exists]. *) +val hv_delete : hv -> string -> unit +(** Delete the given key from the hash. Same as Perl [delete]. *) +val hv_clear : hv -> unit +(** Remove all elements from the [HV]. Same as Perl [%av = ()]. *) +val hv_undef : hv -> unit +(** Delete the [HV] (and all elements in it). Same as Perl [undef %hv]. *) val get_sv : ?create:bool -> string -> sv (** Return a scalar value by name. For example, if you have a symbol @@ -200,6 +215,8 @@ val get_sv : ?create:bool -> string -> sv *) val get_av : ?create:bool -> string -> av (** Same as {!Perl.get_sv} except will return and/or create [\@a]. *) +val get_hv : ?create:bool -> string -> hv +(** Same as {!Perl.get_sv} except will return and/or create [%a]. *) val call : ?sv:sv -> ?fn:string -> sv list -> sv (** Call a Perl function in a scalar context, either by name (using the [?fn] diff --git a/perl_c.c b/perl_c.c index 9056591..9ad8d68 100644 --- a/perl_c.c +++ b/perl_c.c @@ -1,6 +1,6 @@ /* Interface to Perl from OCaml. * Copyright (C) 2003 Merjis Ltd. - * $Id: perl_c.c,v 1.7 2003-10-16 11:03:51 rich Exp $ + * $Id: perl_c.c,v 1.8 2003-10-18 12:36:09 rich Exp $ */ #include @@ -42,6 +42,8 @@ static value unoption (value option, value deflt); #define Sv_val(svv) (Voidptr_val (SV, (svv))) #define Val_av(av) (Val_voidptr ((av))) #define Av_val(avv) (Voidptr_val (AV, (avv))) +#define Val_hv(hv) (Val_voidptr ((hv))) +#define Hv_val(hvv) (Voidptr_val (HV, (hvv))) CAMLprim value perl4caml_init (value unit) @@ -193,14 +195,14 @@ perl4caml_sv_is_undef (value svv) { CAMLparam1 (svv); SV *sv = Sv_val (svv); - CAMLreturn (sv == &PL_sv_undef ? Val_true : Val_false); + CAMLreturn (SvLEN (sv) == 0 ? Val_true : Val_false); } CAMLprim value perl4caml_sv_undef (value unit) { CAMLparam1 (unit); - CAMLreturn (Val_sv (&PL_sv_undef)); + CAMLreturn (Val_sv (newSV (0))); } CAMLprim value @@ -281,6 +283,25 @@ perl4caml_deref_array (value svv) } CAMLprim value +perl4caml_deref_hash (value svv) +{ + CAMLparam1 (svv); + CAMLlocal1 (rhvv); + SV *sv = Sv_val (svv); + + if (SvTYPE (sv) != SVt_RV) + invalid_argument ("deref_array: SV is not a reference"); + switch (SvTYPE (SvRV (sv))) { + case SVt_PVHV: + break; + default: + invalid_argument ("deref_array: SV is not a reference to a hash"); + } + rhvv = Val_hv ((HV *) SvRV (sv)); + CAMLreturn (rhvv); +} + +CAMLprim value perl4caml_av_empty (value unit) { CAMLparam1 (unit); @@ -419,6 +440,72 @@ perl4caml_av_extend (value avv, value i) } CAMLprim value +perl4caml_hv_empty (value unit) +{ + CAMLparam1 (unit); + HV *hv = newHV (); + CAMLreturn (Val_hv (hv)); +} + +CAMLprim value +perl4caml_hv_set (value hvv, value key, value svv) +{ + CAMLparam3 (hvv, key, svv); + HV *hv = Hv_val (hvv); + SV *sv = Sv_val (svv); + SvREFCNT_inc (sv); + if (hv_store (hv, String_val (key), string_length (key), sv, 0) == 0) + SvREFCNT_dec (sv); + CAMLreturn (Val_unit); +} + +CAMLprim value +perl4caml_hv_get (value hvv, value key) +{ + CAMLparam2 (hvv, key); + HV *hv = Hv_val (hvv); + SV **svp = hv_fetch (hv, String_val (key), string_length (key), 0); + if (svp == 0) raise_not_found (); + CAMLreturn (Val_sv (*svp)); +} + +CAMLprim value +perl4caml_hv_exists (value hvv, value key) +{ + CAMLparam2 (hvv, key); + HV *hv = Hv_val (hvv); + bool r = hv_exists (hv, String_val (key), string_length (key)); + CAMLreturn (r ? Val_true : Val_false); +} + +CAMLprim value +perl4caml_hv_delete (value hvv, value key) +{ + CAMLparam2 (hvv, key); + HV *hv = Hv_val (hvv); + hv_delete (hv, String_val (key), string_length (key), G_DISCARD); + CAMLreturn (Val_unit); +} + +CAMLprim value +perl4caml_hv_clear (value hvv) +{ + CAMLparam1 (hvv); + HV *hv = Hv_val (hvv); + hv_clear (hv); + CAMLreturn (Val_unit); +} + +CAMLprim value +perl4caml_hv_undef (value hvv) +{ + CAMLparam1 (hvv); + HV *hv = Hv_val (hvv); + hv_undef (hv); + CAMLreturn (Val_unit); +} + +CAMLprim value perl4caml_get_sv (value optcreate, value name) { CAMLparam2 (optcreate, name); @@ -446,6 +533,20 @@ perl4caml_get_av (value optcreate, value name) CAMLreturn (Val_av (av)); } +CAMLprim value +perl4caml_get_hv (value optcreate, value name) +{ + CAMLparam2 (optcreate, name); + CAMLlocal1 (create); + HV *hv; + + create = unoption (optcreate, Val_false); + hv = get_hv (String_val (name), create == Val_true ? TRUE : FALSE); + if (hv == NULL) raise_not_found (); + + CAMLreturn (Val_hv (hv)); +} + static inline void check_perl_failure () {