hx_cbor 2021.8.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +30 -0
  3. data/.travis.yml +24 -0
  4. data/ChangeLog +106 -0
  5. data/Gemfile +11 -0
  6. data/README.rdoc +191 -0
  7. data/Rakefile +97 -0
  8. data/doclib/cbor.rb +80 -0
  9. data/doclib/cbor/buffer.rb +193 -0
  10. data/doclib/cbor/core_ext.rb +133 -0
  11. data/doclib/cbor/error.rb +14 -0
  12. data/doclib/cbor/packer.rb +133 -0
  13. data/doclib/cbor/simple.rb +15 -0
  14. data/doclib/cbor/tagged.rb +16 -0
  15. data/doclib/cbor/unpacker.rb +138 -0
  16. data/ext/cbor/3424.i.rb +29 -0
  17. data/ext/cbor/buffer.c +693 -0
  18. data/ext/cbor/buffer.h +484 -0
  19. data/ext/cbor/buffer_class.c +516 -0
  20. data/ext/cbor/buffer_class.h +41 -0
  21. data/ext/cbor/cbor.h +69 -0
  22. data/ext/cbor/compat.h +147 -0
  23. data/ext/cbor/core_ext.c +201 -0
  24. data/ext/cbor/core_ext.h +35 -0
  25. data/ext/cbor/example.rb +10 -0
  26. data/ext/cbor/extconf.rb +29 -0
  27. data/ext/cbor/install.sh +1 -0
  28. data/ext/cbor/packer.c +169 -0
  29. data/ext/cbor/packer.h +362 -0
  30. data/ext/cbor/packer_class.c +304 -0
  31. data/ext/cbor/packer_class.h +39 -0
  32. data/ext/cbor/rbinit.c +51 -0
  33. data/ext/cbor/renamer.h +56 -0
  34. data/ext/cbor/rmem.c +103 -0
  35. data/ext/cbor/rmem.h +118 -0
  36. data/ext/cbor/sysdep.h +139 -0
  37. data/ext/cbor/sysdep_endian.h +59 -0
  38. data/ext/cbor/sysdep_types.h +55 -0
  39. data/ext/cbor/unpacker.c +784 -0
  40. data/ext/cbor/unpacker.h +135 -0
  41. data/ext/cbor/unpacker_class.c +439 -0
  42. data/ext/cbor/unpacker_class.h +39 -0
  43. data/hx_cbor.gemspec +25 -0
  44. data/lib/cbor.rb +6 -0
  45. data/lib/cbor/version.rb +3 -0
  46. data/spec/buffer_io_spec.rb +260 -0
  47. data/spec/buffer_spec.rb +576 -0
  48. data/spec/cases.cbor +0 -0
  49. data/spec/cases.cbor_stream +0 -0
  50. data/spec/cases.json +1 -0
  51. data/spec/cases.msg +0 -0
  52. data/spec/cases_compact.msg +0 -0
  53. data/spec/cases_spec.rb +39 -0
  54. data/spec/format_spec.rb +540 -0
  55. data/spec/packer_spec.rb +127 -0
  56. data/spec/random_compat.rb +24 -0
  57. data/spec/spec_helper.rb +68 -0
  58. data/spec/unpacker_spec.rb +260 -0
  59. metadata +198 -0
