lang/c/msgpack: added Messagepack, a binary-based efficient data interchange format.

git-svn-id: file:///Users/frsyuki/project/msgpack-git/svn/x@48 5a5092ae-2292-43ba-b2d5-dcab9c1a2731
This commit is contained in:
frsyuki 2009-02-15 09:09:55 +00:00
commit 269cda016d
50 changed files with 4869 additions and 0 deletions

20
README Normal file
View File

@ -0,0 +1,20 @@
MessagePack
-----------
Binary-based efficient data interchange format.
Copyright (C) 2008 FURUHASHI Sadayuki
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

17
c/Makefile Normal file
View File

@ -0,0 +1,17 @@
CFLAGS = -I.. -Wall -g -O4
LDFLAGS = -L.
all: bench
bench: pack.o unpack.o unpack_inline.o bench.o pack.h pack_inline.h unpack.h unpack_context.h
$(CC) $(LDFLAGS) unpack.o unpack_inline.o pack.o bench.o -lyajl_s -o $@
bench_inline: pack.o bench_inline.o pack.h pack_inline.h
$(CC) $(LDFLAGS) pack.o bench_inline.o -lyajl_s -o $@
.PHONY: clean
clean:
$(RM) unpack.o unpack_inline.o pack.o test.o bench.o bench_inline.o
$(RM) bench bench_inline

338
c/bench.c Normal file
View File

@ -0,0 +1,338 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <msgpack/pack.h>
#include <msgpack/unpack.h>
#include <yajl/yajl_parse.h>
#include <yajl/yajl_gen.h>
static struct timeval g_timer;
void reset_timer()
{
gettimeofday(&g_timer, NULL);
}
double show_timer()
{
struct timeval endtime;
gettimeofday(&endtime, NULL);
double sec = (endtime.tv_sec - g_timer.tv_sec)
+ (double)(endtime.tv_usec - g_timer.tv_usec) / 1000 / 1000;
printf("%f sec\n", sec);
return sec;
}
static int reformat_null(void * ctx) { return 1; }
static int reformat_boolean(void * ctx, int boolean) { return 1; }
static int reformat_number(void * ctx, const char * s, unsigned int l) { return 1; }
static int reformat_string(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { return 1; }
static int reformat_map_key(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { return 1; }
static int reformat_start_map(void * ctx) { return 1; }
static int reformat_end_map(void * ctx) { return 1; }
static int reformat_start_array(void * ctx) { return 1; }
static int reformat_end_array(void * ctx) { return 1; }
static void* unpack_unsigned_int_8(void* data, uint8_t d) { return NULL; }
static void* unpack_unsigned_int_16(void* data, uint16_t d) { return NULL; }
static void* unpack_unsigned_int_32(void* data, uint32_t d) { return NULL; }
static void* unpack_unsigned_int_64(void* data, uint64_t d) { return NULL; }
static void* unpack_signed_int_8(void* data, int8_t d) { return NULL; }
static void* unpack_signed_int_16(void* data, int16_t d) { return NULL; }
static void* unpack_signed_int_32(void* data, int32_t d) { return NULL; }
static void* unpack_signed_int_64(void* data, int64_t d) { return NULL; }
static void* unpack_float(void* data, float d) { return NULL; }
static void* unpack_double(void* data, double d) { return NULL; }
static void* unpack_nil(void* data) { return NULL; }
static void* unpack_true(void* data) { return NULL; }
static void* unpack_false(void* data) { return NULL; }
static void* unpack_array_start(void* data, unsigned int n) { return NULL; }
static void unpack_array_item(void* data, void* c, void* o) { }
static void* unpack_map_start(void* data, unsigned int n) { return NULL; }
static void unpack_map_item(void* data, void* c, void* k, void* v) { }
static void* unpack_string(void* data, const void* b, size_t l) { return NULL; }
static void* unpack_raw(void* data, const void* b, size_t l) { /*printf("unpack raw %p %lu\n",b,l);*/ return NULL; }
typedef struct {
size_t allocated;
size_t length;
char* buffer;
} pack_buffer;
static const size_t PACK_INITIAL_BUFFER_SIZE = 512;
static void pack_buffer_init(pack_buffer* data)
{
data->buffer = malloc(PACK_INITIAL_BUFFER_SIZE);
data->length = 0;
data->allocated = PACK_INITIAL_BUFFER_SIZE;
}
static void pack_buffer_reset(pack_buffer* data)
{
data->buffer = realloc(data->buffer, PACK_INITIAL_BUFFER_SIZE);
data->allocated = PACK_INITIAL_BUFFER_SIZE;
data->length = 0;
}
static void pack_buffer_free(pack_buffer* data)
{
free(data->buffer);
}
static void pack_append_buffer(void* user, const unsigned char* b, unsigned int l)
{
pack_buffer* data = (pack_buffer*)user;
if(data->allocated - data->length < l) {
data->buffer = realloc(data->buffer, data->allocated*2);
data->allocated *= 2;
}
memcpy(data->buffer + data->length, b, l);
data->length += l;
}
static const unsigned int TASK_INT_NUM = 1<<24;
static const unsigned int TASK_STR_LEN = 1<<15;
//static const unsigned int TASK_INT_NUM = 1<<20;
//static const unsigned int TASK_STR_LEN = 1<<12;
static const char* TASK_STR_PTR;
void bench_json(void)
{
puts("== JSON ==");
yajl_gen_config gcfg = {0, NULL};
yajl_gen g = yajl_gen_alloc(&gcfg);
yajl_parser_config hcfg = { 0, 0 };
yajl_callbacks callbacks = {
reformat_null,
reformat_boolean,
NULL,
NULL,
reformat_number,
reformat_string,
reformat_start_map,
reformat_map_key,
reformat_end_map,
reformat_start_array,
reformat_end_array
};
yajl_handle h = yajl_alloc(&callbacks, &hcfg, NULL);
double sec;
const unsigned char * buf;
unsigned int len;
puts("generate integer");
reset_timer();
{
unsigned int i;
yajl_gen_array_open(g);
for(i=0; i < TASK_INT_NUM; ++i) {
yajl_gen_integer(g, i);
}
yajl_gen_array_close(g);
}
sec = show_timer();
yajl_gen_get_buf(g, &buf, &len);
printf("%u KB\n", len / 1024);
printf("%f MB/s\n", len / sec / 1024 / 1024);
puts("----");
puts("parse integer");
reset_timer();
{
yajl_status stat = yajl_parse(h, buf, len);
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
unsigned char * str = yajl_get_error(h, 1, buf, len);
fprintf(stderr, (const char *) str);
}
}
sec = show_timer();
printf("%f MB/s\n", len / sec / 1024 / 1024);
//yajl_gen_clear(g);
yajl_gen_free(g);
g = yajl_gen_alloc(&gcfg);
yajl_free(h);
h = yajl_alloc(&callbacks, &hcfg, NULL);
puts("----");
puts("generate string");
reset_timer();
{
unsigned int i;
yajl_gen_array_open(g);
for(i=0; i < TASK_STR_LEN; ++i) {
yajl_gen_string(g, (const unsigned char*)TASK_STR_PTR, i);
}
yajl_gen_array_close(g);
}
sec = show_timer();
yajl_gen_get_buf(g, &buf, &len);
printf("%u KB\n", len / 1024);
printf("%f MB/s\n", len / sec / 1024 / 1024);
puts("----");
puts("parse string");
reset_timer();
{
yajl_status stat = yajl_parse(h, buf, len);
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
unsigned char * str = yajl_get_error(h, 1, buf, len);
fprintf(stderr, (const char *) str);
}
}
sec = show_timer();
printf("%f MB/s\n", len / sec / 1024 / 1024);
yajl_gen_free(g);
yajl_free(h);
}
void bench_msgpack(void)
{
puts("== MessagePack ==");
pack_buffer mpkbuf;
pack_buffer_init(&mpkbuf);
msgpack_pack_t* mpk = msgpack_pack_new(
&mpkbuf, pack_append_buffer);
msgpack_unpack_callback cb = {
unpack_unsigned_int_8,
unpack_unsigned_int_16,
unpack_unsigned_int_32,
unpack_unsigned_int_64,
unpack_signed_int_8,
unpack_signed_int_16,
unpack_signed_int_32,
unpack_signed_int_64,
unpack_float,
unpack_double,
unpack_nil,
unpack_true,
unpack_false,
unpack_array_start,
unpack_array_item,
unpack_map_start,
unpack_map_item,
unpack_string,
unpack_raw,
};
msgpack_unpack_t* mupk = msgpack_unpack_new(NULL, &cb);
double sec;
size_t len;
const char* buf;
puts("pack integer");
reset_timer();
{
unsigned int i;
msgpack_pack_array(mpk, TASK_INT_NUM);
for(i=0; i < TASK_INT_NUM; ++i) {
msgpack_pack_unsigned_int(mpk, i);
}
}
sec = show_timer();
len = mpkbuf.length;
buf = mpkbuf.buffer;
printf("%lu KB\n", len / 1024);
printf("%f MB/s\n", len / sec / 1024 / 1024);
puts("----");
puts("unpack integer");
reset_timer();
{
size_t off = 0;
int ret = msgpack_unpack_execute(mupk, buf, len, &off);
if(ret < 0) {
fprintf(stderr, "Parse error.\n");
} else if(ret == 0) {
fprintf(stderr, "Not finished.\n");
}
}
sec = show_timer();
printf("%f MB/s\n", len / sec / 1024 / 1024);
pack_buffer_reset(&mpkbuf);
msgpack_unpack_reset(mupk);
puts("----");
puts("pack string");
reset_timer();
{
unsigned int i;
msgpack_pack_array(mpk, TASK_STR_LEN);
for(i=0; i < TASK_STR_LEN; ++i) {
msgpack_pack_raw(mpk, TASK_STR_PTR, i);
}
}
sec = show_timer();
len = mpkbuf.length;
buf = mpkbuf.buffer;
printf("%lu KB\n", len / 1024);
printf("%f MB/s\n", len / sec / 1024 / 1024);
puts("----");
puts("unpack string");
reset_timer();
{
size_t off = 0;
int ret = msgpack_unpack_execute(mupk, buf, len, &off);
if(ret < 0) {
fprintf(stderr, "Parse error.\n");
} else if(ret == 0) {
fprintf(stderr, "Not finished.\n");
}
}
sec = show_timer();
printf("%f MB/s\n", len / sec / 1024 / 1024);
msgpack_unpack_free(mupk);
msgpack_pack_free(mpk);
pack_buffer_free(&mpkbuf);
}
int main(int argc, char* argv[])
{
char* str = malloc(TASK_STR_LEN);
memset(str, 'a', TASK_STR_LEN);
TASK_STR_PTR = str;
bench_msgpack();
bench_json();
return 0;
}

329
c/bench_inline.c Normal file
View File

