psych 5.0.1-java → 5.1.0.pre1-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,14 +27,6 @@
27
27
  ***** END LICENSE BLOCK *****/
28
28
  package org.jruby.ext.psych;
29
29
 
30
- import java.io.ByteArrayInputStream;
31
- import java.io.InputStreamReader;
32
- import java.nio.charset.Charset;
33
- import java.nio.charset.CharsetDecoder;
34
- import java.nio.charset.CodingErrorAction;
35
- import java.nio.charset.MalformedInputException;
36
- import java.util.Map;
37
-
38
30
  import org.jcodings.Encoding;
39
31
  import org.jcodings.specific.UTF16BEEncoding;
40
32
  import org.jcodings.specific.UTF16LEEncoding;
@@ -51,49 +43,67 @@ import org.jruby.RubyModule;
51
43
  import org.jruby.RubyObject;
52
44
  import org.jruby.RubyString;
53
45
  import org.jruby.anno.JRubyMethod;
54
- import static org.jruby.ext.psych.PsychLibrary.YAMLEncoding.*;
55
46
  import org.jruby.runtime.Block;
56
47
  import org.jruby.runtime.Helpers;
57
- import org.jruby.runtime.ObjectAllocator;
58
48
  import org.jruby.runtime.ThreadContext;
59
49
  import org.jruby.runtime.builtin.IRubyObject;
50
+ import org.jruby.runtime.callsite.CachingCallSite;
51
+ import org.jruby.runtime.callsite.FunctionalCachingCallSite;
52
+ import org.jruby.util.ByteList;
60
53
  import org.jruby.util.IOInputStream;
61
54
  import org.jruby.util.io.EncodingUtils;
62
- import org.jruby.util.log.Logger;
63
- import org.jruby.util.log.LoggerFactory;
64
- import org.yaml.snakeyaml.DumperOptions;
65
- import org.yaml.snakeyaml.error.Mark;
66
- import org.yaml.snakeyaml.error.MarkedYAMLException;
67
- import org.yaml.snakeyaml.error.YAMLException;
68
- import org.yaml.snakeyaml.events.AliasEvent;
69
- import org.yaml.snakeyaml.events.DocumentEndEvent;
70
- import org.yaml.snakeyaml.events.DocumentStartEvent;
71
- import org.yaml.snakeyaml.events.Event;
72
- import org.yaml.snakeyaml.events.Event.ID;
73
- import org.yaml.snakeyaml.events.MappingStartEvent;
74
- import org.yaml.snakeyaml.events.ScalarEvent;
75
- import org.yaml.snakeyaml.events.SequenceStartEvent;
76
- import org.yaml.snakeyaml.parser.Parser;
77
- import org.yaml.snakeyaml.parser.ParserException;
78
- import org.yaml.snakeyaml.parser.ParserImpl;
79
- import org.yaml.snakeyaml.reader.ReaderException;
80
- import org.yaml.snakeyaml.reader.StreamReader;
81
- import org.yaml.snakeyaml.scanner.ScannerException;
55
+ import org.snakeyaml.engine.v2.api.LoadSettings;
56
+ import org.snakeyaml.engine.v2.api.LoadSettingsBuilder;
57
+ import org.snakeyaml.engine.v2.common.Anchor;
58
+ import org.snakeyaml.engine.v2.common.FlowStyle;
59
+ import org.snakeyaml.engine.v2.common.ScalarStyle;
60
+ import org.snakeyaml.engine.v2.common.SpecVersion;
61
+ import org.snakeyaml.engine.v2.events.AliasEvent;
62
+ import org.snakeyaml.engine.v2.events.DocumentEndEvent;
63
+ import org.snakeyaml.engine.v2.events.DocumentStartEvent;
64
+ import org.snakeyaml.engine.v2.events.Event;
65
+ import org.snakeyaml.engine.v2.events.ImplicitTuple;
66
+ import org.snakeyaml.engine.v2.events.MappingStartEvent;
67
+ import org.snakeyaml.engine.v2.events.ScalarEvent;
68
+ import org.snakeyaml.engine.v2.events.SequenceStartEvent;
69
+ import org.snakeyaml.engine.v2.exceptions.Mark;
70
+ import org.snakeyaml.engine.v2.exceptions.MarkedYamlEngineException;
71
+ import org.snakeyaml.engine.v2.exceptions.ParserException;
72
+ import org.snakeyaml.engine.v2.exceptions.ReaderException;
73
+ import org.snakeyaml.engine.v2.exceptions.ScannerException;
74
+ import org.snakeyaml.engine.v2.exceptions.YamlEngineException;
75
+ import org.snakeyaml.engine.v2.parser.Parser;
76
+ import org.snakeyaml.engine.v2.parser.ParserImpl;
77
+ import org.snakeyaml.engine.v2.scanner.ScannerImpl;
78
+ import org.snakeyaml.engine.v2.scanner.StreamReader;
79
+ import org.snakeyaml.engine.v2.schema.CoreSchema;
82
80
 
