ninjudd-tuple 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|