@ -0,0 +1,329 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <msgpack/pack.h>
#include <msgpack/unpack.h>
#include <yajl/yajl_parse.h>
#include <yajl/yajl_gen.h>
static struct timeval g_timer;
void reset_timer()
{
gettimeofday(&g_timer, NULL);
}
double show_timer()
{
struct timeval endtime;
gettimeofday(&endtime, NULL);
double sec = (endtime.tv_sec - g_timer.tv_sec)
+ (double)(endtime.tv_usec - g_timer.tv_usec) / 1000 / 1000;
printf("%f sec\n", sec);
return sec;
}
static int reformat_null(void * ctx) { return 1; }
static int reformat_boolean(void * ctx, int boolean) { return 1; }
static int reformat_number(void * ctx, const char * s, unsigned int l) { return 1; }
static int reformat_string(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { return 1; }
static int reformat_map_key(void * ctx, const unsigned char * stringVal, unsigned int stringLen) { return 1; }
static int reformat_start_map(void * ctx) { return 1; }
static int reformat_end_map(void * ctx) { return 1; }
static int reformat_start_array(void * ctx) { return 1; }
static int reformat_end_array(void * ctx) { return 1; }
typedef void* msgpack_object;
typedef struct {
} msgpack_unpack_context;
#include "msgpack/unpack/inline_context.h"
static inline void* msgpack_unpack_init(msgpack_unpack_context* x) { return NULL; }
static inline void* msgpack_unpack_unsigned_int_8(msgpack_unpack_context* x, uint8_t d) { return NULL; }
static inline void* msgpack_unpack_unsigned_int_16(msgpack_unpack_context* x, uint16_t d) { return NULL; }
static inline void* msgpack_unpack_unsigned_int_32(msgpack_unpack_context* x, uint32_t d) { return NULL; }
static inline void* msgpack_unpack_unsigned_int_64(msgpack_unpack_context* x, uint64_t d) { return NULL; }
static inline void* msgpack_unpack_signed_int_8(msgpack_unpack_context* x, int8_t d) { return NULL; }
static inline void* msgpack_unpack_signed_int_16(msgpack_unpack_context* x, int16_t d) { return NULL; }
static inline void* msgpack_unpack_signed_int_32(msgpack_unpack_context* x, int32_t d) { return NULL; }
static inline void* msgpack_unpack_signed_int_64(msgpack_unpack_context* x, int64_t d) { return NULL; }
static inline void* msgpack_unpack_float(msgpack_unpack_context* x, float d) { return NULL; }
static inline void* msgpack_unpack_double(msgpack_unpack_context* x, double d) { return NULL; }
static inline void* msgpack_unpack_big_int(msgpack_unpack_context* x, const void* b, unsigned int l) { return NULL; }
static inline void* msgpack_unpack_big_float(msgpack_unpack_context* x, const void* b, unsigned int l) { return NULL; }
static inline void* msgpack_unpack_nil(msgpack_unpack_context* x) { return NULL; }
static inline void* msgpack_unpack_true(msgpack_unpack_context* x) { return NULL; }
static inline void* msgpack_unpack_false(msgpack_unpack_context* x) { return NULL; }
static inline void* msgpack_unpack_array_start(msgpack_unpack_context* x, unsigned int n) { return NULL; }
static inline void msgpack_unpack_array_item(msgpack_unpack_context* x, void* c, void* o) { }
static inline void* msgpack_unpack_map_start(msgpack_unpack_context* x, unsigned int n) { return NULL; }
static inline void msgpack_unpack_map_item(msgpack_unpack_context* x, void* c, void* k, void* v) { }
static inline void* msgpack_unpack_string(msgpack_unpack_context* x, const void* b, size_t l) { return NULL; }
static inline void* msgpack_unpack_raw(msgpack_unpack_context* x, const void* b, size_t l) { return NULL; }
#include "msgpack/unpack/inline_impl.h"
typedef struct {
size_t allocated;
size_t length;
char* buffer;
} pack_buffer;
static const size_t PACK_INITIAL_BUFFER_SIZE = 512;
static void pack_buffer_init(pack_buffer* data)
{
data->buffer = malloc(PACK_INITIAL_BUFFER_SIZE);
data->length = 0;
data->allocated = PACK_INITIAL_BUFFER_SIZE;
}
static void pack_buffer_reset(pack_buffer* data)
{
data->buffer = realloc(data->buffer, PACK_INITIAL_BUFFER_SIZE);
data->allocated = PACK_INITIAL_BUFFER_SIZE;
data->length = 0;
}
static void pack_buffer_free(pack_buffer* data)
{
free(data->buffer);
}
static void pack_append_buffer(void* user, const unsigned char* b, unsigned int l)
{
pack_buffer* data = (pack_buffer*)user;
if(data->allocated - data->length < l) {
data->buffer = realloc(data->buffer, data->allocated*2);
data->allocated *= 2;
}
memcpy(data->buffer + data->length, b, l);
data->length += l;
}
static const unsigned int TASK_INT_NUM = 1<<24;
static const unsigned int TASK_STR_LEN = 1<<15;
//static const unsigned int TASK_INT_NUM = 1<<20;
//static const unsigned int TASK_STR_LEN = 1<<12;
static const char* TASK_STR_PTR;
void bench_json(void)
{
puts("== JSON ==");
yajl_gen_config gcfg = {0, NULL};
yajl_gen g = yajl_gen_alloc(&gcfg);
yajl_parser_config hcfg = { 0, 0 };
yajl_callbacks callbacks = {
reformat_null,
reformat_boolean,
NULL,
NULL,
reformat_number,
reformat_string,
reformat_start_map,
reformat_map_key,
reformat_end_map,
reformat_start_array,
reformat_end_array
};
yajl_handle h = yajl_alloc(&callbacks, &hcfg, NULL);
double sec;
const unsigned char * buf;
unsigned int len;
puts("generate integer");
reset_timer();
{
unsigned int i;
yajl_gen_array_open(g);
for(i=0; i < TASK_INT_NUM; ++i) {
yajl_gen_integer(g, i);
}
yajl_gen_array_close(g);
}
sec = show_timer();
yajl_gen_get_buf(g, &buf, &len);
printf("%u KB\n", len / 1024);
printf("%f Mbps\n", len / sec / 1024 / 1024);
puts("----");
puts("parse integer");
reset_timer();
{
yajl_status stat = yajl_parse(h, buf, len);
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
unsigned char * str = yajl_get_error(h, 1, buf, len);
fprintf(stderr, (const char *) str);
}
}
sec = show_timer();
printf("%f Mbps\n", len / sec / 1024 / 1024);
//yajl_gen_clear(g);
yajl_gen_free(g);
g = yajl_gen_alloc(&gcfg);
yajl_free(h);
h = yajl_alloc(&callbacks, &hcfg, NULL);
puts("----");
puts("generate string");
reset_timer();
{
unsigned int i;
yajl_gen_array_open(g);
for(i=0; i < TASK_STR_LEN; ++i) {
yajl_gen_string(g, (const unsigned char*)TASK_STR_PTR, i);
}
yajl_gen_array_close(g);
}
sec = show_timer();
yajl_gen_get_buf(g, &buf, &len);
printf("%u KB\n", len / 1024);
printf("%f Mbps\n", len / sec / 1024 / 1024);
puts("----");
puts("parse string");
reset_timer();
{
yajl_status stat = yajl_parse(h, buf, len);
if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
unsigned char * str = yajl_get_error(h, 1, buf, len);
fprintf(stderr, (const char *) str);
}
}
sec = show_timer();
printf("%f Mbps\n", len / sec / 1024 / 1024);
yajl_gen_free(g);
yajl_free(h);
}
void bench_msgpack(void)
{
puts("== MessagePack ==");
pack_buffer mpkbuf;
pack_buffer_init(&mpkbuf);
msgpack_pack_t* mpk = msgpack_pack_new(
&mpkbuf, pack_append_buffer);
msgpack_unpacker mupk;
msgpack_unpacker_init(&mupk);
double sec;
size_t len;
const char* buf;
puts("pack integer");
reset_timer();
{
unsigned int i;
msgpack_pack_array(mpk, TASK_INT_NUM);
for(i=0; i < TASK_INT_NUM; ++i) {
msgpack_pack_unsigned_int(mpk, i);
}
}
sec = show_timer();
len = mpkbuf.length;
buf = mpkbuf.buffer;
printf("%lu KB\n", len / 1024);
printf("%f Mbps\n", len / sec / 1024 / 1024);
puts("----");
puts("unpack integer");
reset_timer();
{
size_t off = 0;
int ret = msgpack_unpacker_execute(&mupk, buf, len, &off);
if(ret < 0) {
fprintf(stderr, "Parse error.\n");
} else if(ret == 0) {
fprintf(stderr, "Not finished.\n");
}
}
sec = show_timer();
printf("%f Mbps\n", len / sec / 1024 / 1024);
pack_buffer_reset(&mpkbuf);
msgpack_unpacker_init(&mupk);
puts("----");
puts("pack string");
reset_timer();
{
unsigned int i;
msgpack_pack_array(mpk, TASK_STR_LEN);
for(i=0; i < TASK_STR_LEN; ++i) {
msgpack_pack_raw(mpk, TASK_STR_PTR, i);
}
}
sec = show_timer();
len = mpkbuf.length;
buf = mpkbuf.buffer;
printf("%lu KB\n", len / 1024);
printf("%f Mbps\n", len / sec / 1024 / 1024);
puts("----");
puts("unpack string");
reset_timer();
{
size_t off = 0;
int ret = msgpack_unpacker_execute(&mupk, buf, len, &off);
if(ret < 0) {
fprintf(stderr, "Parse error.\n");
} else if(ret == 0) {
fprintf(stderr, "Not finished.\n");
}
}
sec = show_timer();
printf("%f Mbps\n", len / sec / 1024 / 1024);
msgpack_pack_free(mpk);
pack_buffer_free(&mpkbuf);
}
int main(int argc, char* argv[])
{
char* str = malloc(TASK_STR_LEN);
memset(str, 'a', TASK_STR_LEN);
TASK_STR_PTR = str;
bench_msgpack();
//bench_json();
return 0;
}

1
c/msgpack Symbolic link
View File

@ -0,0 +1 @@
.

40
c/pack.c Normal file
View File

@ -0,0 +1,40 @@
/*
* MessagePack packing routine for C
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pack_inline.h"
#include <stdlib.h>
#include <stdio.h>
msgpack_pack_t* msgpack_pack_new(void* data, msgpack_pack_callback_t callback)
{
msgpack_pack_t* ctx = calloc(1, sizeof(msgpack_pack_t));
if(!ctx) { return NULL; }
ctx->data = data;
ctx->callback = callback;
return ctx;
}
void msgpack_pack_free(msgpack_pack_t* ctx)
{
free(ctx);
}
static inline void msgpack_pack_append_buffer(msgpack_pack_t* ctx, const unsigned char* b, unsigned int l)
{
ctx->callback(ctx->data, b, l);
}

38
c/pack.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef MSGPACK_PACK_H__
#define MSGPACK_PACK_H__
#include <stddef.h>
#include <stdint.h>
typedef void (*msgpack_pack_callback_t)(void* data, const unsigned char* b, unsigned int i);
typedef struct {
void* data;
msgpack_pack_callback_t callback;
} msgpack_pack_t;
msgpack_pack_t* msgpack_pack_new(void* data, msgpack_pack_callback_t callback);
void msgpack_pack_free(msgpack_pack_t* ctx);
void msgpack_pack_int(msgpack_pack_t* ctx, int d);
void msgpack_pack_unsigned_int(msgpack_pack_t* ctx, unsigned int d);
void msgpack_pack_unsigned_int_8(msgpack_pack_t* ctx, uint8_t d);
void msgpack_pack_unsigned_int_16(msgpack_pack_t* ctx, uint16_t d);
void msgpack_pack_unsigned_int_32(msgpack_pack_t* ctx, uint32_t d);
void msgpack_pack_unsigned_int_64(msgpack_pack_t* ctx, uint64_t d);
void msgpack_pack_signed_int_8(msgpack_pack_t* ctx, int8_t d);
void msgpack_pack_signed_int_16(msgpack_pack_t* ctx, int16_t d);
void msgpack_pack_signed_int_32(msgpack_pack_t* ctx, int32_t d);
void msgpack_pack_signed_int_64(msgpack_pack_t* ctx, int64_t d);
void msgpack_pack_float(msgpack_pack_t* ctx, float d);
void msgpack_pack_double(msgpack_pack_t* ctx, double d);
void msgpack_pack_nil(msgpack_pack_t* ctx);
void msgpack_pack_true(msgpack_pack_t* ctx);
void msgpack_pack_false(msgpack_pack_t* ctx);
void msgpack_pack_array(msgpack_pack_t* ctx, unsigned int n);
void msgpack_pack_map(msgpack_pack_t* ctx, unsigned int n);
void msgpack_pack_string(msgpack_pack_t* ctx, const char* b);
void msgpack_pack_raw(msgpack_pack_t* ctx, const void* b, size_t l);
#endif /* msgpack/pack.h */

14
c/pack_inline.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef PACK_INLINE_H__
#define PACK_INLINE_H__
#include "pack.h"
typedef msgpack_pack_t* msgpack_pack_context;
static inline void msgpack_pack_append_buffer(msgpack_pack_t* x, const unsigned char* b, unsigned int l);
#include "msgpack/pack/inline_impl.h"
#endif /* pack_inline.h */

56
c/unpack.c Normal file
View File

