schleyfox-bert 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{bert}
8
+ s.version = "1.1.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tom Preston-Werner"]
12
+ s.date = %q{2010-04-01}
13
+ s.description = %q{BERT Serializiation for Ruby}
14
+ s.email = %q{tom@mojombo.com}
15
+ s.extensions = ["ext/bert/c/extconf.rb", "ext/bert/c/extconf.rb"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".gitignore",
23
+ "History.txt",
24
+ "LICENSE",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bench/bench.rb",
29
+ "bench/decode_bench.rb",
30
+ "bench/encode_bench.rb",
31
+ "bench/results.txt",
32
+ "bert.gemspec",
33
+ "ext/bert/c/decode.c",
34
+ "ext/bert/c/extconf.rb",
35
+ "lib/bert.rb",
36
+ "lib/bert/bert.rb",
37
+ "lib/bert/decode.rb",
38
+ "lib/bert/decoder.rb",
39
+ "lib/bert/encode.rb",
40
+ "lib/bert/encoder.rb",
41
+ "lib/bert/types.rb",
42
+ "test/bert_test.rb",
43
+ "test/decoder_test.rb",
44
+ "test/encoder_test.rb",
45
+ "test/test_helper.rb"
46
+ ]
47
+ s.homepage = %q{http://github.com/mojombo/bert}
48
+ s.rdoc_options = ["--charset=UTF-8"]
49
+ s.require_paths = ["lib", "ext"]
50
+ s.rubygems_version = %q{1.3.6}
51
+ s.summary = %q{BERT Serializiation for Ruby}
52
+ s.test_files = [
53
+ "test/bert_test.rb",
54
+ "test/decoder_test.rb",
55
+ "test/encoder_test.rb",
56
+ "test/test_helper.rb"
57
+ ]
58
+
59
+ if s.respond_to? :specification_version then
60
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
61
+ s.specification_version = 3
62
+
63
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
64
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
65
+ else
66
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
67
+ end
68
+ else
69
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
70
+ end
71
+ end
72
+
@@ -0,0 +1,438 @@
1
+ #include "ruby.h"
2
+ #include <string.h>
3
+
4
+ #define ERL_VERSION 131
5
+ #define ERL_SMALL_INT 97
6
+ #define ERL_INT 98
7
+ #define ERL_SMALL_BIGNUM 110
8
+ #define ERL_LARGE_BIGNUM 111
9
+ #define ERL_FLOAT 99
10
+ #define ERL_ATOM 100
11
+ #define ERL_SMALL_TUPLE 104
12
+ #define ERL_LARGE_TUPLE 105
13
+ #define ERL_NIL 106
14
+ #define ERL_STRING 107
15
+ #define ERL_LIST 108
16
+ #define ERL_BIN 109
17
+
18
+ static VALUE mBERT;
19
+ static VALUE cDecode;
20
+ static VALUE cTuple;
21
+ void Init_decode();
22
+
23
+ VALUE method_decode(VALUE klass, VALUE rString);
24
+
25
+ VALUE read_any_raw(unsigned char **pData);
26
+
27
+ // printers
28
+
29
+ void p(VALUE val) {
30
+ rb_funcall(rb_mKernel, rb_intern("p"), 1, val);
31
+ }
32
+
33
+ // checkers
34
+
35
+ void check_int(int num) {
36
+ char buf[17];
37
+ sprintf(buf, "%u", num);
38
+ rb_raise(rb_eStandardError, buf);
39
+ }
40
+
41
+ void check_str(char *str) {
42
+ rb_raise(rb_eStandardError, str);
43
+ }
44
+
45
+ // string peekers/readers
46
+
47
+ unsigned int peek_1(unsigned char **pData) {
48
+ return (unsigned int) **pData;
49
+ }
50
+
51
+ unsigned int peek_2(unsigned char **pData) {
52
+ return (unsigned int) ((**pData << 8) + *(*pData + 1));
53
+ }
54
+
55
+ unsigned int peek_4(unsigned char **pData) {
56
+ return (unsigned int) ((**pData << 24) + (*(*pData + 1) << 16) + (*(*pData + 2) << 8) + *(*pData + 3));
57
+ }
58
+
59
+ unsigned int read_1(unsigned char **pData) {
60
+ unsigned int val = peek_1(pData);
61
+ *pData += 1;
62
+ return val;
63
+ }
64
+
65
+ unsigned int read_2(unsigned char **pData) {
66
+ unsigned int val = peek_2(pData);
67
+ *pData += 2;
68
+ return val;
69
+ }
70
+
71
+ unsigned int read_4(unsigned char **pData) {
72
+ unsigned int val = peek_4(pData);
73
+ *pData += 4;
74
+ return val;
75
+ }
76
+
77
+ // tuples
78
+
79
+ VALUE read_tuple(unsigned char **pData, unsigned int arity);
80
+
81
+ VALUE read_dict_pair(unsigned char **pData) {
82
+ if(read_1(pData) != ERL_SMALL_TUPLE) {
83
+ rb_raise(rb_eStandardError, "Invalid dict pair, not a small tuple");
84
+ }
85
+
86
+ int arity = read_1(pData);
87
+
88
+ if(arity != 2) {
89
+ rb_raise(rb_eStandardError, "Invalid dict pair, not a 2-tuple");
90
+ }
91
+
92
+ return read_tuple(pData, arity);
93
+ }
94
+
95
+ VALUE read_dict(unsigned char **pData) {
96
+ int type = read_1(pData);
97
+ if(!(type == ERL_LIST || type == ERL_NIL)) {
98
+ rb_raise(rb_eStandardError, "Invalid dict spec, not an erlang list");
99
+ }
100
+
101
+ unsigned int length = 0;
102
+ if(type == ERL_LIST) {
103
+ length = read_4(pData);
104
+ }
105
+
106
+ VALUE cHash = rb_const_get(rb_cObject, rb_intern("Hash"));
107
+ VALUE hash = rb_funcall(cHash, rb_intern("new"), 0);
108
+
109
+ int i;
110
+ for(i = 0; i < length; ++i) {
111
+ VALUE pair = read_dict_pair(pData);
112
+ VALUE first = rb_ary_entry(pair, 0);
113
+ VALUE last = rb_ary_entry(pair, 1);
114
+ rb_funcall(hash, rb_intern("store"), 2, first, last);
115
+ }
116
+
117
+ if(type == ERL_LIST) {
118
+ read_1(pData);
119
+ }
120
+
121
+ return hash;
122
+ }
123
+
124
+ VALUE read_complex_type(unsigned char **pData, int arity) {
125
+ VALUE type = read_any_raw(pData);
126
+ ID id = SYM2ID(type);
127
+ if(id == rb_intern("nil")) {
128
+ return Qnil;
129
+ } else if(id == rb_intern("true")) {
130
+ return Qtrue;
131
+ } else if(id == rb_intern("false")) {
132
+ return Qfalse;
133
+ } else if(id == rb_intern("time")) {
134
+ VALUE megasecs = read_any_raw(pData);
135
+ VALUE msecs = rb_funcall(megasecs, rb_intern("*"), 1, INT2NUM(1000000));
136
+ VALUE secs = read_any_raw(pData);
137
+ VALUE microsecs = read_any_raw(pData);
138
+ VALUE stamp = rb_funcall(msecs, rb_intern("+"), 1, secs);
139
+ return rb_funcall(rb_cTime, rb_intern("at"), 2, stamp, microsecs);
140
+ } else if(id == rb_intern("regex")) {
141
+ VALUE source = read_any_raw(pData);
142
+ VALUE opts = read_any_raw(pData);
143
+ int flags = 0;
144
+ if(rb_ary_includes(opts, ID2SYM(rb_intern("caseless"))))
145
+ flags = flags | 1;
146
+ if(rb_ary_includes(opts, ID2SYM(rb_intern("extended"))))
147
+ flags = flags | 2;
148
+ if(rb_ary_includes(opts, ID2SYM(rb_intern("multiline"))))
149
+ flags = flags | 4;
150
+ return rb_funcall(rb_cRegexp, rb_intern("new"), 2, source, INT2NUM(flags));
151
+ } else if(id == rb_intern("dict")) {
152
+ return read_dict(pData);
153
+ } else {
154
+ return Qnil;
155
+ }
156
+ }
157
+
158
+ VALUE read_tuple(unsigned char **pData, unsigned int arity) {
159
+ if(arity > 0) {
160
+ VALUE tag = read_any_raw(pData);
161
+ if(SYM2ID(tag) == rb_intern("bert")) {
162
+ return read_complex_type(pData, arity);
163
+ } else {
164
+ VALUE tuple = rb_funcall(cTuple, rb_intern("new"), 1, INT2NUM(arity));
165
+ rb_ary_store(tuple, 0, tag);
166
+ int i;
167
+ for(i = 1; i < arity; ++i) {
168
+ rb_ary_store(tuple, i, read_any_raw(pData));
169
+ }
170
+ return tuple;
171
+ }
172
+ } else {
173
+ return rb_funcall(cTuple, rb_intern("new"), 0);
174
+ }
175
+ }
176
+
177
+ VALUE read_small_tuple(unsigned char **pData) {
178
+ if(read_1(pData) != ERL_SMALL_TUPLE) {
179
+ rb_raise(rb_eStandardError, "Invalid Type, not a small tuple");
180
+ }
181
+
182
+ int arity = read_1(pData);
183
+ return read_tuple(pData, arity);
184
+ }
185
+
186
+ VALUE read_large_tuple(unsigned char **pData) {
187
+ if(read_1(pData) != ERL_LARGE_TUPLE) {
188
+ rb_raise(rb_eStandardError, "Invalid Type, not a large tuple");
189
+ }
190
+
191
+ unsigned int arity = read_4(pData);
192
+ return read_tuple(pData, arity);
193
+ }
194
+
195
+ // lists
196
+
197
+ VALUE read_list(unsigned char **pData) {
198
+ if(read_1(pData) != ERL_LIST) {
199
+ rb_raise(rb_eStandardError, "Invalid Type, not an erlang list");
200
+ }
201
+
202
+ unsigned int size = read_4(pData);
203
+
204
+ VALUE array = rb_ary_new2(size);
205
+
206
+ int i;
207
+ for(i = 0; i < size; ++i) {
208
+ rb_ary_store(array, i, read_any_raw(pData));
209
+ }
210
+
211
+ read_1(pData);
212
+
213
+ return array;
214
+ }
215
+
216
+ // primitives
217
+
218
+ void read_string_raw(unsigned char *dest, unsigned char **pData, unsigned int length) {
219
+ memcpy((char *) dest, (char *) *pData, length);
220
+ *(dest + length) = (unsigned char) 0;
221
+ *pData += length;
222
+ }
223
+
224
+ VALUE read_bin(unsigned char **pData) {
225
+ if(read_1(pData) != ERL_BIN) {
226
+ rb_raise(rb_eStandardError, "Invalid Type, not an erlang binary");
227
+ }
228
+
229
+ unsigned int length = read_4(pData);
230
+
231
+ VALUE rStr = rb_str_new((char *) *pData, length);
232
+ *pData += length;
233
+
234
+ return rStr;
235
+ }
236
+
237
+ VALUE read_string(unsigned char **pData) {
238
+ if(read_1(pData) != ERL_STRING) {
239
+ rb_raise(rb_eStandardError, "Invalid Type, not an erlang string");
240
+ }
241
+
242
+ int length = read_2(pData);
243
+ VALUE array = rb_ary_new2(length);
244
+
245
+ int i = 0;
246
+ for(i; i < length; ++i) {
247
+ rb_ary_store(array, i, INT2NUM(**pData));
248
+ *pData += 1;
249
+ }
250
+
251
+ return array;
252
+ }
253
+
254
+ VALUE read_atom(unsigned char **pData) {
255
+ if(read_1(pData) != ERL_ATOM) {
256
+ rb_raise(rb_eStandardError, "Invalid Type, not an atom");
257
+ }
258
+
259
+ int length = read_2(pData);
260
+
261
+ unsigned char buf[length + 1];
262
+ read_string_raw(buf, pData, length);
263
+
264
+ return ID2SYM(rb_intern((char *) buf));
265
+ }
266
+
267
+ VALUE read_small_int(unsigned char **pData) {
268
+ if(read_1(pData) != ERL_SMALL_INT) {
269
+ rb_raise(rb_eStandardError, "Invalid Type, not a small int");
270
+ }
271
+
272
+ int value = read_1(pData);
273
+
274
+ return INT2FIX(value);
275
+ }
276
+
277
+ VALUE read_int(unsigned char **pData) {
278
+ if(read_1(pData) != ERL_INT) {
279
+ rb_raise(rb_eStandardError, "Invalid Type, not an int");
280
+ }
281
+
282
+ long long value = read_4(pData);
283
+
284
+ long long negative = ((value >> 31) & 0x1 == 1);
285
+
286
+ if(negative) {
287
+ value = (value - ((long long) 1 << 32));
288
+ }
289
+
290
+ return INT2FIX(value);
291
+ }
292
+
293
+ VALUE read_small_bignum(unsigned char **pData) {
294
+ if(read_1(pData) != ERL_SMALL_BIGNUM) {
295
+ rb_raise(rb_eStandardError, "Invalid Type, not a small bignum");
296
+ }
297
+
298
+ unsigned int size = read_1(pData);
299
+ unsigned int sign = read_1(pData);
300
+
301
+ VALUE num = INT2NUM(0);
302
+ VALUE tmp;
303
+
304
+ unsigned char buf[size + 1];
305
+ read_string_raw(buf, pData, size);
306
+
307
+ int i;
308
+ for(i = 0; i < size; ++i) {
309
+ tmp = INT2FIX(*(buf + i));
310
+ tmp = rb_funcall(tmp, rb_intern("<<"), 1, INT2NUM(i * 8));
311
+ num = rb_funcall(num, rb_intern("+"), 1, tmp);
312
+ }
313
+
314
+ if(sign) {
315
+ num = rb_funcall(num, rb_intern("*"), 1, INT2NUM(-1));
316
+ }
317
+
318
+ return num;
319
+ }
320
+
321
+ VALUE read_large_bignum(unsigned char **pData) {
322
+ if(read_1(pData) != ERL_LARGE_BIGNUM) {
323
+ rb_raise(rb_eStandardError, "Invalid Type, not a small bignum");
324
+ }
325
+
326
+ unsigned int size = read_4(pData);
327
+ unsigned int sign = read_1(pData);
328
+
329
+ VALUE num = INT2NUM(0);
330
+ VALUE tmp;
331
+
332
+ unsigned char buf[size + 1];
333
+ read_string_raw(buf, pData, size);
334
+
335
+ int i;
336
+ for(i = 0; i < size; ++i) {
337
+ tmp = INT2FIX(*(buf + i));
338
+ tmp = rb_funcall(tmp, rb_intern("<<"), 1, INT2NUM(i * 8));
339
+
340
+ num = rb_funcall(num, rb_intern("+"), 1, tmp);
341
+ }
342
+
343
+ if(sign) {
344
+ num = rb_funcall(num, rb_intern("*"), 1, INT2NUM(-1));
345
+ }
346
+
347
+ return num;
348
+ }
349
+
350
+ VALUE read_float(unsigned char **pData) {
351
+ if(read_1(pData) != ERL_FLOAT) {
352
+ rb_raise(rb_eStandardError, "Invalid Type, not a float");
353
+ }
354
+
355
+ unsigned char buf[32];
356
+ read_string_raw(buf, pData, 31);
357
+
358
+ VALUE rString = rb_str_new2((char *) buf);
359
+
360
+ return rb_funcall(rString, rb_intern("to_f"), 0);
361
+ }
362
+
363
+ VALUE read_nil(unsigned char **pData) {
364
+ if(read_1(pData) != ERL_NIL) {
365
+ rb_raise(rb_eStandardError, "Invalid Type, not a nil list");
366
+ }
367
+
368
+ return rb_ary_new2(0);
369
+ }
370
+
371
+ // read_any_raw
372
+
373
+ VALUE read_any_raw(unsigned char **pData) {
374
+ switch(peek_1(pData)) {
375
+ case ERL_SMALL_INT:
376
+ return read_small_int(pData);
377
+ break;
378
+ case ERL_INT:
379
+ return read_int(pData);
380
+ break;
381
+ case ERL_FLOAT:
382
+ return read_float(pData);
383
+ break;
384
+ case ERL_ATOM:
385
+ return read_atom(pData);
386
+ break;
387
+ case ERL_SMALL_TUPLE:
388
+ return read_small_tuple(pData);
389
+ break;
390
+ case ERL_LARGE_TUPLE:
391
+ return read_large_tuple(pData);
392
+ break;
393
+ case ERL_NIL:
394
+ return read_nil(pData);
395
+ break;
396
+ case ERL_STRING:
397
+ return read_string(pData);
398
+ break;
399
+ case ERL_LIST:
400
+ return read_list(pData);
401
+ break;
402
+ case ERL_BIN:
403
+ return read_bin(pData);
404
+ break;
405
+ case ERL_SMALL_BIGNUM:
406
+ return read_small_bignum(pData);
407
+ break;
408
+ case ERL_LARGE_BIGNUM:
409
+ return read_large_bignum(pData);
410
+ break;
411
+ }
412
+ return Qnil;
413
+ }
414
+
415
+ VALUE method_decode(VALUE klass, VALUE rString) {
416
+ unsigned char *data = (unsigned char *) StringValuePtr(rString);
417
+
418
+ unsigned char **pData = &data;
419
+
420
+ // check protocol version
421
+ if(read_1(pData) != ERL_VERSION) {
422
+ rb_raise(rb_eStandardError, "Bad Magic");
423
+ }
424
+
425
+ return read_any_raw(pData);
426
+ }
427
+
428
+ VALUE method_impl(VALUE klass) {
429
+ return rb_str_new("C", 1);
430
+ }
431
+
432
+ void Init_decode() {
433
+ mBERT = rb_const_get(rb_cObject, rb_intern("BERT"));
434
+ cDecode = rb_define_class_under(mBERT, "Decode", rb_cObject);
435
+ cTuple = rb_const_get(mBERT, rb_intern("Tuple"));
436
+ rb_define_singleton_method(cDecode, "decode", method_decode, 1);
437
+ rb_define_singleton_method(cDecode, "impl", method_impl, 0);
438
+ }