summaryrefslogtreecommitdiff
path: root/ext/Storable/Storable.xs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/Storable/Storable.xs')
-rw-r--r--ext/Storable/Storable.xs228
1 files changed, 129 insertions, 99 deletions
diff --git a/ext/Storable/Storable.xs b/ext/Storable/Storable.xs
index cd2a76b551..bb830a9757 100644
--- a/ext/Storable/Storable.xs
+++ b/ext/Storable/Storable.xs
@@ -3,29 +3,16 @@
*/
/*
- * $Id: Storable.xs,v 0.7.1.3 2000/08/23 23:00:41 ram Exp $
+ * $Id: Storable.xs,v 1.0 2000/09/01 19:40:41 ram Exp $
*
* Copyright (c) 1995-2000, Raphael Manfredi
*
- * You may redistribute only under the terms of the Artistic License,
- * as specified in the README file that comes with the distribution.
+ * You may redistribute only under the same terms as Perl 5, as specified
+ * in the README file that comes with the distribution.
*
* $Log: Storable.xs,v $
- * Revision 0.7.1.3 2000/08/23 23:00:41 ram
- * patch3: ANSI-fied most of the code, preparing for Perl core integration
- * patch3: dispatch tables moved upfront to relieve some compilers
- * patch3: merged 64-bit fixes from perl5-porters
- *
- * Revision 0.7.1.2 2000/08/14 07:19:27 ram
- * patch2: added a refcnt dec in retrieve_tied_key()
- *
- * Revision 0.7.1.1 2000/08/13 20:10:06 ram
- * patch1: was wrongly optimizing for "undef" values in hashes
- * patch1: added support for ref to tied items in hash/array
- * patch1: added overloading support
- *
- * Revision 0.7 2000/08/03 22:04:44 ram
- * Baseline for second beta release.
+ * Revision 1.0 2000/09/01 19:40:41 ram
+ * Baseline for first official release.
*
*/
@@ -34,8 +21,10 @@
#include <patchlevel.h> /* Perl's one, needed since 5.6 */
#include <XSUB.h>
-/*#define DEBUGME /* Debug mode, turns assertions on as well */
-/*#define DASSERT /* Assertion mode */
+#if 0
+#define DEBUGME /* Debug mode, turns assertions on as well */
+#define DASSERT /* Assertion mode */
+#endif
/*
* Pre PerlIO time when none of USE_PERLIO and PERLIO_IS_STDIO is defined
@@ -82,12 +71,12 @@ typedef double NV; /* Older perls lack the NV type */
#endif /* PERL_VERSION -- perls < 5.6 */
#ifndef NVef /* The following were not part of perl 5.6 */
-#if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && defined(PERL_PRIfldbl)
-#define NVef PERL_PRIeldbl
-#define NVff PERL_PRIfldbl
-#define NVgf PERL_PRIgldbl
-#endif
-#ifndef NVef
+#if defined(USE_LONG_DOUBLE) && \
+ defined(HAS_LONG_DOUBLE) && defined(PERL_PRIfldbl)
+#define NVef PERL_PRIeldbl
+#define NVff PERL_PRIfldbl
+#define NVgf PERL_PRIgldbl
+#else
#define NVef "e"
#define NVff "f"
#define NVgf "g"
@@ -266,8 +255,8 @@ typedef struct stcxt {
#endif /* < perl5.004_68 */
#define dSTCXT_PTR(T,name) \
- T name = (T)(perinterp_sv && SvIOK(perinterp_sv)\
- ? INT2PTR(T, SvIVX(perinterp_sv)) : NULL)
+ T name = (perinterp_sv && SvIOK(perinterp_sv) \
+ ? INT2PTR(T, SvIVX(perinterp_sv)) : (T) 0)
#define dSTCXT \
dSTCXT_SV; \
dSTCXT_PTR(stcxt_t *, cxt)
@@ -316,6 +305,37 @@ static stcxt_t *Context_ptr = &Context;
*/
/*
+ * LOW_32BITS
+ *
+ * Keep only the low 32 bits of a pointer (used for tags, which are not
+ * really pointers).
+ */
+
+#if PTRSIZE <= 4
+#define LOW_32BITS(x) ((I32) (x))
+#else
+#define LOW_32BITS(x) ((I32) ((unsigned long) (x) & 0xffffffffUL))
+#endif
+
+/*
+ * oI, oS, oC
+ *
+ * Hack for Crays, where sizeof(I32) == 8, and which are big-endians.
+ * Used in the WLEN and RLEN macros.
+ */
+
+#if INTSIZE > 4
+#define oI(x) ((I32 *) ((char *) (x) + 4))
+#define oS(x) ((x) - 4)
+#define oC(x) (x = 0)
+#define CRAY_HACK
+#else
+#define oI(x) (x)
+#define oS(x) (x)
+#define oC(x)
+#endif
+
+/*
* key buffer handling
*/
#define kbuf (cxt->keybuf).arena
@@ -402,6 +422,16 @@ static stcxt_t *Context_ptr = &Context;
return (SV *) 0; \
} while (0)
+#ifdef CRAY_HACK
+#define MBUF_GETINT(x) do { \
+ oC(x); \
+ if ((mptr + 4) <= mend) { \
+ memcpy(oI(&x), mptr, 4); \
+ mptr += 4; \
+ } else \
+ return (SV *) 0; \
+} while (0)
+#else
#define MBUF_GETINT(x) do { \
if ((mptr + sizeof(int)) <= mend) { \
if (int_aligned(mptr)) \
@@ -412,6 +442,7 @@ static stcxt_t *Context_ptr = &Context;
} else \
return (SV *) 0; \
} while (0)
+#endif
#define MBUF_READ(x,s) do { \
if ((mptr + (s)) <= mend) { \
@@ -440,6 +471,13 @@ static stcxt_t *Context_ptr = &Context;
} \
} while (0)
+#ifdef CRAY_HACK
+#define MBUF_PUTINT(i) do { \
+ MBUF_CHK(4); \
+ memcpy(mptr, oI(&i), 4); \
+ mptr += 4; \
+} while (0)
+#else
#define MBUF_PUTINT(i) do { \
MBUF_CHK(sizeof(int)); \
if (int_aligned(mptr)) \
@@ -448,6 +486,7 @@ static stcxt_t *Context_ptr = &Context;
memcpy(mptr, &i, sizeof(int)); \
mptr += sizeof(int); \
} while (0)
+#endif
#define MBUF_WRITE(x,s) do { \
MBUF_CHK(s); \
@@ -456,19 +495,6 @@ static stcxt_t *Context_ptr = &Context;
} while (0)
/*
- * LOW_32BITS
- *
- * Keep only the low 32 bits of a pointer (used for tags, which are not
- * really pointers).
- */
-
-#if PTRSIZE <= 4
-#define LOW_32BITS(x) ((I32) (x))
-#else
-#define LOW_32BITS(x) ((I32) ((unsigned long) (x) & 0xffffffffUL))
-#endif
-
-/*
* Possible return values for sv_type().
*/
@@ -520,7 +546,7 @@ static char old_magicstr[] = "perl-store"; /* Magic number before 0.6 */
static char magicstr[] = "pst0"; /* Used as a magic number */
#define STORABLE_BIN_MAJOR 2 /* Binary major "version" */
-#define STORABLE_BIN_MINOR 1 /* Binary minor "version" */
+#define STORABLE_BIN_MINOR 2 /* Binary minor "version" */
/*
* Useful store shortcuts...
@@ -533,28 +559,31 @@ static char magicstr[] = "pst0"; /* Used as a magic number */
return -1; \
} while (0)
+#define WRITE_I32(x) do { \
+ ASSERT(sizeof(x) == sizeof(I32), ("writing an I32")); \
+ if (!cxt->fio) \
+ MBUF_PUTINT(x); \
+ else if (PerlIO_write(cxt->fio, oI(&x), oS(sizeof(x))) != oS(sizeof(x))) \
+ return -1; \
+ } while (0)
+
#ifdef HAS_HTONL
#define WLEN(x) do { \
if (cxt->netorder) { \
int y = (int) htonl(x); \
if (!cxt->fio) \
MBUF_PUTINT(y); \
- else if (PerlIO_write(cxt->fio, &y, sizeof(y)) != sizeof(y)) \
+ else if (PerlIO_write(cxt->fio,oI(&y),oS(sizeof(y))) != oS(sizeof(y))) \
return -1; \
} else { \
if (!cxt->fio) \
MBUF_PUTINT(x); \
- else if (PerlIO_write(cxt->fio, &x, sizeof(x)) != sizeof(x)) \
+ else if (PerlIO_write(cxt->fio,oI(&x),oS(sizeof(x))) != oS(sizeof(x))) \
return -1; \
} \
} while (0)
#else
-#define WLEN(x) do { \
- if (!cxt->fio) \
- MBUF_PUTINT(x); \
- else if (PerlIO_write(cxt->fio, &x, sizeof(x)) != sizeof(x)) \
- return -1; \
- } while (0)
+#define WLEN(x) WRITE_I32(x)
#endif
#define WRITE(x,y) do { \
@@ -600,22 +629,27 @@ static char magicstr[] = "pst0"; /* Used as a magic number */
return (SV *) 0; \
} while (0)
-#ifdef HAS_NTOHL
-#define RLEN(x) do { \
+#define READ_I32(x) do { \
+ ASSERT(sizeof(x) == sizeof(I32), ("reading an I32")); \
+ oC(x); \
if (!cxt->fio) \
MBUF_GETINT(x); \
- else if (PerlIO_read(cxt->fio, &x, sizeof(x)) != sizeof(x)) \
+ else if (PerlIO_read(cxt->fio, oI(&x), oS(sizeof(x))) != oS(sizeof(x))) \
return (SV *) 0; \
- if (cxt->netorder) \
- x = (int) ntohl(x); \
} while (0)
-#else
+
+#ifdef HAS_NTOHL
#define RLEN(x) do { \
+ oC(x); \
if (!cxt->fio) \
MBUF_GETINT(x); \
- else if (PerlIO_read(cxt->fio, &x, sizeof(x)) != sizeof(x)) \
+ else if (PerlIO_read(cxt->fio, oI(&x), oS(sizeof(x))) != oS(sizeof(x))) \
return (SV *) 0; \
+ if (cxt->netorder) \
+ x = (int) ntohl(x); \
} while (0)
+#else
+#define RLEN(x) READ_I32(x)
#endif
#define READ(x,y) do { \
@@ -1127,9 +1161,7 @@ static SV *pkg_fetchmeth(
gv = gv_fetchmethod_autoload(pkg, method, FALSE);
if (gv && isGV(gv)) {
sv = newRV((SV*) GvCV(gv));
- TRACEME(("%s->%s: 0x%"UVxf,
- HvNAME(pkg), method,
- PTR2UV(sv)));
+ TRACEME(("%s->%s: 0x%"UVxf, HvNAME(pkg), method, PTR2UV(sv)));
} else {
sv = newSVsv(&PL_sv_undef);
TRACEME(("%s->%s: not found", HvNAME(pkg), method));
@@ -1193,8 +1225,7 @@ static SV *pkg_can(
return (SV *) 0;
} else {
TRACEME(("cached %s->%s: 0x%"UVxf,
- HvNAME(pkg), method,
- PTR2UV(sv)));
+ HvNAME(pkg), method, PTR2UV(sv)));
return sv;
}
}
@@ -1367,8 +1398,7 @@ static int store_ref(stcxt_t *cxt, SV *sv)
if (SvOBJECT(sv)) {
HV *stash = (HV *) SvSTASH(sv);
if (stash && Gv_AMG(stash)) {
- TRACEME(("ref (0x%"UVxf") is overloaded",
- PTR2UV(sv)));
+ TRACEME(("ref (0x%"UVxf") is overloaded", PTR2UV(sv)));
PUTMARK(SX_OVERLOAD);
} else
PUTMARK(SX_REF);
@@ -1468,7 +1498,8 @@ static int store_scalar(stcxt_t *cxt, SV *sv)
*/
string:
- STORE_SCALAR(pv, len);
+ wlen = (I32) len; /* WLEN via STORE_SCALAR expects I32 */
+ STORE_SCALAR(pv, wlen);
TRACEME(("ok (scalar 0x%"UVxf" '%s', length = %"IVdf")",
PTR2UV(sv), SvPVX(sv), (IV)len));
@@ -1479,8 +1510,7 @@ static int store_scalar(stcxt_t *cxt, SV *sv)
* Watch for number being an integer in disguise.
*/
if (nv == (NV) (iv = I_V(nv))) {
- TRACEME(("double %"NVff" is actually integer %"IVdf,
- nv, iv));
+ TRACEME(("double %"NVff" is actually integer %"IVdf, nv, iv));
goto integer; /* Share code below */
}
@@ -1493,8 +1523,7 @@ static int store_scalar(stcxt_t *cxt, SV *sv)
PUTMARK(SX_DOUBLE);
WRITE(&nv, sizeof(nv));
- TRACEME(("ok (double 0x%"UVxf", value = %"NVff")",
- PTR2UV(sv), nv));
+ TRACEME(("ok (double 0x%"UVxf", value = %"NVff")", PTR2UV(sv), nv));
} else if (flags & SVp_IOK) { /* SvIOKp(sv) => integer */
iv = SvIV(sv);
@@ -1515,23 +1544,22 @@ static int store_scalar(stcxt_t *cxt, SV *sv)
PUTMARK(siv);
TRACEME(("small integer stored as %d", siv));
} else if (cxt->netorder) {
- int niv;
+ I32 niv;
#ifdef HAS_HTONL
- niv = (int) htonl(iv);
+ niv = (I32) htonl(iv);
TRACEME(("using network order"));
#else
- niv = (int) iv;
+ niv = (I32) iv;
TRACEME(("as-is for network order"));
#endif
PUTMARK(SX_NETINT);
- WRITE(&niv, sizeof(niv));
+ WRITE_I32(niv);
} else {
PUTMARK(SX_INTEGER);
WRITE(&iv, sizeof(iv));
}
- TRACEME(("ok (integer 0x%"UVxf", value = %"IVdf")",
- PTR2UV(sv), iv));
+ TRACEME(("ok (integer 0x%"UVxf", value = %"IVdf")", PTR2UV(sv), iv));
} else
CROAK(("Can't determine type of %s(0x%"UVxf")",
@@ -1684,8 +1712,7 @@ static int store_hash(stcxt_t *cxt, HV *hv)
* Store value first.
*/
- TRACEME(("(#%d) value 0x%"UVxf,
- i, PTR2UV(val)));
+ TRACEME(("(#%d) value 0x%"UVxf, i, PTR2UV(val)));
if (ret = store(cxt, val))
goto out;
@@ -1731,8 +1758,7 @@ static int store_hash(stcxt_t *cxt, HV *hv)
* Store value first.
*/
- TRACEME(("(#%d) value 0x%"UVxf,
- i, PTR2UV(val)));
+ TRACEME(("(#%d) value 0x%"UVxf, i, PTR2UV(val)));
if (ret = store(cxt, val))
goto out;
@@ -1854,14 +1880,12 @@ static int store_tied_item(stcxt_t *cxt, SV *sv)
if (mg->mg_ptr) {
TRACEME(("store_tied_item: storing a ref to a tied hash item"));
PUTMARK(SX_TIED_KEY);
- TRACEME(("store_tied_item: storing OBJ 0x%"UVxf,
- PTR2UV(mg->mg_obj)));
+ TRACEME(("store_tied_item: storing OBJ 0x%"UVxf, PTR2UV(mg->mg_obj)));
if (ret = store(cxt, mg->mg_obj))
return ret;
- TRACEME(("store_tied_item: storing PTR 0x%"UVxf,
- PTR2UV(mg->mg_ptr)));
+ TRACEME(("store_tied_item: storing PTR 0x%"UVxf, PTR2UV(mg->mg_ptr)));
if (ret = store(cxt, (SV *) mg->mg_ptr))
return ret;
@@ -1870,8 +1894,7 @@ static int store_tied_item(stcxt_t *cxt, SV *sv)
TRACEME(("store_tied_item: storing a ref to a tied array item "));
PUTMARK(SX_TIED_IDX);
- TRACEME(("store_tied_item: storing OBJ 0x%"UVxf,
- PTR2UV(mg->mg_obj)));
+ TRACEME(("store_tied_item: storing OBJ 0x%"UVxf, PTR2UV(mg->mg_obj)));
if (ret = store(cxt, mg->mg_obj))
return ret;
@@ -2064,8 +2087,7 @@ static int store_hook(
if (svh = hv_fetch(cxt->hseen, (char *) &xsv, sizeof(xsv), FALSE))
goto sv_seen; /* Avoid moving code too far to the right */
- TRACEME(("listed object %d at 0x%"UVxf" is unknown",
- i-1, PTR2UV(xsv)));
+ TRACEME(("listed object %d at 0x%"UVxf" is unknown", i-1, PTR2UV(xsv)));
/*
* We need to recurse to store that object and get it to be known
@@ -2126,7 +2148,8 @@ static int store_hook(
* If we recursed, the SX_HOOK has already been emitted.
*/
- TRACEME(("SX_HOOK (recursed=%d) flags=0x%x class=%"IVdf" len=%"IVdf" len2=%"IVdf" len3=%d",
+ TRACEME(("SX_HOOK (recursed=%d) flags=0x%x "
+ "class=%"IVdf" len=%"IVdf" len2=%"IVdf" len3=%d",
recursed, flags, (IV)classnum, (IV)len, (IV)len2, count-1));
/* SX_HOOK <flags> */
@@ -2180,7 +2203,7 @@ static int store_hook(
for (i = 1; i < count; i++) {
I32 tagval = htonl(LOW_32BITS(ary[i]));
- WRITE(&tagval, sizeof(I32));
+ WRITE_I32(tagval);
TRACEME(("object %d, tag #%d", i-1, ntohl(tagval)));
}
}
@@ -2434,11 +2457,10 @@ static int store(stcxt_t *cxt, SV *sv)
if (svh) {
I32 tagval = htonl(LOW_32BITS(*svh));
- TRACEME(("object 0x%"UVxf" seen as #%d",
- PTR2UV(sv), ntohl(tagval)));
+ TRACEME(("object 0x%"UVxf" seen as #%d", PTR2UV(sv), ntohl(tagval)));
PUTMARK(SX_OBJECT);
- WRITE(&tagval, sizeof(I32));
+ WRITE_I32(tagval);
return 0;
}
@@ -2531,10 +2553,12 @@ static int magic_write(stcxt_t *cxt)
PUTMARK((unsigned char) sizeof(int));
PUTMARK((unsigned char) sizeof(long));
PUTMARK((unsigned char) sizeof(char *));
+ PUTMARK((unsigned char) sizeof(NV));
- TRACEME(("ok (magic_write byteorder = 0x%lx [%d], I%d L%d P%d)",
+ TRACEME(("ok (magic_write byteorder = 0x%lx [%d], I%d L%d P%d D%d)",
(unsigned long) BYTEORDER, (int) c,
- (int) sizeof(int), (int) sizeof(long), (int) sizeof(char *)));
+ (int) sizeof(int), (int) sizeof(long),
+ (int) sizeof(char *), (int) sizeof(NV)));
return 0;
}
@@ -3051,7 +3075,7 @@ static SV *retrieve_hook(stcxt_t *cxt)
SV **svh;
SV *xsv;
- READ(&tag, sizeof(I32));
+ READ_I32(tag);
tag = ntohl(tag);
svh = av_fetch(cxt->aseen, tag, FALSE);
if (!svh)
@@ -3379,7 +3403,7 @@ static SV *retrieve_tied_idx(stcxt_t *cxt)
*/
static SV *retrieve_lscalar(stcxt_t *cxt)
{
- STRLEN len;
+ I32 len;
SV *sv;
RLEN(len);
@@ -3502,11 +3526,11 @@ static SV *retrieve_integer(stcxt_t *cxt)
static SV *retrieve_netint(stcxt_t *cxt)
{
SV *sv;
- int iv;
+ I32 iv;
TRACEME(("retrieve_netint (#%d)", cxt->tagnum));
- READ(&iv, sizeof(iv));
+ READ_I32(iv);
#ifdef HAS_NTOHL
sv = newSViv((int) ntohl(iv));
TRACEME(("network integer %d", (int) ntohl(iv)));
@@ -4028,6 +4052,12 @@ magic_ok:
if ((int) c != sizeof(char *))
CROAK(("Pointer integer size is not compatible"));
+ if (version_major >= 2 && version_minor >= 2) {
+ GETMARK(c); /* sizeof(NV) */
+ if ((int) c != sizeof(NV))
+ CROAK(("Double size is not compatible"));
+ }
+
return &PL_sv_undef; /* OK */
}
@@ -4116,7 +4146,7 @@ again:
if (type == SX_OBJECT) {
I32 tag;
- READ(&tag, sizeof(I32));
+ READ_I32(tag);
tag = ntohl(tag);
svh = av_fetch(cxt->aseen, tag, FALSE);
if (!svh)