@ -0,0 +1,56 @@
/*
* MessagePack packing routine for C
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "unpack.h"
#include "unpack_context.h"
#include <stdlib.h>
msgpack_unpack_t* msgpack_unpack_new(void* data, msgpack_unpack_callback* callback)
{
msgpack_unpacker* ctx;
ctx = (msgpack_unpacker*)calloc(1, sizeof(msgpack_unpacker));
if(ctx == NULL) { return NULL; }
msgpack_unpacker_init(ctx);
((msgpack_unpack_t*)ctx)->data = data;
((msgpack_unpack_t*)ctx)->callback = *callback;
return (msgpack_unpack_t*)ctx;
}
void msgpack_unpack_free(msgpack_unpack_t* ctx)
{
free((msgpack_unpacker*)ctx);
}
void* msgpack_unpack_data(msgpack_unpack_t* ctx)
{
return msgpack_unpacker_data((msgpack_unpacker*)ctx);
}
void msgpack_unpack_reset(msgpack_unpack_t* ctx)
{
msgpack_unpack_t x = ((msgpack_unpacker*)ctx)->user;
msgpack_unpacker_init((msgpack_unpacker*)ctx);
((msgpack_unpacker*)ctx)->user = x;
}
int msgpack_unpack_execute(msgpack_unpack_t* ctx, const char* data, size_t len, size_t* off)
{
return msgpack_unpacker_execute(
(msgpack_unpacker*)ctx,
data, len, off);
}

59
c/unpack.h Normal file
View File

@ -0,0 +1,59 @@
/*
* MessagePack unpacking routine for C
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSGPACK_UNPACK_H__
#define MSGPACK_UNPACK_H__
#include <stdint.h>
#include <stddef.h>
typedef struct {
void* (*unpack_unsigned_int_8)(void* data, uint8_t d);
void* (*unpack_unsigned_int_16)(void* data, uint16_t d);
void* (*unpack_unsigned_int_32)(void* data, uint32_t d);
void* (*unpack_unsigned_int_64)(void* data, uint64_t d);
void* (*unpack_signed_int_8)(void* data, int8_t d);
void* (*unpack_signed_int_16)(void* data, int16_t d);
void* (*unpack_signed_int_32)(void* data, int32_t d);
void* (*unpack_signed_int_64)(void* data, int64_t d);
void* (*unpack_float)(void* data, float d);
void* (*unpack_double)(void* data, double d);
void* (*unpack_nil)(void* data);
void* (*unpack_true)(void* data);
void* (*unpack_false)(void* data);
void* (*unpack_array_start)(void* data, unsigned int n);
void (*unpack_array_item)(void* data, void* c, void* o);
void* (*unpack_map_start)(void* data, unsigned int n);
void (*unpack_map_item)(void* data, void* c, void* k, void* v);
void* (*unpack_string)(void* data, const void* b, size_t l);
void* (*unpack_raw)(void* data, const void* b, size_t l);
} msgpack_unpack_callback;
typedef struct {
void* data;
msgpack_unpack_callback callback;
} msgpack_unpack_t;
msgpack_unpack_t* msgpack_unpack_new(void* data, msgpack_unpack_callback* callback);
void msgpack_unpack_free(msgpack_unpack_t* ctx);
void msgpack_unpack_reset(msgpack_unpack_t* ctx);
int msgpack_unpack_execute(msgpack_unpack_t* ctx, const char* data, size_t len, size_t* off);
void* msgpack_unpack_data(msgpack_unpack_t* ctx);
#endif /* msgpack/unpack.h */

30
c/unpack_context.h Normal file
View File

@ -0,0 +1,30 @@
/*
* MessagePack unpacking routine for C
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef UNPACK_CONTEXT_H__
#define UNPACK_CONTEXT_H__
#include "unpack.h"
typedef void* msgpack_object;
typedef msgpack_unpack_t msgpack_unpack_context;
#include "msgpack/unpack/inline_context.h"
#endif /* unpack_context.h */

82
c/unpack_inline.c Normal file
View File

@ -0,0 +1,82 @@
/*
* MessagePack unpacking routine for C
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "unpack_context.h"
static inline void* msgpack_unpack_init(msgpack_unpack_t* x)
{ return NULL; }
static inline void* msgpack_unpack_unsigned_int_8(msgpack_unpack_t* x, uint8_t d)
{ return x->callback.unpack_unsigned_int_8(x->data, d); }
static inline void* msgpack_unpack_unsigned_int_16(msgpack_unpack_t* x, uint16_t d)
{ return x->callback.unpack_unsigned_int_16(x->data, d); }
static inline void* msgpack_unpack_unsigned_int_32(msgpack_unpack_t* x, uint32_t d)
{ return x->callback.unpack_unsigned_int_32(x->data, d); }
static inline void* msgpack_unpack_unsigned_int_64(msgpack_unpack_t* x, uint64_t d)
{ return x->callback.unpack_unsigned_int_64(x->data, d); }
static inline void* msgpack_unpack_signed_int_8(msgpack_unpack_t* x, int8_t d)
{ return x->callback.unpack_signed_int_8(x->data, d); }
static inline void* msgpack_unpack_signed_int_16(msgpack_unpack_t* x, int16_t d)
{ return x->callback.unpack_signed_int_16(x->data, d); }
static inline void* msgpack_unpack_signed_int_32(msgpack_unpack_t* x, int32_t d)
{ return x->callback.unpack_signed_int_32(x->data, d); }
static inline void* msgpack_unpack_signed_int_64(msgpack_unpack_t* x, int64_t d)
{ return x->callback.unpack_signed_int_64(x->data, d); }
static inline void* msgpack_unpack_float(msgpack_unpack_t* x, float d)
{ return x->callback.unpack_float(x->data, d); }
static inline void* msgpack_unpack_double(msgpack_unpack_t* x, double d)
{ return x->callback.unpack_double(x->data, d); }
static inline void* msgpack_unpack_nil(msgpack_unpack_t* x)
{ return x->callback.unpack_nil(x->data); }
static inline void* msgpack_unpack_true(msgpack_unpack_t* x)
{ return x->callback.unpack_true(x->data); }
static inline void* msgpack_unpack_false(msgpack_unpack_t* x)
{ return x->callback.unpack_false(x->data); }
static inline void* msgpack_unpack_array_start(msgpack_unpack_t* x, unsigned int n)
{ return x->callback.unpack_array_start(x->data, n); }
static inline void msgpack_unpack_array_item(msgpack_unpack_t* x, void* c, void* o)
{ x->callback.unpack_array_item(x->data, c, o); }
static inline void* msgpack_unpack_map_start(msgpack_unpack_t* x, unsigned int n)
{ return x->callback.unpack_map_start(x->data, n); }
static inline void msgpack_unpack_map_item(msgpack_unpack_t* x, void* c, void* k, void* v)
{ x->callback.unpack_map_item(x->data, c, k, v); }
static inline void* msgpack_unpack_string(msgpack_unpack_t* x, const void* b, size_t l)
{ return x->callback.unpack_string(x->data, b, l); }
static inline void* msgpack_unpack_raw(msgpack_unpack_t* x, const void* b, size_t l)
{ return x->callback.unpack_raw(x->data, b, l); }
#include "msgpack/unpack/inline_impl.h"

30
cpp/unpack.cc Normal file
View File

@ -0,0 +1,30 @@
#include "unpack.h"
#include "unpack_context.h"
#include <stdlib.h>
msgpack_unpack_t* msgpack_unpack_new(void)
{
msgpack_unpacker* ctx;
ctx = (msgpack_unpacker*)calloc(1, sizeof(msgpack_unpacker));
if(ctx == NULL) { return NULL; }
msgpack_unpacker_init(ctx);
return (msgpack_unpack_t*)ctx;
}
void msgpack_unpack_free(msgpack_unpack_t* ctx)
{
free((msgpack_unpacker*)ctx);
}
int msgpack_unpack_execute(msgpack_unpack_t* ctx, const char* data, size_t len, size_t* off)
{
return msgpack_unpacker_execute(
(msgpack_unpacker*)ctx,
data, len, off);
}
void* msgpack_unpack_data(msgpack_unpack_t* ctx)
{
return msgpack_unpacker_data((msgpack_unpacker*)ctx);
}

126
cpp/unpack.h Normal file
View File

@ -0,0 +1,126 @@
#ifndef MSGPACK_UNPACK_H__
#define MSGPACK_UNPACK_H__
#include <stdint.h>
#include <stddef.h>
namespace MessagePack {
class Unpacker {
class object {
template <typename T>
object(const T& x) : m_obj(new holder<T>(x)) {}
};
class type_error : public std::exception { };
class cast_error : public type_error { };
class overflow_error : public type_error { };
class underflow_error : public type_error { };
struct object {
virtual ~object() {}
virtual bool isnil() const { return false; }
virtual bool xbool() const { throw cast_error(); }
virtual uint8_t xu8() const { throw cast_error(); }
virtual uint16_t xu16() const { throw cast_error(); }
virtual uint32_t xu32() const { throw cast_error(); }
virtual uint64_t xu64() const { throw cast_error(); }
virtual int8_t xi8() const { throw cast_error(); }
virtual int16_t xi16() const { throw cast_error(); }
virtual int32_t xi32() const { throw cast_error(); }
virtual int64_t xi64() const { throw cast_error(); }
virtual float xfloat() const { throw cast_error(); }
virtual double xdouble() const { throw cast_error(); }
virtual std::map<object, object>& xmap() const { throw cast_error(); }
virtual std::string& xstring() const { throw cast_error(); }
virtual std::pair<const char*, size_t> xraw() const { throw cast_error(); }
public:
template <typename T, typename X>
inline void check_overflow(X x) {
if(std::numeric_limits<T>::max() < x) { throw overflow_error(); }
}
template <typename T, typename X>
inline void check_underflow(X x) {
if(std::numeric_limits<T>::min() > x) { throw overflow_error(); }
}
};
private:
struct object_nil : object {
bool isnil() const { return true; }
};
struct object_true : object {
bool xbool() const { return true; }
};
struct object_false : object {
bool xbool() const { return false; }
};
struct object_u8 : object {
object_u8(uint8_t val) : m_val(val) {}
uint8_t xu8() const { return m_val; }
uint16_t xu16() const { return static_cast<uint16_t>(m_val); }
uint32_t xu32() const { return static_cast<uint32_t>(m_val); }
uint64_t xu64() const { return static_cast<uint64_t>(m_val); }
int8_t xi8() const { check_overflow<int8_t>(m_val); return m_val; }
int16_t xi16() const { return static_cast<int16_t>(m_val); }
int32_t xi32() const { return static_cast<int32_t>(m_val); }
int64_t xi64() const { return static_cast<int64_t>(m_val); }
private:
uint8_t m_val;
};
struct object_u16 : object {
object_u16(uint16_t val) : m_val(val) {}
uint8_t xu8() const { check_overflow<uint8_t>(m_val); return m_val; }
uint16_t xu16() const { return m_val; }
uint32_t xu32() const { return static_cast<uint32_t>(m_val); }
uint64_t xu64() const { return static_cast<uint64_t>(m_val); }
int8_t xi8() const { check_overflow< int8_t>(m_val); return m_val; }
int16_t xi16() const { check_overflow<int16_t>(m_val); return m_val; }
int32_t xi32() const { return static_cast<int32_t>(m_val); }
int64_t xi64() const { return static_cast<int64_t>(m_val); }
private:
uint16_t m_val;
};
...
};
} // namespace MessagePack
typedef struct {
void* (*unpack_unsigned_int_8)(void* data, uint8_t d);
void* (*unpack_unsigned_int_16)(void* data, uint16_t d);
void* (*unpack_unsigned_int_32)(void* data, uint32_t d);
void* (*unpack_unsigned_int_64)(void* data, uint64_t d);
void* (*unpack_signed_int_8)(void* data, int8_t d);
void* (*unpack_signed_int_16)(void* data, int16_t d);
void* (*unpack_signed_int_32)(void* data, int32_t d);
void* (*unpack_signed_int_64)(void* data, int64_t d);
void* (*unpack_float)(void* data, float d);
void* (*unpack_double)(void* data, double d);
void* (*unpack_big_int)(void* data, const void* b, unsigned int l);
void* (*unpack_big_float)(void* data, const void* b, unsigned int l);
void* (*unpack_nil)(void* data);
void* (*unpack_true)(void* data);
void* (*unpack_false)(void* data);
void* (*unpack_array_start)(void* data, unsigned int n);
void (*unpack_array_item)(void* data, void* c, void* o);
void* (*unpack_map_start)(void* data, unsigned int n);
void (*unpack_map_item)(void* data, void* c, void* k, void* v);
void* (*unpack_string)(void* data, const void* b, size_t l);
void* (*unpack_raw)(void* data, const void* b, size_t l);
void* data;
} msgpack_unpack_t;
msgpack_unpack_t* msgpack_unpack_new(void);
void msgpack_unpack_free(msgpack_unpack_t* ctx);
int msgpack_unpack_execute(msgpack_unpack_t* ctx, const char* data, size_t len, size_t* off);
void* msgpack_unpack_data(msgpack_unpack_t* ctx);
#endif /* msgpack/unpack.h */

