edn_turbo 0.5.7 → 0.7.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.
@@ -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
  }