use gfx's standard header.

This commit is contained in:
tokuhirom 2010-09-10 20:42:40 +09:00
parent 5bb8b6f16c
commit b79c1345b9
4 changed files with 140 additions and 36 deletions

View File

@ -8,10 +8,29 @@ SYNOPSIS
DESCRIPTION
This module converts Perl data structures to MessagePack and vice versa.
ABOUT MESSAGEPACK FORMAT
MessagePack is a binary-based efficient object serialization format. It
enables to exchange structured objects between many languages like JSON.
But unlike JSON, it is very fast and small.
ADVANTAGES
PORTABILITY
Messagepack is language independent binary serialize format.
SMALL SIZE
say length(JSON::XS::encode_json({a=>1, b=>2})); # => 13
say length(Storable::nfreeze({a=>1, b=>2})); # => 21
say length(Data::MessagePack->pack({a=>1, b=>2})); # => 7
MessagePack format saves memory than JSON and Storable format.
STREAMING DESERIALIZER
MessagePack supports streaming deserializer. It is useful for
networking such as RPC.
If you want to get more informations about messagepack format, please
visit to <http://msgpack.org/>.
METHODS
my $packed = Data::MessagePack->pack($data);
pack the $data to messagepack format string.
@ -23,6 +42,28 @@ Configuration Variables
$Data::MessagePack::PreferInteger
Pack the string as int when the value looks like int(EXPERIMENTAL).
SPEED
This is result of benchmark/serialize.pl and benchmark/deserialize.pl on
my SC440(Linux 2.6.32-23-server #37-Ubuntu SMP).
-- serialize
JSON::XS: 2.3
Data::MessagePack: 0.20
Storable: 2.21
Benchmark: timing 1000000 iterations of json, mp, storable...
json: 5 wallclock secs ( 3.95 usr + 0.00 sys = 3.95 CPU) @ 253164.56/s (n=1000000)
mp: 3 wallclock secs ( 2.69 usr + 0.00 sys = 2.69 CPU) @ 371747.21/s (n=1000000)
storable: 26 wallclock secs (27.21 usr + 0.00 sys = 27.21 CPU) @ 36751.19/s (n=1000000)
-- deserialize
JSON::XS: 2.3
Data::MessagePack: 0.20
Storable: 2.21
Benchmark: timing 1000000 iterations of json, mp, storable...
json: 4 wallclock secs ( 4.45 usr + 0.00 sys = 4.45 CPU) @ 224719.10/s (n=1000000)
mp: 6 wallclock secs ( 5.45 usr + 0.00 sys = 5.45 CPU) @ 183486.24/s (n=1000000)
storable: 7 wallclock secs ( 7.77 usr + 0.00 sys = 7.77 CPU) @ 128700.13/s (n=1000000)
AUTHORS
Tokuhiro Matsuno
@ -40,5 +81,5 @@ LICENSE
under the same terms as Perl itself.
SEE ALSO
<http://msgpack.org/>
<http://msgpack.org/> is official web site for MessagePack format.

76
perl/perlxs.h Normal file
View File

@ -0,0 +1,76 @@
/*
perlxs.h - Standard XS header file
Copyright (c) Fuji, Goro (gfx)
*/
#ifdef __cplusplus
extern "C" {
#endif
#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include <EXTERN.h>
#include <perl.h>
#define NO_XSLOCKS /* for exceptions */
#include <XSUB.h>
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "ppport.h"
/* portability stuff not supported by ppport.h yet */
#ifndef STATIC_INLINE /* from 5.13.4 */
# if defined(__GNUC__) || defined(__cplusplus__) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
# define STATIC_INLINE static inline
# else
# define STATIC_INLINE static
# endif
#endif /* STATIC_INLINE */
#ifndef __attribute__format__
#define __attribute__format__(a,b,c) /* nothing */
#endif
#ifndef LIKELY /* they are just a compiler's hint */
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif
#ifndef newSVpvs_share
#define newSVpvs_share(s) Perl_newSVpvn_share(aTHX_ STR_WITH_LEN(s), 0U)
#endif
#ifndef get_cvs
#define get_cvs(name, flags) get_cv(name, flags)
#endif
#ifndef GvNAME_get
#define GvNAME_get GvNAME
#endif
#ifndef GvNAMELEN_get
#define GvNAMELEN_get GvNAMELEN
#endif
#ifndef CvGV_set
#define CvGV_set(cv, gv) (CvGV(cv) = (gv))
#endif
/* general utility */
#if PERL_BCDVERSION >= 0x5008005
#define LooksLikeNumber(x) looks_like_number(x)
#else
#define LooksLikeNumber(x) (SvPOKp(x) ? looks_like_number(x) : (I32)SvNIOKp(x))
#endif
#define newAV_mortal() (AV*)sv_2mortal((SV*)newAV())
#define newHV_mortal() (HV*)sv_2mortal((SV*)newHV())
#define DECL_BOOT(name) EXTERN_C XS(CAT2(boot_, name))
#define CALL_BOOT(name) STMT_START { \
PUSHMARK(SP); \
CALL_FPTR(CAT2(boot_, name))(aTHX_ cv); \
} STMT_END

View File

@ -2,16 +2,7 @@
* code is written by tokuhirom.
* buffer alocation technique is taken from JSON::XS. thanks to mlehmann.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#ifdef __cplusplus
};
#endif
#include "perlxs.h"
#include "msgpack/pack_define.h"

View File