13
cpp/unpack_context.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef UNPACK_CONTEXT_H__
#define UNPACK_CONTEXT_H__
#include "unpack.h"
typedef void* msgpack_object;
typedef msgpack_unpack_t msgpack_unpack_context;
#include "msgpack/unpack/inline_context.h"
#endif /* unpack_context.h */

View File

@ -0,0 +1,2 @@

287
msgpack/pack/inline_impl.h Normal file
View File

@ -0,0 +1,287 @@
/*
* MessagePack packing routine
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSGPACK_PACK_INLINE_IMPL_H__
#define MSGPACK_PACK_INLINE_IMPL_H__
#include <string.h>
#include <arpa/inet.h>
#ifdef __LITTLE_ENDIAN__
#define STORE_16(d) \
((char*)&d)[1], ((char*)&d)[0]
#define STORE_32(d) \
((char*)&d)[3], ((char*)&d)[2], ((char*)&d)[1], ((char*)&d)[0]
#define STORE_64(d) \
((char*)&d)[7], ((char*)&d)[6], ((char*)&d)[5], ((char*)&d)[4], \
((char*)&d)[3], ((char*)&d)[2], ((char*)&d)[1], ((char*)&d)[0]
#elif __BIG_ENDIAN__
#define STORE_16(d) \
((char*)&d)[2], ((char*)&d)[3]
#define STORE_32(d) \
((char*)&d)[0], ((char*)&d)[1], ((char*)&d)[2], ((char*)&d)[3]
#define STORE_32(d) \
((char*)&d)[0], ((char*)&d)[1], ((char*)&d)[2], ((char*)&d)[3], \
((char*)&d)[4], ((char*)&d)[5], ((char*)&d)[6], ((char*)&d)[7]
#endif
/*
* Integer
*/
// wrapper
inline void msgpack_pack_int(msgpack_pack_context x, int d)
{
if(d < -32) {
if(d < -32768) { // signed 32
const unsigned char buf[5] = {0xd2, STORE_32(d)};
msgpack_pack_append_buffer(x, buf, 5);
} else if(d < -128) { // signed 16
const unsigned char buf[3] = {0xd1, STORE_16(d)};
msgpack_pack_append_buffer(x, buf, 3);
} else { // signed 8
const unsigned char buf[2] = {0xd0, (uint8_t)d};
msgpack_pack_append_buffer(x, buf, 2);
}
} else if(d < 128) { // fixnum
msgpack_pack_append_buffer(x, (uint8_t*)&d, 1);
} else {
if(d < 256) {
// unsigned 8
const unsigned char buf[2] = {0xcc, (uint8_t)d};
msgpack_pack_append_buffer(x, buf, 2);
} else if(d < 65536) {
// unsigned 16
const unsigned char buf[3] = {0xcd, STORE_16(d)};
msgpack_pack_append_buffer(x, buf, 3);
} else {
// unsigned 32
const unsigned char buf[5] = {0xce, STORE_32(d)};
msgpack_pack_append_buffer(x, buf, 5);
}
}
}
// wrapper
inline void msgpack_pack_unsigned_int(msgpack_pack_context x, unsigned int d)
{
if(d < 128) {
// fixnum
msgpack_pack_append_buffer(x, (uint8_t*)&d, 1);
} else if(d < 256) {
// unsigned 8
const unsigned char buf[2] = {0xcc, (uint8_t)d};
msgpack_pack_append_buffer(x, buf, 2);
} else if(d < 65536) {
// unsigned 16
const unsigned char buf[3] = {0xcd, STORE_16(d)};
msgpack_pack_append_buffer(x, buf, 3);
} else {
// unsigned 32
const unsigned char buf[5] = {0xce, STORE_32(d)};
msgpack_pack_append_buffer(x, buf, 5);
}
}
inline void msgpack_pack_unsigned_int_8(msgpack_pack_context x, uint8_t d)
{
if(d < 128) {
msgpack_pack_append_buffer(x, &d, 1);
} else {
const unsigned char buf[2] = {0xcc, d};
msgpack_pack_append_buffer(x, buf, 2);
}
}
inline void msgpack_pack_unsigned_int_16(msgpack_pack_context x, uint16_t d)
{
const unsigned char buf[3] = {0xcd, STORE_16(d)};
msgpack_pack_append_buffer(x, buf, 3);
}
inline void msgpack_pack_unsigned_int_32(msgpack_pack_context x, uint32_t d)
{
const unsigned char buf[5] = {0xce, STORE_32(d)};
msgpack_pack_append_buffer(x, buf, 5);
}
inline void msgpack_pack_unsigned_int_64(msgpack_pack_context x, uint64_t d)
{
// FIXME
const unsigned char buf[9] = {0xcf, STORE_64(d)};
msgpack_pack_append_buffer(x, buf, 9);
}
inline void msgpack_pack_signed_int_8(msgpack_pack_context x, int8_t d)
{
if(d > 0) {
msgpack_pack_append_buffer(x, (uint8_t*)&d, 1);
} else if(d >= -32) {
msgpack_pack_append_buffer(x, (uint8_t*)&d, 1);
} else {
const unsigned char buf[2] = {0xd0, d};
msgpack_pack_append_buffer(x, buf, 2);
}
}
inline void msgpack_pack_signed_int_16(msgpack_pack_context x, int16_t d)
{
const unsigned char buf[3] = {0xd1, STORE_16(d)};
msgpack_pack_append_buffer(x, buf, 3);
}
inline void msgpack_pack_signed_int_32(msgpack_pack_context x, int32_t d)
{
const unsigned char buf[5] = {0xd2, STORE_32(d)};
msgpack_pack_append_buffer(x, buf, 5);
}
inline void msgpack_pack_signed_int_64(msgpack_pack_context x, int64_t d)
{
// FIXME
const unsigned char buf[9] = {0xd3, STORE_64(d)};
msgpack_pack_append_buffer(x, buf, 9);
}
/*
* Float
*/
inline void msgpack_pack_float(msgpack_pack_context x, float d)
{
uint32_t n = *((uint32_t*)&d); // FIXME
const unsigned char buf[5] = {0xca, STORE_32(n)};
msgpack_pack_append_buffer(x, buf, 5);
}
inline void msgpack_pack_double(msgpack_pack_context x, double d)
{
uint64_t n = *((uint64_t*)&d); // FIXME
const unsigned char buf[9] = {0xcb, STORE_64(n)};
msgpack_pack_append_buffer(x, buf, 9);
}
/*
* Nil
*/
inline void msgpack_pack_nil(msgpack_pack_context x)
{
static const unsigned char d = 0xc0;
msgpack_pack_append_buffer(x, &d, 1);
}
/*
* Boolean
*/
inline void msgpack_pack_true(msgpack_pack_context x)
{
static const unsigned char d = 0xc3;
msgpack_pack_append_buffer(x, &d, 1);
}
inline void msgpack_pack_false(msgpack_pack_context x)
{
static const unsigned char d = 0xc2;
msgpack_pack_append_buffer(x, &d, 1);
}
/*
* Array
*/
inline void msgpack_pack_array(msgpack_pack_context x, unsigned int n)
{
if(n < 16) {
unsigned char d = 0x90 | n;
msgpack_pack_append_buffer(x, &d, 1);
} else if(n < 65536) {
uint16_t d = (uint16_t)n;
unsigned char buf[3] = {0xdc, STORE_16(d)};
msgpack_pack_append_buffer(x, buf, 3);
} else {
uint32_t d = (uint32_t)n;
unsigned char buf[5] = {0xdd, STORE_32(d)};
msgpack_pack_append_buffer(x, buf, 5);
}
}
/*
* Map
*/
inline void msgpack_pack_map(msgpack_pack_context x, unsigned int n)
{
if(n < 16) {
unsigned char d = 0x80 | n;
msgpack_pack_append_buffer(x, &d, 1);
} else if(n < 65536) {
uint16_t d = (uint16_t)n;
unsigned char buf[3] = {0xde, STORE_16(d)};
msgpack_pack_append_buffer(x, buf, 3);
} else {
uint32_t d = (uint32_t)n;
unsigned char buf[5] = {0xdf, STORE_32(d)};
msgpack_pack_append_buffer(x, buf, 5);
}
}
/*
* String
*/
inline void msgpack_pack_string(msgpack_pack_context x, const char* b)
{
uint32_t l = strlen(b);
msgpack_pack_append_buffer(x, (const unsigned char*)b, l+1);
}
inline void msgpack_pack_raw(msgpack_pack_context x, const void* b, size_t l)
{
if(l < 32) {
unsigned char d = 0xa0 | l;
msgpack_pack_append_buffer(x, &d, 1);
} else if(l < 65536) {
uint16_t d = (uint16_t)l;
unsigned char buf[3] = {0xda, STORE_16(d)};
msgpack_pack_append_buffer(x, buf, 3);
} else {
uint32_t d = (uint32_t)l;
unsigned char buf[5] = {0xdb, STORE_32(d)};
msgpack_pack_append_buffer(x, buf, 5);
}
msgpack_pack_append_buffer(x, b, l);
}
#endif /* msgpack/pack/inline_impl.h */

24
msgpack/unpack/callback.h Normal file
View File

@ -0,0 +1,24 @@
msgpack_object msgpack_unpack_init(msgpack_unpack_context* x);
msgpack_object msgpack_unpack_unsigned_int_8(msgpack_unpack_context* x, uint8_t d);
msgpack_object msgpack_unpack_unsigned_int_16(msgpack_unpack_context* x, uint16_t d);
msgpack_object msgpack_unpack_unsigned_int_32(msgpack_unpack_context* x, uint32_t d);
msgpack_object msgpack_unpack_unsigned_int_64(msgpack_unpack_context* x, uint64_t d);
msgpack_object msgpack_unpack_signed_int_8(msgpack_unpack_context* x, int8_t d);
msgpack_object msgpack_unpack_signed_int_16(msgpack_unpack_context* x, int16_t d);
msgpack_object msgpack_unpack_signed_int_32(msgpack_unpack_context* x, int32_t d);
msgpack_object msgpack_unpack_signed_int_64(msgpack_unpack_context* x, int64_t d);
msgpack_object msgpack_unpack_float(msgpack_unpack_context* x, float d);
msgpack_object msgpack_unpack_double(msgpack_unpack_context* x, double d);
msgpack_object msgpack_unpack_big_int(msgpack_unpack_context* x, const void* b, unsigned int l);
msgpack_object msgpack_unpack_big_float(msgpack_unpack_context* x, const void* b, unsigned int l);
msgpack_object msgpack_unpack_nil(msgpack_unpack_context* x);
msgpack_object msgpack_unpack_true(msgpack_unpack_context* x);
msgpack_object msgpack_unpack_false(msgpack_unpack_context* x);
msgpack_object msgpack_unpack_array_start(msgpack_unpack_context* x, unsigned int n);
void msgpack_unpack_array_item(msgpack_unpack_context* x, msgpack_object c, msgpack_object o);
msgpack_object msgpack_unpack_map_start(msgpack_unpack_context* x, unsigned int n);
void msgpack_unpack_map_item(msgpack_unpack_context* x, msgpack_object c, msgpack_object k, msgpack_object v);
msgpack_object msgpack_unpack_string(msgpack_unpack_context* x, const void* b, size_t l);
msgpack_object msgpack_unpack_raw(msgpack_unpack_context* x, const void* b, size_t l);

View File

