edn_turbo 0.5.7 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # The MIT License (MIT)
4
+
5
+ # Copyright (c) 2015-2021 Ed Porras
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+
3
25
  require 'mkmf'
4
26
 
5
27
  header_dirs =
@@ -38,7 +60,20 @@ lib_dirs =
38
60
  dir_config('icuuc', header_dirs, lib_dirs)
39
61
 
40
62
  # feels very hackish to do this but the new icu4c needs it on MacOS
41
- $CXXFLAGS << ' -stdlib=libc++ -std=c++11' if RUBY_PLATFORM.match?(/darwin/)
63
+ if RUBY_PLATFORM =~ /darwin/
64
+ $CXXFLAGS << ' -stdlib=libc++ -Wno-deprecated-register'
65
+ else
66
+ # remove some flags that are either clang-specific or unrecognized
67
+ # but somehow get passed under linux (?!)
68
+ %w[
69
+ -Wno-self-assign -Wno-parentheses-equality -Wno-constant-logical-operand
70
+ -Wno-cast-function-type -Wdeclaration-after-statement -Wimplicit-function-declaration
71
+ -Wimplicit-int
72
+ ].each do |f|
73
+ $warnflags.sub!(f, '')
74
+ end
75
+ end
76
+ $CXXFLAGS << ' -std=c++11 -std=gnu++11'
42
77
 
43
78
  abort "\n>> failed to find icu4c headers - is icu4c installed?\n\n" unless
44
79
  find_header('unicode/uversion.h')
@@ -1,159 +1,183 @@
1
+ // The MIT License (MIT)
2
+
3
+ // Copyright (c) 2015-2021 Ed Porras
4
+
5
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ // of this software and associated documentation files (the "Software"), to deal
7
+ // in the Software without restriction, including without limitation the rights
8
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ // copies of the Software, and to permit persons to whom the Software is
10
+ // furnished to do so, subject to the following conditions:
11
+
12
+ // The above copyright notice and this permission notice shall be included in
13
+ // all copies or substantial portions of the Software.
14
+
15
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ // THE SOFTWARE.
22
+
1
23
  #include <signal.h>
2
24
  #include <iostream>
3
25
  #include <clocale>
4
26
  #include <cstring>
5
27
 
6
28
  #include <ruby/ruby.h>
29
+ #include <ruby/version.h>
7
30
  #include <ruby/io.h>
8
31
 
9
32
  #include "parser.h"
10
33
 
