sereal 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/rsrl +5 -3
- data/ext/sereal/buffer.h +133 -57
- data/ext/sereal/decode.c +224 -187
- data/ext/sereal/encode.c +187 -184
- data/ext/sereal/proto.h +1 -1
- data/ext/sereal/sereal.c +18 -2
- data/ext/sereal/sereal.h +34 -23
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06153f3bc1df8650c81eff2d5ef44f260920830c
|
4
|
+
data.tar.gz: e6e3e806787c10d2511ff7ea63256f922a45b0f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 278c31a6754bd905858874e88d3cd87ed88986dbec21e3d7a5544d8b3fd7fab2d011ac3f7e22aff808a412e5b900e8f8d12427e8c1b3d05823cba271075b7379
|
7
|
+
data.tar.gz: a10efcc28da1409da425e6e6c222712fdaa7d62bee525728d9ea9b1edfc2a34ea0b14cb358fd98540063b4af1623f5e3b5995d0f17c251f044e67243513bea21
|
data/bin/rsrl
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
begin
|
3
|
-
require '
|
3
|
+
require File.join(File.dirname(__FILE__),'..','lib','sereal')
|
4
4
|
rescue LoadError
|
5
5
|
require 'sereal'
|
6
6
|
end
|
7
7
|
|
8
|
-
content = ARGF.read
|
8
|
+
content = ENV['Sereal_STREAM'] ? STDIN : ARGF.read
|
9
9
|
compress = Sereal::RAW
|
10
10
|
|
11
11
|
{'Sereal_SNAPPY' => Sereal::SNAPPY,'Sereal_SNAPPY_INCR' => Sereal::SNAPPY_INCR }.each do |k,v|
|
@@ -13,9 +13,11 @@ compress = Sereal::RAW
|
|
13
13
|
compress = v
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
|
+
if ENV['Sereal_STREAM'] || content[0..3] == '=srl'
|
17
18
|
Sereal.decode(content) do |x|
|
18
19
|
STDOUT.write(x)
|
20
|
+
puts
|
19
21
|
end
|
20
22
|
else
|
21
23
|
STDOUT.write(Sereal.encode(eval(content), compress))
|
data/ext/sereal/buffer.h
CHANGED
@@ -1,105 +1,181 @@
|
|
1
1
|
#include "sereal.h"
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
#include <errno.h>
|
3
|
+
static void s_dump(sereal_t *s);
|
4
|
+
|
5
|
+
static inline void s_free_data_if_not_mine(sereal_t *s) {
|
6
|
+
if (!(s->flags & FLAG_NOT_MINE)) {
|
7
|
+
if (s->data)
|
8
|
+
free(s->data);
|
9
|
+
s->data = NULL;
|
10
|
+
}
|
10
11
|
}
|
11
12
|
|
12
|
-
static inline sereal_t *
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
static inline void s_reset_tracker(sereal_t *s) {
|
14
|
+
if (s->tracked != Qnil)
|
15
|
+
rb_gc_unregister_address(&s->tracked);
|
16
|
+
s->tracked = Qnil;
|
16
17
|
}
|
17
18
|
|
18
19
|
static inline void s_destroy(sereal_t *s) {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
if (!s)
|
21
|
+
return;
|
22
|
+
|
23
|
+
s_reset_tracker(s);
|
24
|
+
s_free_data_if_not_mine(s);
|
25
|
+
free(s);
|
26
|
+
}
|
27
|
+
|
28
|
+
static inline void *s_realloc_or_raise(sereal_t *s, void *p, u32 n) {
|
29
|
+
u8 *buf = realloc(p,n);
|
30
|
+
if (!buf)
|
31
|
+
s_raise(s,rb_eNoMemError,"memory allocation failure for %d bytes",n);
|
32
|
+
return buf;
|
33
|
+
}
|
34
|
+
static inline void *s_alloc_or_raise(sereal_t *s,u32 n) {
|
35
|
+
return s_realloc_or_raise(s,NULL,n);
|
36
|
+
}
|
23
37
|
|
24
|
-
|
38
|
+
static inline sereal_t * s_create(void) {
|
39
|
+
sereal_t *s = s_alloc_or_raise(NULL,sizeof(*s));
|
40
|
+
ZERO(s,sizeof(*s));
|
41
|
+
s->tracked = Qnil;
|
42
|
+
return s;
|
25
43
|
}
|
26
44
|
|
27
45
|
static inline void s_alloc(sereal_t *s, u32 len) {
|
28
|
-
|
29
|
-
|
46
|
+
if (s->rsize > s->size + len)
|
47
|
+
return;
|
30
48
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
49
|
+
u32 size = s->size + len + 512; // every time allocate 512b more, so we wont alloc for a while
|
50
|
+
u8 *buf = s_realloc_or_raise(s,s->data,size);
|
51
|
+
s->data = buf;
|
52
|
+
s->rsize = size;
|
35
53
|
}
|
36
54
|
|
37
55
|
static inline void s_append(sereal_t *s, void *suffix, u32 s_len) {
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
56
|
+
s_alloc(s,s_len);
|
57
|
+
COPY(suffix,(s->data + s->size), s_len);
|
58
|
+
s->size += s_len;
|
59
|
+
s->pos += s_len;
|
42
60
|
}
|
43
61
|
|
44
62
|
static inline void s_append_u8(sereal_t *s,u8 b) {
|
45
|
-
|
63
|
+
s_append(s,&b,sizeof(b));
|
46
64
|
}
|
47
65
|
|
48
66
|
static inline void s_append_u32(sereal_t *s,u32 b) {
|
49
|
-
|
67
|
+
s_append(s,&b,sizeof(b));
|
68
|
+
}
|
69
|
+
|
70
|
+
static inline int s_read_stream(sereal_t *s, u32 end) {
|
71
|
+
u32 pos = s->pos;
|
72
|
+
while (s->size < end) {
|
73
|
+
u32 req = end - s->size;
|
74
|
+
u32 left = s->buffer.size - s->buffer.pos;
|
75
|
+
if (left == 0) {
|
76
|
+
int rc = read(s->fd,s->buffer.data,BUFSIZ);
|
77
|
+
if (rc <= 0)
|
78
|
+
return -1;
|
79
|
+
s->buffer.size = rc;
|
80
|
+
s->buffer.pos = 0;
|
81
|
+
left = rc;
|
82
|
+
}
|
83
|
+
left = left > req ? req : left;
|
84
|
+
s_append(s,s->buffer.data + s->buffer.pos,left);
|
85
|
+
s->buffer.pos += left;
|
86
|
+
};
|
87
|
+
s->pos = pos;
|
88
|
+
return 1;
|
50
89
|
}
|
51
90
|
|
52
91
|
static inline void *s_get_p_at_pos(sereal_t *s, u32 pos,u32 req) {
|
53
|
-
|
54
|
-
|
55
|
-
|
92
|
+
// returning s->data[pos], so we just make size count from 0
|
93
|
+
if (pos + req >= s->size) {
|
94
|
+
if (s->flags & FLAG_STREAM) {
|
95
|
+
if (s_read_stream(s,pos + req + 1) < 0) {
|
96
|
+
s_raise(s,rb_eRangeError,"stream request for %d bytes failed (err: %s)",
|
97
|
+
req,strerror(errno));
|
98
|
+
}
|
99
|
+
} else {
|
100
|
+
u32 size = s->size;
|
101
|
+
s_raise(s,rb_eRangeError,"position is out of bounds (%d + %d > %d)",pos,req,size);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
return &s->data[pos];
|
56
105
|
}
|
57
106
|
|
58
107
|
static inline void *s_get_p_at_pos_bang(sereal_t *s, u32 pos,u32 req) {
|
59
|
-
|
60
|
-
|
61
|
-
|
108
|
+
void *p = s_get_p_at_pos(s,pos,req);
|
109
|
+
s->pos += req;
|
110
|
+
return p;
|
62
111
|
}
|
63
112
|
|
113
|
+
static inline void *s_end_p(sereal_t *s) {
|
114
|
+
return s_get_p_at_pos(s,s->size - 1,0);
|
115
|
+
}
|
116
|
+
static inline void *s_get_p_req_inclusive(sereal_t *s, int req) {
|
117
|
+
return s_get_p_at_pos(s,s->pos,req > 0 ? req - 1 : 0);
|
118
|
+
}
|
119
|
+
static inline void *s_get_p_req(sereal_t *s, int req) {
|
120
|
+
return s_get_p_at_pos(s,s->pos,req);
|
121
|
+
}
|
64
122
|
static inline void *s_get_p(sereal_t *s) {
|
65
|
-
|
123
|
+
return s_get_p_at_pos(s,s->pos,0);
|
66
124
|
}
|
67
125
|
|
68
126
|
static inline u8 s_get_u8(sereal_t *s) {
|
69
|
-
|
127
|
+
return *((u8 *) s_get_p(s));
|
70
128
|
}
|
71
129
|
|
72
130
|
static inline u8 s_get_u8_bang(sereal_t *s) {
|
73
|
-
|
74
|
-
|
75
|
-
|
131
|
+
u8 r = s_get_u8(s);
|
132
|
+
s->pos++;
|
133
|
+
return r;
|
76
134
|
}
|
77
135
|
|
78
136
|
static inline u32 s_get_u32_bang(sereal_t *s) {
|
79
|
-
|
80
|
-
|
81
|
-
|
137
|
+
u32 *r = (u32 *) s_get_p_at_pos(s,s->pos,sizeof(u32) - 1); /* current position + 3 bytes */
|
138
|
+
s->pos += sizeof(*r);
|
139
|
+
return *r;
|
140
|
+
}
|
141
|
+
|
142
|
+
static inline float s_get_float_bang(sereal_t *s) {
|
143
|
+
float *f = (float *) s_get_p_at_pos(s,s->pos,sizeof(*f) - 1);
|
144
|
+
s->pos += sizeof(*f);
|
145
|
+
return *f;
|
146
|
+
}
|
147
|
+
|
148
|
+
static inline double s_get_double_bang(sereal_t *s) {
|
149
|
+
double *d = (double *) s_get_p_at_pos(s,s->pos,sizeof(*d) - 1);
|
150
|
+
s->pos += sizeof(*d);
|
151
|
+
return *d;
|
152
|
+
}
|
153
|
+
|
154
|
+
static inline long double s_get_long_double_bang(sereal_t *s) {
|
155
|
+
long double *d = (long double *) s_get_p_at_pos(s,s->pos,sizeof(*d) - 1);
|
156
|
+
s->pos += sizeof(*d);
|
157
|
+
return *d;
|
82
158
|
}
|
83
159
|
|
84
160
|
static inline u32 s_shift_position_bang(sereal_t *s, u32 len) {
|
85
|
-
|
86
|
-
|
161
|
+
s->pos += len;
|
162
|
+
return len;
|
87
163
|
}
|
88
164
|
|
89
165
|
static void b_dump(u8 *p, u32 len, u32 pos) {
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
166
|
+
int i;
|
167
|
+
|
168
|
+
fprintf(stderr,"\n-----------\n");
|
169
|
+
for (i = 0; i < len; i++) {
|
170
|
+
if (i == pos)
|
171
|
+
fprintf(stderr," [%c %d] ",p[i],p[i]);
|
172
|
+
else
|
173
|
+
fprintf(stderr," (%c %d) ",p[i],p[i]);
|
174
|
+
}
|
175
|
+
fprintf(stderr,"\n-----------\n");
|
100
176
|
}
|
101
177
|
|
102
178
|
static void s_dump(sereal_t *s) {
|
103
|
-
|
179
|
+
E("[ pos: %d, size: %d, rsize: %d ]\n",s->pos,s->size,s->rsize);
|
180
|
+
b_dump(s->data,s->size,s->pos);
|
104
181
|
}
|
105
|
-
|
data/ext/sereal/decode.c
CHANGED
@@ -4,295 +4,332 @@
|
|
4
4
|
#include "snappy/csnappy_decompress.c"
|
5
5
|
|
6
6
|
static VALUE s_default_reader(sereal_t *s, u8 tag) {
|
7
|
-
|
8
|
-
|
9
|
-
return Qnil;
|
7
|
+
s_raise(s,rb_eTypeError,"unsupported tag %d [ 0x%x ]",tag,tag);
|
8
|
+
return Qnil;
|
10
9
|
}
|
11
10
|
|
12
11
|
/* VARINT */
|
13
12
|
static u64 s_get_varint_bang(sereal_t *s) {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
u64 uv = 0;
|
14
|
+
unsigned int lshift = 0;
|
15
|
+
while (s_get_u8(s) & 0x80) {
|
16
|
+
uv |= ((u64)(s_get_u8_bang(s) & 0x7F) << lshift);
|
17
|
+
lshift += 7;
|
18
|
+
if (lshift > (sizeof(uv) * 8))
|
19
|
+
s_raise(s,rb_eTypeError, "varint too big");
|
20
|
+
}
|
21
|
+
uv |= ((u64)(s_get_u8_bang(s)) << lshift);
|
22
|
+
return uv;
|
24
23
|
}
|
25
24
|
|
26
25
|
/* ZIGZAG */
|
27
26
|
static VALUE s_read_zigzag(sereal_t *s, u8 tag) {
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
signed long long z = 0;
|
28
|
+
u64 v = s_get_varint_bang(s);
|
29
|
+
if (v & 1) {
|
30
|
+
z = ((long) v >> 1);
|
31
|
+
} else {
|
32
|
+
z = (long) v >> 1;
|
33
|
+
}
|
34
|
+
return LL2NUM(z);
|
36
35
|
}
|
37
36
|
|
38
37
|
/* VARINT */
|
39
38
|
static VALUE s_read_varint(sereal_t *s, u8 tag) {
|
40
|
-
|
39
|
+
return ULL2NUM(s_get_varint_bang(s));
|
41
40
|
}
|
42
41
|
|
43
42
|
/* FLOAT */
|
44
43
|
static VALUE s_read_float(sereal_t *s, u8 tag) {
|
45
|
-
|
46
|
-
return DBL2NUM((double) *f);
|
44
|
+
return DBL2NUM(s_get_float_bang(s));
|
47
45
|
}
|
48
46
|
|
49
47
|
/* DOUBLE */
|
50
48
|
static VALUE s_read_double(sereal_t *s, u8 tag) {
|
51
|
-
|
52
|
-
return DBL2NUM(*d);
|
49
|
+
return DBL2NUM(s_get_double_bang(s));
|
53
50
|
}
|
54
51
|
|
55
52
|
/* LONG DOUBLE */
|
56
53
|
static VALUE s_read_long_double(sereal_t *s, u8 tag) {
|
57
|
-
|
58
|
-
return DBL2NUM((double) *d);
|
54
|
+
return DBL2NUM((double) s_get_long_double(s));
|
59
55
|
}
|
60
56
|
|
61
57
|
/* POS */
|
62
58
|
static VALUE s_read_small_positive_int(sereal_t *s, u8 tag) {
|
63
|
-
|
59
|
+
return INT2FIX(tag);
|
64
60
|
}
|
65
61
|
|
66
62
|
/* NEG */
|
67
63
|
static VALUE s_read_small_negative_int(sereal_t *s, u8 tag) {
|
68
|
-
|
64
|
+
return INT2FIX(tag - 32);
|
69
65
|
}
|
70
66
|
|
71
67
|
/* ARRAY */
|
72
68
|
static inline VALUE s_read_array_with_len(sereal_t *s, u32 len) {
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
VALUE arr[len];
|
70
|
+
register u32 i;
|
71
|
+
for (i = 0; i < len; i++)
|
72
|
+
arr[i] = sereal_to_rb_object(s);
|
73
|
+
return rb_ary_new4(len,arr);
|
78
74
|
}
|
79
75
|
|
80
76
|
/* ARRAY */
|
81
77
|
static VALUE s_read_array(sereal_t *s,u8 tag) {
|
82
|
-
|
78
|
+
return s_read_array_with_len(s,s_get_varint_bang(s));
|
83
79
|
}
|
84
80
|
|
85
81
|
/* ARRAY */
|
86
82
|
static VALUE s_read_arrayref(sereal_t *s, u8 tag) {
|
87
|
-
|
83
|
+
return s_read_array_with_len(s,tag & SRL_MASK_ARRAYREF_COUNT);
|
88
84
|
}
|
89
85
|
|
90
86
|
/* HASH */
|
91
87
|
static inline VALUE s_read_hash_with_len(sereal_t *s, u32 len) {
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
88
|
+
VALUE hash = rb_hash_new();
|
89
|
+
register u32 i;
|
90
|
+
for (i = 0; i < len; i++) {
|
91
|
+
VALUE key = sereal_to_rb_object(s);
|
92
|
+
VALUE value = sereal_to_rb_object(s);
|
93
|
+
rb_hash_aset(hash,key,value);
|
94
|
+
}
|
95
|
+
return hash;
|
100
96
|
}
|
101
97
|
|
102
98
|
/* HASH */
|
103
99
|
static VALUE s_read_hash(sereal_t *s, u8 tag) {
|
104
|
-
|
100
|
+
return s_read_hash_with_len(s,s_get_varint_bang(s));
|
105
101
|
}
|
106
102
|
|
107
103
|
/* HASH */
|
108
104
|
static VALUE s_read_hashref(sereal_t *s, u8 tag) {
|
109
|
-
|
105
|
+
return s_read_hash_with_len(s,tag & SRL_MASK_HASHREF_COUNT);
|
110
106
|
}
|
111
107
|
|
112
108
|
static VALUE s_read_rb_string_bang(sereal_t *s,u8 t) {
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
109
|
+
u32 len = 0;
|
110
|
+
VALUE string;
|
111
|
+
// len - 1: we also use the current byte, similar to u32,float.. casts
|
112
|
+
#define RETURN_STRING(fx_l,fx_gen) \
|
113
|
+
do { \
|
114
|
+
len = fx_l; \
|
115
|
+
u8 *ptr = len == 0 ? 0 : s_get_p_req_inclusive(s,len); \
|
116
|
+
string = fx_gen; \
|
117
|
+
s_shift_position_bang(s,len); \
|
118
|
+
return string; \
|
119
|
+
} while(0);
|
120
|
+
|
121
|
+
if (t == SRL_HDR_STR_UTF8) {
|
122
|
+
RETURN_STRING(s_get_varint_bang(s),
|
123
|
+
rb_enc_str_new(ptr,len,
|
124
|
+
rb_utf8_encoding()));
|
125
|
+
} else if (t == SRL_HDR_BINARY || t == SRL_HDR_SYM) {
|
126
|
+
RETURN_STRING(s_get_varint_bang(s),
|
127
|
+
rb_str_new(ptr,len));
|
128
|
+
} else if (IS_SHORT_BINARY(t)) {
|
129
|
+
RETURN_STRING((t & SRL_MASK_SHORT_BINARY_LEN),
|
130
|
+
rb_str_new(ptr, len));
|
131
|
+
}
|
134
132
|
#undef RETURN_STRING
|
135
|
-
|
133
|
+
s_raise(s,rb_eTypeError, "undefined string type %d",t);
|
136
134
|
}
|
137
135
|
|
138
136
|
static VALUE s_read_next_rb_string_bang(sereal_t *s) {
|
139
|
-
|
137
|
+
return s_read_rb_string_bang(s,s_get_u8_bang(s));
|
140
138
|
}
|
141
139
|
|
142
140
|
static VALUE s_read_regexp(sereal_t *s, u8 tag) {
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
141
|
+
VALUE pattern = s_read_next_rb_string_bang(s);
|
142
|
+
VALUE modifiers = s_read_next_rb_string_bang(s);
|
143
|
+
|
144
|
+
u32 flags = 0;
|
145
|
+
if (strchr(RSTRING_PTR(modifiers),'i'))
|
146
|
+
flags |= IGNORECASE;
|
147
|
+
|
148
|
+
if (strchr(RSTRING_PTR(modifiers),'m'))
|
149
|
+
flags |= MULTILINE;
|
150
|
+
|
151
|
+
if (strchr(RSTRING_PTR(modifiers),'x'))
|
152
|
+
flags |= EXTENDED;
|
153
|
+
|
154
|
+
#ifdef RUBINIUS
|
155
|
+
return rb_reg_new(RSTRING_PTR(pattern),RSTRING_LEN(pattern),flags);
|
156
|
+
#else
|
157
|
+
return rb_reg_new_str(pattern,flags);
|
158
|
+
#endif
|
160
159
|
}
|
161
160
|
|
162
161
|
static VALUE s_read_nil(sereal_t *s, u8 tag) {
|
163
|
-
|
162
|
+
return Qnil;
|
164
163
|
}
|
165
164
|
|
166
165
|
static VALUE s_read_true(sereal_t *s, u8 tag) {
|
167
|
-
|
166
|
+
return Qtrue;
|
168
167
|
}
|
169
168
|
|
170
169
|
static VALUE s_read_false(sereal_t *s, u8 tag) {
|
171
|
-
|
170
|
+
return Qfalse;
|
172
171
|
}
|
173
172
|
|
174
173
|
static VALUE s_read_pad(sereal_t *s, u8 tag) {
|
175
|
-
|
176
|
-
|
174
|
+
/* just skip this byte and go forward */
|
175
|
+
return sereal_to_rb_object(s);
|
177
176
|
}
|
178
177
|
|
179
178
|
static VALUE s_read_extend(sereal_t *s, u8 tag) {
|
180
|
-
|
179
|
+
s_raise(s,rb_eArgError,"extend tags are not supported");
|
181
180
|
}
|
182
181
|
|
183
182
|
static VALUE s_read_ref(sereal_t *s, u8 tag) {
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
183
|
+
u64 off = s_get_varint_bang(s);
|
184
|
+
if (s->tracked == Qnil)
|
185
|
+
s_raise(s,rb_eArgError,"there are no references stored");
|
186
|
+
return rb_hash_aref(s->tracked,INT2FIX(off + s->hdr_end));
|
188
187
|
}
|
189
188
|
|
190
189
|
static VALUE s_read_copy(sereal_t *s, u8 tag) {
|
191
|
-
|
192
|
-
|
190
|
+
VALUE ref = s_red_ref(s,tag);
|
191
|
+
return rb_obj_dup(ref);
|
193
192
|
}
|
194
193
|
|
195
194
|
VALUE sereal_to_rb_object(sereal_t *s) {
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
}
|
215
|
-
return decoded;
|
195
|
+
u8 t, tracked;
|
196
|
+
S_RECURSE_INC(s);
|
197
|
+
u32 pos;
|
198
|
+
while (s->pos < s->size || (s->flags & FLAG_STREAM)) {
|
199
|
+
t = s_get_u8_bang(s);
|
200
|
+
tracked = (t & SRL_HDR_TRACK_FLAG ? 1 : 0);
|
201
|
+
t &= ~SRL_HDR_TRACK_FLAG;
|
202
|
+
pos = s->pos;
|
203
|
+
|
204
|
+
S_RECURSE_DEC(s);
|
205
|
+
|
206
|
+
VALUE decoded = (*READERS[t])(s,t);
|
207
|
+
if (tracked) {
|
208
|
+
if (s->tracked == Qnil) {
|
209
|
+
s->tracked = rb_hash_new();
|
210
|
+
rb_gc_register_address(&s->tracked);
|
211
|
+
}
|
212
|
+
rb_hash_aset(s->tracked,INT2FIX(pos),decoded);
|
216
213
|
}
|
217
|
-
|
218
|
-
|
214
|
+
return decoded;
|
215
|
+
}
|
216
|
+
s_raise(s,rb_eArgError,"bad packet, or broken decoder");
|
217
|
+
return Qnil;
|
219
218
|
}
|
220
219
|
|
221
220
|
VALUE method_sereal_decode(VALUE self, VALUE args) {
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
221
|
+
u32 argc = RARRAY_LEN(args);
|
222
|
+
if (argc < 1)
|
223
|
+
rb_raise(rb_eArgError,"need at least 1 argument (object)");
|
224
|
+
VALUE payload = rb_ary_shift(args);
|
225
|
+
u8 have_block = rb_block_given_p();
|
226
|
+
sereal_t *s = s_create();
|
227
|
+
u64 offset = 0;
|
228
|
+
if (TYPE(payload) == T_FILE) {
|
229
|
+
if (!have_block)
|
230
|
+
s_raise(s,rb_eTypeError,"block is required when reading from a stream")
|
231
|
+
|
232
|
+
rb_io_t *fptr;
|
233
|
+
GetOpenFile(payload, fptr);
|
234
|
+
s->flags |= FLAG_STREAM;
|
235
|
+
s->fd = fptr->fd;
|
236
|
+
} else if (TYPE(payload) != T_STRING) {
|
237
|
+
rb_raise(rb_eTypeError,"can not decode objects of type %s",rb_obj_classname(payload));
|
238
|
+
}
|
239
|
+
|
231
240
|
again:
|
232
|
-
|
233
|
-
|
241
|
+
s->pos = 0;
|
242
|
+
s_reset_tracker(s);
|
243
|
+
|
244
|
+
if (s->flags & FLAG_STREAM) {
|
245
|
+
s->size = 0;
|
246
|
+
s->rsize = 0;
|
247
|
+
if (s_read_stream(s,__MIN_SIZE) < 0) {
|
248
|
+
s_destroy(s);
|
234
249
|
return Qnil;
|
235
250
|
}
|
251
|
+
|
252
|
+
} else {
|
253
|
+
u32 size = RSTRING_LEN(payload) - offset;
|
254
|
+
if (offset > RSTRING_LEN(payload) || (offset > 0 && size < __MIN_SIZE)) {
|
255
|
+
s_destroy(s);
|
256
|
+
return Qnil;
|
257
|
+
}
|
258
|
+
if (size < __MIN_SIZE)
|
259
|
+
s_raise(s,rb_eTypeError,"size(%d) is less then min packet size %d, offset: %d",size,__MIN_SIZE,offset);
|
260
|
+
|
236
261
|
s->flags |= FLAG_NOT_MINE;
|
237
262
|
s->data = RSTRING_PTR(payload) + offset;
|
238
|
-
s->size =
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
if (snappy_header_len == CSNAPPY_E_HEADER_BAD)
|
268
|
-
rb_raise(rb_eTypeError,"invalid snappy header");
|
269
|
-
u8 *uncompressed = alloc_or_raise(uncompressed_len);
|
270
|
-
int done = csnappy_decompress(s_get_p(s),
|
271
|
-
compressed_len,
|
272
|
-
uncompressed,
|
273
|
-
uncompressed_len) == CSNAPPY_E_OK ? 1 : 0;
|
274
|
-
if (!done)
|
275
|
-
s_raise(s,rb_eTypeError, "decompression failed error: %d type: %d, unompressed size: %d compressed size: %d",done,is_compressed,uncompressed_len,compressed_len);
|
276
|
-
|
277
|
-
offset += s->pos + compressed_len;
|
278
|
-
s->data = uncompressed;
|
279
|
-
s->size = uncompressed_len;
|
280
|
-
s->pos = 0;
|
281
|
-
s->flags &= ~FLAG_NOT_MINE;
|
263
|
+
s->size = size;
|
264
|
+
}
|
265
|
+
|
266
|
+
u32 magic = s_get_u32_bang(s);
|
267
|
+
if (magic != SRL_MAGIC_STRING_LILIPUTIAN)
|
268
|
+
s_raise(s,rb_eTypeError,"invalid header: %d (%x)",magic,magic);
|
269
|
+
|
270
|
+
u8 version = s_get_u8_bang(s);
|
271
|
+
u8 suffix = s_get_varint_bang(s);
|
272
|
+
u8 is_compressed;
|
273
|
+
|
274
|
+
if ((version & SRL_PROTOCOL_ENCODING_MASK) == SRL_PROTOCOL_ENCODING_SNAPPY)
|
275
|
+
is_compressed = __SNAPPY;
|
276
|
+
else if ((version & SRL_PROTOCOL_ENCODING_MASK) == SRL_PROTOCOL_ENCODING_SNAPPY_INCR)
|
277
|
+
is_compressed = __SNAPPY_INCR;
|
278
|
+
else
|
279
|
+
is_compressed = __RAW;
|
280
|
+
|
281
|
+
if (is_compressed) {
|
282
|
+
u32 uncompressed_len;
|
283
|
+
u32 compressed_len;
|
284
|
+
|
285
|
+
if (is_compressed == __SNAPPY_INCR) {
|
286
|
+
compressed_len = s_get_varint_bang(s);
|
287
|
+
} else {
|
288
|
+
if (s->flags & FLAG_STREAM)
|
289
|
+
s_raise(s,rb_eTypeError,"parsing non incremental compressed objects, from stream of data, is not supported");
|
290
|
+
|
291
|
+
compressed_len = s->size - s->pos;
|
282
292
|
}
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
293
|
+
|
294
|
+
if (s->flags & FLAG_STREAM)
|
295
|
+
s_get_p_req_inclusive(s,compressed_len);
|
296
|
+
|
297
|
+
int snappy_header_len = csnappy_get_uncompressed_length(s_get_p_req_inclusive(s,compressed_len),
|
298
|
+
compressed_len,
|
299
|
+
&uncompressed_len);
|
300
|
+
if (snappy_header_len == CSNAPPY_E_HEADER_BAD)
|
301
|
+
s_raise(s,rb_eTypeError,"invalid snappy header");
|
302
|
+
|
303
|
+
u8 *uncompressed = s_alloc_or_raise(s,uncompressed_len);
|
304
|
+
int done = csnappy_decompress(s_get_p_req_inclusive(s,compressed_len),
|
305
|
+
compressed_len,
|
306
|
+
uncompressed,
|
307
|
+
uncompressed_len) == CSNAPPY_E_OK ? 1 : 0;
|
308
|
+
if (!done)
|
309
|
+
s_raise(s,rb_eTypeError, "decompression failed error: %d type: %d, unompressed size: %d compressed size: %d",
|
310
|
+
done,is_compressed,uncompressed_len,compressed_len);
|
311
|
+
|
312
|
+
s_free_data_if_not_mine(s);
|
313
|
+
s->data = uncompressed;
|
314
|
+
s->size = uncompressed_len;
|
315
|
+
offset += s->pos + compressed_len;
|
316
|
+
s->pos = 0;
|
317
|
+
s->flags &= ~FLAG_NOT_MINE;
|
318
|
+
}
|
319
|
+
s->hdr_end = s->pos;
|
320
|
+
VALUE result = sereal_to_rb_object(s);
|
321
|
+
if (!is_compressed)
|
322
|
+
offset += s->pos;
|
323
|
+
if (have_block) {
|
324
|
+
rb_yield(result);
|
325
|
+
s_free_data_if_not_mine(s);
|
326
|
+
goto again;
|
327
|
+
} else {
|
328
|
+
if (s->pos < s->size) {
|
329
|
+
s_raise(s,rb_eTypeError,"there is still some data left in the buffer, use block read, otherwise we are losing it");
|
290
330
|
}
|
291
331
|
s_destroy(s);
|
292
|
-
if (have_block) {
|
293
|
-
rb_yield(result);
|
294
|
-
return Qnil;
|
295
|
-
}
|
296
332
|
return result;
|
333
|
+
}
|
297
334
|
}
|
298
335
|
|