@ -0,0 +1,52 @@
/*
* MessagePack unpacking routine
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSGPACK_UNPACK_INLINE_CONTEXT_H__
#define MSGPACK_UNPACK_INLINE_CONTEXT_H__
#include <stddef.h>
#include <stdint.h>
#ifndef MSG_STACK_SIZE
#define MSG_STACK_SIZE 16
#endif
typedef struct {
msgpack_object obj;
size_t count;
unsigned int ct;
union {
const unsigned char* terminal_trail_start;
msgpack_object map_key;
} tmp;
} msgpack_unpacker_stack;
typedef struct {
msgpack_unpack_context user; // must be first
unsigned int cs;
size_t trail;
unsigned int top;
msgpack_unpacker_stack stack[MSG_STACK_SIZE];
} msgpack_unpacker;
void msgpack_unpacker_init(msgpack_unpacker* ctx);
int msgpack_unpacker_execute(msgpack_unpacker* ctx, const char* data, size_t len, size_t* off);
#define msgpack_unpacker_data(unpacker) (unpacker)->stack[0].obj
#endif /* msgpack/unpack/inline_context.h */

View File

@ -0,0 +1,438 @@
/*
* MessagePack unpacking routine
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MSGPACK_UNPACK_INLINE_IMPL_H__
#define MSGPACK_UNPACK_INLINE_IMPL_H__
#include <string.h>
#include <assert.h>
#include <arpa/inet.h>
/*#include <stdio.h>*/
// Positive FixNum 0xxxxxxx 0x00 - 0x7f
// Negative FixNum 111xxxxx 0xe0 - 0xff
// Variable 110xxxxx 0xc0 - 0xdf
// nil 00000 0xc0
// string 00001 0xc1
// false 00010 0xc2
// true 00011 0xc3
// (?) 00100 0xc4
// (?) 00101 0xc5
// (?) 00110 0xc6
// (?) 00111 0xc7
// (?) 01000 0xc8
// (?) 01001 0xc9
// float 01010 0xca
// double 01011 0xcb
// uint 8 01100 0xcc
// uint 16 01101 0xcd
// uint 32 01110 0xce
// uint 64 01111 0xcf
// int 8 10000 0xd0
// int 16 10001 0xd1
// int 32 10010 0xd2
// int 64 10011 0xd3
// (?) 10100 0xd4
// (?) 10101 0xd5
// (big float 16) 10110 0xd6
// (big float 32) 10111 0xd7
// (big integer 16) 11000 0xd8
// (big integer 32) 11001 0xd9
// raw 16 11010 0xda
// raw 32 11011 0xdb
// array 16 11100 0xdc
// array 32 11101 0xdd
// map 16 11110 0xde
// map 32 11111 0xdf
// FixRaw 101xxxxx 0xa0 - 0xbf
// FixArray 1001xxxx 0x90 - 0x9f
// FixMap 1000xxxx 0x80 - 0x8f
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define __LITTLE_ENDIAN__
#elif __BYTE_ORDER == __BIG_ENDIAN
#define __BIG_ENDIAN__
#endif
#endif
static inline uint64_t ntohll(uint64_t x) {
#ifdef __LITTLE_ENDIAN__ // FIXME
#if defined(__bswap_64)
return __bswap_64(x);
#elif defined(__DARWIN_OSSwapInt64)
return __DARWIN_OSSwapInt64(x);
#else
return ((x << 56) & 0xff00000000000000ULL ) |
((x << 40) & 0x00ff000000000000ULL ) |
((x << 24) & 0x0000ff0000000000ULL ) |
((x << 8) & 0x000000ff00000000ULL ) |
((x >> 8) & 0x00000000ff000000ULL ) |
((x >> 24) & 0x0000000000ff0000ULL ) |
((x >> 40) & 0x000000000000ff00ULL ) |
((x >> 56) & 0x00000000000000ffULL ) ;
#endif
#else
return x;
#endif
}
typedef enum {
CS_HEADER = 0x00, // nil
CS_STRING = 0x01,
//CS_ = 0x02, // false
//CS_ = 0x03, // true
//CS_ = 0x04,
//CS_ = 0x05,
//CS_ = 0x06,
//CS_ = 0x07,
//CS_ = 0x08,
//CS_ = 0x09,
CS_FLOAT = 0x0a,
CS_DOUBLE = 0x0b,
CS_UNSIGNED_INT_8 = 0x0c,
CS_UNSIGNED_INT_16 = 0x0d,
CS_UNSIGNED_INT_32 = 0x0e,
CS_UNSIGNED_INT_64 = 0x0f,
CS_SIGNED_INT_8 = 0x10,
CS_SIGNED_INT_16 = 0x11,
CS_SIGNED_INT_32 = 0x12,
CS_SIGNED_INT_64 = 0x13,
//CS_ = 0x14,
//CS_ = 0x15,
//CS_BIG_INT_16 = 0x16,
//CS_BIG_INT_32 = 0x17,
//CS_BIG_FLOAT_16 = 0x18,
//CS_BIG_FLOAT_32 = 0x19,
CS_RAW_16 = 0x1a,
CS_RAW_32 = 0x1b,
CS_ARRAY_16 = 0x1c,
CS_ARRAY_32 = 0x1d,
CS_MAP_16 = 0x1e,
CS_MAP_32 = 0x1f,
//ACS_BIG_INT_VALUE,
//ACS_BIG_FLOAT_VALUE,
ACS_RAW_VALUE,
} current_state_t;
typedef enum {
CT_ARRAY_ITEM,
CT_MAP_KEY,
CT_MAP_VALUE,
} container_type_t;
void msgpack_unpacker_init(msgpack_unpacker* ctx)
{
memset(ctx, 0, sizeof(msgpack_unpacker)); // FIXME init ctx->user?
ctx->cs = CS_HEADER;
ctx->trail = 0;
ctx->top = 0;
ctx->stack[0].obj = msgpack_unpack_init(&ctx->user);
}
int msgpack_unpacker_execute(msgpack_unpacker* ctx, const char* data, size_t len, size_t* off)
{
assert(len >= *off);
const unsigned char* p = (unsigned char*)data + *off;
const unsigned char* const pe = (unsigned char*)data + len;
const void* n = NULL;
size_t trail = ctx->trail;
unsigned int cs = ctx->cs;
unsigned int top = ctx->top;
msgpack_unpacker_stack* stack = ctx->stack;
msgpack_unpack_context* user = &ctx->user;
msgpack_object obj;
int ret;
#define push_simple_value(func) \
obj = func(user); \
/*printf("obj %d\n",obj);*/ \
goto _push
#define push_fixed_value(func, arg) \
obj = func(user, arg); \
/*printf("obj %d\n",obj);*/ \
goto _push
#define push_variable_value(func, arg, arglen) \
obj = func(user, arg, arglen); \
/*printf("obj %d\n",obj);*/ \
goto _push
#define again_terminal_trail(_cs, from) \
cs = _cs; \
stack[top].tmp.terminal_trail_start = from; \
goto _terminal_trail_again
#define again_fixed_trail(_cs, trail_len) \
trail = trail_len; \
cs = _cs; \
goto _fixed_trail_again
#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
trail = trail_len; \
if(trail == 0) { goto ifzero; } \
cs = _cs; \
goto _fixed_trail_again
#define start_container(func, count_, ct_) \
stack[top].obj = func(user, count_); \
if((count_) == 0) { obj = stack[top].obj; goto _push; } \
if(top >= MSG_STACK_SIZE) { goto _failed; } \
stack[top].ct = ct_; \
stack[top].count = count_; \
/*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \
/*printf("stack push %d\n", top);*/ \
++top; \
goto _header_again
#define NEXT_CS(p) \
((unsigned int)*p & 0x1f)
#define PTR_CAST_8(ptr) (*(uint8_t*)ptr)
#define PTR_CAST_16(ptr) ntohs(*(uint16_t*)ptr)
#define PTR_CAST_32(ptr) ntohl(*(uint32_t*)ptr)
#define PTR_CAST_64(ptr) ntohll(*(uint64_t*)ptr)
if(p == pe) { goto _out; }
do {
switch(cs) {
case CS_HEADER:
switch(*p) {
case 0x00 ... 0x7f: // Positive Fixnum
push_fixed_value(msgpack_unpack_unsigned_int_8, *(uint8_t*)p);
case 0xe0 ... 0xff: // Negative Fixnum
push_fixed_value(msgpack_unpack_signed_int_8, *(int8_t*)p);
case 0xc0 ... 0xdf: // Variable
switch(*p) {
case 0xc0: // nil
push_simple_value(msgpack_unpack_nil);
case 0xc1: // string
again_terminal_trail(NEXT_CS(p), p+1);
case 0xc2: // false
push_simple_value(msgpack_unpack_false);
case 0xc3: // true
push_simple_value(msgpack_unpack_true);
//case 0xc4:
//case 0xc5:
//case 0xc6:
//case 0xc7:
//case 0xc8:
//case 0xc9:
case 0xca: // float
case 0xcb: // double
case 0xcc: // unsigned int 8
case 0xcd: // unsigned int 16
case 0xce: // unsigned int 32
case 0xcf: // unsigned int 64
case 0xd0: // signed int 8
case 0xd1: // signed int 16
case 0xd2: // signed int 32
case 0xd3: // signed int 64
again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
//case 0xd4:
//case 0xd5:
//case 0xd6: // big integer 16
//case 0xd7: // big integer 32
//case 0xd8: // big float 16
//case 0xd9: // big float 32
case 0xda: // raw 16
case 0xdb: // raw 32
case 0xdc: // array 16
case 0xdd: // array 32
case 0xde: // map 16
case 0xdf: // map 32
again_fixed_trail(NEXT_CS(p), 2 << (((unsigned int)*p) & 0x01));
default:
goto _failed;
}
case 0xa0 ... 0xbf: // FixRaw
again_fixed_trail_if_zero(ACS_RAW_VALUE, ((unsigned int)*p & 0x1f), _raw_zero);
case 0x90 ... 0x9f: // FixArray
start_container(msgpack_unpack_array_start, ((unsigned int)*p) & 0x0f, CT_ARRAY_ITEM);
case 0x80 ... 0x8f: // FixMap
start_container(msgpack_unpack_map_start, ((unsigned int)*p) & 0x0f, CT_MAP_KEY);
default:
goto _failed;
}
// end CS_HEADER
_terminal_trail_again:
++p;
case CS_STRING:
if(*p == 0) {
const unsigned char* start = stack[top].tmp.terminal_trail_start;
obj = msgpack_unpack_string(user, start, p-start);
goto _push;
}
goto _terminal_trail_again;
_fixed_trail_again:
++p;
default:
if((size_t)(pe - p) < trail) { goto _out; }
n = p; p += trail - 1;
switch(cs) {
//case CS_
//case CS_
case CS_FLOAT: {
uint32_t x = PTR_CAST_32(n); // FIXME
push_fixed_value(msgpack_unpack_float, *((float*)&x)); }
case CS_DOUBLE: {
uint64_t x = PTR_CAST_64(n); // FIXME
push_fixed_value(msgpack_unpack_double, *((double*)&x)); }
case CS_UNSIGNED_INT_8:
push_fixed_value(msgpack_unpack_unsigned_int_8, (uint8_t)PTR_CAST_8(n));
case CS_UNSIGNED_INT_16:
push_fixed_value(msgpack_unpack_unsigned_int_16, (uint16_t)PTR_CAST_16(n));
case CS_UNSIGNED_INT_32:
push_fixed_value(msgpack_unpack_unsigned_int_32, (uint32_t)PTR_CAST_32(n));
case CS_UNSIGNED_INT_64:
push_fixed_value(msgpack_unpack_unsigned_int_64, (uint64_t)PTR_CAST_64(n));
case CS_SIGNED_INT_8:
push_fixed_value(msgpack_unpack_signed_int_8, (int8_t)PTR_CAST_8(n));
case CS_SIGNED_INT_16:
push_fixed_value(msgpack_unpack_signed_int_16, (int16_t)PTR_CAST_16(n));
case CS_SIGNED_INT_32:
push_fixed_value(msgpack_unpack_signed_int_32, (int32_t)PTR_CAST_32(n));
case CS_SIGNED_INT_64:
push_fixed_value(msgpack_unpack_signed_int_64, (int64_t)PTR_CAST_64(n));
//case CS_
//case CS_
//case CS_BIG_INT_16:
// again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, (uint16_t)PTR_CAST_16(n), _big_int_zero);
//case CS_BIG_INT_32:
// again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, (uint32_t)PTR_CAST_32(n), _big_int_zero);
//case ACS_BIG_INT_VALUE:
//_big_int_zero:
// // FIXME
// push_variable_value(msgpack_unpack_big_int, n, trail);
//case CS_BIG_FLOAT_16:
// again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, (uint16_t)PTR_CAST_16(n), _big_float_zero);
//case CS_BIG_FLOAT_32:
// again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, (uint32_t)PTR_CAST_32(n), _big_float_zero);
//case ACS_BIG_FLOAT_VALUE:
//_big_float_zero:
// // FIXME
// push_variable_value(msgpack_unpack_big_float, n, trail);
case CS_RAW_16:
again_fixed_trail_if_zero(ACS_RAW_VALUE, (uint16_t)PTR_CAST_16(n), _raw_zero);
case CS_RAW_32:
again_fixed_trail_if_zero(ACS_RAW_VALUE, (uint32_t)PTR_CAST_32(n), _raw_zero);
case ACS_RAW_VALUE:
_raw_zero:
push_variable_value(msgpack_unpack_raw, n, trail);
case CS_ARRAY_16:
start_container(msgpack_unpack_array_start, (uint16_t)PTR_CAST_16(n), CT_ARRAY_ITEM);
case CS_ARRAY_32:
start_container(msgpack_unpack_array_start, (uint32_t)PTR_CAST_32(n), CT_ARRAY_ITEM);
case CS_MAP_16:
start_container(msgpack_unpack_map_start, (uint16_t)PTR_CAST_16(n), CT_MAP_KEY);
case CS_MAP_32:
start_container(msgpack_unpack_map_start, (uint32_t)PTR_CAST_32(n), CT_MAP_KEY);
default:
goto _failed;
}
}
_push:
if(top == 0) { goto _finish; }
msgpack_unpacker_stack* c = &stack[top-1];
switch(c->ct) {
case CT_ARRAY_ITEM:
msgpack_unpack_array_item(user, c->obj, obj);
if(--c->count == 0) {
obj = c->obj;
--top;
/*printf("stack pop %d\n", top);*/
goto _push;
}
goto _header_again;
case CT_MAP_KEY:
c->tmp.map_key = obj;
c->ct = CT_MAP_VALUE;
goto _header_again;
case CT_MAP_VALUE:
msgpack_unpack_map_item(user, c->obj, c->tmp.map_key, obj);
if(--c->count == 0) {
obj = c->obj;
--top;
/*printf("stack pop %d\n", top);*/
goto _push;
}
c->ct = CT_MAP_KEY;
goto _header_again;
default:
goto _failed;
}
_header_again:
cs = CS_HEADER;
++p;
} while(p != pe);
goto _out;
_finish:
stack[0].obj = obj;
++p;
ret = 1;
/*printf("-- finish --\n"); */
goto _end;
_failed:
/*printf("** FAILED **\n"); */
ret = -1;
goto _end;
_out:
ret = 0;
goto _end;
_end:
ctx->cs = cs;
ctx->trail = trail;
ctx->top = top;
*off = p - (const unsigned char*)data;
return ret;
}
#endif /* msgpack/unpack/inline_impl.h */

