rcstorable 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|