@@ -0,0 +1,516 @@
1
+ /*
2
+ * CBOR for Ruby
3
+ *
4
+ * Copyright (C) 2013 Carsten Bormann
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License").
7
+ *
8
+ * Based on:
9
+ ***********/
10
+ /*
11
+ * MessagePack for Ruby
12
+ *
13
+ * Copyright (C) 2008-2013 Sadayuki Furuhashi
14
+ *
15
+ * Licensed under the Apache License, Version 2.0 (the "License");
16
+ * you may not use this file except in compliance with the License.
17
+ * You may obtain a copy of the License at
18
+ *
19
+ * http://www.apache.org/licenses/LICENSE-2.0
20
+ *
21
+ * Unless required by applicable law or agreed to in writing, software
22
+ * distributed under the License is distributed on an "AS IS" BASIS,
23
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
+ * See the License for the specific language governing permissions and
25
+ * limitations under the License.
26
+ */
27
+
28
+ #include "compat.h"
29
+ #include "ruby.h"
30
+ #include "buffer.h"
31
+ #include "buffer_class.h"
32
+
33
+ VALUE cMessagePack_Buffer;
34
+
35
+ static ID s_read;
36
+ static ID s_readpartial;
37
+ static ID s_write;
38
+ static ID s_append;
39
+ static ID s_close;
40
+
41
+ #define BUFFER(from, name) \
42
+ msgpack_buffer_t *name = NULL; \
43
+ Data_Get_Struct(from, msgpack_buffer_t, name); \
44
+ if(name == NULL) { \
45
+ rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
46
+ }
47
+
48
+ #define CHECK_STRING_TYPE(value) \
49
+ value = rb_check_string_type(value); \
50
+ if( NIL_P(value) ) { \
51
+ rb_raise(rb_eTypeError, "instance of String needed"); \
52
+ }
53
+
54
+ static void Buffer_free(void* data)
55
+ {
56
+ if(data == NULL) {
57
+ return;
58
+ }
59
+ msgpack_buffer_t* b = (msgpack_buffer_t*) data;
60
+ msgpack_buffer_destroy(b);
61
+ free(b);
62
+ }
63
+
64
+ static VALUE Buffer_alloc(VALUE klass)
65
+ {
66
+ msgpack_buffer_t* b = ALLOC_N(msgpack_buffer_t, 1);
67
+ msgpack_buffer_init(b);
68
+
69
+ return Data_Wrap_Struct(klass, msgpack_buffer_mark, Buffer_free, b);
70
+ }
71
+
72
+ static ID get_partial_read_method(VALUE io)
73
+ {
74
+ if(rb_respond_to(io, s_readpartial)) {
75
+ return s_readpartial;
76
+ } else if(rb_respond_to(io, s_read)) {
77
+ return s_read;
78
+ } else {
79
+ return s_read;
80
+ }
81
+ }
82
+
83
+ static ID get_write_all_method(VALUE io)
84
+ {
85
+ if(rb_respond_to(io, s_write)) {
86
+ return s_write;
87
+ } else if(rb_respond_to(io, s_append)) {
88
+ return s_append;
89
+ } else {
90
+ return s_write;
91
+ }
92
+ }
93
+
94
+ void MessagePack_Buffer_initialize(msgpack_buffer_t* b, VALUE io, VALUE options)
95
+ {
96
+ b->io = io;
97
+ b->io_partial_read_method = get_partial_read_method(io);
98
+ b->io_write_all_method = get_write_all_method(io);
99
+
100
+ if(options != Qnil) {
101
+ VALUE v;
102
+
103
+ v = rb_hash_aref(options, ID2SYM(rb_intern("read_reference_threshold")));
104
+ if(v != Qnil) {
105
+ msgpack_buffer_set_read_reference_threshold(b, NUM2ULONG(v));
106
+ }
107
+
108
+ v = rb_hash_aref(options, ID2SYM(rb_intern("write_reference_threshold")));
109
+ if(v != Qnil) {
110
+ msgpack_buffer_set_write_reference_threshold(b, NUM2ULONG(v));
111
+ }
112
+
113
+ v = rb_hash_aref(options, ID2SYM(rb_intern("io_buffer_size")));
114
+ if(v != Qnil) {
115
+ msgpack_buffer_set_io_buffer_size(b, NUM2ULONG(v));
116
+ }
117
+ }
118
+ }
119
+
120
+ VALUE MessagePack_Buffer_wrap(msgpack_buffer_t* b, VALUE owner)
121
+ {
122
+ b->owner = owner;
123
+ return Data_Wrap_Struct(cMessagePack_Buffer, msgpack_buffer_mark, NULL, b);
124
+ }
125
+
126
+ static VALUE Buffer_initialize(int argc, VALUE* argv, VALUE self)
127
+ {
128
+ VALUE io = Qnil;
129
+ VALUE options = Qnil;
130
+
131
+ if(argc == 0 || (argc == 1 && argv[0] == Qnil)) {
132
+ /* Qnil */
133
+
134
+ } else if(argc == 1) {
135
+ VALUE v = argv[0];
136
+ if(rb_type(v) == T_HASH) {
137
+ options = v;
138
+ } else {
139
+ io = v;
140
+ }
141
+
142
+ } else if(argc == 2) {
143
+ io = argv[0];
144
+ options = argv[1];
145
+ if(rb_type(options) != T_HASH) {
146
+ rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(io));
147
+ }
148
+
149
+ } else {
150
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
151
+ }
152
+
153
+ BUFFER(self, b);
154
+
155
+ MessagePack_Buffer_initialize(b, io, options);
156
+
157
+ return self;
158
+ }
159
+
160
+ static VALUE Buffer_clear(VALUE self)
161
+ {
162
+ BUFFER(self, b);
163
+ msgpack_buffer_clear(b);
164
+ return Qnil;
165
+ }
166
+
167
+ static VALUE Buffer_size(VALUE self)
168
+ {
169
+ BUFFER(self, b);
170
+ size_t size = msgpack_buffer_all_readable_size(b);
171
+ return SIZET2NUM(size);
172
+ }
173
+
174
+ static VALUE Buffer_empty_p(VALUE self)
175
+ {
176
+ BUFFER(self, b);
177
+ if(msgpack_buffer_top_readable_size(b) == 0) {
178
+ return Qtrue;
179
+ } else {
180
+ return Qfalse;
181
+ }
182
+ }
183
+
184
+ static VALUE Buffer_write(VALUE self, VALUE string_or_buffer)
185
+ {
186
+ BUFFER(self, b);
187
+
188
+ VALUE string = string_or_buffer; // TODO optimize if string_or_buffer is a Buffer
189
+ StringValue(string);
190
+
191
+ size_t length = msgpack_buffer_append_string(b, string);
192
+
193
+ return SIZET2NUM(length);
194
+ }
195
+
196
+ static VALUE Buffer_append(VALUE self, VALUE string_or_buffer)
197
+ {
198
+ BUFFER(self, b);
199
+
200
+ VALUE string = string_or_buffer; // TODO optimize if string_or_buffer is a Buffer
201
+ StringValue(string);
202
+
203
+ msgpack_buffer_append_string(b, string);
204
+
205
+ return self;
206
+ }
207
+
208
+
209
+ #define MAKE_EMPTY_STRING(orig) \
210
+ if(orig == Qnil) { \
211
+ orig = rb_str_buf_new(0); \
212
+ } else { \
213
+ rb_str_resize(orig, 0); \
214
+ }
215
+
216
+ static VALUE read_until_eof_rescue(VALUE args)
217
+ {
218
+ msgpack_buffer_t* b = (void*) ((VALUE*) args)[0];
219
+ VALUE out = ((VALUE*) args)[1];
220
+ unsigned long max = ((VALUE*) args)[2];
221
+ size_t* sz = (void*) ((VALUE*) args)[3];
222
+
223
+ while(true) {
224
+ size_t rl;
225
+ if(max == 0) {
226
+ if(out == Qnil) {
227
+ rl = msgpack_buffer_skip(b, b->io_buffer_size);
228
+ } else {
229
+ rl = msgpack_buffer_read_to_string(b, out, b->io_buffer_size);
230
+ }
231
+ if(rl == 0) {
232
+ break;
233
+ }
234
+ *sz += rl;
235
+
236
+ } else {
237
+ if(out == Qnil) {
238
+ rl = msgpack_buffer_skip(b, max);
239
+ } else {
240
+ rl = msgpack_buffer_read_to_string(b, out, max);
241
+ }
242
+ if(rl == 0) {
243
+ break;
244
+ }
245
+ *sz += rl;
246
+ if(max <= rl) {
247
+ break;
248
+ } else {
249
+ max -= rl;
250
+ }
251
+ }
252
+ }
253
+
254
+ return Qnil;
255
+ }
256
+
257
+ static VALUE read_until_eof_error(VALUE args)
258
+ {
259
+ /* ignore EOFError */
260
+ UNUSED(args);
261
+ return Qnil;
262
+ }
263
+
264
+ static inline size_t read_until_eof(msgpack_buffer_t* b, VALUE out, unsigned long max)
265
+ {
266
+ if(msgpack_buffer_has_io(b)) {
267
+ size_t sz = 0;
268
+ VALUE args[4] = { (VALUE)(void*) b, out, (VALUE) max, (VALUE)(void*) &sz };
269
+ rb_rescue2(read_until_eof_rescue, (VALUE)(void*) args,
270
+ read_until_eof_error, (VALUE)(void*) args,
271
+ rb_eEOFError, NULL);
272
+ return sz;
273
+
274
+ } else {
275
+ if(max == 0) {
276
+ max = ULONG_MAX;
277
+ }
278
+ if(out == Qnil) {
279
+ return msgpack_buffer_skip_nonblock(b, max);
280
+ } else {
281
+ return msgpack_buffer_read_to_string_nonblock(b, out, max);
282
+ }
283
+ }
284
+ }
285
+
286
+ static inline VALUE read_all(msgpack_buffer_t* b, VALUE out)
287
+ {
288
+ #ifndef DISABLE_BUFFER_READ_TO_S_OPTIMIZE
289
+ if(out == Qnil && !msgpack_buffer_has_io(b)) {
290
+ /* same as to_s && clear; optimize */
291
+ VALUE str = msgpack_buffer_all_as_string(b);
292
+ msgpack_buffer_clear(b);
293
+ return str;
294
+ }
295
+ #endif
296
+ MAKE_EMPTY_STRING(out);
297
+ read_until_eof(b, out, 0);
298
+ return out;
299
+ }
300
+
301
+ static VALUE Buffer_skip(VALUE self, VALUE sn)
302
+ {
303
+ BUFFER(self, b);
304
+
305
+ unsigned long n = FIX2ULONG(sn);
306
+
307
+ /* do nothing */
308
+ if(n == 0) {
309
+ return ULONG2NUM(0);
310
+ }
311
+
312
+ size_t sz = read_until_eof(b, Qnil, n);
313
+ return ULONG2NUM(sz);
314
+ }
315
+
316
+ static VALUE Buffer_skip_all(VALUE self, VALUE sn)
317
+ {
318
+ BUFFER(self, b);
319
+
320
+ unsigned long n = FIX2ULONG(sn);
321
+
322
+ /* do nothing */
323
+ if(n == 0) {
324
+ return self;
325
+ }
326
+
327
+ if(!msgpack_buffer_ensure_readable(b, n)) {
328
+ rb_raise(rb_eEOFError, "end of buffer reached");
329
+ }
330
+
331
+ msgpack_buffer_skip_nonblock(b, n);
332
+
333
+ return self;
334
+ }
335
+
336
+ static VALUE Buffer_read_all(int argc, VALUE* argv, VALUE self)
337
+ {
338
+ VALUE out = Qnil;
339
+ unsigned long n = 0;
340
+ bool all = false;
341
+
342
+ switch(argc) {
343
+ case 2:
344
+ out = argv[1];
345
+ /* pass through */
346
+ case 1:
347
+ n = FIX2ULONG(argv[0]);
348
+ break;
349
+ case 0:
350
+ all = true;
351
+ break;
352
+ default:
353
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
354
+ }
355
+
356
+ BUFFER(self, b);
357
+
358
+ if(out != Qnil) {
359
+ CHECK_STRING_TYPE(out);
360
+ }
361
+
362
+ if(all) {
363
+ return read_all(b, out);
364
+ }
365
+
366
+ if(n == 0) {
367
+ /* do nothing */
368
+ MAKE_EMPTY_STRING(out);
369
+ return out;
370
+ }
371
+
372
+ if(!msgpack_buffer_ensure_readable(b, n)) {
373
+ rb_raise(rb_eEOFError, "end of buffer reached");
374
+ }
375
+
376
+ MAKE_EMPTY_STRING(out);
377
+ msgpack_buffer_read_to_string_nonblock(b, out, n);
378
+
379
+ return out;
380
+ }
381
+
382
+ static VALUE Buffer_read(int argc, VALUE* argv, VALUE self)
383
+ {
384
+ VALUE out = Qnil;
385
+ unsigned long n = -1;
386
+ bool all = false;
387
+
388
+ switch(argc) {
389
+ case 2:
390
+ out = argv[1];
391
+ /* pass through */
392
+ case 1:
393
+ n = FIX2ULONG(argv[0]);
394
+ break;
395
+ case 0:
396
+ all = true;
397
+ break;
398
+ default:
399
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
400
+ }
401
+
402
+ BUFFER(self, b);
403
+
404
+ if(out != Qnil) {
405
+ CHECK_STRING_TYPE(out);
406
+ }
407
+
408
+ if(all) {
409
+ return read_all(b, out);
410
+ }
411
+
412
+ if(n == 0) {
413
+ /* do nothing */
414
+ MAKE_EMPTY_STRING(out);
415
+ return out;
416
+ }
417
+
418
+ #ifndef DISABLE_BUFFER_READ_TO_S_OPTIMIZE
419
+ if(!msgpack_buffer_has_io(b) && out == Qnil &&
420
+ msgpack_buffer_all_readable_size(b) <= n) {
421
+ /* same as to_s && clear; optimize */
422
+ VALUE str = msgpack_buffer_all_as_string(b);
423
+ msgpack_buffer_clear(b);
424
+
425
+ if(RSTRING_LEN(str) == 0) {
426
+ return Qnil;
427
+ } else {
428
+ return str;
429
+ }
430
+ }
431
+ #endif
432
+
433
+ MAKE_EMPTY_STRING(out);
434
+ read_until_eof(b, out, n);
435
+
436
+ if(RSTRING_LEN(out) == 0) {
437
+ return Qnil;
438
+ } else {
439
+ return out;
440
+ }
441
+ }
442
+
443
+ static VALUE Buffer_to_str(VALUE self)
444
+ {
445
+ BUFFER(self, b);
446
+ return msgpack_buffer_all_as_string(b);
447
+ }
448
+
449
+ static VALUE Buffer_to_a(VALUE self)
450
+ {
451
+ BUFFER(self, b);
452
+ return msgpack_buffer_all_as_string_array(b);
453
+ }
454
+
455
+ static VALUE Buffer_flush(VALUE self)
456
+ {
457
+ BUFFER(self, b);
458
+ msgpack_buffer_flush(b);
459
+ return self;
460
+ }
461
+
462
+ static VALUE Buffer_io(VALUE self)
463
+ {
464
+ BUFFER(self, b);
465
+ return b->io;
466
+ }
467
+
468
+ static VALUE Buffer_close(VALUE self)
469
+ {
470
+ BUFFER(self, b);
471
+ if(b->io != Qnil) {
472
+ return rb_funcall(b->io, s_close, 0);
473
+ }
474
+ return Qnil;
475
+ }
476
+
477
+ static VALUE Buffer_write_to(VALUE self, VALUE io)
478
+ {
479
+ BUFFER(self, b);
480
+ size_t sz = msgpack_buffer_flush_to_io(b, io, s_write, true);
481
+ return ULONG2NUM(sz);
482
+ }
483
+
484
+ void MessagePack_Buffer_module_init(VALUE mMessagePack)
485
+ {
486
+ s_read = rb_intern("read");
487
+ s_readpartial = rb_intern("readpartial");
488
+ s_write = rb_intern("write");
489
+ s_append = rb_intern("<<");
490
+ s_close = rb_intern("close");
491
+
492
+ msgpack_buffer_static_init();
493
+
494
+ cMessagePack_Buffer = rb_define_class_under(mMessagePack, "Buffer", rb_cObject);
495
+
496
+ rb_define_alloc_func(cMessagePack_Buffer, Buffer_alloc);
497
+
498
+ rb_define_method(cMessagePack_Buffer, "initialize", Buffer_initialize, -1);
499
+ rb_define_method(cMessagePack_Buffer, "clear", Buffer_clear, 0);
500
+ rb_define_method(cMessagePack_Buffer, "size", Buffer_size, 0);
501
+ rb_define_method(cMessagePack_Buffer, "empty?", Buffer_empty_p, 0);
502
+ rb_define_method(cMessagePack_Buffer, "write", Buffer_write, 1);
503
+ rb_define_method(cMessagePack_Buffer, "<<", Buffer_append, 1);
504
+ rb_define_method(cMessagePack_Buffer, "skip", Buffer_skip, 1);
505
+ rb_define_method(cMessagePack_Buffer, "skip_all", Buffer_skip_all, 1);
506
+ rb_define_method(cMessagePack_Buffer, "read", Buffer_read, -1);
507
+ rb_define_method(cMessagePack_Buffer, "read_all", Buffer_read_all, -1);
508
+ rb_define_method(cMessagePack_Buffer, "io", Buffer_io, 0);
509
+ rb_define_method(cMessagePack_Buffer, "flush", Buffer_flush, 0);
510
+ rb_define_method(cMessagePack_Buffer, "close", Buffer_close, 0);
511
+ rb_define_method(cMessagePack_Buffer, "write_to", Buffer_write_to, 1);
512
+ rb_define_method(cMessagePack_Buffer, "to_str", Buffer_to_str, 0);
513
+ rb_define_alias(cMessagePack_Buffer, "to_s", "to_str");
514
+ rb_define_method(cMessagePack_Buffer, "to_a", Buffer_to_a, 0);
515
+ }
516
+