11
34
  namespace edn {
12
35
 
13
- VALUE rb_mEDN;
14
- VALUE rb_mEDNT;
15
-
16
- // Symbols used to call into the ruby world.
17
- VALUE EDN_MAKE_SYMBOL_METHOD = Qnil;
18
- VALUE EDN_MAKE_LIST_METHOD = Qnil;
19
- VALUE EDN_MAKE_SET_METHOD = Qnil;
20
- VALUE EDN_MAKE_BIG_DECIMAL_METHOD = Qnil;
21
- VALUE EDN_TAGGED_ELEM_METHOD = Qnil;
22
- VALUE EDNT_EXTENDED_VALUE_METHOD = Qnil;
23
-
24
- VALUE RUBY_STRING_TO_I_METHOD = Qnil;
25
- VALUE RUBY_STRING_TO_F_METHOD = Qnil;
26
- VALUE RUBY_READ_METHOD = Qnil;
27
-
28
- // returned when EOF - defined as a constant in EDN module
29
- VALUE EDN_EOF_CONST = Qnil;
30
-
31
- //
32
- // Wrappers to hook the class w/ the C-api.
33
- static void delete_parser(void* p_ptr) {
34
- delete reinterpret_cast<edn::Parser*>(p_ptr);
35
- }
36
-
37
- static const rb_data_type_t parser_data_type = {
38
- "edn_turbo::Parser",
39
- {0, delete_parser, 0, {0}},
40
- 0, 0,
41
- RUBY_TYPED_FREE_IMMEDIATELY,
42
- };
43
-
44
- static VALUE wrap_parser_ptr(VALUE klass, edn::Parser* ptr) {
45
- return TypedData_Wrap_Struct(klass, &parser_data_type, ptr);
46
- }
47
-
48
- static VALUE alloc_obj(VALUE self){
49
- return wrap_parser_ptr(self, new Parser());
50
- }
51
-
52
- static inline Parser* get_parser(VALUE self)
53
- {
54
- Parser *p;
55
- TypedData_Get_Struct( self, edn::Parser, &parser_data_type, p );
56
- return p;
57
- }
58
- static VALUE set_source(VALUE self, VALUE data);
59
-
60
- //
61
- // Called by the constructor - sets the source if passed.
62
- static VALUE initialize(int argc, VALUE* argv, VALUE self)
63
- {
64
- if (argc > 0) {
65
- set_source( self, argv[0] );
66
- }
67
- return self;
68
- }
69
-
70
- //
71
- // change the input source
72
- static VALUE set_source(VALUE self, VALUE data)
73
- {
74
- Parser* p = get_parser(self);
75
-
76
- switch (TYPE(data))
77
- {
78
- case T_STRING:
79
- {
36
+ VALUE rb_mEDN;
37
+ VALUE rb_mEDNT;
38
+
39
+ // Symbols used to call into the ruby world.
40
+ VALUE EDN_MAKE_SYMBOL_METHOD = Qnil;
41
+ VALUE EDN_MAKE_LIST_METHOD = Qnil;
42
+ VALUE EDN_MAKE_SET_METHOD = Qnil;
43
+ VALUE EDN_MAKE_BIG_DECIMAL_METHOD = Qnil;
44
+ VALUE EDN_MAKE_RATIONAL_METHOD = Qnil;
45
+ VALUE EDN_TAGGED_ELEM_METHOD = Qnil;
46
+ VALUE EDNT_EXTENDED_VALUE_METHOD = Qnil;
47
+
48
+ VALUE RUBY_STRING_TO_I_METHOD = Qnil;
49
+ VALUE RUBY_STRING_TO_F_METHOD = Qnil;
50
+ VALUE RUBY_READ_METHOD = Qnil;
51
+
52
+ VALUE RUBY_NAN_CONST = Qnil;
53
+ VALUE RUBY_INF_CONST = Qnil;
54
+
55
+ // returned when EOF - defined as a constant in EDN module
56
+ VALUE EDN_EOF_CONST = Qnil;
57
+
58
+ //
59
+ // Wrappers to hook the class w/ the C-api.
60
+ static void delete_parser(void* p_ptr) {
61
+ delete reinterpret_cast<edn::Parser*>(p_ptr);
62
+ }
63
+
64
+ static const rb_data_type_t parser_data_type = {
65
+ "edn_turbo::Parser",
66
+ {0, delete_parser, 0, 0},
67
+ 0, 0,
68
+ RUBY_TYPED_FREE_IMMEDIATELY,
69
+ };
70
+
71
+ static VALUE wrap_parser_ptr(VALUE klass, edn::Parser* ptr) {
72
+ return TypedData_Wrap_Struct(klass, &parser_data_type, ptr);
73
+ }
74
+
75
+ static VALUE alloc_obj(VALUE self){
76
+ return wrap_parser_ptr(self, new Parser());
77
+ }
78
+
79
+ static inline Parser* get_parser(VALUE self)
80
+ {
81
+ Parser *p;
82
+ TypedData_Get_Struct( self, edn::Parser, &parser_data_type, p );
83
+ return p;
84
+ }
85
+ static VALUE set_source(VALUE self, VALUE data);
86
+
87
+ //
88
+ // Called by the constructor - sets the source if passed.
89
+ static VALUE initialize(int argc, VALUE* argv, VALUE self)
90
+ {
91
+ if (argc > 0) {
92
+ set_source( self, argv[0] );
93
+ }
94
+ return self;
95
+ }
96
+
97
+ //
98
+ // change the input source
99
+ static VALUE set_source(VALUE self, VALUE data)
100
+ {
101
+ Parser* p = get_parser(self);
102
+
103
+ switch (TYPE(data))
104
+ {
105
+ case T_STRING:
106
+ {
80
107
  const char* stream = StringValueCStr(data);
81
108
  if (stream) {
82
- p->set_source( stream, std::strlen(stream) );
109
+ p->set_source( stream, std::strlen(stream) );
83
110
  }
84
111
  break;
85
- }
86
- case T_FILE:
87
- {
112
+ }
113
+ case T_FILE:
114
+ {
88
115
  // extract the stream pointer
89
116
  rb_io_t* fptr = RFILE(data)->fptr;
90
117
  if (!fptr) {
91
- rb_raise(rb_eRuntimeError, "Ruby IO - fptr is NULL");
118
+ rb_raise(rb_eRuntimeError, "Ruby IO - fptr is null");
92
119
  }
93
120
 
94
121
  rb_io_check_char_readable(fptr);
95
122
 
96
123
  FILE* fp = rb_io_stdio_file(fptr);
97
124
  if (!fp) {
98
- rb_raise(rb_eRuntimeError, "Ruby IO - fptr->fp is NULL");
125
+ rb_raise(rb_eRuntimeError, "Ruby IO - fptr->fp is null");
99
126
  }
100
127
 
101
128
  p->set_source(fp);
102
129
  break;
103
- }
104
- case T_DATA:
105
- {
106
- // StringIO or some other IO not part of the ruby core -
107
- // this is very inefficient as it'll require read()
108
- // calls from the ruby side (involves a lot of data
109
- // wrapping, etc)
130
+ }
131
+ case T_DATA:
132
+ {
133
+ // StringIO or some other IO not part of the ruby core
110
134
  if (rb_respond_to(data, RUBY_READ_METHOD)) {
111
- p->set_source(data);
112
- break;
135
+ p->set_source(data);
136
+ break;
113
137
  }
114
- }
115
- default:
116
- rb_raise(rb_eRuntimeError, "set_source expected String, core IO, or IO that responds to read()");
117
- break;
118
- }
119
-
120
- return self;
121
- }
122
-
123
- //
124
- // eof?
125
- static VALUE eof(VALUE self, VALUE data)
126
- {
127
- return get_parser(self)->is_eof();
128
- }
129
-
130
- //
131
- // parses an entire stream
132
- static VALUE read(VALUE self, VALUE data)
133
- {
134
- if (TYPE(data) != T_STRING) {
135
- rb_raise(rb_eTypeError, "Expected String data");
136
- }
137
- const char* stream = StringValueCStr(data);
138
- if (stream) {
139
- return get_parser(self)->parse(stream, std::strlen(stream) );
140
- }
141
- return Qnil;
142
- }
143
-
144
- //
145
- // gets the next token in the current stream
146
- static VALUE next(VALUE self, VALUE data)
147
- {
148
- return get_parser(self)->next();
149
- }
150
-
151
- //
152
- // signal handler
153
- static void die(int sig)
154
- {
155
- exit(-1);
156
- }
138
+ }
139
+ default:
140
+ rb_raise(rb_eArgError, "set_source expected String, core IO, or IO that responds to read()");
141
+ break;
142
+ }
143
+
144
+ return self;
145
+ }
146
+
147
+ //
148
+ // eof?
149
+ static VALUE eof(VALUE self, VALUE data)
150
+ {
151
+ return get_parser(self)->is_eof();
152
+ }
153
+
154
+ //
155
+ // parses an entire stream
156
+ static VALUE read(VALUE self, VALUE data)
157
+ {
158
+ if (TYPE(data) != T_STRING) {
159
+ rb_raise(rb_eTypeError, "Expected String data");
160
+ }
161
+ const char* stream = StringValueCStr(data);
162
+ if (stream) {
163
+ return get_parser(self)->parse(stream, std::strlen(stream) );
164
+ }
165
+ return Qnil;
166
+ }
167
+
168
+ //
169
+ // gets the next token in the current stream
170
+ static VALUE next(VALUE self, VALUE data)
171
+ {
172
+ return get_parser(self)->next();
173
+ }
174
+
175
+ //
176
+ // signal handler
177
+ [[noreturn]] static void die(int sig)
178
+ {
179
+ exit(-1);
180
+ }
157
181
  }