153
ruby/Makefile Normal file
View File

@ -0,0 +1,153 @@
SHELL = /bin/sh
#### Start of system configuration section. ####
srcdir = .
topdir = /Users/frsyuki/ports/lib/ruby/1.8/i686-darwin9.1.0
hdrdir = $(topdir)
VPATH = $(srcdir):$(topdir):$(hdrdir)
prefix = $(DESTDIR)/Users/frsyuki/ports
exec_prefix = $(prefix)
sitedir = $(prefix)/lib/ruby/site_ruby
rubylibdir = $(libdir)/ruby/$(ruby_version)
docdir = $(datarootdir)/doc/$(PACKAGE)
dvidir = $(docdir)
datarootdir = $(prefix)/share
archdir = $(rubylibdir)/$(arch)
sbindir = $(exec_prefix)/sbin
psdir = $(docdir)
vendordir = $(prefix)/lib/ruby/vendor_ruby
localedir = $(datarootdir)/locale
htmldir = $(docdir)
datadir = $(datarootdir)
includedir = $(prefix)/include
infodir = $(datarootdir)/info
sysconfdir = $(prefix)/etc
mandir = $(DESTDIR)/Users/frsyuki/ports/share/man
libdir = $(exec_prefix)/lib
sharedstatedir = $(prefix)/com
oldincludedir = $(DESTDIR)/usr/include
pdfdir = $(docdir)
sitearchdir = $(sitelibdir)/$(sitearch)
vendorarchdir = $(vendorlibdir)/$(vendorarch)
bindir = $(exec_prefix)/bin
localstatedir = $(prefix)/var
vendorlibdir = $(vendordir)/$(ruby_version)
sitelibdir = $(sitedir)/$(ruby_version)
libexecdir = $(exec_prefix)/libexec
CC = /usr/bin/gcc-4.0
LIBRUBY = $(LIBRUBY_SO)
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
RUBY_EXTCONF_H =
CFLAGS = -fno-common -O2 -fno-common -pipe -fno-common -I.. -Wall -O9
INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
CPPFLAGS = -I/Users/frsyuki/ports/include
CXXFLAGS = $(CFLAGS)
DLDFLAGS = -L. -L/Users/frsyuki/ports/lib
LDSHARED = cc -dynamic -bundle -undefined suppress -flat_namespace
AR = ar
EXEEXT =
RUBY_INSTALL_NAME = ruby
RUBY_SO_NAME = ruby
arch = i686-darwin9.1.0
sitearch = i686-darwin9.1.0
vendorarch = i686-darwin9.1.0
ruby_version = 1.8
ruby = /Users/frsyuki/ports/bin/ruby
RUBY = $(ruby)
RM = rm -f
MAKEDIRS = mkdir -p
INSTALL = /usr/bin/install
INSTALL_PROG = $(INSTALL) -m 0755
INSTALL_DATA = $(INSTALL) -m 644
COPY = cp
#### End of system configuration section. ####
preload =
libpath = . $(libdir)
LIBPATH = -L"." -L"$(libdir)"
DEFFILE =
CLEANFILES = mkmf.log
DISTCLEANFILES =
extout =
extout_prefix =
target_prefix =
LOCAL_LIBS =
LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc
SRCS = pack.c rbinit.c unpack.c unpack_inline.c
OBJS = pack.o rbinit.o unpack.o unpack_inline.o
TARGET = msgpack
DLLIB = $(TARGET).bundle
EXTSTATIC =
STATIC_LIB =
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
TARGET_SO = $(DLLIB)
CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
all: $(DLLIB)
static: $(STATIC_LIB)
clean:
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
distclean: clean
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
realclean: distclean
install: install-so install-rb
install-so: $(RUBYARCHDIR)
install-so: $(RUBYARCHDIR)/$(DLLIB)
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
install-rb: pre-install-rb install-rb-default
install-rb-default: pre-install-rb-default
pre-install-rb: Makefile
pre-install-rb-default: Makefile
$(RUBYARCHDIR):
$(MAKEDIRS) $@
site-install: site-install-so site-install-rb
site-install-so: install-so
site-install-rb: install-rb
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
.cc.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cxx.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cpp.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.C.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.c.o:
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
$(DLLIB): $(OBJS)
@-$(RM) $@
$(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
$(OBJS): ruby.h defines.h

60
ruby/bench.rb Normal file
View File

@ -0,0 +1,60 @@
require 'rubygems'
require 'json'
require 'msgpack'
def show10(str)
puts "#{str.length/1024} KB"
puts str[0, 10].unpack('C*').map{|x|"%02x"%x}.join(' ') + " ..."
end
ary = []
i = 0
while i < (1<<23)
ary << (1<<23)
#ary << i
i += 1
end
GC.start
puts "----"
puts "MessagePack"
a = Time.now
packed = MessagePack::pack(ary)
b = Time.now
show10(packed)
puts "#{b-a} sec."
GC.start
puts "----"
puts "JSON"
a = Time.now
json = ary.to_json
b = Time.now
show10(json)
puts "#{b-a} sec."
ary = nil
GC.start
puts "----"
puts "MessagePack"
a = Time.now
ary = MessagePack::unpack(packed)
b = Time.now
puts "#{b-a} sec."
ary = nil
GC.start
puts "----"
puts "JSON"
a = Time.now
ary = JSON::load(json)
b = Time.now
puts "#{b-a} sec."

4
ruby/extconf.rb Normal file
View File

@ -0,0 +1,4 @@
require 'mkmf'
$CFLAGS << " -I.. -Wall -O9"
create_makefile('msgpack')

19
ruby/gem.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
cp extconf.rb gem/ext/
cp pack.c gem/ext/
cp pack.h gem/ext/
cp pack_inline.h gem/ext/
cp rbinit.c gem/ext/
cp unpack.c gem/ext/
cp unpack.h gem/ext/
cp unpack_context.h gem/ext/
cp unpack_inline.c gem/ext/
cp ../README gem/README.txt
cp ../msgpack/pack/inline_context.h gem/msgpack/pack/
cp ../msgpack/pack/inline_impl.h gem/msgpack/pack/
cp ../msgpack/unpack/inline_context.h gem/msgpack/unpack/
cp ../msgpack/unpack/inline_impl.h gem/msgpack/unpack/
cd gem && rake --trace package

1
ruby/gem/AUTHORS Normal file
View File

@ -0,0 +1 @@
FURUHASHI Sadayuki <frsyuki _at_ users.sourceforge.jp>

0
ruby/gem/History.txt Normal file
View File

13
ruby/gem/License.txt Normal file
View File

@ -0,0 +1,13 @@
Copyright 2008 Furuhashi Sadayuki
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

26
ruby/gem/Manifest.txt Normal file
View File

@ -0,0 +1,26 @@
License.txt
Manifest.txt
README.txt
Rakefile
config/hoe.rb
config/requirements.rb
ext/extconf.rb
ext/pack.c
ext/pack.h
ext/pack_inline.h
ext/rbinit.c
ext/unpack.c
ext/unpack.h
ext/unpack_context.h
ext/unpack_inline.c
msgpack/pack/inline_context.h
msgpack/pack/inline_impl.h
msgpack/unpack/inline_context.h
msgpack/unpack/inline_impl.h
lib/msgpack/version.rb
script/console
script/destroy
script/generate
setup.rb
tasks/deployment.rake
tasks/environment.rake

1
ruby/gem/PostInstall.txt Normal file
View File

@ -0,0 +1 @@

4
ruby/gem/Rakefile Normal file
View File

@ -0,0 +1,4 @@
require 'config/requirements'
require 'config/hoe' # setup Hoe + all gem configuration
Dir['tasks/**/*.rake'].each { |rake| load rake }

75
ruby/gem/config/hoe.rb Normal file
View File

@ -0,0 +1,75 @@
require 'msgpack/version'
AUTHOR = 'FURUHASHI Sadayuki' # can also be an array of Authors
EMAIL = "fr _at_ syuki.skr.jp"
DESCRIPTION = "An object-oriented parser generator based on Parser Expression Grammar"
GEM_NAME = 'msgpack' # what ppl will type to install your gem
RUBYFORGE_PROJECT = 'msgpack' # The unix name for your project
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
EXTRA_DEPENDENCIES = [
# ['activesupport', '>= 1.3.1']
] # An array of rubygem dependencies [name, version]
@config_file = "~/.rubyforge/user-config.yml"
@config = nil
RUBYFORGE_USERNAME = "unknown"
def rubyforge_username
unless @config
begin
@config = YAML.load(File.read(File.expand_path(@config_file)))
rescue
puts <<-EOS
ERROR: No rubyforge config file found: #{@config_file}
Run 'rubyforge setup' to prepare your env for access to Rubyforge
- See http://newgem.rubyforge.org/rubyforge.html for more details
EOS
exit
end
end
RUBYFORGE_USERNAME.replace @config["username"]
end
REV = nil
# UNCOMMENT IF REQUIRED:
# REV = YAML.load(`svn info`)['Revision']
VERS = MessagePack::VERSION::STRING + (REV ? ".#{REV}" : "")
RDOC_OPTS = ['--quiet', '--title', 'msgpack documentation',
"--opname", "index.html",
"--line-numbers",
"--main", "README",
"--inline-source"]
class Hoe
def extra_deps
@extra_deps.reject! { |x| Array(x).first == 'hoe' }
@extra_deps
end
end
# Generate all the Rake tasks
# Run 'rake -T' to see list of generated tasks (from gem root directory)
$hoe = Hoe.new(GEM_NAME, VERS) do |p|
p.developer(AUTHOR, EMAIL)
p.description = DESCRIPTION
p.summary = DESCRIPTION
p.url = HOMEPATH
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
p.test_globs = ["test/**/test_*.rb"]
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
# == Optional
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
#p.extra_deps = EXTRA_DEPENDENCIES
p.spec_extras = { # A hash of extra values to set in the gemspec.
:extensions => %w[ext/extconf.rb]
}
end
CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
$hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
$hoe.rsync_args = '-av --delete --ignore-errors'
$hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""

View File

@ -0,0 +1,15 @@
require 'fileutils'
include FileUtils
require 'rubygems'
%w[rake hoe newgem rubigen].each do |req_gem|
begin
require req_gem
rescue LoadError
puts "This Rakefile requires the '#{req_gem}' RubyGem."
puts "Installation: gem install #{req_gem} -y"
exit
end
end
$:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))