81
+ import java.io.ByteArrayInputStream;
82
+ import java.io.InputStreamReader;
83
+ import java.nio.charset.Charset;
84
+ import java.nio.charset.CharsetDecoder;
85
+ import java.nio.charset.CodingErrorAction;
86
+ import java.nio.charset.MalformedInputException;
87
+ import java.util.Arrays;
88
+ import java.util.Map;
89
+ import java.util.Optional;
90
+
91
+ import static org.jruby.ext.psych.PsychLibrary.YAMLEncoding.*;
83
92
  import static org.jruby.runtime.Helpers.arrayOf;
84
93
  import static org.jruby.runtime.Helpers.invoke;
85
- import org.jruby.util.ByteList;
86
94
 
87
95
  public class PsychParser extends RubyObject {
88
96
 
89
- private static final Logger LOG = LoggerFactory.getLogger(PsychParser.class);
90
-
97
+ public static final String JRUBY_CALL_SITES = "_jruby_call_sites";
98
+
91
99
  public static void initPsychParser(Ruby runtime, RubyModule psych) {
92
- RubyClass psychParser = runtime.defineClassUnder("Parser", runtime.getObject(), new ObjectAllocator() {
93
- public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
94
- return new PsychParser(runtime, klazz);
95
- }
96
- }, psych);
100
+ RubyClass psychParser = runtime.defineClassUnder("Parser", runtime.getObject(), PsychParser::new, psych);
101
+
102
+ CachingCallSite[] sites =
103
+ Arrays.stream(Call.values())
104
+ .map((call) -> new FunctionalCachingCallSite(call.name()))
105
+ .toArray(CachingCallSite[]::new);
106
+ psychParser.setInternalVariable(JRUBY_CALL_SITES, sites);
97
107
 
98
108
  runtime.getLoadService().require("psych/syntax_error");
99
109
  psychParser.defineConstant("ANY", runtime.newFixnum(YAML_ANY_ENCODING.ordinal()));
@@ -106,78 +116,91 @@ public class PsychParser extends RubyObject {
106
116
 
107
117
  public PsychParser(Ruby runtime, RubyClass klass) {
108
118
  super(runtime, klass);
119
+
120
+ CachingCallSite[] sites = (CachingCallSite[]) klass.getInternalVariable(JRUBY_CALL_SITES);
121
+ this.path = sites[Call.path.ordinal()];
122
+ this.event_location = sites[Call.event_location.ordinal()];
123
+ this.start_stream = sites[Call.start_stream.ordinal()];
124
+ this.start_document = sites[Call.start_document.ordinal()];
125
+ this.end_document = sites[Call.end_document.ordinal()];
126
+ this.alias = sites[Call.alias.ordinal()];
127
+ this.scalar = sites[Call.scalar.ordinal()];
128
+ this.start_sequence = sites[Call.start_sequence.ordinal()];
129
+ this.end_sequence = sites[Call.end_sequence.ordinal()];
130
+ this.start_mapping = sites[Call.start_mapping.ordinal()];
131
+ this.end_mapping = sites[Call.end_mapping.ordinal()];
132
+ this.end_stream = sites[Call.end_stream.ordinal()];
133
+ this.loadSettingsBuilder = LoadSettings.builder().setSchema(new CoreSchema());
109
134
  }
110
135
 
111
- private IRubyObject stringOrNilFor(ThreadContext context, String value, boolean tainted) {
112
- if (value == null) return context.nil;
136
+ private IRubyObject stringOrNilForAnchor(ThreadContext context, Optional<Anchor> value) {
137
+ if (!value.isPresent()) return context.nil;
113
138
 
114
- return stringFor(context, value, tainted);
139
+ return stringFor(context, value.get().getValue());
140
+ }
141
+
142
+ private IRubyObject stringOrNilFor(ThreadContext context, Optional<String> value) {
143
+ if (!value.isPresent()) return context.nil;
144
+
145
+ return stringFor(context, value.get());
115
146
  }
116
147
 
117
- private RubyString stringFor(ThreadContext context, String value, boolean tainted) {
148
+ private IRubyObject stringFor(ThreadContext context, String value) {
118
149
  Ruby runtime = context.runtime;
119
150
 
151
+ boolean isUTF8 = true;
152
+ Charset charset = RubyEncoding.UTF8;
153
+
120
154
  Encoding encoding = runtime.getDefaultInternalEncoding();
121
155
  if (encoding == null) {
122
156
  encoding = UTF8Encoding.INSTANCE;
157
+ charset = RubyEncoding.UTF8;
158
+ } else {
159
+ Charset encodingCharset = encoding.getCharset();
160
+ if (encodingCharset != null) {
161
+ isUTF8 = encodingCharset == RubyEncoding.UTF8;
162
+ charset = encodingCharset;
163
+ }
123
164
  }
124
165
 
125
- Charset charset = RubyEncoding.UTF8;
126
- if (encoding.getCharset() != null) {
127
- charset = encoding.getCharset();
128
- }
129
-
130
- ByteList bytes = new ByteList(value.getBytes(charset), encoding);
166
+ ByteList bytes = new ByteList(
167
+ isUTF8 ?
168
+ RubyEncoding.encodeUTF8(value) :
169
+ RubyEncoding.encode(value, charset),
170
+ encoding);
131
171
  RubyString string = RubyString.newString(runtime, bytes);
132
172
 
133
- string.setTaint(tainted);
134
-
135
173
  return string;
136
174
  }
137
175
 
138
- private StreamReader readerFor(ThreadContext context, IRubyObject yaml) {
176
+ private StreamReader readerFor(ThreadContext context, IRubyObject yaml, LoadSettings loadSettings) {
139
177
  if (yaml instanceof RubyString) {
140
- ByteList byteList = ((RubyString)yaml).getByteList();
141
- Encoding enc = byteList.getEncoding();
142
-
143
- // if not unicode, transcode to UTF8
144
- if (!(enc instanceof UnicodeEncoding)) {
145
- byteList = EncodingUtils.strConvEnc(context, byteList, enc, UTF8Encoding.INSTANCE);
146
- enc = UTF8Encoding.INSTANCE;
147
- }
148
-
149
- ByteArrayInputStream bais = new ByteArrayInputStream(byteList.getUnsafeBytes(), byteList.getBegin(), byteList.getRealSize());
150
-
151
- Charset charset = enc.getCharset();
152
-
153
- assert charset != null : "charset for encoding " + enc + " should not be null";
154
-
155
- InputStreamReader isr = new InputStreamReader(bais, charset);
156
-
157
- return new StreamReader(isr);
178
+ return readerForString(context, (RubyString) yaml, loadSettings);
158
179
  }
159
180
 
160
181
  // fall back on IOInputStream, using default charset
161
- if (yaml.respondsTo("read")) {
162
- Charset charset = null;
163
- if (yaml instanceof RubyIO) {
182
+ return readerForIO(context, yaml, loadSettings);
183
+ }
184
+
185
+ private static StreamReader readerForIO(ThreadContext context, IRubyObject yaml, LoadSettings loadSettings) {
186
+ boolean isIO = yaml instanceof RubyIO;
187
+ if (isIO || yaml.respondsTo("read")) {
188
+ // default to UTF8 unless RubyIO has UTF16 as encoding
189
+ Charset charset = RubyEncoding.UTF8;
190
+
191
+ if (isIO) {
164
192
  Encoding enc = ((RubyIO) yaml).getReadEncoding();
165
- charset = enc.getCharset();
166
193
 
167
194
  // libyaml treats non-utf encodings as utf-8 and hopes for the best.
168
- if (!(enc instanceof UTF8Encoding) && !(enc instanceof UTF16LEEncoding) && !(enc instanceof UTF16BEEncoding)) {
169
- charset = UTF8Encoding.INSTANCE.getCharset();
195
+ if (enc instanceof UTF16LEEncoding || enc instanceof UTF16BEEncoding) {
196
+ charset = enc.getCharset();
170
197
  }
171
198
  }
172
- if (charset == null) {
173
- // If we can't get it from the IO or it doesn't have a charset, fall back on UTF-8
174
- charset = UTF8Encoding.INSTANCE.getCharset();
175
- }
199
+
176
200
  CharsetDecoder decoder = charset.newDecoder();
177
201
  decoder.onMalformedInput(CodingErrorAction.REPORT);
178
- decoder.onMalformedInput(CodingErrorAction.REPORT);
179
202
 
180
- return new StreamReader(new InputStreamReader(new IOInputStream(yaml), decoder));
203
+ return new StreamReader(loadSettings, new InputStreamReader(new IOInputStream(yaml), decoder));
181
204
  } else {
182
205
  Ruby runtime = context.runtime;
183
206
 
@@ -185,59 +208,92 @@ public class PsychParser extends RubyObject {
185
208
  }
186
209
  }
187
210
 
211
+ private static StreamReader readerForString(ThreadContext context, RubyString string, LoadSettings loadSettings) {
212
+ ByteList byteList = string.getByteList();
213
+ Encoding enc = byteList.getEncoding();
214
+
215
+ // if not unicode, transcode to UTF8
216
+ if (!(enc instanceof UnicodeEncoding)) {
217
+ byteList = EncodingUtils.strConvEnc(context, byteList, enc, UTF8Encoding.INSTANCE);
218
+ enc = UTF8Encoding.INSTANCE;
219
+ }
220
+
221
+ ByteArrayInputStream bais = new ByteArrayInputStream(byteList.getUnsafeBytes(), byteList.getBegin(), byteList.getRealSize());
222
+
223
+ Charset charset = enc.getCharset();
224
+
225
+ assert charset != null : "charset for encoding " + enc + " should not be null";
226
+
227
+ InputStreamReader isr = new InputStreamReader(bais, charset);
228
+
229
+ return new StreamReader(loadSettings, isr);
230
+ }
231
+
188
232
  @JRubyMethod(name = "_native_parse")
189
233
  public IRubyObject parse(ThreadContext context, IRubyObject handler, IRubyObject yaml, IRubyObject path) {
190
234
  Ruby runtime = context.runtime;
191
- boolean tainted = yaml.isTaint() || yaml instanceof RubyIO;
192
235
 
193
236
  try {
194
- parser = new ParserImpl(readerFor(context, yaml));
237
+ LoadSettings loadSettings = loadSettingsBuilder.build();
238
+ parser = new ParserImpl(loadSettings, new ScannerImpl(loadSettings, readerFor(context, yaml, loadSettings)));
195
239
 
196
240
  if (path.isNil() && yaml.respondsTo("path")) {
197
- path = yaml.callMethod(context, "path");
241
+ path = this.path.call(context, this, yaml);
198
242
  }
199
243
 
200
- while (true) {
201
- event = parser.getEvent();
202
-
203
- IRubyObject start_line = runtime.newFixnum(event.getStartMark().getLine());
204
- IRubyObject start_column = runtime.newFixnum(event.getStartMark().getColumn());
205
- IRubyObject end_line = runtime.newFixnum(event.getEndMark().getLine());
206
- IRubyObject end_column = runtime.newFixnum(event.getEndMark().getColumn());
207
- invoke(context, handler, "event_location", start_line, start_column, end_line, end_column);
208
-
209
- // FIXME: Event should expose a getID, so it can be switched
210
- if (event.is(ID.StreamStart)) {
211
- invoke(context, handler, "start_stream", runtime.newFixnum(YAML_ANY_ENCODING.ordinal()));
212
- } else if (event.is(ID.DocumentStart)) {
213
- handleDocumentStart(context, (DocumentStartEvent) event, tainted, handler);
214
- } else if (event.is(ID.DocumentEnd)) {
215
- IRubyObject notExplicit = runtime.newBoolean(!((DocumentEndEvent) event).getExplicit());
216
-
217
- invoke(context, handler, "end_document", notExplicit);
218
- } else if (event.is(ID.Alias)) {
219
- IRubyObject alias = stringOrNilFor(context, ((AliasEvent)event).getAnchor(), tainted);
220
-
221
- invoke(context, handler, "alias", alias);
222
- } else if (event.is(ID.Scalar)) {
223
- handleScalar(context, (ScalarEvent) event, tainted, handler);
224
- } else if (event.is(ID.SequenceStart)) {
225
- handleSequenceStart(context,(SequenceStartEvent) event, tainted, handler);
226
- } else if (event.is(ID.SequenceEnd)) {
227
- invoke(context, handler, "end_sequence");
228
- } else if (event.is(ID.MappingStart)) {
229
- handleMappingStart(context, (MappingStartEvent) event, tainted, handler);
230
- } else if (event.is(ID.MappingEnd)) {
231
- invoke(context, handler, "end_mapping");
232
- } else if (event.is(ID.StreamEnd)) {
233
- invoke(context, handler, "end_stream");
234
-
235
- break;
244
+ while (parser.hasNext()) {
245
+ event = parser.next();
246
+
247
+ Mark start = event.getStartMark().orElseThrow(RuntimeException::new);
248
+ IRubyObject start_line = runtime.newFixnum(start.getLine());
249
+ IRubyObject start_column = runtime.newFixnum(start.getColumn());
250
+
251
+ Mark end = event.getEndMark().orElseThrow(RuntimeException::new);
252
+ IRubyObject end_line = runtime.newFixnum(end.getLine());
253
+ IRubyObject end_column = runtime.newFixnum(end.getColumn());
254
+
255
+ event_location.call(context, this, handler, start_line, start_column, end_line, end_column);
256
+
257
+ switch (event.getEventId()) {
258
+ case StreamStart:
259
+ start_stream.call(context, this, handler, runtime.newFixnum(YAML_ANY_ENCODING.ordinal()));
260
+ break;
261
+ case DocumentStart:
262
+ handleDocumentStart(context, (DocumentStartEvent) event, handler);
263
+ break;
264
+ case DocumentEnd:
265
+ IRubyObject notExplicit = runtime.newBoolean(!((DocumentEndEvent) event).isExplicit());
266
+
267
+ end_document.call(context, this, handler, notExplicit);
268
+ break;
269
+ case Alias:
270
+ IRubyObject alias = stringOrNilForAnchor(context, ((AliasEvent) event).getAnchor());
271
+
272
+ this.alias.call(context, this, handler, alias);
273
+ break;
274
+ case Scalar:
275
+ handleScalar(context, (ScalarEvent) event, handler);
276
+ break;
277
+ case SequenceStart:
278
+ handleSequenceStart(context, (SequenceStartEvent) event, handler);
279
+ break;
280
+ case SequenceEnd:
281
+ end_sequence.call(context, this, handler);
282
+ break;
283
+ case MappingStart:
284
+ handleMappingStart(context, (MappingStartEvent) event, handler);
285
+ break;
286
+ case MappingEnd:
287
+ end_mapping.call(context, this, handler);
288
+ break;
289
+ case StreamEnd:
290
+ end_stream.call(context, this, handler);
291
+ break;
236
292
  }
237
293
  }
238
294
  } catch (ParserException pe) {
239
295
  parser = null;
240
- raiseParserException(context, yaml, pe, path);
296
+ raiseParserException(context, pe, path);
241
297
 
242
298
  } catch (ScannerException se) {
243
299
  parser = null;
@@ -245,18 +301,18 @@ public class PsychParser extends RubyObject {
245
301
  if (se.getProblemMark() != null) {
246
302
  message.append(se.getProblemMark().toString());
247
303
  }
248
- raiseParserException(context, yaml, se, path);
304
+ raiseParserException(context, se, path);
249
305
 
250
306
  } catch (ReaderException re) {
251
307
  parser = null;
252
- raiseParserException(context, yaml, re, path);
308
+ raiseParserException(context, re, path);
253
309
 
254
- } catch (YAMLException ye) {
310
+ } catch (YamlEngineException ye) {
255
311
  Throwable cause = ye.getCause();
256
312
 
257
313
  if (cause instanceof MalformedInputException) {
258
314
  // failure due to improperly encoded input
259
- raiseParserException(context, yaml, (MalformedInputException) cause, path);
315
+ raiseParserException(context, (MalformedInputException) cause, path);
260
316
  }
261
317
 
262
318
  throw ye;
@@ -269,94 +325,99 @@ public class PsychParser extends RubyObject {
269
325
  return this;
270
326
  }
271
327
 
272
- private void handleDocumentStart(ThreadContext context, DocumentStartEvent dse, boolean tainted, IRubyObject handler) {
328
+ private void handleDocumentStart(ThreadContext context, DocumentStartEvent dse, IRubyObject handler) {
273
329
  Ruby runtime = context.runtime;
274
- DumperOptions.Version _version = dse.getVersion();
275
- IRubyObject version = _version == null ?
276
- RubyArray.newArray(runtime) :
277
- RubyArray.newArray(runtime, runtime.newFixnum(_version.major()), runtime.newFixnum(_version.minor()));
278
-
330
+
331
+ Optional<SpecVersion> specVersion = dse.getSpecVersion();
332
+ IRubyObject version = specVersion.isPresent() ?
333
+ RubyArray.newArray(runtime, runtime.newFixnum(specVersion.get().getMajor()), runtime.newFixnum(specVersion.get().getMinor())) :
334
+ RubyArray.newEmptyArray(runtime);
335
+
279
336
  Map<String, String> tagsMap = dse.getTags();
280
- RubyArray tags = RubyArray.newArray(runtime);
281
- if (tagsMap != null && tagsMap.size() > 0) {
337
+ RubyArray tags;
338
+ int size;
339
+ if (tagsMap != null && (size = tagsMap.size()) > 0) {
340
+ tags = RubyArray.newArray(runtime, size);
282
341
  for (Map.Entry<String, String> tag : tagsMap.entrySet()) {
283
- IRubyObject key = stringFor(context, tag.getKey(), tainted);
284
- IRubyObject value = stringFor(context, tag.getValue(), tainted);
342
+ IRubyObject key = stringFor(context, tag.getKey());
343
+ IRubyObject value = stringFor(context, tag.getValue());
285
344
 
286
345
  tags.append(RubyArray.newArray(runtime, key, value));
287
346
  }
347
+ } else {
348
+ tags = RubyArray.newEmptyArray(runtime);
288
349
  }
289
- IRubyObject notExplicit = runtime.newBoolean(!dse.getExplicit());
290
350
 
291
- invoke(context, handler, "start_document", version, tags, notExplicit);
351
+ IRubyObject notExplicit = runtime.newBoolean(!dse.isExplicit());
352
+
353
+ start_document.call(context, this, handler, version, tags, notExplicit);
292
354
  }
293
355
 
294
- private void handleMappingStart(ThreadContext context, MappingStartEvent mse, boolean tainted, IRubyObject handler) {
356
+ private void handleMappingStart(ThreadContext context, MappingStartEvent mse, IRubyObject handler) {
295
357
  Ruby runtime = context.runtime;
296
- IRubyObject anchor = stringOrNilFor(context, mse.getAnchor(), tainted);
297
- IRubyObject tag = stringOrNilFor(context, mse.getTag(), tainted);
298
- IRubyObject implicit = runtime.newBoolean(mse.getImplicit());
358
+ IRubyObject anchor = stringOrNilForAnchor(context, mse.getAnchor());
359
+ IRubyObject tag = stringOrNilFor(context, mse.getTag());
360
+ IRubyObject implicit = runtime.newBoolean(mse.isImplicit());
299
361
  IRubyObject style = runtime.newFixnum(translateFlowStyle(mse.getFlowStyle()));
300
362
 
301
- invoke(context, handler, "start_mapping", anchor, tag, implicit, style);
363
+ start_mapping.call(context, this, handler, anchor, tag, implicit, style);
302
364
  }
303
365
 
304
- private void handleScalar(ThreadContext context, ScalarEvent se, boolean tainted, IRubyObject handler) {
366
+ private void handleScalar(ThreadContext context, ScalarEvent se, IRubyObject handler) {
305
367
  Ruby runtime = context.runtime;
306
368
 
307
- IRubyObject anchor = stringOrNilFor(context, se.getAnchor(), tainted);
308
- IRubyObject tag = stringOrNilFor(context, se.getTag(), tainted);
309
- IRubyObject plain_implicit = runtime.newBoolean(se.getImplicit().canOmitTagInPlainScalar());
310
- IRubyObject quoted_implicit = runtime.newBoolean(se.getImplicit().canOmitTagInNonPlainScalar());
369
+ IRubyObject anchor = stringOrNilForAnchor(context, se.getAnchor());
370
+ IRubyObject tag = stringOrNilFor(context, se.getTag());
371
+ ImplicitTuple implicit = se.getImplicit();
372
+ IRubyObject plain_implicit = runtime.newBoolean(implicit.canOmitTagInPlainScalar());
373
+ IRubyObject quoted_implicit = runtime.newBoolean(implicit.canOmitTagInNonPlainScalar());
311
374
  IRubyObject style = runtime.newFixnum(translateStyle(se.getScalarStyle()));
312
- IRubyObject val = stringFor(context, se.getValue(), tainted);
375
+ IRubyObject val = stringFor(context, se.getValue());
313
376
 
314
- invoke(context, handler, "scalar", val, anchor, tag, plain_implicit,
377
+ scalar.call(context, this, handler, val, anchor, tag, plain_implicit,
315
378
  quoted_implicit, style);
316
379
  }
317
380
 
318
- private void handleSequenceStart(ThreadContext context, SequenceStartEvent sse, boolean tainted, IRubyObject handler) {
381
+ private void handleSequenceStart(ThreadContext context, SequenceStartEvent sse, IRubyObject handler) {
319
382
  Ruby runtime = context.runtime;
320
- IRubyObject anchor = stringOrNilFor(context, sse.getAnchor(), tainted);
321
- IRubyObject tag = stringOrNilFor(context, sse.getTag(), tainted);
322
- IRubyObject implicit = runtime.newBoolean(sse.getImplicit());
383
+ IRubyObject anchor = stringOrNilForAnchor(context, sse.getAnchor());
384
+ IRubyObject tag = stringOrNilFor(context, sse.getTag());
385
+ IRubyObject implicit = runtime.newBoolean(sse.isImplicit());
323
386
  IRubyObject style = runtime.newFixnum(translateFlowStyle(sse.getFlowStyle()));
324
387
 
325
- invoke(context, handler, "start_sequence", anchor, tag, implicit, style);
388
+ start_sequence.call(context, this, handler, anchor, tag, implicit, style);
326
389
  }
327
390
 
328
- private static void raiseParserException(ThreadContext context, IRubyObject yaml, ReaderException re, IRubyObject rbPath) {
329
- Ruby runtime;
391
+ private static void raiseParserException(ThreadContext context, ReaderException re, IRubyObject rbPath) {
392
+ Ruby runtime = context.runtime;
330
393
  RubyClass se;
331
394
  IRubyObject exception;
332
395
 
333
- runtime = context.runtime;
334
- se = (RubyClass)runtime.getModule("Psych").getConstant("SyntaxError");
396
+ se = (RubyClass) runtime.getModule("Psych").getConstant("SyntaxError");
335
397
 
336
398
  exception = se.newInstance(context,
337
399
  new IRubyObject[] {
338
400
  rbPath,
339
- runtime.newFixnum(0),
340
- runtime.newFixnum(0),
401
+ RubyFixnum.zero(runtime),
402
+ RubyFixnum.zero(runtime),
341
403
  runtime.newFixnum(re.getPosition()),
342
- (null == re.getName() ? runtime.getNil() : runtime.newString(re.getName())),
343
- (null == re.toString() ? runtime.getNil() : runtime.newString(re.toString()))
404
+ (null == re.getName() ? context.nil : runtime.newString(re.getName())),
405
+ (null == re.toString() ? context.nil : runtime.newString(re.toString()))
344
406
  },
345
407
  Block.NULL_BLOCK);
346
408
 
347
409
  RubyKernel.raise(context, runtime.getKernel(), new IRubyObject[] { exception }, Block.NULL_BLOCK);
348
410
  }
349
411
 
350
- private static void raiseParserException(ThreadContext context, IRubyObject yaml, MarkedYAMLException mye, IRubyObject rbPath) {
351
- Ruby runtime;
412
+ private static void raiseParserException(ThreadContext context, MarkedYamlEngineException mye, IRubyObject rbPath) {
413
+ Ruby runtime = context.runtime;
352
414
  Mark mark;
353
415
  RubyClass se;
354
416
  IRubyObject exception;
355
417
 
356
- runtime = context.runtime;
357
418
  se = (RubyClass)runtime.getModule("Psych").getConstant("SyntaxError");
358
419
 
359
- mark = mye.getProblemMark();
420
+ mark = mye.getProblemMark().get();
360
421
 
361
422
  exception = se.newInstance(context,
362
423
  new IRubyObject[] {
@@ -364,21 +425,19 @@ public class PsychParser extends RubyObject {
364
425
  runtime.newFixnum(mark.getLine() + 1),
365
426
  runtime.newFixnum(mark.getColumn() + 1),
366
427
  runtime.newFixnum(mark.getIndex()),
367
- (null == mye.getProblem() ? runtime.getNil() : runtime.newString(mye.getProblem())),
368
- (null == mye.getContext() ? runtime.getNil() : runtime.newString(mye.getContext()))
428
+ (null == mye.getProblem() ? context.nil : runtime.newString(mye.getProblem())),
429
+ (null == mye.getContext() ? context.nil : runtime.newString(mye.getContext()))
369
430
  },
370
431
  Block.NULL_BLOCK);
371
432
 
372
433
  RubyKernel.raise(context, runtime.getKernel(), new IRubyObject[] { exception }, Block.NULL_BLOCK);
373
434
  }
374
435
 
375
- private static void raiseParserException(ThreadContext context, IRubyObject yaml, MalformedInputException mie, IRubyObject rbPath) {
376
- Ruby runtime;
377
- Mark mark;
436
+ private static void raiseParserException(ThreadContext context, MalformedInputException mie, IRubyObject rbPath) {
437
+ Ruby runtime = context.runtime;
378
438
  RubyClass se;
379
439
  IRubyObject exception;
380
440
 
381
- runtime = context.runtime;
382
441
  se = (RubyClass)runtime.getModule("Psych").getConstant("SyntaxError");
383
442
 
384
443
  mie.getInputLength();
@@ -386,18 +445,18 @@ public class PsychParser extends RubyObject {
386
445
  exception = se.newInstance(context,
387
446
  arrayOf(
388
447
  rbPath,
389
- runtime.newFixnum(-1),
390
- runtime.newFixnum(-1),
448
+ RubyFixnum.minus_one(runtime),
449
+ RubyFixnum.minus_one(runtime),
391
450
  runtime.newFixnum(mie.getInputLength()),
392
- runtime.getNil(),
393
- runtime.getNil()
451
+ context.nil,
452
+ context.nil
394
453
  ),
395
454
  Block.NULL_BLOCK);
396
455
 
397
456
  RubyKernel.raise(context, runtime.getKernel(), new IRubyObject[] { exception }, Block.NULL_BLOCK);
398
457
  }
399
458
 
400
- private static int translateStyle(DumperOptions.ScalarStyle style) {
459
+ private static int translateStyle(ScalarStyle style) {
401
460
  if (style == null) return 0; // any
402
461
 
403
462
  switch (style) {
@@ -410,7 +469,7 @@ public class PsychParser extends RubyObject {
410
469
  }
411
470
  }
412
471
 
413
- private static int translateFlowStyle(DumperOptions.FlowStyle flowStyle) {
472
+ private static int translateFlowStyle(FlowStyle flowStyle) {
414
473
  switch (flowStyle) {
415
474
  case AUTO: return 0;
416
475
  case BLOCK: return 1;
@@ -425,14 +484,17 @@ public class PsychParser extends RubyObject {
425
484
 
426
485
  Event event = null;
427
486
 
487
+ Parser parser = this.parser;
428
488
  if (parser != null) {
429
- event = parser.peekEvent();
430
-
431
- if (event == null) event = this.event;
489
+ if (parser.hasNext()) {
490
+ event = parser.peekEvent();
491
+ } else {
492
+ event = this.event;
493
+ }
432
494
  }
433
495
 
434
496
  if (event == null) {
435
- return ((RubyClass)context.runtime.getClassFromPath("Psych::Parser::Mark")).newInstance(
497
+ return ((RubyClass) runtime.getClassFromPath("Psych::Parser::Mark")).newInstance(
436
498
  context,
437
499
  RubyFixnum.zero(runtime),
438
500
  RubyFixnum.zero(runtime),
@@ -441,9 +503,9 @@ public class PsychParser extends RubyObject {
441
503
  );
442
504
  }
443
505
 
444
- Mark mark = event.getStartMark();
506
+ Mark mark = event.getStartMark().orElseThrow(RuntimeException::new);
445
507
 
446
- return ((RubyClass)context.runtime.getClassFromPath("Psych::Parser::Mark")).newInstance(
508
+ return ((RubyClass) runtime.getClassFromPath("Psych::Parser::Mark")).newInstance(
447
509
  context,
448
510
  RubyFixnum.zero(runtime),
449
511
  runtime.newFixnum(mark.getLine()),
@@ -452,6 +514,17 @@ public class PsychParser extends RubyObject {
452
514
  );
453
515
  }
454
516
 
517
+ private LoadSettings buildSettings() {
518
+ return loadSettingsBuilder.build();
519
+ }
520
+
455
521
  private Parser parser;
456
522
  private Event event;
523
+ private final LoadSettingsBuilder loadSettingsBuilder;
524
+
525
+ private enum Call {
526
+ path, event_location, start_stream, start_document, end_document, alias, scalar, start_sequence, end_sequence, start_mapping, end_mapping, end_stream
527
+ }
528
+
529
+ private final CachingCallSite path, event_location, start_stream, start_document, end_document, alias, scalar, start_sequence, end_sequence, start_mapping, end_mapping, end_stream;
457
530
  }