ninjudd-tuple 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +1 -1
- data/ext/extconf.rb +5 -0
- data/ext/tuple.c +152 -0
- metadata +7 -5
data/VERSION.yml
CHANGED
data/ext/extconf.rb
ADDED
data/ext/tuple.c
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
VALUE mTuple;
|
4
|
+
|
5
|
+
#define TRUE_SORT 128 // TrueClass
|
6
|
+
#define SYM_SORT 64 // Symbol
|
7
|
+
#define STR_SORT 32 // String
|
8
|
+
#define INTP_SORT 16 // Integer (Positive)
|
9
|
+
#define INTN_SORT 8 // Integer (Negative)
|
10
|
+
#define FALSE_SORT 1 // FalseClass
|
11
|
+
#define NIL_SORT 0 // NilClass
|
12
|
+
|
13
|
+
#define MAX_INT 0xffffffff
|
14
|
+
|
15
|
+
#define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits)
|
16
|
+
|
17
|
+
/*
|
18
|
+
* call-seq:
|
19
|
+
* Tuple.dump(tuple) -> string
|
20
|
+
*
|
21
|
+
* Dumps an array of simple Ruby types into a string of binary data.
|
22
|
+
*
|
23
|
+
*/
|
24
|
+
static VALUE tuple_dump(VALUE self, VALUE tuple) {
|
25
|
+
VALUE data = rb_str_new2("");
|
26
|
+
VALUE item;
|
27
|
+
int i, j, len, sign;
|
28
|
+
u_int8_t header[4];
|
29
|
+
u_int32_t digit;
|
30
|
+
BDIGIT *digits;
|
31
|
+
|
32
|
+
Check_Type(tuple, T_ARRAY);
|
33
|
+
for (i = 0; i < RARRAY(tuple)->len; i++) {
|
34
|
+
item = RARRAY(tuple)->ptr[i];
|
35
|
+
header[0] = header[1] = header[2] = header[3] = 0;
|
36
|
+
if (FIXNUM_P(item)) {
|
37
|
+
sign = (digit >= 0);
|
38
|
+
header[2] = (sign ? INTP_SORT : INTN_SORT);
|
39
|
+
header[3] = 0;
|
40
|
+
rb_str_cat(data, (char*)&header, sizeof(header));
|
41
|
+
|
42
|
+
digit = htonl(FIX2INT(item) + (sign ? 0 : MAX_INT));
|
43
|
+
rb_str_cat(data, (char*)&digit, sizeof(digit));
|
44
|
+
} else if (TYPE(item) == T_BIGNUM) {
|
45
|
+
sign = RBIGNUM(item)->sign;
|
46
|
+
header[2] = sign ? INTP_SORT : INTN_SORT;
|
47
|
+
header[3] = RBIGNUM(item)->len;
|
48
|
+
rb_str_cat(data, (char*)&header, sizeof(header));
|
49
|
+
|
50
|
+
digits = BDIGITS(item);
|
51
|
+
for (j = header[3]-1; j >= 0; j--) {
|
52
|
+
digit = htonl(sign ? digits[j] : (MAX_INT - digits[j]));
|
53
|
+
rb_str_cat(data, (char*)&digit, sizeof(digit));
|
54
|
+
}
|
55
|
+
} else if (SYMBOL_P(item) || TYPE(item) == T_STRING) {
|
56
|
+
if (SYMBOL_P(item)) {
|
57
|
+
header[2] = SYM_SORT;
|
58
|
+
item = rb_funcall(item, rb_intern("to_s"), 0);
|
59
|
+
} else {
|
60
|
+
header[2] = STR_SORT;
|
61
|
+
}
|
62
|
+
rb_str_cat(data, (char*)&header, sizeof(header));
|
63
|
+
len = RSTRING_LEN(item);
|
64
|
+
rb_str_cat(data, RSTRING_PTR(item), len);
|
65
|
+
|
66
|
+
// Pad with null bytes so subsequent fields will be aligned.
|
67
|
+
while (len % 4 != 0) {
|
68
|
+
rb_str_cat(data, (char*)&header, 1);
|
69
|
+
len++;
|
70
|
+
}
|
71
|
+
} else {
|
72
|
+
if (item == Qnil) header[2] = NIL_SORT;
|
73
|
+
else if (item == Qtrue) header[2] = TRUE_SORT;
|
74
|
+
else if (item == Qfalse) header[2] = FALSE_SORT;
|
75
|
+
else rb_raise(rb_eTypeError, "invalid type %s in tuple", rb_obj_classname(item));
|
76
|
+
|
77
|
+
rb_str_cat(data, (char*)&header, sizeof(header));
|
78
|
+
}
|
79
|
+
}
|
80
|
+
return data;
|
81
|
+
}
|
82
|
+
|
83
|
+
/*
|
84
|
+
* call-seq:
|
85
|
+
* Tuple.load(string) -> tuple
|
86
|
+
*
|
87
|
+
* Reads in a previously dumped tuple from a string of binary data.
|
88
|
+
*
|
89
|
+
*/
|
90
|
+
static VALUE tuple_load(VALUE self, VALUE data) {
|
91
|
+
VALUE tuple = rb_ary_new();
|
92
|
+
VALUE item;
|
93
|
+
data = StringValue(data);
|
94
|
+
void* ptr = RSTRING_PTR(data);
|
95
|
+
void* end = ptr + RSTRING_LEN(data);
|
96
|
+
int i, len, sign;
|
97
|
+
u_int8_t header[4];
|
98
|
+
u_int32_t digit;
|
99
|
+
BDIGIT *digits;
|
100
|
+
|
101
|
+
while (ptr < end) {
|
102
|
+
memcpy(header, ptr, 4);
|
103
|
+
ptr += 4;
|
104
|
+
|
105
|
+
switch(header[2]) {
|
106
|
+
case TRUE_SORT: rb_ary_push(tuple, Qtrue); break;
|
107
|
+
case FALSE_SORT: rb_ary_push(tuple, Qfalse); break;
|
108
|
+
case NIL_SORT: rb_ary_push(tuple, Qnil); break;
|
109
|
+
case INTP_SORT:
|
110
|
+
case INTN_SORT:
|
111
|
+
sign = (header[2] == INTP_SORT);
|
112
|
+
if (header[3] == 0) {
|
113
|
+
digit = ntohl(*(u_int32_t*)ptr) - (sign ? 0 : MAX_INT);
|
114
|
+
ptr += 4;
|
115
|
+
rb_ary_push(tuple, INT2NUM(digit));
|
116
|
+
} else {
|
117
|
+
// Create an empty bignum with the right number of digits.
|
118
|
+
NEWOBJ(item, struct RBignum);
|
119
|
+
OBJSETUP(item, rb_cBignum, T_BIGNUM);
|
120
|
+
item->sign = sign ? 1 : 0;
|
121
|
+
item->len = header[3];
|
122
|
+
item->digits = ALLOC_N(BDIGIT, header[3]);
|
123
|
+
|
124
|
+
digits = BDIGITS(item);
|
125
|
+
for (i = header[3]-1; i >= 0; i--) {
|
126
|
+
digit = ntohl(*(u_int32_t*)ptr);
|
127
|
+
digits[i] = sign ? digit : MAX_INT - digit;
|
128
|
+
ptr += 4;
|
129
|
+
}
|
130
|
+
rb_ary_push(tuple, (VALUE)item);
|
131
|
+
}
|
132
|
+
break;
|
133
|
+
case STR_SORT:
|
134
|
+
case SYM_SORT:
|
135
|
+
item = rb_str_new2(ptr);
|
136
|
+
len = RSTRING_LEN(item);
|
137
|
+
while (len % 4 != 0) len++;
|
138
|
+
ptr += len;
|
139
|
+
if (header[2] == SYM_SORT) item = rb_funcall(item, rb_intern("to_sym"), 0);
|
140
|
+
rb_ary_push(tuple, item);
|
141
|
+
break;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
return tuple;
|
145
|
+
}
|
146
|
+
|
147
|
+
VALUE mTuple;
|
148
|
+
void Init_tuple() {
|
149
|
+
mTuple = rb_define_module("Tuple");
|
150
|
+
rb_define_module_function(mTuple, "dump", tuple_dump, 1);
|
151
|
+
rb_define_module_function(mTuple, "load", tuple_load, 1);
|
152
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ninjudd-tuple
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Balthrop
|
@@ -17,13 +17,15 @@ description: Fast, binary-sortable serialization for arrays of simple Ruby types
|
|
17
17
|
email: code@justinbalthrop.com
|
18
18
|
executables: []
|
19
19
|
|
20
|
-
extensions:
|
21
|
-
|
20
|
+
extensions:
|
21
|
+
- ext/extconf.rb
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
25
|
- README.rdoc
|
26
26
|
- VERSION.yml
|
27
|
+
- ext/tuple.c
|
28
|
+
- ext/extconf.rb
|
27
29
|
- test/test_helper.rb
|
28
30
|
- test/tuple_test.rb
|
29
31
|
has_rdoc: true
|
@@ -34,7 +36,7 @@ rdoc_options:
|
|
34
36
|
- --inline-source
|
35
37
|
- --charset=UTF-8
|
36
38
|
require_paths:
|
37
|
-
-
|
39
|
+
- ext
|
38
40
|
required_ruby_version: !ruby/object:Gem::Requirement
|
39
41
|
requirements:
|
40
42
|
- - ">="
|
@@ -53,6 +55,6 @@ rubyforge_project:
|
|
53
55
|
rubygems_version: 1.3.5
|
54
56
|
signing_key:
|
55
57
|
specification_version: 2
|
56
|
-
summary:
|
58
|
+
summary: Tuple serialization functions.
|
57
59
|
test_files: []
|
58
60
|
|