psych 5.4.0-java → 5.5.0-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.
- checksums.yaml +4 -4
- data/README.md +53 -0
- data/ext/psych/extconf.rb +22 -0
- data/ext/psych/psych.c +33 -1
- data/ext/psych/psych.h +4 -0
- data/ext/psych/psych_emitter.c +4 -0
- data/ext/psych/psych_parser.c +79 -18
- data/lib/psych/class_loader.rb +1 -0
- data/lib/psych/parser.rb +40 -1
- data/lib/psych/scalar_scanner.rb +15 -3
- data/lib/psych/versions.rb +1 -1
- data/lib/psych/visitors/to_ruby.rb +20 -9
- data/lib/psych/visitors/yaml_tree.rb +0 -3
- data/lib/psych.jar +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7429988183a896844c649cc6c90e91f722a0a5bb97d48266e76f3ec81706a750
|
|
4
|
+
data.tar.gz: 27660902dac288a8ff13063046809f41c22dc4371e0fe4d496b34ad63f7ffa37
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 675ef39857c198e61ca4e3aa2b8b3db97971e09ce3330a3d5fab1d4658d0c73eef19e001616064fbd8783414dd8807ddec60a0aebc557c770b93bf54f6eff3aa
|
|
7
|
+
data.tar.gz: bd40e9dd4011b980631e11615f60ade26630ef7e9b1a4ef64fe982e52f0d90dc610a83c0610a02c734741ec3d0d13b18978e92bb45f7f7693da0a5c389327cef
|
data/README.md
CHANGED
|
@@ -23,6 +23,7 @@ Psych.dump("foo") # => "--- foo\n...\n"
|
|
|
23
23
|
## Dependencies
|
|
24
24
|
|
|
25
25
|
* libyaml
|
|
26
|
+
* libfyaml (optional, only for the experimental `--enable-libfyaml` backend)
|
|
26
27
|
|
|
27
28
|
## Installation
|
|
28
29
|
|
|
@@ -57,6 +58,58 @@ gem 'psych'
|
|
|
57
58
|
|
|
58
59
|
JRuby ships with a pure Java implementation of Psych.
|
|
59
60
|
|
|
61
|
+
## Experimental libfyaml backend
|
|
62
|
+
|
|
63
|
+
Psych ships an experimental, opt-in backend built on
|
|
64
|
+
[libfyaml](https://github.com/pantoniou/libfyaml), a fully YAML 1.2 compliant
|
|
65
|
+
parser and emitter. It is compiled only when you explicitly pass
|
|
66
|
+
`--enable-libfyaml` at build time. Without the flag the default libyaml
|
|
67
|
+
backend is used and nothing changes.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# libfyaml and pkg-config must be installed first, for example:
|
|
71
|
+
# apt-get install libfyaml-dev # Debian/Ubuntu
|
|
72
|
+
# brew install libfyaml # macOS
|
|
73
|
+
gem install psych -- --enable-libfyaml
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
This backend is not supported on Windows.
|
|
77
|
+
|
|
78
|
+
Because libfyaml follows YAML 1.2, the YAML 1.1 booleans `yes`, `no`, `on`, and
|
|
79
|
+
`off` load as plain strings instead of `true`/`false` (only `true`/`false` are
|
|
80
|
+
booleans). This resolves the so-called "Norway problem", where the country
|
|
81
|
+
code `no` was parsed as `false`:
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
Psych.load("country: no") # => {"country" => "no"}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
You can check which backend is active:
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
Psych::BACKEND # => "libfyaml" (or "libyaml")
|
|
91
|
+
Psych.libfyaml_version # => "0.9.6"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The backend is experimental. Its output is valid YAML but is formatted
|
|
95
|
+
differently from libyaml in places, and a few emitter edge cases are not yet
|
|
96
|
+
matched. The default libyaml backend remains the supported choice.
|
|
97
|
+
|
|
98
|
+
Two more differences are worth knowing. Scalars emitted with the default
|
|
99
|
+
(`ANY`) style may be quoted or laid out differently from libyaml, so
|
|
100
|
+
byte-for-byte output is not guaranteed to match. On a parse error,
|
|
101
|
+
`Psych::SyntaxError#problem` carries libfyaml's full diagnostic message and
|
|
102
|
+
`Psych::SyntaxError#context` is always `nil`, whereas libyaml splits the
|
|
103
|
+
description across `#problem` and `#context`.
|
|
104
|
+
|
|
105
|
+
This backend targets YAML 1.2 compliance, not speed. In a rough
|
|
106
|
+
single-machine benchmark that loads and dumps in-memory documents, parsing
|
|
107
|
+
was roughly on par with libyaml (sometimes faster on string-heavy input),
|
|
108
|
+
while emitting was about 1.7x to 1.9x slower. Your numbers will vary, but the
|
|
109
|
+
shape holds: libfyaml is competitive at parsing and slower at emitting. Use
|
|
110
|
+
this backend when you need YAML 1.2 semantics. If throughput is your priority,
|
|
111
|
+
keep using the default libyaml backend.
|
|
112
|
+
|
|
60
113
|
## Release
|
|
61
114
|
|
|
62
115
|
We used the trusted publisher and [rubygems/release-gem](https://github.com/rubygems/release-gem) workflow.
|
data/ext/psych/extconf.rb
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
require 'mkmf'
|
|
4
4
|
|
|
5
|
+
# Experimental, opt-in libfyaml backend. Only used when psych is built with
|
|
6
|
+
# --enable-libfyaml. Without the flag nothing below changes and the default
|
|
7
|
+
# libyaml backend is built exactly as before.
|
|
8
|
+
if enable_config("libfyaml", false)
|
|
9
|
+
if $mswin or $mingw or $cygwin
|
|
10
|
+
abort "The libfyaml backend (--enable-libfyaml) is not supported on Windows"
|
|
11
|
+
end
|
|
12
|
+
unless pkg_config('libfyaml')
|
|
13
|
+
abort "libfyaml was requested with --enable-libfyaml but was not found via pkg-config"
|
|
14
|
+
end
|
|
15
|
+
# libfyaml 0.8 and earlier crash psych's emitter, so require a known-good
|
|
16
|
+
# version rather than building something that segfaults at runtime.
|
|
17
|
+
pkgconfig = ENV["PKG_CONFIG"] || "pkg-config"
|
|
18
|
+
unless system(pkgconfig, "--atleast-version=0.9", "libfyaml")
|
|
19
|
+
abort "The libfyaml backend requires libfyaml 0.9 or newer"
|
|
20
|
+
end
|
|
21
|
+
$defs << "-DPSYCH_USE_LIBFYAML"
|
|
22
|
+
|
|
23
|
+
create_makefile 'psych'
|
|
24
|
+
return
|
|
25
|
+
end
|
|
26
|
+
|
|
5
27
|
if $mswin or $mingw or $cygwin
|
|
6
28
|
$CPPFLAGS << " -DYAML_DECLARE_STATIC"
|
|
7
29
|
end
|
data/ext/psych/psych.c
CHANGED
|
@@ -2,14 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
/* call-seq: Psych.libyaml_version
|
|
4
4
|
*
|
|
5
|
-
* Returns the version of
|
|
5
|
+
* Returns the version of the underlying YAML library as a three-element
|
|
6
|
+
* array. This is libyaml by default. On the experimental libfyaml backend,
|
|
7
|
+
* where libyaml is not linked, it reports the libfyaml version instead.
|
|
6
8
|
*/
|
|
7
9
|
static VALUE libyaml_version(VALUE module)
|
|
8
10
|
{
|
|
9
11
|
int major, minor, patch;
|
|
10
12
|
VALUE list[3];
|
|
11
13
|
|
|
14
|
+
#ifdef PSYCH_USE_LIBFYAML
|
|
15
|
+
/* Experimental libfyaml backend: there is no libyaml linked in. Report
|
|
16
|
+
* the libfyaml version so callers still receive a 3-element version. */
|
|
17
|
+
const struct fy_version *v = fy_version_default();
|
|
18
|
+
major = v ? v->major : 0;
|
|
19
|
+
minor = v ? v->minor : 0;
|
|
20
|
+
patch = 0;
|
|
21
|
+
#else
|
|
12
22
|
yaml_get_version(&major, &minor, &patch);
|
|
23
|
+
#endif
|
|
13
24
|
|
|
14
25
|
list[0] = INT2NUM(major);
|
|
15
26
|
list[1] = INT2NUM(minor);
|
|
@@ -18,6 +29,20 @@ static VALUE libyaml_version(VALUE module)
|
|
|
18
29
|
return rb_ary_new4((long)3, list);
|
|
19
30
|
}
|
|
20
31
|
|
|
32
|
+
#ifdef PSYCH_USE_LIBFYAML
|
|
33
|
+
/* call-seq: Psych.libfyaml_version
|
|
34
|
+
*
|
|
35
|
+
* Returns the libfyaml version string. This method is only defined when
|
|
36
|
+
* psych was built with the experimental libfyaml backend
|
|
37
|
+
* (+--enable-libfyaml+).
|
|
38
|
+
*/
|
|
39
|
+
static VALUE libfyaml_version(VALUE module)
|
|
40
|
+
{
|
|
41
|
+
const char *v = fy_library_version();
|
|
42
|
+
return v ? rb_usascii_str_new2(v) : Qnil;
|
|
43
|
+
}
|
|
44
|
+
#endif
|
|
45
|
+
|
|
21
46
|
VALUE mPsych;
|
|
22
47
|
|
|
23
48
|
void Init_psych(void)
|
|
@@ -29,6 +54,13 @@ void Init_psych(void)
|
|
|
29
54
|
|
|
30
55
|
rb_define_singleton_method(mPsych, "libyaml_version", libyaml_version, 0);
|
|
31
56
|
|
|
57
|
+
#ifdef PSYCH_USE_LIBFYAML
|
|
58
|
+
rb_define_singleton_method(mPsych, "libfyaml_version", libfyaml_version, 0);
|
|
59
|
+
rb_define_const(mPsych, "BACKEND", rb_usascii_str_new2("libfyaml"));
|
|
60
|
+
#else
|
|
61
|
+
rb_define_const(mPsych, "BACKEND", rb_usascii_str_new2("libyaml"));
|
|
62
|
+
#endif
|
|
63
|
+
|
|
32
64
|
Init_psych_parser();
|
|
33
65
|
Init_psych_emitter();
|
|
34
66
|
Init_psych_to_ruby();
|
data/ext/psych/psych.h
CHANGED
data/ext/psych/psych_emitter.c
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#include <psych.h>
|
|
2
2
|
|
|
3
|
+
#ifndef PSYCH_USE_LIBFYAML
|
|
4
|
+
|
|
3
5
|
#if !defined(RARRAY_CONST_PTR)
|
|
4
6
|
#define RARRAY_CONST_PTR(s) (const VALUE *)RARRAY_PTR(s)
|
|
5
7
|
#endif
|
|
@@ -587,3 +589,5 @@ void Init_psych_emitter(void)
|
|
|
587
589
|
id_indentation = rb_intern("indentation");
|
|
588
590
|
id_canonical = rb_intern("canonical");
|
|
589
591
|
}
|
|
592
|
+
|
|
593
|
+
#endif /* PSYCH_USE_LIBFYAML */
|
data/ext/psych/psych_parser.c
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#include <psych.h>
|
|
2
2
|
|
|
3
|
+
#ifndef PSYCH_USE_LIBFYAML
|
|
4
|
+
|
|
3
5
|
VALUE cPsychParser;
|
|
4
6
|
|
|
5
7
|
static ID id_read;
|
|
6
|
-
static ID id_path;
|
|
7
8
|
static ID id_empty;
|
|
8
9
|
static ID id_start_stream;
|
|
9
10
|
static ID id_end_stream;
|
|
@@ -51,19 +52,28 @@ static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read)
|
|
|
51
52
|
return 1;
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
/* The parser calls back into Ruby for every event, so a handler can call
|
|
56
|
+
* Psych::Parser#parse again on the same object. parse() reinitialises the
|
|
57
|
+
* parser it is handed, which would pull the input out from under the loop
|
|
58
|
+
* still driving it, so keep a flag to reject a reentrant call. */
|
|
59
|
+
typedef struct {
|
|
60
|
+
yaml_parser_t yaml_parser;
|
|
61
|
+
int parsing;
|
|
62
|
+
} psych_parser_t;
|
|
63
|
+
|
|
54
64
|
static void dealloc(void * ptr)
|
|
55
65
|
{
|
|
56
|
-
|
|
66
|
+
psych_parser_t * parser;
|
|
57
67
|
|
|
58
|
-
parser = (
|
|
59
|
-
yaml_parser_delete(parser);
|
|
68
|
+
parser = (psych_parser_t *)ptr;
|
|
69
|
+
yaml_parser_delete(&parser->yaml_parser);
|
|
60
70
|
xfree(parser);
|
|
61
71
|
}
|
|
62
72
|
|
|
63
73
|
#if 0
|
|
64
74
|
static size_t memsize(const void *ptr)
|
|
65
75
|
{
|
|
66
|
-
const
|
|
76
|
+
const psych_parser_t *parser = ptr;
|
|
67
77
|
/* TODO: calculate parser's size */
|
|
68
78
|
return 0;
|
|
69
79
|
}
|
|
@@ -80,10 +90,10 @@ static const rb_data_type_t psych_parser_type = {
|
|
|
80
90
|
|
|
81
91
|
static VALUE allocate(VALUE klass)
|
|
82
92
|
{
|
|
83
|
-
|
|
84
|
-
VALUE obj = TypedData_Make_Struct(klass,
|
|
93
|
+
psych_parser_t * parser;
|
|
94
|
+
VALUE obj = TypedData_Make_Struct(klass, psych_parser_t, &psych_parser_type, parser);
|
|
85
95
|
|
|
86
|
-
yaml_parser_initialize(parser);
|
|
96
|
+
yaml_parser_initialize(&parser->yaml_parser);
|
|
87
97
|
|
|
88
98
|
return obj;
|
|
89
99
|
}
|
|
@@ -256,9 +266,22 @@ static VALUE protected_event_location(VALUE pointer)
|
|
|
256
266
|
return rb_funcall3(args[0], id_event_location, 4, args + 1);
|
|
257
267
|
}
|
|
258
268
|
|
|
259
|
-
|
|
269
|
+
struct parse_args {
|
|
270
|
+
psych_parser_t * psych_parser;
|
|
271
|
+
VALUE self;
|
|
272
|
+
VALUE handler;
|
|
273
|
+
VALUE yaml;
|
|
274
|
+
VALUE path;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
static VALUE parse_body(VALUE ptr)
|
|
260
278
|
{
|
|
261
|
-
|
|
279
|
+
struct parse_args * pargs = (struct parse_args *)ptr;
|
|
280
|
+
yaml_parser_t * parser = &pargs->psych_parser->yaml_parser;
|
|
281
|
+
VALUE self = pargs->self;
|
|
282
|
+
VALUE handler = pargs->handler;
|
|
283
|
+
VALUE yaml = pargs->yaml;
|
|
284
|
+
VALUE path = pargs->path;
|
|
262
285
|
yaml_event_t event;
|
|
263
286
|
int done = 0;
|
|
264
287
|
int state = 0;
|
|
@@ -266,8 +289,6 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
|
|
|
266
289
|
int encoding = rb_utf8_encindex();
|
|
267
290
|
rb_encoding * internal_enc = rb_default_internal_encoding();
|
|
268
291
|
|
|
269
|
-
TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);
|
|
270
|
-
|
|
271
292
|
yaml_parser_delete(parser);
|
|
272
293
|
yaml_parser_initialize(parser);
|
|
273
294
|
|
|
@@ -311,6 +332,10 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
|
|
|
311
332
|
event_args[3] = end_line;
|
|
312
333
|
event_args[4] = end_column;
|
|
313
334
|
rb_protect(protected_event_location, (VALUE)event_args, &state);
|
|
335
|
+
if (state) {
|
|
336
|
+
yaml_event_delete(&event);
|
|
337
|
+
rb_jump_tag(state);
|
|
338
|
+
}
|
|
314
339
|
|
|
315
340
|
switch(event.type) {
|
|
316
341
|
case YAML_STREAM_START_EVENT:
|
|
@@ -495,7 +520,11 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
|
|
|
495
520
|
rb_protect(protected_end_mapping, handler, &state);
|
|
496
521
|
break;
|
|
497
522
|
case YAML_NO_EVENT:
|
|
523
|
+
/* Once libyaml has produced the stream end, every later call
|
|
524
|
+
* succeeds with a zeroed event and YAML_STREAM_END_EVENT can no
|
|
525
|
+
* longer be reached. Stop rather than loop forever. */
|
|
498
526
|
rb_protect(protected_empty, handler, &state);
|
|
527
|
+
done = 1;
|
|
499
528
|
break;
|
|
500
529
|
case YAML_STREAM_END_EVENT:
|
|
501
530
|
rb_protect(protected_end_stream, handler, &state);
|
|
@@ -509,6 +538,37 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
|
|
|
509
538
|
return self;
|
|
510
539
|
}
|
|
511
540
|
|
|
541
|
+
static VALUE parse_ensure(VALUE ptr)
|
|
542
|
+
{
|
|
543
|
+
psych_parser_t * parser = (psych_parser_t *)ptr;
|
|
544
|
+
|
|
545
|
+
parser->parsing = 0;
|
|
546
|
+
|
|
547
|
+
return Qnil;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
|
|
551
|
+
{
|
|
552
|
+
psych_parser_t * parser;
|
|
553
|
+
struct parse_args pargs;
|
|
554
|
+
|
|
555
|
+
TypedData_Get_Struct(self, psych_parser_t, &psych_parser_type, parser);
|
|
556
|
+
|
|
557
|
+
if (parser->parsing) {
|
|
558
|
+
rb_raise(rb_const_get(mPsych, rb_intern("Exception")),
|
|
559
|
+
"parser is already parsing, it cannot be reused from a handler callback");
|
|
560
|
+
}
|
|
561
|
+
parser->parsing = 1;
|
|
562
|
+
|
|
563
|
+
pargs.psych_parser = parser;
|
|
564
|
+
pargs.self = self;
|
|
565
|
+
pargs.handler = handler;
|
|
566
|
+
pargs.yaml = yaml;
|
|
567
|
+
pargs.path = path;
|
|
568
|
+
|
|
569
|
+
return rb_ensure(parse_body, (VALUE)&pargs, parse_ensure, (VALUE)parser);
|
|
570
|
+
}
|
|
571
|
+
|
|
512
572
|
/*
|
|
513
573
|
* call-seq:
|
|
514
574
|
* parser.mark # => #<Psych::Parser::Mark>
|
|
@@ -520,13 +580,13 @@ static VALUE mark(VALUE self)
|
|
|
520
580
|
{
|
|
521
581
|
VALUE mark_klass;
|
|
522
582
|
VALUE args[3];
|
|
523
|
-
|
|
583
|
+
psych_parser_t * parser;
|
|
524
584
|
|
|
525
|
-
TypedData_Get_Struct(self,
|
|
585
|
+
TypedData_Get_Struct(self, psych_parser_t, &psych_parser_type, parser);
|
|
526
586
|
mark_klass = rb_const_get_at(cPsychParser, rb_intern("Mark"));
|
|
527
|
-
args[0] = SIZET2NUM(parser->mark.index);
|
|
528
|
-
args[1] = SIZET2NUM(parser->mark.line);
|
|
529
|
-
args[2] = SIZET2NUM(parser->mark.column);
|
|
587
|
+
args[0] = SIZET2NUM(parser->yaml_parser.mark.index);
|
|
588
|
+
args[1] = SIZET2NUM(parser->yaml_parser.mark.line);
|
|
589
|
+
args[2] = SIZET2NUM(parser->yaml_parser.mark.column);
|
|
530
590
|
|
|
531
591
|
return rb_class_new_instance(3, args, mark_klass);
|
|
532
592
|
}
|
|
@@ -559,7 +619,6 @@ void Init_psych_parser(void)
|
|
|
559
619
|
rb_define_method(cPsychParser, "mark", mark, 0);
|
|
560
620
|
|
|
561
621
|
id_read = rb_intern("read");
|
|
562
|
-
id_path = rb_intern("path");
|
|
563
622
|
id_empty = rb_intern("empty");
|
|
564
623
|
id_start_stream = rb_intern("start_stream");
|
|
565
624
|
id_end_stream = rb_intern("end_stream");
|
|
@@ -573,3 +632,5 @@ void Init_psych_parser(void)
|
|
|
573
632
|
id_end_mapping = rb_intern("end_mapping");
|
|
574
633
|
id_event_location = rb_intern("event_location");
|
|
575
634
|
}
|
|
635
|
+
|
|
636
|
+
#endif /* PSYCH_USE_LIBFYAML */
|
data/lib/psych/class_loader.rb
CHANGED
data/lib/psych/parser.rb
CHANGED
|
@@ -59,7 +59,46 @@ module Psych
|
|
|
59
59
|
# See Psych::Parser and Psych::Parser#handler
|
|
60
60
|
|
|
61
61
|
def parse yaml, path = yaml.respond_to?(:path) ? yaml.path : "<unknown>"
|
|
62
|
-
_native_parse @handler, yaml, path
|
|
62
|
+
_native_parse @handler, strip_bom(yaml), path
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
BOM = {
|
|
68
|
+
Encoding::UTF_8 => "\u{FEFF}".freeze,
|
|
69
|
+
Encoding::UTF_16LE => "\u{FEFF}".encode(Encoding::UTF_16LE).freeze,
|
|
70
|
+
Encoding::UTF_16BE => "\u{FEFF}".encode(Encoding::UTF_16BE).freeze,
|
|
71
|
+
Encoding::UTF_32LE => "\u{FEFF}".encode(Encoding::UTF_32LE).freeze,
|
|
72
|
+
Encoding::UTF_32BE => "\u{FEFF}".encode(Encoding::UTF_32BE).freeze,
|
|
73
|
+
}.freeze
|
|
74
|
+
private_constant :BOM
|
|
75
|
+
|
|
76
|
+
# libyaml only skips a leading byte order mark when it detects the stream
|
|
77
|
+
# encoding by itself. Psych passes the encoding explicitly whenever it is
|
|
78
|
+
# known, and on that path libyaml counts the BOM as a first-line character,
|
|
79
|
+
# which shifts the column of every token on the first line and silently
|
|
80
|
+
# terminates a block mapping at the second line [Bug #13615].
|
|
81
|
+
def strip_bom yaml
|
|
82
|
+
if String === yaml
|
|
83
|
+
bom = BOM[yaml.encoding]
|
|
84
|
+
# delete_prefix copies even when there is no prefix, so keep the guard.
|
|
85
|
+
return yaml.delete_prefix(bom) if bom && yaml.start_with?(bom)
|
|
86
|
+
elsif yaml.respond_to?(:read) && yaml.respond_to?(:external_encoding) &&
|
|
87
|
+
yaml.respond_to?(:pos) && yaml.respond_to?(:seek)
|
|
88
|
+
bom = BOM[yaml.external_encoding]
|
|
89
|
+
skip_io_bom yaml, bom.b if bom
|
|
90
|
+
end
|
|
91
|
+
yaml
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def skip_io_bom io, bom
|
|
95
|
+
begin
|
|
96
|
+
pos = io.pos
|
|
97
|
+
rescue SystemCallError, IOError
|
|
98
|
+
return # Not seekable; nothing has been consumed yet.
|
|
99
|
+
end
|
|
100
|
+
head = io.read(bom.bytesize)
|
|
101
|
+
io.seek(pos, IO::SEEK_SET) if head && head.b != bom
|
|
63
102
|
end
|
|
64
103
|
end
|
|
65
104
|
end
|
data/lib/psych/scalar_scanner.rb
CHANGED
|
@@ -24,6 +24,18 @@ module Psych
|
|
|
24
24
|
|[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
|
|
25
25
|
|[-+]?0x[_,]*[0-9a-fA-F][0-9a-fA-F_,]* (?# base 16))$/x
|
|
26
26
|
|
|
27
|
+
# YAML 1.1 treats yes/no/on/off as booleans in addition to true/false,
|
|
28
|
+
# while YAML 1.2's core schema only recognizes true/false. The default
|
|
29
|
+
# libyaml backend keeps the 1.1 set for backward compatibility; the
|
|
30
|
+
# experimental libfyaml backend follows 1.2.
|
|
31
|
+
if defined?(Psych::BACKEND) && Psych::BACKEND == 'libfyaml'
|
|
32
|
+
BOOLEAN_TRUE = /^true$/i
|
|
33
|
+
BOOLEAN_FALSE = /^false$/i
|
|
34
|
+
else
|
|
35
|
+
BOOLEAN_TRUE = /^(yes|true|on)$/i
|
|
36
|
+
BOOLEAN_FALSE = /^(no|false|off)$/i
|
|
37
|
+
end
|
|
38
|
+
|
|
27
39
|
attr_reader :class_loader
|
|
28
40
|
|
|
29
41
|
# Create a new scanner
|
|
@@ -48,9 +60,9 @@ module Psych
|
|
|
48
60
|
string
|
|
49
61
|
elsif string == '~' || string.match?(/^null$/i)
|
|
50
62
|
nil
|
|
51
|
-
elsif string.match?(
|
|
63
|
+
elsif string.match?(BOOLEAN_TRUE)
|
|
52
64
|
true
|
|
53
|
-
elsif string.match?(
|
|
65
|
+
elsif string.match?(BOOLEAN_FALSE)
|
|
54
66
|
false
|
|
55
67
|
else
|
|
56
68
|
string
|
|
@@ -115,7 +127,7 @@ module Psych
|
|
|
115
127
|
def parse_time string
|
|
116
128
|
klass = class_loader.load 'Time'
|
|
117
129
|
|
|
118
|
-
date, time = *(string.split(/[
|
|
130
|
+
date, time = *(string.split(/[Tt]|\s+/, 2))
|
|
119
131
|
(yy, m, dd) = date.match(/^(-?\d{4})-(\d{1,2})-(\d{1,2})/).captures.map { |x| x.to_i }
|
|
120
132
|
md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/)
|
|
121
133
|
|
data/lib/psych/versions.rb
CHANGED
|
@@ -72,7 +72,7 @@ module Psych
|
|
|
72
72
|
when '!binary', 'tag:yaml.org,2002:binary'
|
|
73
73
|
o.value.unpack('m').first
|
|
74
74
|
when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
|
|
75
|
-
klass =
|
|
75
|
+
klass = resolve_subclass($1, String)
|
|
76
76
|
if klass
|
|
77
77
|
klass.allocate.replace o.value
|
|
78
78
|
else
|
|
@@ -87,6 +87,7 @@ module Psych
|
|
|
87
87
|
DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
|
|
88
88
|
(t.subsec/86400)
|
|
89
89
|
when '!ruby/encoding'
|
|
90
|
+
class_loader.encoding
|
|
90
91
|
::Encoding.find o.value
|
|
91
92
|
when "!ruby/object:Complex"
|
|
92
93
|
class_loader.complex
|
|
@@ -156,7 +157,7 @@ module Psych
|
|
|
156
157
|
}
|
|
157
158
|
map
|
|
158
159
|
when /^!(?:seq|ruby\/array):(.*)$/
|
|
159
|
-
klass =
|
|
160
|
+
klass = resolve_subclass($1, Array)
|
|
160
161
|
list = register(o, klass.allocate)
|
|
161
162
|
o.children.each { |c| list.push accept c }
|
|
162
163
|
list
|
|
@@ -246,7 +247,7 @@ module Psych
|
|
|
246
247
|
end
|
|
247
248
|
|
|
248
249
|
when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
|
|
249
|
-
klass =
|
|
250
|
+
klass = resolve_subclass($1, String)
|
|
250
251
|
members = {}
|
|
251
252
|
string = nil
|
|
252
253
|
|
|
@@ -267,7 +268,7 @@ module Psych
|
|
|
267
268
|
end
|
|
268
269
|
init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
|
|
269
270
|
when /^!ruby\/array:(.*)$/
|
|
270
|
-
klass =
|
|
271
|
+
klass = resolve_subclass($1, Array)
|
|
271
272
|
list = register(o, klass.allocate)
|
|
272
273
|
|
|
273
274
|
members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
|
|
@@ -301,7 +302,7 @@ module Psych
|
|
|
301
302
|
set
|
|
302
303
|
|
|
303
304
|
when /^!ruby\/hash-with-ivars(?::(.*))?$/
|
|
304
|
-
hash = $1 ?
|
|
305
|
+
hash = $1 ? resolve_subclass($1, Hash).allocate : {}
|
|
305
306
|
register o, hash
|
|
306
307
|
o.children.each_slice(2) do |key, value|
|
|
307
308
|
case key.value
|
|
@@ -316,7 +317,7 @@ module Psych
|
|
|
316
317
|
hash
|
|
317
318
|
|
|
318
319
|
when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/
|
|
319
|
-
revive_hash register(o,
|
|
320
|
+
revive_hash register(o, resolve_subclass($1, Hash).allocate), o
|
|
320
321
|
|
|
321
322
|
when '!omap', 'tag:yaml.org,2002:omap'
|
|
322
323
|
map = register(o, class_loader.psych_omap.new)
|
|
@@ -444,9 +445,6 @@ module Psych
|
|
|
444
445
|
end
|
|
445
446
|
end
|
|
446
447
|
|
|
447
|
-
def merge_key hash, key, val
|
|
448
|
-
end
|
|
449
|
-
|
|
450
448
|
def revive klass, node
|
|
451
449
|
s = register(node, klass.allocate)
|
|
452
450
|
init_with(s, revive_hash({}, node, true), node)
|
|
@@ -468,6 +466,19 @@ module Psych
|
|
|
468
466
|
def resolve_class klassname
|
|
469
467
|
class_loader.load klassname
|
|
470
468
|
end
|
|
469
|
+
|
|
470
|
+
# Resolve +klassname+ and ensure it is +parent+ or one of its
|
|
471
|
+
# subclasses. Tags such as !ruby/hash-with-ivars are only ever emitted
|
|
472
|
+
# for subclasses of a specific core class; without this check a crafted
|
|
473
|
+
# document could name an unrelated (but permitted) class and have its
|
|
474
|
+
# state populated directly, bypassing the class's own init_with.
|
|
475
|
+
def resolve_subclass klassname, parent
|
|
476
|
+
klass = resolve_class(klassname)
|
|
477
|
+
if klass && !(klass <= parent)
|
|
478
|
+
raise ArgumentError, "Invalid tag: expected a subclass of #{parent}, got #{klass}"
|
|
479
|
+
end
|
|
480
|
+
klass
|
|
481
|
+
end
|
|
471
482
|
end
|
|
472
483
|
|
|
473
484
|
class NoAliasRuby < ToRuby
|
data/lib/psych.jar
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: psych
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.5.0
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Aaron Patterson
|
|
@@ -133,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
133
133
|
version: '0'
|
|
134
134
|
requirements:
|
|
135
135
|
- jar org.snakeyaml:snakeyaml-engine, 2.10
|
|
136
|
-
rubygems_version: 4.0.
|
|
136
|
+
rubygems_version: 4.0.19
|
|
137
137
|
specification_version: 4
|
|
138
138
|
summary: Psych is a YAML parser and emitter
|
|
139
139
|
test_files: []
|