158
182
 
159
183
 
@@ -162,45 +186,56 @@ namespace edn {
162
186
  extern "C"
163
187
  void Init_edn_turbo(void)
164
188
  {
165
- struct sigaction a;
166
- a.sa_handler = edn::die;
167
- sigemptyset(&a.sa_mask);
168
- a.sa_flags = 0;
169
- sigaction(SIGINT, &a, NULL);
170
-
171
- // pass things back as utf-8
172
- if (!setlocale( LC_ALL, "" )) {
173
- rb_raise(rb_eRuntimeError, "Extension init error calling setlocale() - It appears your system's locale is not configured correctly.\n");
174
- }
175
-
176
- edn::rb_mEDN = rb_const_get(rb_cObject, rb_intern("EDN"));
177
- edn::rb_mEDNT = rb_define_module("EDNT");
178
-
179
- // bind the ruby Parser class to the C++ one
180
- VALUE rb_cParser = rb_define_class_under(edn::rb_mEDNT, "Parser", rb_cObject);
181
- rb_define_alloc_func(rb_cParser, edn::alloc_obj);
182
- rb_define_method(rb_cParser, "initialize", (VALUE(*)(ANYARGS)) &edn::initialize, -1 );
183
- rb_define_method(rb_cParser, "ext_eof", (VALUE(*)(ANYARGS)) &edn::eof, 0 );
184
-
185
- rb_define_method(rb_cParser, "set_input", (VALUE(*)(ANYARGS)) &edn::set_source, 1 );
186
- rb_define_method(rb_cParser, "parse", (VALUE(*)(ANYARGS)) &edn::read, 1 );
187
- rb_define_method(rb_cParser, "read", (VALUE(*)(ANYARGS)) &edn::next, 0 );
188
-
189
- // bind ruby methods we'll call - these should be defined in edn_turbo.rb
190
- edn::EDN_MAKE_SYMBOL_METHOD = rb_intern("symbol");
191
- edn::EDN_MAKE_LIST_METHOD = rb_intern("list");
192
- edn::EDN_MAKE_SET_METHOD = rb_intern("set");
193
- edn::EDN_MAKE_BIG_DECIMAL_METHOD = rb_intern("big_decimal");
194
- edn::EDN_TAGGED_ELEM_METHOD = rb_intern("tagged_element");
195
-
196
- // defined in EDNT - see edn_parser.rb
197
- edn::EDNT_EXTENDED_VALUE_METHOD = rb_intern("extend_for_meta");
198
-
199
- // ruby methods
200
- edn::RUBY_STRING_TO_I_METHOD = rb_intern("to_i");
201
- edn::RUBY_STRING_TO_F_METHOD = rb_intern("to_f");
202
- edn::RUBY_READ_METHOD = rb_intern("read");
203
-
204
- // so we can return EOF directly
205
- edn::EDN_EOF_CONST = rb_const_get(edn::rb_mEDN, rb_intern("EOF"));
189
+ struct sigaction a;
190
+ a.sa_handler = edn::die;
191
+ sigemptyset(&a.sa_mask);
192
+ a.sa_flags = 0;
193
+ sigaction(SIGINT, &a, nullptr);
194
+
195
+ // pass things back as utf-8
196
+ if (!setlocale( LC_ALL, "" )) {
197
+ rb_raise(rb_eRuntimeError, "Extension init error calling setlocale() - It appears your system's locale is not configured correctly.\n");
198
+ }
199
+
200
+ edn::rb_mEDN = rb_const_get(rb_cObject, rb_intern("EDN"));
201
+ edn::rb_mEDNT = rb_define_module("EDNT");
202
+
203
+ // bind the ruby Parser class to the C++ one
204
+ VALUE rb_cParser = rb_define_class_under(edn::rb_mEDNT, "Parser", rb_cObject);
205
+ rb_define_alloc_func(rb_cParser, edn::alloc_obj);
206
+ rb_define_method(rb_cParser, "initialize",
207
+ reinterpret_cast<VALUE(*)(ANYARGS)>(&edn::initialize), -1 );
208
+ rb_define_method(rb_cParser, "ext_eof",
209
+ reinterpret_cast<VALUE(*)(ANYARGS)>(&edn::eof), 0 );
210
+ rb_define_method(rb_cParser, "set_input",
211
+ reinterpret_cast<VALUE(*)(ANYARGS)>(&edn::set_source), 1 );
212
+ rb_define_method(rb_cParser, "parse",
213
+ reinterpret_cast<VALUE(*)(ANYARGS)>(&edn::read), 1 );
214
+ rb_define_method(rb_cParser, "read",
215
+ reinterpret_cast<VALUE(*)(ANYARGS)>(&edn::next), 0 );
216
+
217
+ // bind edn-ruby methods we'll call
218
+ edn::EDN_MAKE_SYMBOL_METHOD = rb_intern("symbol");
219
+ edn::EDN_MAKE_LIST_METHOD = rb_intern("list");
220
+ edn::EDN_MAKE_SET_METHOD = rb_intern("set");
221
+ edn::EDN_TAGGED_ELEM_METHOD = rb_intern("tagged_element");
222
+
223
+ // see lib/edn_turbo.rb
224
+ edn::EDN_MAKE_BIG_DECIMAL_METHOD = rb_intern("big_decimal_edn_turbo");
225
+
226
+ // defined in EDNT - see edn_parser.rb
227
+ edn::EDNT_EXTENDED_VALUE_METHOD = rb_intern("extend_for_meta");
228
+ edn::EDN_MAKE_RATIONAL_METHOD = rb_intern("rational"); // should be in edn-ruby
229
+
230
+ // ruby methods
231
+ edn::RUBY_STRING_TO_I_METHOD = rb_intern("to_i");
232
+ edn::RUBY_STRING_TO_F_METHOD = rb_intern("to_f");
233
+ edn::RUBY_READ_METHOD = rb_intern("read");
234
+
235
+ VALUE rb_mFloat = rb_const_get(rb_cObject, rb_intern("Float"));
236
+ edn::RUBY_NAN_CONST = rb_const_get(rb_mFloat, rb_intern("NAN"));
237
+ edn::RUBY_INF_CONST = rb_const_get(rb_mFloat, rb_intern("INFINITY"));
238
+
239
+ // so we can return EOF directly
240
+ edn::EDN_EOF_CONST = rb_const_get(edn::rb_mEDN, rb_intern("EOF"));
206
241
  }