summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Perl-RPM/Makefile.PL5
-rw-r--r--Perl-RPM/RPM.h80
-rw-r--r--Perl-RPM/RPM.xs3
-rw-r--r--Perl-RPM/RPM/Database.pm5
-rw-r--r--Perl-RPM/RPM/Database.xs130
-rw-r--r--Perl-RPM/RPM/Header.pm5
-rw-r--r--Perl-RPM/RPM/Header.xs223
-rwxr-xr-xPerl-RPM/t/01_database.t59
-rw-r--r--Perl-RPM/typemap41
9 files changed, 266 insertions, 285 deletions
diff --git a/Perl-RPM/Makefile.PL b/Perl-RPM/Makefile.PL
index e4618cb7b..349488753 100644
--- a/Perl-RPM/Makefile.PL
+++ b/Perl-RPM/Makefile.PL
@@ -1,6 +1,6 @@
#!/bin/perl
-# $Id: Makefile.PL,v 1.13 2000/10/13 08:42:32 rjray Exp $
+# $Id: Makefile.PL,v 1.14 2000/11/10 08:49:57 rjray Exp $
use Config;
use ExtUtils::MakeMaker;
@@ -95,8 +95,9 @@ WriteMakefile(
XS => \%XS,
EXE_FILES => [ @SAMPLES ],
OBJECT => $OBJECT,
- INC => "-I. -I$rpm_libdir",
+ INC => "-Wunused -I. -I$rpm_libdir",
DIR => [],
+ XSOPT => '-nolinenumbers',
dist => { COMPRESS => 'gzip -9f' },
clean => { FILES => $CLEAN }
);
diff --git a/Perl-RPM/RPM.h b/Perl-RPM/RPM.h
index fb745e31a..270179e04 100644
--- a/Perl-RPM/RPM.h
+++ b/Perl-RPM/RPM.h
@@ -1,5 +1,5 @@
/*
- * $Id: RPM.h,v 1.12 2000/10/10 08:37:20 rjray Exp $
+ * $Id: RPM.h,v 1.13 2000/11/10 08:49:57 rjray Exp $
*
* Various C-specific decls/includes/etc. for the RPM linkage
*/
@@ -51,9 +51,33 @@
#define RPM_HEADER_READONLY 0x01
#define RPM_HEADER_FROM_REF 0x02
-#define RPM_PACKAGE_MASK 0xf0
-#define RPM_PACKAGE_READONLY 0x10
-#define RPM_PACKAGE_NOREAD 0x20
+#define RPM_PACKAGE_MASK 0x0f00
+#define RPM_PACKAGE_READONLY 0x0100
+#define RPM_PACKAGE_NOREAD 0x0200
+
+/*
+ Use this define for deriving the saved underlying struct, rather than coding
+ it a dozen places.
+*/
+#define struct_from_object_ret(type, header, object, err_ret) \
+ { \
+ MAGIC* mg = mg_find((SV *)(object), '~'); \
+ if (mg) \
+ (header) = (type *)SvIV(mg->mg_obj); \
+ else \
+ return (err_ret); \
+ }
+/* And a no-return version: */
+#define struct_from_object(type, header, object) \
+ { \
+ MAGIC* mg = mg_find((SV *)(object), '~'); \
+ if (mg) \
+ (header) = (type *)SvIV(mg->mg_obj); \
+ else \
+ (header) = Null(type *); \
+ }
+
+#define new_RPM_storage(type) (type *)safemalloc(sizeof(type))
/*
* Perl complement: RPM::Database
@@ -61,9 +85,7 @@
/*
This is the underlying struct that implements the interface to the RPM
- database. Since we need the actual object to be a hash, the struct will
- be stored as an SV (actually, a pointer to a struct) on a special key
- defined below.
+ database.
*/
typedef struct {
@@ -76,12 +98,12 @@ typedef struct {
int offx;
int* offsets;
#endif
+ /* This HV will be used to cache key/value pairs to avoid re-computing */
+ HV* storage;
} RPM_Database;
typedef HV* RPM__Database;
-#define new_RPM__Database(x) x = newHV()
-
/*
* Perl complement: RPM::Header
@@ -89,9 +111,7 @@ typedef HV* RPM__Database;
/*
This is the underlying struct that implements the interface to the RPM
- headers. As above, we need the actual object to be a hash, so the struct
- will be stored as an SV on the same sort of special key as RPM__Database
- uses.
+ headers.
*/
typedef struct {
@@ -104,6 +124,8 @@ typedef struct {
int isSource; /* If this header is for a source RPM (SRPM) */
int major; /* Major and minor rev numbers of package's format */
int minor;
+ /* This HV will be used to cache key/value pairs to avoid re-computing */
+ HV* storage;
/* Keep a per-header iterator for things like FIRSTKEY and NEXTKEY */
HeaderIterator iterator;
int read_only;
@@ -114,8 +136,6 @@ typedef struct {
typedef HV* RPM__Header;
-#define new_RPM__Header(x) x = newHV()
-
/*
* Perl complement: RPM::Package
@@ -139,34 +159,12 @@ typedef struct {
int readonly;
/* The current notify/callback function associated with this package */
CV* callback;
+ /* Any data they want to have passed to the callback */
+ SV* cb_data;
} RPM_Package;
typedef RPM_Package* RPM__Package;
-#define new_RPM__Package(x) x = (RPM__Package)safemalloc(sizeof(RPM_Package))
-
-
-/*
- Because our HV* are going to be set magical, the following is needed for
- explicit fetch and store calls that are done within the tied FETCH/STORE
- methods.
-*/
-#define hv_fetch_nomg(SVP, h, k, kl, f) \
- SvMAGICAL_off((SV *)(h)); \
- (SVP) = hv_fetch((h), (k), (kl), (f)); \
- SvMAGICAL_on((SV *)(h))
-#define hv_store_nomg(h, k, kl, v, f) \
- SvMAGICAL_off((SV *)(h)); \
- hv_store((h), (k), (kl), (v), (f)); \
- SvMAGICAL_on((SV *)(h))
-
-/*
- This silly-looking key is what will be used on the RPM::Header and
- RPM::Database objects to stash the underlying struct.
-*/
-#define STRUCT_KEY "<<<struct>>>"
-/* This must match! */
-#define STRUCT_KEY_LEN 13
/*
These represent the various interfaces that are allowed for use outside
@@ -184,11 +182,11 @@ extern void rpm_error(pTHX_ int, const char *);
/* RPM/Header.xs: */
extern const char* sv2key(pTHX_ SV *);
-extern RPM__Header rpmhdr_TIEHASH(pTHX_ SV *, SV *, int);
+extern RPM__Header rpmhdr_TIEHASH(pTHX_ char *, SV *, int);
extern SV* rpmhdr_FETCH(pTHX_ RPM__Header, SV *, const char *, int, int);
extern int rpmhdr_STORE(pTHX_ RPM__Header, SV *, SV *);
extern int rpmhdr_DELETE(pTHX_ RPM__Header, SV *);
-extern int rpmhdr_EXISTS(pTHX_ RPM__Header, SV *);
+extern bool rpmhdr_EXISTS(pTHX_ RPM__Header, SV *);
extern unsigned int rpmhdr_size(pTHX_ RPM__Header);
extern int rpmhdr_tagtype(pTHX_ RPM__Header, SV *);
extern int rpmhdr_write(pTHX_ RPM__Header, SV *, int);
@@ -199,7 +197,7 @@ extern int rpmhdr_scalar_tag(pTHX_ SV*, int);
/* RPM/Database.xs: */
extern RPM__Database rpmdb_TIEHASH(pTHX_ char *, SV *);
extern RPM__Header rpmdb_FETCH(pTHX_ RPM__Database, SV *);
-extern int rpmdb_EXISTS(pTHX_ RPM__Database, SV *);
+extern bool rpmdb_EXISTS(pTHX_ RPM__Database, SV *);
/* RPM/Package.xs: */
extern RPM__Package rpmpkg_new(pTHX_ char *, SV *, int);
diff --git a/Perl-RPM/RPM.xs b/Perl-RPM/RPM.xs
index 865560df6..092ce11c0 100644
--- a/Perl-RPM/RPM.xs
+++ b/Perl-RPM/RPM.xs
@@ -4,7 +4,7 @@
#include "RPM.h"
-static char * const rcsid = "$Id: RPM.xs,v 1.8 2000/10/13 09:24:05 rjray Exp $";
+static char * const rcsid = "$Id: RPM.xs,v 1.9 2000/11/10 08:49:57 rjray Exp $";
extern XS(boot_RPM__Constants);
extern XS(boot_RPM__Header);
@@ -59,7 +59,6 @@ const char* num2tag(pTHX_ int num)
{
SV** svp;
char str_num[8];
- SV* tmp;
Zero(str_num, 1, 8);
snprintf(str_num, 8, "%d", num);
diff --git a/Perl-RPM/RPM/Database.pm b/Perl-RPM/RPM/Database.pm
index d5933568e..e1e2df2e8 100644
--- a/Perl-RPM/RPM/Database.pm
+++ b/Perl-RPM/RPM/Database.pm
@@ -5,7 +5,7 @@
#
###############################################################################
#
-# $Id: Database.pm,v 1.11 2000/10/13 08:47:26 rjray Exp $
+# $Id: Database.pm,v 1.12 2000/11/10 08:49:57 rjray Exp $
#
# Description: The RPM::Database class provides access to the RPM database
# as a tied hash, whose keys are taken as the names of
@@ -36,7 +36,7 @@ require RPM;
require RPM::Header;
$VERSION = '0.291';
-$revision = do { my @r=(q$Revision: 1.11 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
+$revision = do { my @r=(q$Revision: 1.12 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
1;
@@ -46,7 +46,6 @@ sub new
my %hash = ();
tie %hash, $class;
- return (tied %hash);
}
###############################################################################
diff --git a/Perl-RPM/RPM/Database.xs b/Perl-RPM/RPM/Database.xs
index f33399010..bfbd6a3ef 100644
--- a/Perl-RPM/RPM/Database.xs
+++ b/Perl-RPM/RPM/Database.xs
@@ -5,22 +5,7 @@
#include <fcntl.h>
#include "RPM.h"
-static char * const rcsid = "$Id: Database.xs,v 1.8 2000/10/05 04:48:59 rjray Exp $";
-
-/*
- Use this define for deriving the saved rpmdb struct, rather than coding
- it a dozen places. Note that the hv_fetch call is the no-magic one defined
- in RPM.h
-*/
-#define dbstruct_from_object_ret(s_ptr, rdb, object, err_ret) \
- hv_fetch_nomg((s_ptr), (object), STRUCT_KEY, STRUCT_KEY_LEN, FALSE); \
- (rdb) = ((s_ptr) && SvOK(*(s_ptr))) ? (RPM_Database *)SvIV(*(s_ptr)) : NULL; \
- if (! (rdb)) return (err_ret);
-/* And a no-return-value version: */
-#define dbstruct_from_object(s_ptr, rdb, object) \
- hv_fetch_nomg((s_ptr), (object), STRUCT_KEY, STRUCT_KEY_LEN, FALSE); \
- (rdb) = ((s_ptr) && SvOK(*(s_ptr))) ? (RPM_Database *)SvIV(*(s_ptr)) : NULL; \
- if (! (rdb)) return;
+static char * const rcsid = "$Id: Database.xs,v 1.9 2000/11/10 08:49:57 rjray Exp $";
/*
rpmdb_TIEHASH
@@ -36,10 +21,10 @@ RPM__Database rpmdb_TIEHASH(pTHX_ char* class, SV* opts)
int mode = O_RDONLY;
mode_t perms = 0;
HV* opt_hash;
- SV* value;
+ SV* t_magic;
SV** svp;
- RPM_Database* dbstruct;
- RPM__Database TIEHASH;
+ RPM_Database* retvalp; /* For "private" */
+ RPM__Database RETVAL;
if (opts)
{
@@ -68,29 +53,31 @@ RPM__Database rpmdb_TIEHASH(pTHX_ char* class, SV* opts)
}
/* With that all processed, attempt to open the actual RPM DB */
- /* The dbstruct is used for the C-level rpmlib information on databases */
- dbstruct = safemalloc(sizeof(RPM_Database));
- Zero(dbstruct, 1, RPM_Database);
- if (rpmdbOpen(root, &dbstruct->dbp, mode, perms) != 0)
+ /* The retvalp is used for the C-level rpmlib information on databases */
+ retvalp = new_RPM_storage(RPM_Database);
+ if (rpmdbOpen(root, &retvalp->dbp, mode, perms) != 0)
/* rpm lib will have set the error already */
return (Null(RPM__Database));
else
{
- dbstruct->current_rec = 0;
+ retvalp->current_rec = 0;
#if RPM_MAJOR < 4
- dbstruct->index_set = (void *)NULL;
+ retvalp->index_set = (void *)NULL;
#else
- dbstruct->noffs = dbstruct->offx = 0;
- dbstruct->offsets = (int *)NULL;
+ retvalp->noffs = retvalp->offx = 0;
+ retvalp->offsets = (int *)NULL;
#endif
}
- new_RPM__Database(TIEHASH);
- /* STRUCT_KEY is used to stash the C-level struct on the TIEHASH obj */
- hv_store_nomg(TIEHASH,
- STRUCT_KEY, STRUCT_KEY_LEN, newSViv((unsigned)dbstruct),
- FALSE);
- return TIEHASH;
+ RETVAL = newHV();
+ retvalp->storage = newHV();
+ t_magic = newSViv((unsigned)retvalp);
+
+ sv_magic((SV *)RETVAL, Nullsv, 'P', Nullch, 0);
+ sv_magic((SV *)RETVAL, t_magic, '~', Nullch, 0);
+ SvREFCNT_dec(t_magic);
+
+ return RETVAL;
}
RPM__Header rpmdb_FETCH(pTHX_ RPM__Database self, SV* key)
@@ -109,7 +96,7 @@ RPM__Header rpmdb_FETCH(pTHX_ RPM__Database self, SV* key)
/* Any successful operation will re-assign this */
FETCH = Null(RPM__Header);
- dbstruct_from_object_ret(svp, dbstruct, self, FETCH);
+ struct_from_object_ret(RPM_Database, dbstruct, self, FETCH);
/* De-reference key, if it is a reference */
if (SvROK(key))
key = SvRV(key);
@@ -124,10 +111,10 @@ RPM__Header rpmdb_FETCH(pTHX_ RPM__Database self, SV* key)
/* Step 1: Check to see if this has already been requested and is
thus cached on the hash itself */
- hv_fetch_nomg(svp, self, (char *)name, namelen, FALSE);
- if (svp && SvOK(*svp))
+ svp = hv_fetch(dbstruct->storage, (char *)name, namelen, FALSE);
+ if (svp && SvROK(*svp))
{
- FETCH = (RPM__Header)SvIV(*svp);
+ FETCH = (RPM__Header)SvRV(*svp);
return FETCH;
}
@@ -201,15 +188,16 @@ RPM__Header rpmdb_FETCH(pTHX_ RPM__Database self, SV* key)
#if RPM_MAJOR >= 4
hdr = headerLink(hdr);
#endif
- FETCH = rpmhdr_TIEHASH(aTHX_ sv_2mortal(newSVpv("RPM::Header", 12)),
- sv_2mortal(newRV((SV *)hdr)),
+ FETCH = rpmhdr_TIEHASH(aTHX_ "RPM::Header",
+ sv_2mortal(newSViv((unsigned)hdr)),
RPM_HEADER_FROM_REF | RPM_HEADER_READONLY);
/* If name is no longer NULL, it means our vector in was a string
(key), so put the result back into the hash-cache. */
if (name != NULL)
{
- hv_store_nomg(self, (char *)name, namelen,
- newSViv((unsigned)FETCH), FALSE);
+ hv_store(dbstruct->storage, (char *)name, namelen,
+ newRV((SV *)FETCH), FALSE);
+ SvREFCNT_inc((SV *)FETCH);
}
}
#if RPM_MAJOR >= 4
@@ -219,13 +207,12 @@ RPM__Header rpmdb_FETCH(pTHX_ RPM__Database self, SV* key)
return FETCH;
}
-int rpmdb_EXISTS(pTHX_ RPM__Database self, SV* key)
+bool rpmdb_EXISTS(pTHX_ RPM__Database self, SV* key)
{
SV* tmp;
tmp = (SV *)rpmdb_FETCH(aTHX_ self, key);
- /* There is probably a cleaner test for (SV *)tmp == PL_sv_undef */
- return (SvANY(tmp) != NULL);
+ return (tmp != Nullsv);
}
/*
@@ -237,9 +224,8 @@ int rpmdb_EXISTS(pTHX_ RPM__Database self, SV* key)
int rpmdb_FIRSTKEY(pTHX_ RPM__Database self, SV** key, RPM__Header* value)
{
RPM_Database* dbstruct;
- SV** svp;
- dbstruct_from_object_ret(svp, dbstruct, self, 0);
+ struct_from_object_ret(RPM_Database, dbstruct, self, 0);
#if RPM_MAJOR < 4
/* This more or less resets our "iterator" */
dbstruct->current_rec = 0;
@@ -285,9 +271,8 @@ int rpmdb_NEXTKEY(pTHX_ RPM__Database self, SV* key,
SV** nextkey, RPM__Header* nextvalue)
{
RPM_Database* dbstruct;
- SV** svp;
- dbstruct_from_object_ret(svp, dbstruct, self, 0);
+ struct_from_object_ret(RPM_Database, dbstruct, self, 0);
#if RPM_MAJOR < 4
if (! (dbstruct->current_rec = rpmdbNextRecNum(dbstruct->dbp,
@@ -311,10 +296,9 @@ int rpmdb_NEXTKEY(pTHX_ RPM__Database self, SV* key,
void rpmdb_DESTROY(pTHX_ RPM__Database self)
{
- SV** svp;
RPM_Database* dbstruct; /* This is the struct used to hold C-level data */
- dbstruct_from_object(svp, dbstruct, self);
+ struct_from_object(RPM_Database, dbstruct, self);
rpmdbClose(dbstruct->dbp);
#if RPM_MAJOR < 4
@@ -323,10 +307,10 @@ void rpmdb_DESTROY(pTHX_ RPM__Database self)
#else
if (dbstruct->offsets)
safefree(dbstruct->offsets);
- dbstruct->noffs = dbstruct->offx = 0;
- dbstruct->offsets = NULL;
#endif
+ hv_undef(dbstruct->storage);
+ safefree(dbstruct);
hv_undef(self);
}
@@ -349,7 +333,6 @@ AV* rpmdb_find_by_whatever(pTHX_ RPM__Database self, SV* string, int idx)
{
const char* str = NULL; /* For the actual string out of (SV *)string */
STRLEN len; /* Arg for SvPV(..., len) */
- SV** svp;
RPM_Database* dbstruct; /* This is the struct used to hold C-level data */
AV* return_val;
int result, loop;
@@ -357,11 +340,11 @@ AV* rpmdb_find_by_whatever(pTHX_ RPM__Database self, SV* string, int idx)
#if RPM_MAJOR >= 4
rpmdbMatchIterator mi;
#endif
-
+
/* Any successful operation will store items on this */
return_val = newAV();
- dbstruct_from_object_ret(svp, dbstruct, self, return_val);
+ struct_from_object_ret(RPM_Database, dbstruct, self, return_val);
/* De-reference key, if it is a reference */
if (SvROK(string))
string = SvRV(string);
@@ -418,6 +401,7 @@ AV* rpmdb_find_by_whatever(pTHX_ RPM__Database self, SV* string, int idx)
return return_val;
}
+
MODULE = RPM::Database PACKAGE = RPM::Database PREFIX = rpmdb_
@@ -442,8 +426,8 @@ rpmdb_FETCH(self, key)
RETVAL
int
-rpmdb_STORE(self, key, value)
- RPM::Database self;
+rpmdb_STORE(self=NULL, key=NULL, value=NULL)
+ SV* self;
SV* key;
SV* value;
PROTOTYPE: $$$
@@ -455,22 +439,22 @@ rpmdb_STORE(self, key, value)
OUTPUT:
RETVAL
-int
-rpmdb_DELETE(self, key)
- RPM::Database self;
+SV*
+rpmdb_DELETE(self=NULL, key=NULL)
+ SV* self;
SV* key;
PROTOTYPE: $$
CODE:
{
rpm_error(aTHX_ RPMERR_NOCREATEDB, "DELETE: operation not permitted");
- RETVAL = 0;
+ RETVAL = Nullsv;
}
OUTPUT:
- RETVAL
+ RETVAL
int
-rpmdb_CLEAR(self)
- RPM::Database self;
+rpmdb_CLEAR(self=NULL)
+ SV* self;
PROTOTYPE: $
CODE:
{
@@ -478,9 +462,9 @@ rpmdb_CLEAR(self)
RETVAL = 0;
}
OUTPUT:
- RETVAL
+ RETVAL
-int
+bool
rpmdb_EXISTS(self, key)
RPM::Database self;
SV* key;
@@ -492,13 +476,12 @@ rpmdb_EXISTS(self, key)
void
rpmdb_FIRSTKEY(self)
- RPM::Header self;
+ RPM::Database self;
PROTOTYPE: $
- PREINIT:
- SV* key;
- SV* value;
PPCODE:
{
+ SV* key;
+ SV* value;
RPM__Header hvalue;
if (! rpmdb_FIRSTKEY(aTHX_ self, &key, &hvalue))
@@ -519,17 +502,16 @@ rpmdb_NEXTKEY(self, key=NULL)
RPM::Database self;
SV* key;
PROTOTYPE: $;$
- PREINIT:
- SV* nextkey;
- SV* nextvalue;
PPCODE:
{
+ SV* nextkey;
+ SV* nextvalue;
RPM__Header hvalue;
if (! rpmdb_NEXTKEY(aTHX_ self, key, &nextkey, &hvalue))
{
nextkey = newSVsv(&PL_sv_undef);
- nextvalue = newRV(&PL_sv_undef);
+ nextvalue = newSVsv(&PL_sv_undef);
}
else
nextvalue = newRV((SV *)hvalue);
diff --git a/Perl-RPM/RPM/Header.pm b/Perl-RPM/RPM/Header.pm
index 6e3e39dae..fd2dc2025 100644
--- a/Perl-RPM/RPM/Header.pm
+++ b/Perl-RPM/RPM/Header.pm
@@ -5,7 +5,7 @@
#
###############################################################################
#
-# $Id: Header.pm,v 1.14 2000/10/13 08:47:26 rjray Exp $
+# $Id: Header.pm,v 1.15 2000/11/10 08:49:57 rjray Exp $
#
# Description: The RPM::Header class provides access to the RPM Header
# structure as a tied hash, allowing direct access to the
@@ -39,7 +39,7 @@ use RPM::Error;
use RPM::Constants ':rpmerr';
$VERSION = '0.291';
-$revision = do { my @r=(q$Revision: 1.14 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
+$revision = do { my @r=(q$Revision: 1.15 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
@ISA = qw(Exporter);
@EXPORT = ();
@@ -69,7 +69,6 @@ sub new
my %hash = ();
tie %hash, $class, @_;
- return (tied %hash);
}
###############################################################################
diff --git a/Perl-RPM/RPM/Header.xs b/Perl-RPM/RPM/Header.xs
index fc6da1f94..1e30f1aa6 100644
--- a/Perl-RPM/RPM/Header.xs
+++ b/Perl-RPM/RPM/Header.xs
@@ -4,24 +4,30 @@
#include "RPM.h"
-static char * const rcsid = "$Id: Header.xs,v 1.19 2000/10/12 05:09:16 rjray Exp $";
+static char * const rcsid = "$Id: Header.xs,v 1.20 2000/11/10 08:49:57 rjray Exp $";
static int scalar_tag(pTHX_ SV *, int);
/*
Use this define for deriving the saved Header struct, rather than coding
- it a dozen places. Note that the hv_fetch call is the no-magic one defined
- in RPM.h
+ it a dozen places.
*/
-#define header_from_object_ret(s_ptr, header, object, err_ret) \
- hv_fetch_nomg((s_ptr), (object), STRUCT_KEY, STRUCT_KEY_LEN, FALSE); \
- (header) = ((s_ptr) && SvOK(*(s_ptr))) ? (RPM_Header *)SvIV(*(s_ptr)) : NULL; \
- if (! (header)) \
- return (err_ret);
+#define header_from_object_ret(header, object, err_ret) \
+ { \
+ MAGIC* mg = mg_find((SV *)(object), '~'); \
+ if (mg) \
+ (header) = (RPM_Header *)SvIV(mg->mg_obj); \
+ else \
+ return (err_ret); \
+ }
/* And a no-return version: */
-#define header_from_object(s_ptr, header, object) \
- hv_fetch_nomg((s_ptr), (object), STRUCT_KEY, STRUCT_KEY_LEN, FALSE); \
- (header) = ((s_ptr) && SvOK(*(s_ptr))) ? (RPM_Header *)SvIV(*(s_ptr)) : NULL;
-
+#define header_from_object(header, object) \
+ { \
+ MAGIC* mg = mg_find((SV *)(object), '~'); \
+ if (mg) \
+ (header) = (RPM_Header *)SvIV(mg->mg_obj); \
+ else \
+ (header) = Null(RPM_Header *); \
+ }
/* Any constants that are specific to the RPM::Header class will be exported
from here, via this C-level constant() routine */
@@ -75,11 +81,6 @@ SV* key2sv(pTHX_ const char* key)
return (sv_2mortal(newSVpv((char *)key, PL_na)));
}
-static SV* ikey2sv(pTHX_ int key)
-{
- return (sv_2mortal(newSViv(key)));
-}
-
/* This creates a header data-field from the passed-in data */
static SV* rpmhdr_create(pTHX_ const char* data, int type, int size,
int scalar)
@@ -250,7 +251,7 @@ static int new_from_fname(pTHX_ const char* source, RPM_Header* new_hdr)
return 0;
}
- if (retval = new_from_fd_t(fd, new_hdr))
+ if ((retval = new_from_fd_t(fd, new_hdr)))
{
Fclose(fd);
new_hdr->source_name = safemalloc(strlen(source) + 1);
@@ -260,19 +261,20 @@ static int new_from_fname(pTHX_ const char* source, RPM_Header* new_hdr)
return retval;
}
-RPM__Header rpmhdr_TIEHASH(pTHX_ SV* class, SV* source, int flags)
+RPM__Header rpmhdr_TIEHASH(pTHX_ char* class, SV* source, int flags)
{
char* fname;
int fname_len;
- RPM__Header TIEHASH;
- RPM_Header* hdr_struct; /* Use this to store the actual C-level data */
+ RPM__Header RETVAL;
+ RPM_Header* retvalp; /* Use this to store the actual C-level data */
+ SV* t_magic;
- hdr_struct = safemalloc(sizeof(RPM_Header));
- Zero(hdr_struct, 1, RPM_Header);
- TIEHASH = Null(RPM__Header);
+ retvalp = new_RPM_storage(RPM_Header);
+ Zero(retvalp, 1, RPM_Header);
+ RETVAL = Nullhv;
if (! source)
- hdr_struct->hdr = headerNew();
+ retvalp->hdr = headerNew();
else if (! (flags & RPM_HEADER_FROM_REF))
{
/* If we aren't starting out with a pointer to a Header
@@ -282,52 +284,59 @@ RPM__Header rpmhdr_TIEHASH(pTHX_ SV* class, SV* source, int flags)
if (SvPOK(source))
{
fname = SvPV(source, fname_len);
- if (! new_from_fname(aTHX_ fname, hdr_struct))
+ if (! new_from_fname(aTHX_ fname, retvalp))
{
- return TIEHASH;
+ return RETVAL;
}
}
else if (IoIFP(sv_2io(source)))
{
if (! new_from_fd(PerlIO_fileno(IoIFP(sv_2io(source))),
- hdr_struct))
+ retvalp))
{
- return TIEHASH;
+ return RETVAL;
}
}
else
{
rpm_error(aTHX_ RPMERR_BADARG,
"Argument 2 must be filename or GLOB");
- return TIEHASH;
+ return RETVAL;
}
}
else
{
- hdr_struct->hdr = (Header)SvRV(source);
+ retvalp->hdr = (Header)SvIV(source);
/* We simply don't know these three settings at this point */
- hdr_struct->isSource = 0;
- hdr_struct->major = 0;
- hdr_struct->minor = 0;
+ retvalp->isSource = 0;
+ retvalp->major = 0;
+ retvalp->minor = 0;
}
/* These three are likely to be most of the data requests, anyway */
- headerNVR(hdr_struct->hdr,
- &hdr_struct->name, &hdr_struct->version, &hdr_struct->release);
+ headerNVR(retvalp->hdr,
+ &retvalp->name, &retvalp->version, &retvalp->release);
/* This defaults to false, but RPM::Database will set it true */
- hdr_struct->read_only = flags & RPM_HEADER_READONLY;
+ retvalp->read_only = flags & RPM_HEADER_READONLY;
- hdr_struct->iterator = (HeaderIterator)NULL;
+ retvalp->iterator = (HeaderIterator)NULL;
- new_RPM__Header(TIEHASH);
+ retvalp->storage = newHV();
+ RETVAL = newHV();
+ t_magic = newSViv((unsigned)retvalp);
/* With the actual HV*, store the type-keys for the three cached values: */
- hv_store_nomg(TIEHASH, "NAME_t", 7, newSViv(RPM_STRING_TYPE), FALSE);
- hv_store_nomg(TIEHASH, "VERSION_t", 10, newSViv(RPM_STRING_TYPE), FALSE);
- hv_store_nomg(TIEHASH, "RELEASE_t", 10, newSViv(RPM_STRING_TYPE), FALSE);
- hv_store_nomg(TIEHASH,
- STRUCT_KEY, STRUCT_KEY_LEN,
- newSViv((unsigned)hdr_struct), FALSE);
- return TIEHASH;
+ hv_store(retvalp->storage,
+ "NAME_t", 7, newSViv(RPM_STRING_TYPE), FALSE);
+ hv_store(retvalp->storage,
+ "VERSION_t", 10, newSViv(RPM_STRING_TYPE), FALSE);
+ hv_store(retvalp->storage,
+ "RELEASE_t", 10, newSViv(RPM_STRING_TYPE), FALSE);
+
+ sv_magic((SV *)RETVAL, Nullsv, 'P', Nullch, 0);
+ sv_magic((SV *)RETVAL, t_magic, '~', Nullch, 0);
+ SvREFCNT_dec(t_magic);
+
+ return RETVAL;
}
SV* rpmhdr_FETCH(pTHX_ RPM__Header self, SV* key,
@@ -344,7 +353,7 @@ SV* rpmhdr_FETCH(pTHX_ RPM__Header self, SV* key,
FETCH = newSVsv(&PL_sv_undef);
- header_from_object_ret(svp, hdr, self, FETCH);
+ struct_from_object_ret(RPM_Header, hdr, self, FETCH);
name = sv2key(aTHX_ key);
if (! (name && (namelen = strlen(name))))
@@ -375,7 +384,7 @@ SV* rpmhdr_FETCH(pTHX_ RPM__Header self, SV* key,
{
/* If it wasn't one of those three, then we have to explicitly fetch
it, either from the store in cache or via the headerGetEntry call */
- hv_fetch_nomg(svp, self, uc_name, namelen, FALSE);
+ svp = hv_fetch(hdr->storage, uc_name, namelen, FALSE);
if (svp && SvOK(*svp))
{
FETCH = newSVsv(*svp);
@@ -389,10 +398,10 @@ SV* rpmhdr_FETCH(pTHX_ RPM__Header self, SV* key,
SV* new_item = rpmhdr_create(aTHX_ data_in, type_in, size_in,
scalar_tag(aTHX_ Nullsv, tag_by_num));
- hv_store_nomg(self, uc_name, namelen, newRV((SV *)new_item),
- FALSE);
- hv_store_nomg(self, strcat(uc_name, "_t"), (namelen + 2),
- newSViv(type_in), FALSE);
+ hv_store(hdr->storage, uc_name, namelen, newRV((SV *)new_item),
+ FALSE);
+ hv_store(hdr->storage, strcat(uc_name, "_t"), (namelen + 2),
+ newSViv(type_in), FALSE);
FETCH = new_item;
}
@@ -402,7 +411,6 @@ SV* rpmhdr_FETCH(pTHX_ RPM__Header self, SV* key,
char* new_item_p;
int new_item_type;
int size;
- char urk[2];
/* Pull the tag by the int value we now have */
if (! headerGetEntry(hdr->hdr, tag_by_num,
@@ -417,10 +425,10 @@ SV* rpmhdr_FETCH(pTHX_ RPM__Header self, SV* key,
new_item = rpmhdr_create(aTHX_ new_item_p, new_item_type, size,
scalar_tag(aTHX_ Nullsv, tag_by_num));
- hv_store_nomg(self, uc_name, namelen, newRV((SV *)new_item),
- FALSE);
- hv_store_nomg(self, strcat(uc_name, "_t"), (namelen + 2),
- newSViv(new_item_type), FALSE);
+ hv_store(hdr->storage, uc_name, namelen, newRV((SV *)new_item),
+ FALSE);
+ hv_store(hdr->storage, strcat(uc_name, "_t"), (namelen + 2),
+ newSViv(new_item_type), FALSE);
FETCH = new_item;
}
}
@@ -441,12 +449,12 @@ int rpmhdr_STORE(pTHX_ RPM__Header self, SV* key, SV* value)
char errmsg[256];
STRLEN namelen;
int size, i, is_scalar;
- I32 num_ent, data_type, data_key;
+ I32 num_ent, data_type;
void* data;
AV* a_value = Nullav;
RPM_Header* hdr;
- header_from_object_ret(svp, hdr, self, 0);
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
if (hdr->read_only)
return 0;
@@ -562,7 +570,8 @@ int rpmhdr_STORE(pTHX_ RPM__Header self, SV* key, SV* value)
{
/* This will permanently concat "_t" to uc_name. But we'll craftily
manipulate that later on with namelen. */
- hv_fetch_nomg(svp, self, strcat(uc_name, "_t"), (namelen + 2), FALSE);
+ svp = hv_fetch(hdr->storage, strcat(uc_name, "_t"), (namelen + 2),
+ FALSE);
if (! (svp && SvOK(*svp)))
{
/*
@@ -771,9 +780,9 @@ int rpmhdr_STORE(pTHX_ RPM__Header self, SV* key, SV* value)
/* Store the new data */
headerAddEntry(hdr->hdr, num_ent, data_type, data, size);
/* Store on the hash */
- hv_store_nomg(self, uc_name, namelen,
- (is_scalar) ? newSVsv(value) : newRV_noinc((SV *)a_value),
- FALSE);
+ hv_store(hdr->storage, uc_name, namelen,
+ (is_scalar) ? newSVsv(value) : newRV_noinc((SV *)a_value),
+ FALSE);
return 1;
}
@@ -784,10 +793,9 @@ int rpmhdr_DELETE(pTHX_ RPM__Header self, SV* key)
int namelen; /* Arg for SvPV(..., len) */
char* uc_name; /* UC'd version of name */
RPM_Header* hdr; /* Pointer to C-level struct */
- SV** svp;
int retval, num, i;
- header_from_object_ret(svp, hdr, self, 0);
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
if (hdr->read_only)
return 0;
@@ -821,11 +829,8 @@ int rpmhdr_DELETE(pTHX_ RPM__Header self, SV* key)
}
else
{
- /* Remove magic long enough to do two hv_delete() calls */
- SvMAGICAL_off((SV *)self);
- hv_delete(self, uc_name, namelen, G_DISCARD);
- hv_delete(self, strcat(uc_name, "_t"), namelen + 2, G_DISCARD);
- SvMAGICAL_on((SV *)self);
+ hv_delete(hdr->storage, uc_name, namelen, G_DISCARD);
+ hv_delete(hdr->storage, strcat(uc_name, "_t"), namelen + 2, G_DISCARD);
retval = 1;
}
@@ -833,15 +838,14 @@ int rpmhdr_DELETE(pTHX_ RPM__Header self, SV* key)
return retval;
}
-int rpmhdr_EXISTS(pTHX_ RPM__Header self, SV* key)
+bool rpmhdr_EXISTS(pTHX_ RPM__Header self, SV* key)
{
const char* name;
char* uc_name;
int namelen, tag_by_num, i;
- SV** svp;
RPM_Header* hdr;
- header_from_object_ret(svp, hdr, self, 0);
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
name = sv2key(aTHX_ key);
if (! (name && (namelen = strlen(name))))
return 0;
@@ -856,21 +860,27 @@ int rpmhdr_EXISTS(pTHX_ RPM__Header self, SV* key)
tag_by_num = tag2num(aTHX_ uc_name);
Safefree(uc_name);
if (! tag_by_num)
- /* Later we need to set some sort of error message */
+ {
+ char errmsg[256];
+
+ snprintf(errmsg, 256,
+ "RPM::Header::EXISTS: unknown (to rpm) tag %s", uc_name);
+ rpm_error(aTHX_ RPMERR_BADARG, errmsg);
+ Safefree(uc_name);
return 0;
+ }
return (headerIsEntry(hdr->hdr, tag_by_num));
}
int rpmhdr_FIRSTKEY(pTHX_ RPM__Header self, SV** key, SV** value)
{
- SV** svp;
RPM_Header* hdr;
int tag, type, size;
char* ptr;
const char* tagname;
- header_from_object_ret(svp, hdr, self, 0);
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
/* If there is an existing iterator attached to the struct, free it */
if (hdr->iterator)
headerFreeIterator(hdr->iterator);
@@ -897,13 +907,12 @@ int rpmhdr_FIRSTKEY(pTHX_ RPM__Header self, SV** key, SV** value)
int rpmhdr_NEXTKEY(pTHX_ RPM__Header self, SV* key,
SV** nextkey, SV** nextvalue)
{
- SV** svp;
RPM_Header* hdr;
int tag, type, size;
char* ptr;
const char* tagname;
- header_from_object_ret(svp, hdr, self, 0);
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
/* If there is not an existing iterator, we can't continue */
if (! hdr->iterator)
return 0;
@@ -932,10 +941,9 @@ int rpmhdr_NEXTKEY(pTHX_ RPM__Header self, SV* key,
void rpmhdr_DESTROY(pTHX_ RPM__Header self)
{
- SV** svp;
RPM_Header* hdr;
- header_from_object(svp, hdr, self);
+ struct_from_object(RPM_Header, hdr, self);
if (! hdr) return;
if (hdr->iterator)
@@ -943,15 +951,16 @@ void rpmhdr_DESTROY(pTHX_ RPM__Header self)
if (hdr->hdr)
headerFree(hdr->hdr);
+ hv_undef(hdr->storage);
+ Safefree(hdr);
hv_undef(self);
}
unsigned int rpmhdr_size(pTHX_ RPM__Header self)
{
- SV** svp;
RPM_Header* hdr;
- header_from_object_ret(svp, hdr, self, 0);
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
if (! hdr->hdr)
return 0;
@@ -966,6 +975,9 @@ int rpmhdr_tagtype(pTHX_ RPM__Header self, SV* key)
char* uc_name;
SV** svp;
int i, retval;
+ RPM_Header* hdr;
+
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
name = sv2key(aTHX_ key);
if (! (name && (namelen = strlen(name))))
@@ -979,7 +991,7 @@ int rpmhdr_tagtype(pTHX_ RPM__Header self, SV* key)
retval = RPM_NULL_TYPE;
- hv_fetch_nomg(svp, self, uc_name, strlen(uc_name) + 1, FALSE);
+ svp = hv_fetch(hdr->storage, uc_name, strlen(uc_name), FALSE);
if (svp && SvOK(*svp))
{
/* The base tag has already been fetched and thus we have a type */
@@ -995,12 +1007,14 @@ int rpmhdr_tagtype(pTHX_ RPM__Header self, SV* key)
if (sub_fetch)
{
- hv_fetch_nomg(svp, self, uc_name, strlen(uc_name), FALSE);
+ svp = hv_fetch(hdr->storage, uc_name, strlen(uc_name), FALSE);
if (svp && SvOK(*svp))
{
/* The base tag has now been fetched */
retval = SvIV(*svp);
}
+ SvREFCNT_dec(*svp);
+ SvREFCNT_dec(sub_fetch);
}
}
@@ -1015,12 +1029,11 @@ int rpmhdr_write(pTHX_ RPM__Header self, SV* gv_in, int magicp)
FD_t fd;
RPM_Header* hdr;
GV* gv;
- SV** svp;
int written = 0;
gv = (SvPOK(gv_in) && (SvTYPE(gv_in) == SVt_PVGV)) ?
(GV *)SvRV(gv_in) : (GV *)gv_in;
- header_from_object_ret(svp, hdr, self, 0);
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
if (!gv || !(io = GvIO(gv)) || !(fp = IoIFP(io)))
return written;
@@ -1036,10 +1049,9 @@ int rpmhdr_write(pTHX_ RPM__Header self, SV* gv_in, int magicp)
/* T/F test whether the header references a SRPM */
int rpmhdr_is_source(pTHX_ RPM__Header self)
{
- SV** svp;
RPM_Header* hdr;
- header_from_object_ret(svp, hdr, self, 0);
+ struct_from_object_ret(RPM_Header, hdr, self, 0);
if (! hdr->hdr)
return 0;
@@ -1055,16 +1067,15 @@ int rpmhdr_cmpver(pTHX_ RPM__Header self, RPM__Header other)
{
RPM_Header* one;
RPM_Header* two;
- SV** svp;
- header_from_object(svp, one, self);
+ struct_from_object(RPM_Header, one, self);
if (! one)
{
rpm_error(aTHX_ RPMERR_BADARG,
"RPM::Header::rpmhdr_cmpver: Arg 1 has no header data");
return 0;
}
- header_from_object(svp, two, other);
+ struct_from_object(RPM_Header, two, other);
if (! two)
{
rpm_error(aTHX_ RPMERR_BADARG,
@@ -1081,10 +1092,9 @@ int rpmhdr_cmpver(pTHX_ RPM__Header self, RPM__Header other)
*/
char* rpmhdr_source_name(RPM__Header self)
{
- SV** svp;
RPM_Header* hdr;
- header_from_object(svp, hdr, self);
+ struct_from_object(RPM_Header, hdr, self);
return hdr->source_name;
}
@@ -1146,7 +1156,7 @@ MODULE = RPM::Header PACKAGE = RPM::Header PREFIX = rpmhdr_
RPM::Header
rpmhdr_TIEHASH(class, source=NULL, flags=0)
- SV* class;
+ char* class;
SV* source;
int flags;
PROTOTYPE: $;$$
@@ -1171,8 +1181,6 @@ rpmhdr_STORE(self, key, value)
SV* key;
SV* value;
PROTOTYPE: $$$
- PREINIT:
- AV* avalue;
CODE:
RETVAL = rpmhdr_STORE(aTHX_ self, key, value);
OUTPUT:
@@ -1189,8 +1197,8 @@ rpmhdr_DELETE(self, key)
RETVAL
int
-rpmhdr_CLEAR(self)
- RPM::Header self;
+rpmhdr_CLEAR(self=NULL)
+ SV* self;
PROTOTYPE: $
CODE:
{
@@ -1200,7 +1208,7 @@ rpmhdr_CLEAR(self)
OUTPUT:
RETVAL
-int
+bool
rpmhdr_EXISTS(self, key)
RPM::Header self;
SV* key;
@@ -1214,12 +1222,11 @@ void
rpmhdr_FIRSTKEY(self)
RPM::Header self;
PROTOTYPE: $
- PREINIT:
- SV* key;
- SV* value;
- int i;
PPCODE:
{
+ SV* key;
+ SV* value;
+
if (! rpmhdr_FIRSTKEY(aTHX_ self, &key, &value))
{
key = newSVsv(&PL_sv_undef);
@@ -1235,12 +1242,11 @@ rpmhdr_NEXTKEY(self, key=NULL)
RPM::Header self;
SV* key;
PROTOTYPE: $;$
- PREINIT:
- SV* nextkey;
- SV* nextvalue;
- int i;
PPCODE:
{
+ SV* nextkey;
+ SV* nextvalue;
+
if (! rpmhdr_NEXTKEY(aTHX_ self, key, &nextkey, &nextvalue))
{
nextkey = newSVsv(&PL_sv_undef);
@@ -1322,10 +1328,9 @@ rpmhdr_NVR(self)
PROTOTYPE: $
PPCODE:
{
- SV** svp;
RPM_Header* hdr;
- header_from_object(svp, hdr, self);
+ struct_from_object(RPM_Header, hdr, self);
if (hdr->name)
{
diff --git a/Perl-RPM/t/01_database.t b/Perl-RPM/t/01_database.t
index d4188de09..80955d290 100755
--- a/Perl-RPM/t/01_database.t
+++ b/Perl-RPM/t/01_database.t
@@ -5,10 +5,28 @@ use RPM::Database;
$SIG{__WARN__} = sub { $@ = shift; };
$SIG{__DIE__} = sub { $@ = shift; };
-print "1..12\n";
+print "1..13\n";
+$count = 1;
+
+#
+# Prior to starting up, we need to do some less-direct queries of the RPM
+# database, so that we have baseline data to test against.
+#
+@all_packs = `rpm -q -a --queryformat "\%{NAME}\\n"`;
+chomp(@all_packs);
+$all_packs{$_}++ for (@all_packs);
+
+#
+# With a full list of packages now known, find one to use for package existence
+# testing.
+#
+for (qw(rpm kernel bash file passwd))
+{
+ $test_pack = $_, last if (exists $all_packs{$_});
+}
tie %DB, "RPM::Database" or print "not ";
-print "ok 1\n";
+print "ok $count\n"; $count++;
unless (tied %DB)
{
@@ -16,28 +34,31 @@ unless (tied %DB)
exit -1;
}
-# This package must exist, obviously
-$rpm = $DB{rpm};
+# Start with the test package
+$rpm = $DB{$test_pack};
print "not " unless (defined $rpm and ref $rpm);
-print "ok 2\n";
+print "ok $count\n"; $count++;
# Verify that STORE, DELETE and CLEAR operations are blocked
# STORE
-eval { $DB{foo_package} = 'baz'; print "not " if ($DB{foo_package} eq 'baz') };
-print "ok 3\n";
+eval {
+ $DB{foo_package} = 'baz';
+ print "not " if (exists $DB{foo_package} and ($DB{foo_package} eq 'baz'));
+};
+print "ok $count\n"; $count++;
# DELETE
eval { delete $DB{foo_package} and print "not " };
-print "ok 4\n";
+print "ok $count\n"; $count++;
# CLEAR
eval { %DB = () and print "not " };
-print "ok 5\n";
+print "ok $count\n"; $count++;
# Test the untying
eval { untie %DB };
print "not " if ($@);
-print "ok 6\n";
+print "ok $count\n"; $count++;
# That should cover the basic TIEHASH operands sufficiently.
@@ -49,29 +70,33 @@ print "ok 6\n";
# Test the non-tie approach
$rpm = new RPM::Database;
print "not " unless (defined $rpm and ref $rpm);
-print "ok 7\n";
+print "ok $count\n"; $count++;
+
+# Ensure that the same test package is visible
+print "not " unless (exists $rpm->{$test_pack} and ref($rpm->{$test_pack}));
+print "ok $count\n"; $count++;
@matches = $rpm->find_by_file('/bin/rpm');
# There should be exactly one match:
print "not " unless (@matches == 1);
-print "ok 8\n";
+print "ok $count\n"; $count++;
print "not " unless ($matches[0]->{name} eq 'rpm');
-print "ok 9\n";
+print "ok $count\n"; $count++;
# There may be more than one package that depends on rpm
@matches = $rpm->find_by_required_by('rpm');
for (@matches) { $_ = $_->{name} }
# As long as we see this one (it has to be present to build this package)
-print "not " unless (grep 'rpm-devel', @matches);
-print "ok 10\n";
+print "not " unless (grep($_ eq 'rpm-devel', @matches));
+print "ok $count\n"; $count++;
# Try to fetch a bogus package
$hdr = $rpm->{i_hope_no_one_makes_a_package_by_this_name};
print "not " if $hdr;
-print "ok 11\n";
+print "ok $count\n"; $count++;
undef $rpm;
-print "ok 12\n";
+print "ok $count\n"; $count++;
exit 0;
diff --git a/Perl-RPM/typemap b/Perl-RPM/typemap
index cce50bcc5..a6028019e 100644
--- a/Perl-RPM/typemap
+++ b/Perl-RPM/typemap
@@ -3,35 +3,18 @@
TYPEMAP
const char * T_PTROBJ
-RPM::Database O_RPM_Database
-RPM::Header O_RPM_Header
+RPM::Database O_RPM_Tied
+RPM::Header O_RPM_Tied
RPM::Package O_RPM_Blessed
RPM::Transaction O_RPM_Blessed
-#
-# The following mappings for O_HvRV are taken directly from Dean Roehrich's
-# excellent XS Cookbook, vol. A.
-#
-
OUTPUT
-O_RPM_Database
- if ($var)
- {
- $arg = sv_bless(newRV_noinc((SV*)$var),
- gv_stashpv("RPM::Database", TRUE));
- hv_magic($var, (GV *)Nullhv, 'P');
- }
- else
- {
- $arg = newSVsv(&PL_sv_undef);
- }
-
-O_RPM_Header
+O_RPM_Tied
if ($var)
{
- $arg = sv_bless(newRV_noinc((SV*)$var),
- gv_stashpv("RPM::Header", TRUE));
- hv_magic($var, (GV *)Nullhv, 'P');
+ $arg = sv_bless(sv_2mortal(newRV_noinc((SV*)$var)),
+ gv_stashpv(\"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\",
+ TRUE));
}
else
{
@@ -50,17 +33,7 @@ O_RPM_Blessed
}
INPUT
-O_RPM_Database
- if (sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVHV))
- $var = (HV*)SvRV($arg);
- else
- {
- rpm_error(aTHX_ RPMERR_BADARG,
- \"${Package}::$func_name: not a blessed HV reference\");
- XSRETURN_UNDEF;
- }
-
-O_RPM_Header
+O_RPM_Tied
if (sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVHV))
$var = (HV*)SvRV($arg);
else