rsonal 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []