ninjudd-tuple 0.0.3 → 0.0.4

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.
Files changed (4) hide show
  1. data/VERSION.yml +1 -1
  2. data/ext/extconf.rb +5 -0
  3. data/ext/tuple.c +152 -0
  4. metadata +7 -5
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 0
3
- :patch: 3
3
+ :patch: 4
4
4
  :major: 0
data/ext/extconf.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+ # have_library('icui18n')
3
+ # have_library('icuio')
4
+ # create_makefile('unicode')
5
+ create_makefile('tuple')
data/ext/tuple.c ADDED
@@ -0,0 +1,152 @@
1
+ #include "ruby.h"
2
+
3
+ VALUE mTuple;
4
+
5
+ #define TRUE_SORT 128 // TrueClass
6
+ #define SYM_SORT 64 // Symbol
7
+ #define STR_SORT 32 // String
8
+ #define INTP_SORT 16 // Integer (Positive)
9
+ #define INTN_SORT 8 // Integer (Negative)
10
+ #define FALSE_SORT 1 // FalseClass
11
+ #define NIL_SORT 0 // NilClass
12
+
13
+ #define MAX_INT 0xffffffff
14
+
15
+ #define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits)
16
+
17
+ /*
18
+ * call-seq:
19
+ * Tuple.dump(tuple) -> string
20
+ *
21
+ * Dumps an array of simple Ruby types into a string of binary data.
22
+ *
23
+ */
24
+ static VALUE tuple_dump(VALUE self, VALUE tuple) {
25
+ VALUE data = rb_str_new2("");
26
+ VALUE item;
27
+ int i, j, len, sign;
28
+ u_int8_t header[4];
29
+ u_int32_t digit;
30
+ BDIGIT *digits;
31
+
32
+ Check_Type(tuple, T_ARRAY);
33
+ for (i = 0; i < RARRAY(tuple)->len; i++) {
34
+ item = RARRAY(tuple)->ptr[i];
35
+ header[0] = header[1] = header[2] = header[3] = 0;
36
+ if (FIXNUM_P(item)) {
37
+ sign = (digit >= 0);
38
+ header[2] = (sign ? INTP_SORT : INTN_SORT);
39
+ header[3] = 0;
40
+ rb_str_cat(data, (char*)&header, sizeof(header));
41
+
42
+ digit = htonl(FIX2INT(item) + (sign ? 0 : MAX_INT));
43
+ rb_str_cat(data, (char*)&digit, sizeof(digit));
44
+ } else if (TYPE(item) == T_BIGNUM) {
45
+ sign = RBIGNUM(item)->sign;
46
+ header[2] = sign ? INTP_SORT : INTN_SORT;
47
+ header[3] = RBIGNUM(item)->len;
48
+ rb_str_cat(data, (char*)&header, sizeof(header));
49
+
50
+ digits = BDIGITS(item);
51
+ for (j = header[3]-1; j >= 0; j--) {
52
+ digit = htonl(sign ? digits[j] : (MAX_INT - digits[j]));
53
+ rb_str_cat(data, (char*)&digit, sizeof(digit));
54
+ }
55
+ } else if (SYMBOL_P(item) || TYPE(item) == T_STRING) {
56
+ if (SYMBOL_P(item)) {
57
+ header[2] = SYM_SORT;
58
+ item = rb_funcall(item, rb_intern("to_s"), 0);
59
+ } else {
60
+ header[2] = STR_SORT;
61
+ }
62
+ rb_str_cat(data, (char*)&header, sizeof(header));
63
+ len = RSTRING_LEN(item);
64
+ rb_str_cat(data, RSTRING_PTR(item), len);
65
+
66
+ // Pad with null bytes so subsequent fields will be aligned.
67
+ while (len % 4 != 0) {
68
+ rb_str_cat(data, (char*)&header, 1);
69
+ len++;
70
+ }
71
+ } else {
72
+ if (item == Qnil) header[2] = NIL_SORT;
73
+ else if (item == Qtrue) header[2] = TRUE_SORT;
74
+ else if (item == Qfalse) header[2] = FALSE_SORT;
75
+ else rb_raise(rb_eTypeError, "invalid type %s in tuple", rb_obj_classname(item));
76
+
77
+ rb_str_cat(data, (char*)&header, sizeof(header));
78
+ }
79
+ }
80
+ return data;
81
+ }
82
+
83
+ /*
84
+ * call-seq:
85
+ * Tuple.load(string) -> tuple
86
+ *
87
+ * Reads in a previously dumped tuple from a string of binary data.
88
+ *
89
+ */
90
+ static VALUE tuple_load(VALUE self, VALUE data) {
91
+ VALUE tuple = rb_ary_new();
92
+ VALUE item;
93
+ data = StringValue(data);
94
+ void* ptr = RSTRING_PTR(data);
95
+ void* end = ptr + RSTRING_LEN(data);
96
+ int i, len, sign;
97
+ u_int8_t header[4];
98
+ u_int32_t digit;
99
+ BDIGIT *digits;
100
+
101
+ while (ptr < end) {
102
+ memcpy(header, ptr, 4);
103
+ ptr += 4;
104
+
105
+ switch(header[2]) {
106
+ case TRUE_SORT: rb_ary_push(tuple, Qtrue); break;
107
+ case FALSE_SORT: rb_ary_push(tuple, Qfalse); break;
108
+ case NIL_SORT: rb_ary_push(tuple, Qnil); break;
109
+ case INTP_SORT:
110
+ case INTN_SORT:
111
+ sign = (header[2] == INTP_SORT);
112
+ if (header[3] == 0) {
113
+ digit = ntohl(*(u_int32_t*)ptr) - (sign ? 0 : MAX_INT);
114
+ ptr += 4;
115
+ rb_ary_push(tuple, INT2NUM(digit));
116
+ } else {
117
+ // Create an empty bignum with the right number of digits.
118
+ NEWOBJ(item, struct RBignum);
119
+ OBJSETUP(item, rb_cBignum, T_BIGNUM);
120
+ item->sign = sign ? 1 : 0;
121
+ item->len = header[3];
122
+ item->digits = ALLOC_N(BDIGIT, header[3]);
123
+
124
+ digits = BDIGITS(item);
125
+ for (i = header[3]-1; i >= 0; i--) {
126
+ digit = ntohl(*(u_int32_t*)ptr);
127
+ digits[i] = sign ? digit : MAX_INT - digit;
128
+ ptr += 4;
129
+ }
130
+ rb_ary_push(tuple, (VALUE)item);
131
+ }
132
+ break;
133
+ case STR_SORT:
134
+ case SYM_SORT:
135
+ item = rb_str_new2(ptr);
136
+ len = RSTRING_LEN(item);
137
+ while (len % 4 != 0) len++;
138
+ ptr += len;
139
+ if (header[2] == SYM_SORT) item = rb_funcall(item, rb_intern("to_sym"), 0);
140
+ rb_ary_push(tuple, item);
141
+ break;
142
+ }
143
+ }
144
+ return tuple;
145
+ }
146
+
147
+ VALUE mTuple;
148
+ void Init_tuple() {
149
+ mTuple = rb_define_module("Tuple");
150
+ rb_define_module_function(mTuple, "dump", tuple_dump, 1);
151
+ rb_define_module_function(mTuple, "load", tuple_load, 1);
152
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ninjudd-tuple
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Balthrop
@@ -17,13 +17,15 @@ description: Fast, binary-sortable serialization for arrays of simple Ruby types
17
17
  email: code@justinbalthrop.com
18
18
  executables: []
19
19
 
20
- extensions: []
21
-
20
+ extensions:
21
+ - ext/extconf.rb
22
22
  extra_rdoc_files: []
23
23
 
24
24
  files:
25
25
  - README.rdoc
26
26
  - VERSION.yml
27
+ - ext/tuple.c
28
+ - ext/extconf.rb
27
29
  - test/test_helper.rb
28
30
  - test/tuple_test.rb
29
31
  has_rdoc: true
@@ -34,7 +36,7 @@ rdoc_options:
34
36
  - --inline-source
35
37
  - --charset=UTF-8
36
38
  require_paths:
37
- - lib
39
+ - ext
38
40
  required_ruby_version: !ruby/object:Gem::Requirement
39
41
  requirements:
40
42
  - - ">="
@@ -53,6 +55,6 @@ rubyforge_project:
53
55
  rubygems_version: 1.3.5
54
56
  signing_key:
55
57
  specification_version: 2
56
- summary: TODO
58
+ summary: Tuple serialization functions.
57
59
  test_files: []
58
60