@ -2,13 +2,9 @@
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "util.h"
#define NEED_newRV_noinc
#define NEED_sv_2pv_flags
#include "ppport.h"
#include "perlxs.h"
#ifdef __cplusplus
};
@ -38,7 +34,7 @@ typedef struct {
/* ---------------------------------------------------------------------- */
/* utility functions */
static INLINE SV *
STATIC_INLINE SV *
get_bool (const char *name) {
SV * sv = sv_mortalcopy(get_sv( name, 1 ));
@ -60,19 +56,19 @@ static SV* template_data(msgpack_unpack_t* u);
static int template_execute(msgpack_unpack_t* u,
const char* data, size_t len, size_t* off);
static INLINE SV* template_callback_root(unpack_user* u)
STATIC_INLINE SV* template_callback_root(unpack_user* u)
{ return &PL_sv_undef; }
static INLINE int template_callback_uint8(unpack_user* u, uint8_t d, SV** o)
STATIC_INLINE int template_callback_uint8(unpack_user* u, uint8_t d, SV** o)
{ *o = sv_2mortal(newSVuv(d)); return 0; }
static INLINE int template_callback_uint16(unpack_user* u, uint16_t d, SV** o)
STATIC_INLINE int template_callback_uint16(unpack_user* u, uint16_t d, SV** o)
{ *o = sv_2mortal(newSVuv(d)); return 0; }
static INLINE int template_callback_uint32(unpack_user* u, uint32_t d, SV** o)
STATIC_INLINE int template_callback_uint32(unpack_user* u, uint32_t d, SV** o)
{ *o = sv_2mortal(newSVuv(d)); return 0; }
static INLINE int template_callback_uint64(unpack_user* u, uint64_t d, SV** o)
STATIC_INLINE int template_callback_uint64(unpack_user* u, uint64_t d, SV** o)
{
#if IVSIZE==4
*o = sv_2mortal(newSVnv(d));
@ -82,47 +78,47 @@ static INLINE int template_callback_uint64(unpack_user* u, uint64_t d, SV** o)
return 0;
}
static INLINE int template_callback_int8(unpack_user* u, int8_t d, SV** o)
STATIC_INLINE int template_callback_int8(unpack_user* u, int8_t d, SV** o)
{ *o = sv_2mortal(newSViv((long)d)); return 0; }
static INLINE int template_callback_int16(unpack_user* u, int16_t d, SV** o)
STATIC_INLINE int template_callback_int16(unpack_user* u, int16_t d, SV** o)
{ *o = sv_2mortal(newSViv((long)d)); return 0; }
static INLINE int template_callback_int32(unpack_user* u, int32_t d, SV** o)
STATIC_INLINE int template_callback_int32(unpack_user* u, int32_t d, SV** o)
{ *o = sv_2mortal(newSViv((long)d)); return 0; }
static INLINE int template_callback_int64(unpack_user* u, int64_t d, SV** o)
STATIC_INLINE int template_callback_int64(unpack_user* u, int64_t d, SV** o)
{ *o = sv_2mortal(newSViv(d)); return 0; }
static INLINE int template_callback_float(unpack_user* u, float d, SV** o)
STATIC_INLINE int template_callback_float(unpack_user* u, float d, SV** o)
{ *o = sv_2mortal(newSVnv(d)); return 0; }
static INLINE int template_callback_double(unpack_user* u, double d, SV** o)
STATIC_INLINE int template_callback_double(unpack_user* u, double d, SV** o)
{ *o = sv_2mortal(newSVnv(d)); return 0; }
/* &PL_sv_undef is not so good. see http://gist.github.com/387743 */
static INLINE int template_callback_nil(unpack_user* u, SV** o)
STATIC_INLINE int template_callback_nil(unpack_user* u, SV** o)
{ *o = sv_newmortal(); return 0; }
static INLINE int template_callback_true(unpack_user* u, SV** o)
STATIC_INLINE int template_callback_true(unpack_user* u, SV** o)
{ *o = get_bool("Data::MessagePack::true") ; return 0; }
static INLINE int template_callback_false(unpack_user* u, SV** o)
STATIC_INLINE int template_callback_false(unpack_user* u, SV** o)
{ *o = get_bool("Data::MessagePack::false") ; return 0; }
static INLINE int template_callback_array(unpack_user* u, unsigned int n, SV** o)
STATIC_INLINE int template_callback_array(unpack_user* u, unsigned int n, SV** o)
{ AV* a = (AV*)sv_2mortal((SV*)newAV()); *o = sv_2mortal((SV*)newRV_inc((SV*)a)); av_extend(a, n); return 0; }
static INLINE int template_callback_array_item(unpack_user* u, SV** c, SV* o)
STATIC_INLINE int template_callback_array_item(unpack_user* u, SV** c, SV* o)
{ av_push((AV*)SvRV(*c), o); SvREFCNT_inc(o); return 0; } /* FIXME set value directry RARRAY_PTR(obj)[RARRAY_LEN(obj)++] */
static INLINE int template_callback_map(unpack_user* u, unsigned int n, SV** o)
STATIC_INLINE int template_callback_map(unpack_user* u, unsigned int n, SV** o)
{ HV * h = (HV*)sv_2mortal((SV*)newHV()); *o = sv_2mortal(newRV_inc((SV*)h)); return 0; }
static INLINE int template_callback_map_item(unpack_user* u, SV** c, SV* k, SV* v)
STATIC_INLINE int template_callback_map_item(unpack_user* u, SV** c, SV* k, SV* v)
{ hv_store_ent((HV*)SvRV(*c), k, v, 0); SvREFCNT_inc(v); return 0; }
static INLINE int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, SV** o)
STATIC_INLINE int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, SV** o)
{ *o = sv_2mortal((l==0) ? newSVpv("", 0) : newSVpv(p, l)); return 0; }
/* { *o = newSVpvn_flags(p, l, SVs_TEMP); return 0; } <= this does not works. */