sereal 0.0.7 → 0.0.8
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.
- 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
|
|