rcstorable 0.1.3 → 0.1.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 +1 -1
- data/ext/rcstorable.c +72 -54
- metadata +1 -1
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/ext/rcstorable.c
CHANGED
@@ -5,50 +5,33 @@
|
|
5
5
|
#include "ruby.h"
|
6
6
|
|
7
7
|
VALUE thaw(VALUE, VALUE);
|
8
|
-
VALUE read_object();
|
9
|
-
int read_extended_size();
|
10
|
-
int read_compact_size();
|
11
|
-
void read_n_hash_pairs(VALUE, int);
|
12
|
-
void read_n_array_entries(VALUE, int);
|
13
|
-
VALUE read_string(bool);
|
14
|
-
void read_magic_numbers();
|
15
|
-
|
16
|
-
|
8
|
+
static VALUE read_object();
|
9
|
+
static int read_extended_size();
|
10
|
+
static int read_compact_size();
|
11
|
+
static void read_n_hash_pairs(VALUE, int);
|
12
|
+
static void read_n_array_entries(VALUE, int);
|
13
|
+
static VALUE read_string(bool);
|
14
|
+
static void read_magic_numbers();
|
15
|
+
static void check_pointer(unsigned char*);
|
16
|
+
|
17
|
+
enum perl_types
|
17
18
|
{
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
O_STR = 1,
|
26
|
-
O_ARRAY = 2,
|
27
|
-
O_HASH = 3,
|
28
|
-
O_UNDEFINED = 5
|
29
|
-
};
|
30
|
-
|
31
|
-
enum hash_key_types
|
32
|
-
{
|
33
|
-
H_VECTOR = 4,
|
34
|
-
H_EMPTY = 5,
|
35
|
-
H_STRING = 10,
|
36
|
-
H_STRING_ALT = 23
|
19
|
+
PT_HASH_KEY = 1,
|
20
|
+
PT_ARRAY = 2,
|
21
|
+
PT_HASH = 3,
|
22
|
+
PT_VECTOR = 4,
|
23
|
+
PT_UNDEF = 5,
|
24
|
+
PT_STRING = 10,
|
25
|
+
PT_STRING_ALT = 23
|
37
26
|
};
|
38
27
|
|
39
28
|
// Used globally. Raptors. I know.
|
40
|
-
unsigned char *serialized;
|
41
|
-
unsigned char *serialized_end;
|
42
|
-
|
43
|
-
void
|
44
|
-
check_pointer(unsigned char *ptr)
|
45
|
-
{
|
46
|
-
extern unsigned char *serialized_end;
|
47
|
-
if (ptr > serialized_end) {
|
48
|
-
rb_raise(rb_eRangeError, "malformed data");
|
49
|
-
}
|
50
|
-
}
|
29
|
+
static unsigned char *serialized;
|
30
|
+
static unsigned char *serialized_end;
|
51
31
|
|
32
|
+
/*
|
33
|
+
* Given a perl Storable frozen blob, decode it into a ruby data structure.
|
34
|
+
*/
|
52
35
|
VALUE
|
53
36
|
thaw(VALUE self, VALUE str)
|
54
37
|
{
|
@@ -63,14 +46,35 @@ thaw(VALUE self, VALUE str)
|
|
63
46
|
return read_object();
|
64
47
|
}
|
65
48
|
|
66
|
-
|
49
|
+
/*
|
50
|
+
* Malformed strings can theoretically cause segfaults. Segfaults are bad.
|
51
|
+
* We'll check pretty much everything we do against the pre-computed end-of-string.
|
52
|
+
*/
|
53
|
+
static void
|
54
|
+
check_pointer(unsigned char *ptr)
|
55
|
+
{
|
56
|
+
extern unsigned char *serialized_end;
|
57
|
+
if (ptr > serialized_end) {
|
58
|
+
rb_raise(rb_eRangeError, "malformed data");
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
/*
|
63
|
+
* Certain test cases start with \005\006. Other ones don't.
|
64
|
+
* This will need to be fixed eventually.
|
65
|
+
*/
|
66
|
+
static void
|
67
67
|
read_magic_numbers()
|
68
68
|
{
|
69
69
|
serialized++;
|
70
70
|
serialized++;
|
71
71
|
}
|
72
72
|
|
73
|
-
|
73
|
+
/*
|
74
|
+
* Figure out what type of object is at the front of serialized, read it in, potentially
|
75
|
+
* recursively creating several other sub-objects in the process, and return it.
|
76
|
+
*/
|
77
|
+
static VALUE
|
74
78
|
read_object()
|
75
79
|
{
|
76
80
|
extern unsigned char *serialized;
|
@@ -81,15 +85,15 @@ read_object()
|
|
81
85
|
VALUE object;
|
82
86
|
|
83
87
|
switch(type) {
|
84
|
-
case
|
88
|
+
case PT_HASH:
|
85
89
|
object = rb_hash_new();
|
86
90
|
read_n_hash_pairs(object, size);
|
87
91
|
break;
|
88
|
-
case
|
92
|
+
case PT_ARRAY:
|
89
93
|
object = rb_ary_new();
|
90
94
|
read_n_array_entries(object, size);
|
91
95
|
break;
|
92
|
-
case
|
96
|
+
case PT_UNDEF:
|
93
97
|
object = Qnil;
|
94
98
|
break;
|
95
99
|
}
|
@@ -98,7 +102,11 @@ read_object()
|
|
98
102
|
}
|
99
103
|
|
100
104
|
|
101
|
-
|
105
|
+
/*
|
106
|
+
* We've already created a hash, and read the size of it.
|
107
|
+
* Now we need to read in n items, and add them to the hash.
|
108
|
+
*/
|
109
|
+
static void
|
102
110
|
read_n_hash_pairs(VALUE hash, int num)
|
103
111
|
{
|
104
112
|
extern unsigned char *serialized;
|
@@ -113,16 +121,16 @@ read_n_hash_pairs(VALUE hash, int num)
|
|
113
121
|
VALUE str;
|
114
122
|
|
115
123
|
switch(type) {
|
116
|
-
case
|
124
|
+
case PT_UNDEF:
|
117
125
|
rb_hash_aset(hash, read_string(true), Qnil);
|
118
126
|
break;
|
119
|
-
case
|
127
|
+
case PT_VECTOR:
|
120
128
|
temp = read_object();
|
121
129
|
str = read_string(true);
|
122
130
|
rb_hash_aset(hash, str, temp);
|
123
131
|
break;
|
124
|
-
case
|
125
|
-
case
|
132
|
+
case PT_STRING:
|
133
|
+
case PT_STRING_ALT:
|
126
134
|
temp = read_string(false);
|
127
135
|
rb_hash_aset(hash, read_string(true), temp);
|
128
136
|
break;
|
@@ -131,7 +139,11 @@ read_n_hash_pairs(VALUE hash, int num)
|
|
131
139
|
read_n_hash_pairs(hash, num-1);
|
132
140
|
}
|
133
141
|
|
134
|
-
|
142
|
+
/*
|
143
|
+
* We've already created an array, and read the size of it.
|
144
|
+
* Now we need to read in n items, and add them to the array.
|
145
|
+
*/
|
146
|
+
static void
|
135
147
|
read_n_array_entries(VALUE array, int num)
|
136
148
|
{
|
137
149
|
extern unsigned char *serialized;
|
@@ -145,7 +157,7 @@ read_n_array_entries(VALUE array, int num)
|
|
145
157
|
int type = *serialized++;
|
146
158
|
|
147
159
|
switch(type) {
|
148
|
-
case
|
160
|
+
case PT_HASH_KEY:
|
149
161
|
item = read_string(true);
|
150
162
|
break;
|
151
163
|
}
|
@@ -156,7 +168,12 @@ read_n_array_entries(VALUE array, int num)
|
|
156
168
|
}
|
157
169
|
|
158
170
|
|
159
|
-
|
171
|
+
/*
|
172
|
+
* Given a size, read in a string of that size. Note that Storable seems to use 319 as a
|
173
|
+
* magic value, meaning the string should be read until a very low character is found.
|
174
|
+
* I should test this more specifically, but it's somewhere lower than "0", aka 48.
|
175
|
+
*/
|
176
|
+
static VALUE
|
160
177
|
read_string(bool extended_size)
|
161
178
|
{
|
162
179
|
extern unsigned char *serialized;
|
@@ -192,8 +209,9 @@ read_string(bool extended_size)
|
|
192
209
|
|
193
210
|
/*
|
194
211
|
* Extended sizes are given as [w,x,y,z], where the size is 256*y + z.
|
212
|
+
* This should really be read as a uint_32t, I guess.
|
195
213
|
*/
|
196
|
-
int
|
214
|
+
static int
|
197
215
|
read_extended_size()
|
198
216
|
{
|
199
217
|
extern unsigned char *serialized;
|
@@ -211,7 +229,7 @@ read_extended_size()
|
|
211
229
|
/*
|
212
230
|
* Just one byte.
|
213
231
|
*/
|
214
|
-
int
|
232
|
+
static int
|
215
233
|
read_compact_size() {
|
216
234
|
check_pointer(serialized);
|
217
235
|
extern unsigned char *serialized;
|