View File

@ -0,0 +1,9 @@
module MessagePack
module VERSION #:nodoc:
MAJOR = 0
MINOR = 0
TINY = 1
STRING = [MAJOR, MINOR, TINY].join('.')
end
end

10
ruby/gem/script/console Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env ruby
# File: script/console
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
libs = " -r irb/completion"
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
libs << " -r #{File.dirname(__FILE__) + '/../lib/msgpack.rb'}"
puts "Loading msgpack gem"
exec "#{irb} #{libs} --simple-prompt"

14
ruby/gem/script/destroy Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env ruby
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
begin
require 'rubigen'
rescue LoadError
require 'rubygems'
require 'rubigen'
end
require 'rubigen/scripts/destroy'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
RubiGen::Scripts::Destroy.new.run(ARGV)

14
ruby/gem/script/generate Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env ruby
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
begin
require 'rubigen'
rescue LoadError
require 'rubygems'
require 'rubigen'
end
require 'rubigen/scripts/generate'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
RubiGen::Scripts::Generate.new.run(ARGV)

82
ruby/gem/script/txt2html Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env ruby
GEM_NAME = 'msgpack' # what ppl will type to install your gem
RUBYFORGE_PROJECT = 'msgpack'
require 'rubygems'
begin
require 'newgem'
require 'rubyforge'
rescue LoadError
puts "\n\nGenerating the website requires the newgem RubyGem"
puts "Install: gem install newgem\n\n"
exit(1)
end
require 'redcloth'
require 'syntax/convertors/html'
require 'erb'
require File.dirname(__FILE__) + "/../lib/#{GEM_NAME}/version.rb"
version = MessagePack::VERSION::STRING
download = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
def rubyforge_project_id
RubyForge.new.autoconfig["group_ids"][RUBYFORGE_PROJECT]
end
class Fixnum
def ordinal
# teens
return 'th' if (10..19).include?(self % 100)
# others
case self % 10
when 1: return 'st'
when 2: return 'nd'
when 3: return 'rd'
else return 'th'
end
end
end
class Time
def pretty
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
end
end
def convert_syntax(syntax, source)
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
end
if ARGV.length >= 1
src, template = ARGV
template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
else
puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
exit!
end
template = ERB.new(File.open(template).read)
title = nil
body = nil
File.open(src) do |fsrc|
title_text = fsrc.readline
body_text_template = fsrc.read
body_text = ERB.new(body_text_template).result(binding)
syntax_items = []
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
ident = syntax_items.length
element, syntax, source = $1, $2, $3
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
"syntax-temp-#{ident}"
}
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
body = RedCloth.new(body_text).to_html
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
end
stat = File.stat(src)
created = stat.ctime
modified = stat.mtime
$stdout << template.result(binding)

1585
ruby/gem/setup.rb Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
desc 'Release the website and new gem version'
task :deploy => [:check_version, :website, :release] do
puts "Remember to create SVN tag:"
puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
"svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
puts "Suggested comment:"
puts "Tagging release #{CHANGES}"
end
desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
task :local_deploy => [:website_generate, :install_gem]
task :check_version do
unless ENV['VERSION']
puts 'Must pass a VERSION=x.y.z release version'
exit
end
unless ENV['VERSION'] == VERS
puts "Please update your version.rb to match the release version, currently #{VERS}"
exit
end
end
desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
task :install_gem_no_doc => [:clean, :package] do
sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
end
namespace :manifest do
desc 'Recreate Manifest.txt to include ALL files'
task :refresh do
`rake check_manifest | patch -p0 > Manifest.txt`
end
end

View File

@ -0,0 +1,7 @@
task :ruby_env do
RUBY_APP = if RUBY_PLATFORM =~ /java/
"jruby"
else
"ruby"
end unless defined? RUBY_APP
end

131
ruby/pack.c Normal file
View File

@ -0,0 +1,131 @@
/*
* MessagePack packing routine for Ruby
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pack_inline.h"
#ifndef RUBY_VM
#include "st.h" // ruby hash
#endif
static ID s_to_msgpack;
#define ARG_BUFFER(name, argc, argv) \
VALUE name; \
if(argc == 1) { \
name = argv[0]; \
} else if(argc == 0) { \
name = rb_str_buf_new(0); \
} else { \
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); \
}
static VALUE MessagePack_NilClass_to_msgpack(int argc, VALUE *argv, VALUE self)
{
ARG_BUFFER(out, argc, argv);
msgpack_pack_nil(out);
return out;
}
static VALUE MessagePack_TrueClass_to_msgpack(int argc, VALUE *argv, VALUE self)
{
ARG_BUFFER(out, argc, argv);
msgpack_pack_true(out);
return out;
}
static VALUE MessagePack_FalseClass_to_msgpack(int argc, VALUE *argv, VALUE self)
{
ARG_BUFFER(out, argc, argv);
msgpack_pack_false(out);
return out;
}
static VALUE MessagePack_Fixnum_to_msgpack(int argc, VALUE *argv, VALUE self)
{
ARG_BUFFER(out, argc, argv);
msgpack_pack_int(out, FIX2INT(self));
return out;
}
static VALUE MessagePack_Float_to_msgpack(int argc, VALUE *argv, VALUE self)
{
ARG_BUFFER(out, argc, argv);
msgpack_pack_double(out, rb_num2dbl(self));
return out;
}
static VALUE MessagePack_String_to_msgpack(int argc, VALUE *argv, VALUE self)
{
ARG_BUFFER(out, argc, argv);
msgpack_pack_raw(out, RSTRING_PTR(self), RSTRING_LEN(self));
return out;
}
static VALUE MessagePack_Array_to_msgpack(int argc, VALUE *argv, VALUE self)
{
ARG_BUFFER(out, argc, argv);
msgpack_pack_array(out, RARRAY_LEN(self));
VALUE* p = RARRAY_PTR(self);
VALUE* const pend = p + RARRAY_LEN(self);
for(;p != pend; ++p) {
rb_funcall(*p, s_to_msgpack, 1, out);
}
return out;
}
#ifndef RHASH_SIZE // Ruby 1.8
#define RHASH_SIZE(h) (RHASH(h)->tbl ? RHASH(h)->tbl->num_entries : 0)
#endif
static int MessagePack_Hash_to_msgpack_foreach(VALUE key, VALUE value, VALUE out)
{
if (key == Qundef) { return ST_CONTINUE; }
rb_funcall(key, s_to_msgpack, 1, out);
rb_funcall(value, s_to_msgpack, 1, out);
return ST_CONTINUE;
}
static VALUE MessagePack_Hash_to_msgpack(int argc, VALUE *argv, VALUE self)
{
ARG_BUFFER(out, argc, argv);
msgpack_pack_map(out, RHASH_SIZE(self));
rb_hash_foreach(self, MessagePack_Hash_to_msgpack_foreach, out);
return out;
}
static VALUE MessagePack_pack(VALUE self, VALUE data)
{
return rb_funcall(data, s_to_msgpack, 0);
}
void Init_msgpack_pack(VALUE mMessagePack)
{
s_to_msgpack = rb_intern("to_msgpack");
rb_define_method_id(rb_cNilClass, s_to_msgpack, MessagePack_NilClass_to_msgpack, -1);
rb_define_method_id(rb_cTrueClass, s_to_msgpack, MessagePack_TrueClass_to_msgpack, -1);
rb_define_method_id(rb_cFalseClass, s_to_msgpack, MessagePack_FalseClass_to_msgpack, -1);
rb_define_method_id(rb_cFixnum, s_to_msgpack, MessagePack_Fixnum_to_msgpack, -1);
rb_define_method_id(rb_cFloat, s_to_msgpack, MessagePack_Float_to_msgpack, -1);
rb_define_method_id(rb_cString, s_to_msgpack, MessagePack_String_to_msgpack, -1);
rb_define_method_id(rb_cArray, s_to_msgpack, MessagePack_Array_to_msgpack, -1);
rb_define_method_id(rb_cHash, s_to_msgpack, MessagePack_Hash_to_msgpack, -1);
rb_define_module_function(mMessagePack, "pack", MessagePack_pack, 1);
}

26
ruby/pack.h Normal file
View File

@ -0,0 +1,26 @@
/*
* MessagePack packing routine for Ruby
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PACK_H__
#define PACK_H__
#include "ruby.h"
void Init_msgpack_pack(VALUE mMessagePack);
#endif /* pack.h */

33
ruby/pack_inline.h Normal file
View File

@ -0,0 +1,33 @@
/*
* MessagePack packing routine for Ruby
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PACK_INLINE_H__
#define PACK_INLINE_H__
#include "ruby.h"
typedef VALUE msgpack_pack_context;
static inline void msgpack_pack_append_buffer(VALUE x, const unsigned char* b, unsigned int l)
{
rb_str_buf_cat(x, (const void*)b, l);
}
#include "msgpack/pack/inline_impl.h"
#endif /* pack_inline.h */

29
ruby/rbinit.c Normal file
View File

