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.
- checksums.yaml +7 -0
- data/ext/rsonal/extconf.rb +7 -0
- data/ext/rsonal/rsonal.c +236 -0
- data/ext/rsonal/rsonal_string.c +113 -0
- data/ext/rsonal/rsonal_string.h +23 -0
- data/ext/rsonal/test.rb +4 -0
- data/lib/rsonal.rb +5 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -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
|
data/ext/rsonal/rsonal.c
ADDED
@@ -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);
|
data/ext/rsonal/test.rb
ADDED
data/lib/rsonal.rb
ADDED
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: []
|