psych 5.0.1-java → 5.1.0.pre1-java

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.
@@ -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
  }