rsonal 0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ea30b1cb2c0fbe10886a4db0e627107ac94b7fd4
4
+ data.tar.gz: 1b9a727919135d747cf46fd5af6cc8bc1d71879f
5
+ SHA512:
6
+ metadata.gz: b851890747ecaf86993928735997b49a16a5bc3fd29977be9d3104da04f58f0d6c29e1c2d87541ec0ecdcaefbdf5255e09659429ab1d8d8a030a514e92181164
7
+ data.tar.gz: ff7833d9c3c96960f951f37cdd760df6902678c6ffde0c5b3d1a03d15d6bede3af04087fa744c775b99963e81b1629e082f38a40eca4be50544753475f14afa3
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+ extension_name = 'rsonal'
3
+ dir_config(extension_name)
4
+ abort "missing malloc()" unless have_func "malloc"
5
+ abort "missing free()" unless have_func "free"
6
+ abort "missing ruby.h" unless have_header "ruby.h"
7
+ create_makefile("rsonal/rsonal")
@@ -0,0 +1,236 @@
1
+ #include <ruby.h>
2
+ #include <ruby/encoding.h>
3
+ #include <rsonal_string.h>
4
+
5
+ VALUE Rsonal = Qnil;
6
+
7
+ void Init_rsonal();
8
+ VALUE rsonal_read_json(VALUE self, VALUE file);
9
+ VALUE rsonal_write_json(VALUE self, VALUE input);
10
+ void process_write_json_data(Rst* str, VALUE input);
11
+
12
+
13
+
14
+ void Init_rsonal() {
15
+ Rsonal = rb_define_module("Rsonal");
16
+ rb_define_singleton_method(Rsonal, "write_json", rsonal_write_json, 1);
17
+ }
18
+
19
+ void
20
+ process_write_json_fixnum(Rst* str, VALUE input)
21
+ {
22
+ char conv[64];
23
+ long val = NUM2LONG(input);
24
+ snprintf(conv, 64, "%ld", val);
25
+ rst_cat_clen(str, conv);
26
+ }
27
+
28
+ // int
29
+ // numdigits(double dbl)
30
+ // {
31
+ // long count = 0;
32
+ // while(abs(dbl) >= 0.0000001)
33
+ // {
34
+ // dbl = dbl * 10;
35
+ // count = count + 1;
36
+ // num = num - (int)num;
37
+ // }
38
+ // }
39
+
40
+ void
41
+ process_write_json_float(Rst* str, VALUE input)
42
+ {
43
+ char conv[32];
44
+ double dbl = NUM2DBL(input);
45
+ snprintf(conv, 32, "%09e", dbl);
46
+ rst_cat_clen(str, conv);
47
+ }
48
+
49
+ void
50
+ process_write_json_bignum(Rst* str, VALUE input)
51
+ {
52
+ int i;
53
+ long len;
54
+ VALUE res;
55
+ if(FIXNUM_P(input))
56
+ {
57
+ process_write_json_fixnum(str, input);
58
+ return;
59
+ }
60
+ res = rb_big2str(input,10);
61
+ rst_cat_cstr(str, RSTRING_PTR(res), RSTRING_LEN(res));
62
+ }
63
+
64
+ int
65
+ is_unicode_seq_start(const unsigned char c)
66
+ {
67
+ return (c >= 0xC0 && c <= 0xFD);
68
+ }
69
+
70
+ unsigned short arr_numbytes[] = {0, 0x7E, 0x3E, 0x1E, 0x0E, 0x06};
71
+
72
+ int
73
+ utf_numbytes(const unsigned short inp)
74
+ {
75
+ unsigned i;
76
+ for(i=1;i < 6;i++)
77
+ {
78
+ if((inp >> i) == arr_numbytes[i])
79
+ return 6-i;
80
+ }
81
+ return 0;
82
+ }
83
+
84
+ unsigned int
85
+ offset_mask(int offset)
86
+ {
87
+ return 0xFF >> (offset+1);
88
+ }
89
+
90
+ void
91
+ process_write_json_utf8(Rst* str, VALUE input)
92
+ {
93
+ int i, j, off;
94
+ unsigned long wchar;
95
+ char conv[8] = {0};
96
+ const unsigned char* ptr = (unsigned char*)RSTRING_PTR(input);
97
+ const int siz = RSTRING_LEN(input);
98
+
99
+ for(i=0;i < siz;i++)
100
+ {
101
+ if(!is_unicode_seq_start(ptr[i]))
102
+ {
103
+ rst_add_char(str, ptr[i]);
104
+ continue;
105
+ }
106
+ off = utf_numbytes(ptr[i]);
107
+ wchar = ptr[i] & offset_mask(off);
108
+ for(j=0;j < off && (i+j) < siz;j++)
109
+ {
110
+ wchar <<= 6;
111
+ wchar |= (ptr[++i] & 0x3F);
112
+ };
113
+ off = snprintf(conv, 8, "\\u%02lx%02lx", (wchar & 0xFF00)>>8, wchar&0xFF);
114
+ rst_cat_cstr(str, conv, off);
115
+ }
116
+ }
117
+
118
+ void
119
+ process_write_json_string(Rst* str, VALUE input)
120
+ {
121
+ const char* enc_name = rb_enc_get(input)->name;
122
+ rst_add_char(str, '"');
123
+ if(!strncmp("US-ASCII", enc_name, 8))
124
+ rst_cat_cstr(str, RSTRING_PTR(input), RSTRING_LEN(input));
125
+ else if(!strncmp("UTF-8", enc_name, 5))
126
+ process_write_json_utf8(str, input);
127
+ rst_add_char(str, '"');
128
+ }
129
+
130
+ void
131
+ process_write_json_array(Rst* str, VALUE input)
132
+ {
133
+ int i;
134
+ long siz;
135
+
136
+ siz = RARRAY_LEN(input);
137
+ rst_add_char(str, '[');
138
+ for(i=0;i < siz;i++)
139
+ {
140
+ process_write_json_data(str, rb_ary_entry(input, i));
141
+ if(i + 1 < siz)
142
+ rst_cat_clen(str, ", ");
143
+ }
144
+ rst_add_char(str, ']');
145
+ }
146
+
147
+ void
148
+ process_write_json_symbol(Rst* str, VALUE input)
149
+ {
150
+ process_write_json_string(str, rb_sym_to_s(input));
151
+ }
152
+
153
+ int
154
+ process_write_json_hash_inner(VALUE key, VALUE val, VALUE str)
155
+ {
156
+ Rst* rst;
157
+ rst = rst_unwrap(str);
158
+ process_write_json_data(rst, key);
159
+ rst_cat_clen(rst, ": ");
160
+ process_write_json_data(rst, val);
161
+ rst_add_char(rst, ',');
162
+ return ST_CONTINUE;
163
+ }
164
+
165
+ void
166
+ process_write_json_hash(Rst* str, VALUE input)
167
+ {
168
+ long old_len, new_len;
169
+ rst_add_char(str, '{');
170
+
171
+ old_len = rst_len(str);
172
+ rb_hash_foreach(input, process_write_json_hash_inner, rst_wrap(str));
173
+ new_len = rst_len(str);
174
+
175
+ if(new_len > old_len)
176
+ rst_chomp(str);
177
+ rst_add_char(str, '}');
178
+ }
179
+
180
+ void
181
+ process_write_json_bool(Rst* str, int bool_input)
182
+ {
183
+ if(bool_input)
184
+ rst_cat_clen(str, "true");
185
+ else
186
+ rst_cat_clen(str, "false");
187
+ }
188
+
189
+ void
190
+ process_write_json_null(Rst* str)
191
+ {
192
+ rst_cat_clen(str, "null");
193
+ }
194
+
195
+ void
196
+ process_write_json_other(Rst* str, VALUE input)
197
+ {
198
+ process_write_json_data(str, rb_funcall(input, rb_intern("to_s"), 0));
199
+ }
200
+
201
+ void
202
+ process_write_json_data(Rst* str, VALUE input)
203
+ {
204
+ switch(TYPE(input))
205
+ {
206
+ case T_FIXNUM: process_write_json_fixnum(str, input);break;
207
+ case T_STRING: process_write_json_string(str, input);break;
208
+ case T_ARRAY: process_write_json_array(str, input);break;
209
+ case T_HASH: process_write_json_hash(str, input);break;
210
+ case T_SYMBOL: process_write_json_symbol(str, input);break;
211
+ case T_TRUE: process_write_json_bool(str, 1);break;
212
+ case T_FALSE: process_write_json_bool(str, 0);break;
213
+ case T_NIL: process_write_json_null(str); break;
214
+ case T_FLOAT: process_write_json_float(str, input); break;
215
+ case T_BIGNUM: process_write_json_bignum(str, input);break;
216
+ default: process_write_json_other(str, input);
217
+ }
218
+ }
219
+
220
+ VALUE
221
+ rsonal_write_json(VALUE self, VALUE input)
222
+ {
223
+ rb_encoding* utf8;
224
+ Rst* rst;
225
+ rst = rst_new();
226
+
227
+ process_write_json_data(rst, input);
228
+
229
+ utf8 = rb_enc_find("UTF-8");
230
+ VALUE str = rb_enc_str_new_cstr("", utf8);
231
+ rb_str_cat(str, rst->ptr, rst->len);
232
+ rb_str_cat2(str, "");
233
+ rst_free(rst);
234
+
235
+ return str;
236
+ }
@@ -0,0 +1,113 @@
1
+ #include <stdlib.h>
2
+ #include <rsonal_string.h>
3
+
4
+ VALUE rst_class = 0;
5
+
6
+ Rst*
7
+ rst_new()
8
+ {
9
+ Rst *rst;
10
+ rst = malloc(sizeof(Rst));
11
+ rst->ptr = malloc(sizeof(char)*64);
12
+ rst->free_space = 64;
13
+ rst->max_size = 64;
14
+ rst->len = 0;
15
+ return rst;
16
+ }
17
+
18
+ void
19
+ rst_free(Rst* ptr)
20
+ {
21
+ free(ptr->ptr);
22
+ free(ptr);
23
+ }
24
+
25
+ void
26
+ rst_ptr_free(RstPtr* ptr)
27
+ {
28
+ free(ptr);
29
+ }
30
+
31
+ Rst*
32
+ rst_unwrap(VALUE rst)
33
+ {
34
+ RstPtr *ptr;
35
+ Data_Get_Struct(rst, RstPtr, ptr);
36
+ return ptr->ptr;
37
+ }
38
+
39
+ VALUE
40
+ rst_wrap(Rst* rst)
41
+ {
42
+ RstPtr* ptr;
43
+ RstPtr unwrap_ptr;
44
+ if(rst_class == 0)
45
+ rst_init();
46
+
47
+ ptr = malloc(sizeof(RstPtr));
48
+ ptr->ptr = rst;
49
+ return Data_Wrap_Struct(rst_class, 0, rst_ptr_free, ptr);
50
+ }
51
+
52
+ void
53
+ rst_init()
54
+ {
55
+ rst_class = rb_define_class("RST", rb_cString);
56
+ }
57
+
58
+ void
59
+ rst_resize(Rst* ptr, long len)
60
+ {
61
+ long n_len;
62
+ char* nptr;
63
+
64
+ n_len = 64;
65
+ while(n_len < len)
66
+ n_len *= 2;
67
+
68
+ nptr = realloc(ptr->ptr, sizeof(char)*(ptr->max_size + n_len));
69
+ ptr->ptr = nptr;
70
+ ptr->max_size += n_len;
71
+ ptr->free_space += n_len;
72
+ }
73
+
74
+ long
75
+ rst_len(Rst* ptr)
76
+ {
77
+ return ptr->len;
78
+ }
79
+
80
+ void
81
+ rst_cat_cstr(Rst* dst, const char* input, long len)
82
+ {
83
+ if(dst->free_space <= (len+8))
84
+ rst_resize(dst, len);
85
+
86
+ memcpy(&(dst->ptr[sizeof(char)*dst->len]), (void*)input, len*sizeof(char));
87
+ dst->free_space -= len;
88
+ dst->len += len;
89
+ }
90
+
91
+ void
92
+ rst_add_char(Rst* dst, const char chr)
93
+ {
94
+ if(dst->free_space < 8)
95
+ rst_resize(dst, 8);
96
+
97
+ dst->ptr[sizeof(char)*dst->len] = chr;
98
+ dst->len += 1;
99
+ dst->free_space -= 1;
100
+ }
101
+
102
+ void
103
+ rst_cat_clen(Rst* dst, const char* input)
104
+ {
105
+ rst_cat_cstr(dst, input, strlen(input));
106
+ }
107
+
108
+ void
109
+ rst_chomp(Rst* ptr)
110
+ {
111
+ ptr->free_space += 1;
112
+ ptr->len -= 1;
113
+ }
@@ -0,0 +1,23 @@
1
+ #include <ruby.h>
2
+
3
+ typedef struct _struct_rst {
4
+ char* ptr;
5
+ long len;
6
+ long max_size;
7
+ long free_space;
8
+ } Rst;
9
+
10
+ typedef struct _struct_rst_rb_ptr {
11
+ Rst* ptr;
12
+ } RstPtr;
13
+
14
+ Rst* rst_new();
15
+ void rst_free(Rst* ptr);
16
+ Rst* rst_unwrap(VALUE rst);
17
+ VALUE rst_wrap(Rst* rst);
18
+ void rst_init();
19
+ void rst_cat_cstr(Rst* dst, const char* input, long len);
20
+ void rst_cat_clen(Rst* dst, const char* input);
21
+ long rst_len(Rst* ptr);
22
+ void rst_chomp(Rst* ptr);
23
+ void rst_add_char(Rst* dst, const char chr);
@@ -0,0 +1,4 @@
1
+ require './rsonal.bundle'
2
+ require 'json'
3
+
4
+ p Rsonal.write_json 42**1000
@@ -0,0 +1,5 @@
1
+ module Rsonal
2
+ VERSION=0.1
3
+ end
4
+
5
+ require "rsonal/rsonal"
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rsonal
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Martin Hauser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: |
28
+ rsonal is a simple and efficient JSON writer for Ruby. It is designed
29
+ to allow passing of a ruby object to it's only function, 'json_write'
30
+ which will return specification conforming JSON with as much speed
31
+ as possible.
32
+ email: mh@wrongexit.de
33
+ executables: []
34
+ extensions:
35
+ - ext/rsonal/extconf.rb
36
+ extra_rdoc_files: []
37
+ files:
38
+ - ext/rsonal/extconf.rb
39
+ - ext/rsonal/rsonal.c
40
+ - ext/rsonal/rsonal_string.c
41
+ - ext/rsonal/rsonal_string.h
42
+ - ext/rsonal/test.rb
43
+ - lib/rsonal.rb
44
+ homepage: https://github.com/mbbh/rsonal
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.2.2
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: Simple fast JSON writer
68
+ test_files: []