@ -0,0 +1,29 @@
/*
* MessagePack for Ruby
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pack.h"
#include "unpack.h"
static VALUE mMessagePack;
void Init_msgpack(void)
{
mMessagePack = rb_define_module("MessagePack");
Init_msgpack_unpack(mMessagePack);
Init_msgpack_pack(mMessagePack);
}

128
ruby/test_format.rb Normal file
View File

@ -0,0 +1,128 @@
require 'msgpack'
@up = MessagePack::Unpacker.new
def check(bytes, should)
puts "----"
@up.reset
src = bytes.pack('C*')
ret = @up.execute(src, 0)
if ret != src.length
puts "** EXTRA BYTES **"
end
puts bytes.map{|x|"%x"%x}.join(' ')
data = @up.data
p data
if data != should
puts "** TEST FAILED **"
p should
end
end
# SimpleValue
check([
0x93, 0xc0, 0xc2, 0xc3,
], [nil,false,true])
# Fixnum
check([
0x92,
0x93, 0x00, 0x40, 0x7f,
0x93, 0xe0, 0xf0, 0xff,
], [[0,64,127], [-32,-16,-1]])
# FixArray
check([
0x92,
0x90,
0x91,
0x91, 0xc0,
], [[],[[nil]]])
# FixRaw
check([
0x94,
0xa0,
0xa1, ?a,
0xa2, ?b, ?c,
0xa3, ?d, ?e, ?f,
], ["","a","bc","def"])
# FixMap
check([
0x82,
0xc2, 0x81,
0xc0, 0xc0,
0xc3, 0x81,
0xc0, 0x80,
], {false=>{nil=>nil}, true=>{nil=>{}}})
# unsigned int
check([
0x99,
0xcc, 0,
0xcc, 128,
0xcc, 255,
0xcd, 0x00, 0x00,
0xcd, 0x80, 0x00,
0xcd, 0xff, 0xff,
0xce, 0x00, 0x00, 0x00, 0x00,
0xce, 0x80, 0x00, 0x00, 0x00,
0xce, 0xff, 0xff, 0xff, 0xff,
], [0, 128, 255, 0, 32768, 65535, 0, 2147483648, 4294967295])
# signed int
check([
0x99,
0xd0, 0,
0xd0, 128,
0xd0, 255,
0xd1, 0x00, 0x00,
0xd1, 0x80, 0x00,
0xd1, 0xff, 0xff,
0xd2, 0x00, 0x00, 0x00, 0x00,
0xd2, 0x80, 0x00, 0x00, 0x00,
0xd2, 0xff, 0xff, 0xff, 0xff,
], [0, -128, -1, 0, -32768, -1, 0, -2147483648, -1])
# raw
check([
0x96,
0xda, 0x00, 0x00,
0xda, 0x00, 0x01, ?a,
0xda, 0x00, 0x02, ?a, ?b,
0xdb, 0x00, 0x00, 0x00, 0x00,
0xdb, 0x00, 0x00, 0x00, 0x01, ?a,
0xdb, 0x00, 0x00, 0x00, 0x02, ?a, ?b,
], ["", "a", "ab", "", "a", "ab"])
# array
check([
0x96,
0xdc, 0x00, 0x00,
0xdc, 0x00, 0x01, 0xc0,
0xdc, 0x00, 0x02, 0xc2, 0xc3,
0xdd, 0x00, 0x00, 0x00, 0x00,
0xdd, 0x00, 0x00, 0x00, 0x01, 0xc0,
0xdd, 0x00, 0x00, 0x00, 0x02, 0xc2, 0xc3
], [[], [nil], [false,true], [], [nil], [false,true]])
# map
check([
0x96,
0xde, 0x00, 0x00,
0xde, 0x00, 0x01, 0xc0, 0xc2,
0xde, 0x00, 0x02, 0xc0, 0xc2, 0xc3, 0xc2,
0xdf, 0x00, 0x00, 0x00, 0x00,
0xdf, 0x00, 0x00, 0x00, 0x01, 0xc0, 0xc2,
0xdf, 0x00, 0x00, 0x00, 0x02, 0xc0, 0xc2, 0xc3, 0xc2,
], [{}, {nil=>false}, {true=>false, nil=>false}, {}, {nil=>false}, {true=>false, nil=>false}])
# string
check([
0x92,
0xc1, 0x00,
0xc1, ?a, ?b, ?c, 0x00,
], ["", "abc"])

56
ruby/test_pack.rb Normal file
View File

@ -0,0 +1,56 @@
require 'msgpack'
def check(data)
puts "---"
pack = data.to_msgpack
p data
puts pack.unpack('C*').map{|x|"%02x"%x}.join(' ')
re = MessagePack::unpack(pack)
if re != data
p re
puts "** TEST FAILED **"
end
end
check 0
check 1
check 127
check 128
check 255
check 256
check 65535
check 65536
check -1
check -128
check -129
check -32768
check -32769
check 1.0
check ""
check "a"
check "a"*31
check "a"*32
check nil
check true
check false
check []
check [[]]
check [[], nil]
check( {nil=>0} )
check (1<<23)
__END__
ary = []
i = 0
while i < (1<<16)
ary << i
i += 1
end
check ary

202
ruby/unpack.c Normal file
View File

@ -0,0 +1,202 @@
/*
* MessagePack unpacking routine for Ruby
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ruby.h"
#include "unpack_context.h"
#include <stdio.h>
#define UNPACKER(from, name) \
msgpack_unpacker *name = NULL; \
Data_Get_Struct(from, msgpack_unpacker, name); \
if(name == NULL) { \
rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
}
#define CHECK_STRING_TYPE(value) \
value = rb_check_string_type(value); \
if( NIL_P(value) ) { \
rb_raise(rb_eTypeError, "instance of String needed"); \
}
static VALUE cUnpacker;
static VALUE eUnpackError;
static void MessagePack_Unpacker_free(void* data)
{
if(data) { free(data); }
}
static void MessagePack_Unpacker_mark(msgpack_unpacker *mp)
{
unsigned int i;
for(i=0; i < mp->top; ++i) {
rb_gc_mark(mp->stack[i].obj);
rb_gc_mark(mp->stack[i].tmp.map_key);
}
}
static VALUE MessagePack_Unpacker_alloc(VALUE klass)
{
VALUE obj;
msgpack_unpacker* mp = ALLOC_N(msgpack_unpacker, 1);
obj = Data_Wrap_Struct(klass, MessagePack_Unpacker_mark,
MessagePack_Unpacker_free, mp);
return obj;
}
static VALUE MessagePack_Unpacker_reset(VALUE self)
{
UNPACKER(self, mp);
mp->user.finished = false;
msgpack_unpacker_init(mp);
return self;
}
static VALUE MessagePack_Unpacker_initialize(VALUE self)
{
return MessagePack_Unpacker_reset(self);
}
static VALUE MessagePack_Unpacker_execute_impl(VALUE args)
{
VALUE self = ((VALUE*)args)[0];
VALUE data = ((VALUE*)args)[1];
VALUE off = ((VALUE*)args)[2];
UNPACKER(self, mp);
size_t from = NUM2UINT(off);
char* dptr = RSTRING_PTR(data);
long dlen = RSTRING_LEN(data);
int ret;
if(from >= dlen) {
rb_raise(eUnpackError, "Requested start is after data buffer end.");
}
ret = msgpack_unpacker_execute(mp, dptr, (size_t)dlen, &from);
if(ret < 0) {
rb_raise(eUnpackError, "Parse error.");
} else if(ret > 0) {
mp->user.finished = true;
return ULONG2NUM(from);
} else {
mp->user.finished = false;
return ULONG2NUM(from);
}
}
static VALUE MessagePack_Unpacker_execute_rescue(VALUE nouse)
{
rb_gc_enable();
#ifdef RUBY_VM
rb_exc_raise(rb_errinfo());
#else
rb_exc_raise(ruby_errinfo);
#endif
}
static VALUE MessagePack_Unpacker_execute(VALUE self, VALUE data, VALUE off)
{
// FIXME execute実行中はmp->topが更新されないのでGC markが機能しない
rb_gc_disable();
VALUE args[3] = {self, data, off};
VALUE ret = rb_rescue(MessagePack_Unpacker_execute_impl, (VALUE)args,
MessagePack_Unpacker_execute_rescue, Qnil);
rb_gc_enable();
return ret;
}
static VALUE MessagePack_Unpacker_finished_p(VALUE self)
{
UNPACKER(self, mp);
if(mp->user.finished) {
return Qtrue;
}
return Qfalse;
}
static VALUE MessagePack_Unpacker_data(VALUE self)
{
UNPACKER(self, mp);
return msgpack_unpacker_data(mp);
}
static VALUE MessagePack_unpack_impl(VALUE args)
{
msgpack_unpacker* mp = (msgpack_unpacker*)((VALUE*)args)[0];
VALUE data = ((VALUE*)args)[1];
size_t from = 0;
char* dptr = RSTRING_PTR(data);
long dlen = RSTRING_LEN(data);
int ret;
ret = msgpack_unpacker_execute(mp, dptr, (size_t)dlen, &from);
if(ret < 0) {
rb_raise(eUnpackError, "Parse error.");
} else if(ret == 0) {
rb_raise(eUnpackError, "Insufficient bytes.");
} else {
if(from < dlen) {
rb_raise(eUnpackError, "Extra bytes.");
}
return msgpack_unpacker_data(mp);
}
}
static VALUE MessagePack_unpack_rescue(VALUE args)
{
rb_gc_enable();
#ifdef RUBY_VM
rb_exc_raise(rb_errinfo());
#else
rb_exc_raise(ruby_errinfo);
#endif
}
static VALUE MessagePack_unpack(VALUE self, VALUE data)
{
CHECK_STRING_TYPE(data);
msgpack_unpacker mp;
msgpack_unpacker_init(&mp);
rb_gc_disable();
VALUE args[2] = {(VALUE)&mp, data};
VALUE ret = rb_rescue(MessagePack_unpack_impl, (VALUE)args,
MessagePack_unpack_rescue, Qnil);
rb_gc_enable();
return ret;
}
void Init_msgpack_unpack(VALUE mMessagePack)
{
eUnpackError = rb_define_class_under(mMessagePack, "UnpackError", rb_eStandardError);
cUnpacker = rb_define_class_under(mMessagePack, "Unpacker", rb_cObject);
rb_define_alloc_func(cUnpacker, MessagePack_Unpacker_alloc);
rb_define_method(cUnpacker, "initialize", MessagePack_Unpacker_initialize, 0);
rb_define_method(cUnpacker, "execute", MessagePack_Unpacker_execute, 2);
rb_define_method(cUnpacker, "finished?", MessagePack_Unpacker_finished_p, 0);
rb_define_method(cUnpacker, "data", MessagePack_Unpacker_data, 0);
rb_define_method(cUnpacker, "reset", MessagePack_Unpacker_reset, 0);
rb_define_module_function(mMessagePack, "unpack", MessagePack_unpack, 1);
}

26
ruby/unpack.h Normal file
View File

@ -0,0 +1,26 @@
/*
* MessagePack unpacking routine for Ruby
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef UNPACK_H__
#define UNPACK_H__
#include "ruby.h"
void Init_msgpack_unpack(VALUE mMessagePack);
#endif /* unpack.h */

35
ruby/unpack_context.h Normal file
View File

@ -0,0 +1,35 @@
/*
* MessagePack unpacking routine for Ruby
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef UNPACK_CONTEXT_H__
#define UNPACK_CONTEXT_H__
#include "ruby.h"
#include <stddef.h>
#include <stdbool.h>
typedef VALUE msgpack_object;
typedef struct {
bool finished;
} msgpack_unpack_context;
#include "msgpack/unpack/inline_context.h"
#endif /* unpack_context.h */

81
ruby/unpack_inline.c Normal file
View File

@ -0,0 +1,81 @@
/*
* MessagePack unpacking routine for Ruby
*
* Copyright (C) 2008 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "unpack_context.h"
static inline VALUE msgpack_unpack_init(msgpack_unpack_context* x)
{ return Qnil; }
static inline VALUE msgpack_unpack_unsigned_int_8(msgpack_unpack_context* x, uint8_t d)
{ return INT2FIX(d); }
static inline VALUE msgpack_unpack_unsigned_int_16(msgpack_unpack_context* x, uint16_t d)
{ return INT2FIX(d); }
static inline VALUE msgpack_unpack_unsigned_int_32(msgpack_unpack_context* x, uint32_t d)
{ return UINT2NUM(d); }
static inline VALUE msgpack_unpack_unsigned_int_64(msgpack_unpack_context* x, uint64_t d)
{ return UINT2NUM(d); } // FIXME
static inline VALUE msgpack_unpack_signed_int_8(msgpack_unpack_context* x, int8_t d)
{ return INT2FIX((long)d); }
static inline VALUE msgpack_unpack_signed_int_16(msgpack_unpack_context* x, int16_t d)
{ return INT2FIX((long)d); }
static inline VALUE msgpack_unpack_signed_int_32(msgpack_unpack_context* x, int32_t d)
{ return INT2NUM((long)d); }
static inline VALUE msgpack_unpack_signed_int_64(msgpack_unpack_context* x, int64_t d)
{ return INT2NUM(d); } // FIXME
static inline VALUE msgpack_unpack_float(msgpack_unpack_context* x, float d)
{ return rb_float_new(d); }
static inline VALUE msgpack_unpack_double(msgpack_unpack_context* x, double d)
{ return rb_float_new(d); }
static inline VALUE msgpack_unpack_nil(msgpack_unpack_context* x)
{ return Qnil; }
static inline VALUE msgpack_unpack_true(msgpack_unpack_context* x)
{ return Qtrue; }
static inline VALUE msgpack_unpack_false(msgpack_unpack_context* x)
{ return Qfalse; }
static inline VALUE msgpack_unpack_array_start(msgpack_unpack_context* x, unsigned int n)
{ return rb_ary_new2(n); }
static inline void msgpack_unpack_array_item(msgpack_unpack_context* x, VALUE c, VALUE o)
{ rb_ary_push(c, o); }
static inline VALUE msgpack_unpack_map_start(msgpack_unpack_context* x, unsigned int n)
{ return rb_hash_new(); }
static inline void msgpack_unpack_map_item(msgpack_unpack_context* x, VALUE c, VALUE k, VALUE v)
{ rb_hash_aset(c, k, v); }
static inline VALUE msgpack_unpack_string(msgpack_unpack_context* x, const void* b, size_t l)
{ return rb_str_new(b, l); }
static inline VALUE msgpack_unpack_raw(msgpack_unpack_context* x, const void* b, size_t l)
{ return rb_str_new(b, l); }
#include "msgpack/unpack/inline_impl.h"