diff options
Diffstat (limited to 'ext/psych')
| -rw-r--r-- | ext/psych/depend | 25 | ||||
| -rw-r--r-- | ext/psych/extconf.rb | 9 | ||||
| -rw-r--r-- | ext/psych/lib/psych.rb | 115 | ||||
| -rw-r--r-- | ext/psych/lib/psych/class_loader.rb | 1 | ||||
| -rw-r--r-- | ext/psych/lib/psych/core_ext.rb | 21 | ||||
| -rw-r--r-- | ext/psych/lib/psych/nodes/node.rb | 7 | ||||
| -rw-r--r-- | ext/psych/lib/psych/scalar_scanner.rb | 22 | ||||
| -rw-r--r-- | ext/psych/lib/psych/versions.rb | 4 | ||||
| -rw-r--r-- | ext/psych/lib/psych/visitors/to_ruby.rb | 57 | ||||
| -rw-r--r-- | ext/psych/lib/psych/visitors/yaml_tree.rb | 81 | ||||
| -rw-r--r-- | ext/psych/psych.c | 3 | ||||
| -rw-r--r-- | ext/psych/psych.gemspec | 52 | ||||
| -rw-r--r-- | ext/psych/psych_emitter.c | 276 | ||||
| -rw-r--r-- | ext/psych/psych_parser.c | 536 | ||||
| -rw-r--r-- | ext/psych/psych_to_ruby.c | 5 | ||||
| -rw-r--r-- | ext/psych/psych_yaml_tree.c | 1 |
16 files changed, 718 insertions, 497 deletions
diff --git a/ext/psych/depend b/ext/psych/depend index 78bde9a53d..95175841a2 100644 --- a/ext/psych/depend +++ b/ext/psych/depend @@ -67,6 +67,7 @@ psych.o: $(hdrdir)/ruby/internal/attr/noexcept.h psych.o: $(hdrdir)/ruby/internal/attr/noinline.h psych.o: $(hdrdir)/ruby/internal/attr/nonnull.h psych.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych.o: $(hdrdir)/ruby/internal/attr/packed_struct.h psych.o: $(hdrdir)/ruby/internal/attr/pure.h psych.o: $(hdrdir)/ruby/internal/attr/restrict.h psych.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -135,7 +136,6 @@ psych.o: $(hdrdir)/ruby/internal/intern/enumerator.h psych.o: $(hdrdir)/ruby/internal/intern/error.h psych.o: $(hdrdir)/ruby/internal/intern/eval.h psych.o: $(hdrdir)/ruby/internal/intern/file.h -psych.o: $(hdrdir)/ruby/internal/intern/gc.h psych.o: $(hdrdir)/ruby/internal/intern/hash.h psych.o: $(hdrdir)/ruby/internal/intern/io.h psych.o: $(hdrdir)/ruby/internal/intern/load.h @@ -152,6 +152,7 @@ psych.o: $(hdrdir)/ruby/internal/intern/re.h psych.o: $(hdrdir)/ruby/internal/intern/ruby.h psych.o: $(hdrdir)/ruby/internal/intern/select.h psych.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych.o: $(hdrdir)/ruby/internal/intern/set.h psych.o: $(hdrdir)/ruby/internal/intern/signal.h psych.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych.o: $(hdrdir)/ruby/internal/intern/string.h @@ -166,12 +167,12 @@ psych.o: $(hdrdir)/ruby/internal/memory.h psych.o: $(hdrdir)/ruby/internal/method.h psych.o: $(hdrdir)/ruby/internal/module.h psych.o: $(hdrdir)/ruby/internal/newobj.h -psych.o: $(hdrdir)/ruby/internal/rgengc.h psych.o: $(hdrdir)/ruby/internal/scan_args.h psych.o: $(hdrdir)/ruby/internal/special_consts.h psych.o: $(hdrdir)/ruby/internal/static_assert.h psych.o: $(hdrdir)/ruby/internal/stdalign.h psych.o: $(hdrdir)/ruby/internal/stdbool.h +psych.o: $(hdrdir)/ruby/internal/stdckdint.h psych.o: $(hdrdir)/ruby/internal/symbol.h psych.o: $(hdrdir)/ruby/internal/value.h psych.o: $(hdrdir)/ruby/internal/value_type.h @@ -244,6 +245,7 @@ psych_emitter.o: $(hdrdir)/ruby/internal/attr/noexcept.h psych_emitter.o: $(hdrdir)/ruby/internal/attr/noinline.h psych_emitter.o: $(hdrdir)/ruby/internal/attr/nonnull.h psych_emitter.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych_emitter.o: $(hdrdir)/ruby/internal/attr/packed_struct.h psych_emitter.o: $(hdrdir)/ruby/internal/attr/pure.h psych_emitter.o: $(hdrdir)/ruby/internal/attr/restrict.h psych_emitter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -312,7 +314,6 @@ psych_emitter.o: $(hdrdir)/ruby/internal/intern/enumerator.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/error.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/eval.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/file.h -psych_emitter.o: $(hdrdir)/ruby/internal/intern/gc.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/hash.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/io.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/load.h @@ -329,6 +330,7 @@ psych_emitter.o: $(hdrdir)/ruby/internal/intern/re.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/ruby.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/select.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/set.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/signal.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/string.h @@ -343,12 +345,12 @@ psych_emitter.o: $(hdrdir)/ruby/internal/memory.h psych_emitter.o: $(hdrdir)/ruby/internal/method.h psych_emitter.o: $(hdrdir)/ruby/internal/module.h psych_emitter.o: $(hdrdir)/ruby/internal/newobj.h -psych_emitter.o: $(hdrdir)/ruby/internal/rgengc.h psych_emitter.o: $(hdrdir)/ruby/internal/scan_args.h psych_emitter.o: $(hdrdir)/ruby/internal/special_consts.h psych_emitter.o: $(hdrdir)/ruby/internal/static_assert.h psych_emitter.o: $(hdrdir)/ruby/internal/stdalign.h psych_emitter.o: $(hdrdir)/ruby/internal/stdbool.h +psych_emitter.o: $(hdrdir)/ruby/internal/stdckdint.h psych_emitter.o: $(hdrdir)/ruby/internal/symbol.h psych_emitter.o: $(hdrdir)/ruby/internal/value.h psych_emitter.o: $(hdrdir)/ruby/internal/value_type.h @@ -421,6 +423,7 @@ psych_parser.o: $(hdrdir)/ruby/internal/attr/noexcept.h psych_parser.o: $(hdrdir)/ruby/internal/attr/noinline.h psych_parser.o: $(hdrdir)/ruby/internal/attr/nonnull.h psych_parser.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych_parser.o: $(hdrdir)/ruby/internal/attr/packed_struct.h psych_parser.o: $(hdrdir)/ruby/internal/attr/pure.h psych_parser.o: $(hdrdir)/ruby/internal/attr/restrict.h psych_parser.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -489,7 +492,6 @@ psych_parser.o: $(hdrdir)/ruby/internal/intern/enumerator.h psych_parser.o: $(hdrdir)/ruby/internal/intern/error.h psych_parser.o: $(hdrdir)/ruby/internal/intern/eval.h psych_parser.o: $(hdrdir)/ruby/internal/intern/file.h -psych_parser.o: $(hdrdir)/ruby/internal/intern/gc.h psych_parser.o: $(hdrdir)/ruby/internal/intern/hash.h psych_parser.o: $(hdrdir)/ruby/internal/intern/io.h psych_parser.o: $(hdrdir)/ruby/internal/intern/load.h @@ -506,6 +508,7 @@ psych_parser.o: $(hdrdir)/ruby/internal/intern/re.h psych_parser.o: $(hdrdir)/ruby/internal/intern/ruby.h psych_parser.o: $(hdrdir)/ruby/internal/intern/select.h psych_parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/set.h psych_parser.o: $(hdrdir)/ruby/internal/intern/signal.h psych_parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych_parser.o: $(hdrdir)/ruby/internal/intern/string.h @@ -520,12 +523,12 @@ psych_parser.o: $(hdrdir)/ruby/internal/memory.h psych_parser.o: $(hdrdir)/ruby/internal/method.h psych_parser.o: $(hdrdir)/ruby/internal/module.h psych_parser.o: $(hdrdir)/ruby/internal/newobj.h -psych_parser.o: $(hdrdir)/ruby/internal/rgengc.h psych_parser.o: $(hdrdir)/ruby/internal/scan_args.h psych_parser.o: $(hdrdir)/ruby/internal/special_consts.h psych_parser.o: $(hdrdir)/ruby/internal/static_assert.h psych_parser.o: $(hdrdir)/ruby/internal/stdalign.h psych_parser.o: $(hdrdir)/ruby/internal/stdbool.h +psych_parser.o: $(hdrdir)/ruby/internal/stdckdint.h psych_parser.o: $(hdrdir)/ruby/internal/symbol.h psych_parser.o: $(hdrdir)/ruby/internal/value.h psych_parser.o: $(hdrdir)/ruby/internal/value_type.h @@ -598,6 +601,7 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noexcept.h psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noinline.h psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/nonnull.h psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/packed_struct.h psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/pure.h psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/restrict.h psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -666,7 +670,6 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/enumerator.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/error.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/eval.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/file.h -psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/gc.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/hash.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/io.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/load.h @@ -683,6 +686,7 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/re.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/ruby.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/set.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/signal.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/string.h @@ -697,12 +701,12 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/memory.h psych_to_ruby.o: $(hdrdir)/ruby/internal/method.h psych_to_ruby.o: $(hdrdir)/ruby/internal/module.h psych_to_ruby.o: $(hdrdir)/ruby/internal/newobj.h -psych_to_ruby.o: $(hdrdir)/ruby/internal/rgengc.h psych_to_ruby.o: $(hdrdir)/ruby/internal/scan_args.h psych_to_ruby.o: $(hdrdir)/ruby/internal/special_consts.h psych_to_ruby.o: $(hdrdir)/ruby/internal/static_assert.h psych_to_ruby.o: $(hdrdir)/ruby/internal/stdalign.h psych_to_ruby.o: $(hdrdir)/ruby/internal/stdbool.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/stdckdint.h psych_to_ruby.o: $(hdrdir)/ruby/internal/symbol.h psych_to_ruby.o: $(hdrdir)/ruby/internal/value.h psych_to_ruby.o: $(hdrdir)/ruby/internal/value_type.h @@ -775,6 +779,7 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noexcept.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noinline.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/nonnull.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noreturn.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/packed_struct.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/pure.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/restrict.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -843,7 +848,6 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/enumerator.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/error.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/eval.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/file.h -psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/gc.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/hash.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/io.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/load.h @@ -860,6 +864,7 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/re.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/ruby.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/set.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/signal.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/string.h @@ -874,12 +879,12 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/memory.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/method.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/module.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/newobj.h -psych_yaml_tree.o: $(hdrdir)/ruby/internal/rgengc.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/scan_args.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/special_consts.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/static_assert.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdalign.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdbool.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdckdint.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/symbol.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/value.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/psych/extconf.rb b/ext/psych/extconf.rb index 41daf8c238..589e201c1c 100644 --- a/ext/psych/extconf.rb +++ b/ext/psych/extconf.rb @@ -22,7 +22,7 @@ if yaml_source args = [ yaml_configure, "--enable-#{shared ? 'shared' : 'static'}", - "--host=#{RbConfig::CONFIG['host'].sub(/-unknown-/, '-')}", + "--host=#{RbConfig::CONFIG['host'].sub(/-unknown-/, '-').sub(/arm64/, 'arm')}", "CC=#{RbConfig::CONFIG['CC']}", *(["CFLAGS=-w"] if RbConfig::CONFIG["GCC"] == "yes"), ] @@ -36,8 +36,11 @@ if yaml_source libyaml = "libyaml.#$LIBEXT" $cleanfiles << libyaml $LOCAL_LIBS.prepend("$(LIBYAML) ") -else # default to pre-installed libyaml - pkg_config('yaml-0.1') + + # default to pre-installed libyaml +elsif pkg_config('yaml-0.1') + # found with pkg-config +else dir_config('libyaml') find_header('yaml.h') or abort "yaml.h not found" find_library('yaml', 'yaml_get_version') or abort "libyaml not found" diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb index 4a2ab58514..850a6d1937 100644 --- a/ext/psych/lib/psych.rb +++ b/ext/psych/lib/psych.rb @@ -1,4 +1,6 @@ # frozen_string_literal: true +require 'date' + require_relative 'psych/versions' case RUBY_ENGINE when 'jruby' @@ -21,7 +23,6 @@ require_relative 'psych/parser' require_relative 'psych/omap' require_relative 'psych/set' require_relative 'psych/coder' -require_relative 'psych/core_ext' require_relative 'psych/stream' require_relative 'psych/json/tree_builder' require_relative 'psych/json/stream' @@ -84,7 +85,7 @@ require_relative 'psych/class_loader' # Psych.safe_load_file("data.yml", permitted_classes: [Date]) # Psych.load_file("trusted_database.yml") # -# ==== Exception handling +# ==== \Exception handling # # begin # # The second argument changes only the exception contents @@ -148,7 +149,7 @@ require_relative 'psych/class_loader' # # Returns Psych::Nodes::Document # Psych.parse_file('database.yml') # -# ==== Exception handling +# ==== \Exception handling # # begin # # The second argument changes only the exception contents @@ -268,10 +269,10 @@ module Psych # YAML documents that are supplied via user input. Instead, please use the # load method or the safe_load method. # - def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false + def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true result = parse(yaml, filename: filename) return fallback unless result - result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer) + result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer, parse_symbols: parse_symbols) end ### @@ -319,13 +320,13 @@ module Psych # Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"} # Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"} # - def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false + def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true result = parse(yaml, filename: filename) return fallback unless result class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s), permitted_symbols.map(&:to_s)) - scanner = ScalarScanner.new class_loader, strict_integer: strict_integer + scanner = ScalarScanner.new class_loader, strict_integer: strict_integer, parse_symbols: parse_symbols visitor = if aliases Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze else @@ -340,7 +341,7 @@ module Psych # provided, the object contained in the first document will be returned. # +filename+ will be used in the exception message if any exception # is raised while parsing. If +yaml+ is empty, it returns - # the specified +fallback+ return value, which defaults to +false+. + # the specified +fallback+ return value, which defaults to +nil+. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. # @@ -365,7 +366,7 @@ module Psych # Raises a TypeError when `yaml` parameter is NilClass. This method is # similar to `safe_load` except that `Symbol` objects are allowed by default. # - def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false + def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true safe_load yaml, permitted_classes: permitted_classes, permitted_symbols: permitted_symbols, aliases: aliases, @@ -373,7 +374,8 @@ module Psych fallback: fallback, symbolize_names: symbolize_names, freeze: freeze, - strict_integer: strict_integer + strict_integer: strict_integer, + parse_symbols: parse_symbols end ### @@ -479,6 +481,7 @@ module Psych # # Default: <tt>2</tt>. # [<tt>:line_width</tt>] Max character to wrap line at. + # For unlimited line width use <tt>-1</tt>. # # Default: <tt>0</tt> (meaning "wrap at 81"). # [<tt>:canonical</tt>] Write "canonical" YAML form (very verbose, yet @@ -489,6 +492,10 @@ module Psych # # Default: <tt>false</tt>. # + # [<tt>:stringify_names</tt>] Dump symbol keys in Hash objects as string. + # + # Default: <tt>false</tt>. + # # Example: # # # Dump an array, get back a YAML string @@ -502,6 +509,9 @@ module Psych # # # Dump an array to an IO with indentation set # Psych.dump(['a', ['b']], StringIO.new, indentation: 3) + # + # # Dump hash with symbol keys as string + # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n" def self.dump o, io = nil, options = {} if Hash === io options = io @@ -552,6 +562,7 @@ module Psych # # Default: <tt>2</tt>. # [<tt>:line_width</tt>] Max character to wrap line at. + # For unlimited line width use <tt>-1</tt>. # # Default: <tt>0</tt> (meaning "wrap at 81"). # [<tt>:canonical</tt>] Write "canonical" YAML form (very verbose, yet @@ -562,6 +573,10 @@ module Psych # # Default: <tt>false</tt>. # + # [<tt>:stringify_names</tt>] Dump symbol keys in Hash objects as string. + # + # Default: <tt>false</tt>. + # # Example: # # # Dump an array, get back a YAML string @@ -575,6 +590,9 @@ module Psych # # # Dump an array to an IO with indentation set # Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3) + # + # # Dump hash with symbol keys as string + # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n" def self.safe_dump o, io = nil, options = {} if Hash === io options = io @@ -637,6 +655,35 @@ module Psych end ### + # Load multiple documents given in +yaml+. Returns the parsed documents + # as a list. + # + # Example: + # + # Psych.safe_load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar'] + # + # list = [] + # Psych.safe_load_stream("--- foo\n...\n--- bar\n...") do |ruby| + # list << ruby + # end + # list # => ['foo', 'bar'] + # + def self.safe_load_stream yaml, filename: nil, permitted_classes: [], aliases: false + documents = parse_stream(yaml, filename: filename).children.map do |child| + stream = Psych::Nodes::Stream.new + stream.children << child + safe_load(stream.to_yaml, permitted_classes: permitted_classes, aliases: aliases) + end + + if block_given? + documents.each { |doc| yield doc } + nil + else + documents + end + end + + ### # Load the document contained in +filename+. Returns the yaml contained in # +filename+ as a Ruby object, or if the file is empty, it returns # the specified +fallback+ return value, which defaults to +false+. @@ -653,7 +700,7 @@ module Psych ### # Safely loads the document contained in +filename+. Returns the yaml contained in # +filename+ as a Ruby object, or if the file is empty, it returns - # the specified +fallback+ return value, which defaults to +false+. + # the specified +fallback+ return value, which defaults to +nil+. # See safe_load for options. def self.safe_load_file filename, **kwargs File.open(filename, 'r:bom|utf-8') { |f| @@ -664,7 +711,7 @@ module Psych ### # Loads the document contained in +filename+. Returns the yaml contained in # +filename+ as a Ruby object, or if the file is empty, it returns - # the specified +fallback+ return value, which defaults to +false+. + # the specified +fallback+ return value, which defaults to +nil+. # See load for options. def self.load_file filename, **kwargs File.open(filename, 'r:bom|utf-8') { |f| @@ -694,26 +741,8 @@ module Psych dump_tags[klass] = tag end - # Workaround for emulating `warn '...', uplevel: 1` in Ruby 2.4 or lower. - def self.warn_with_uplevel(message, uplevel: 1) - at = parse_caller(caller[uplevel]).join(':') - warn "#{at}: #{message}" - end - - def self.parse_caller(at) - if /^(.+?):(\d+)(?::in `.*')?/ =~ at - file = $1 - line = $2.to_i - [file, line] - end - end - private_class_method :warn_with_uplevel, :parse_caller - class << self if defined?(Ractor) - require 'forwardable' - extend Forwardable - class Config attr_accessor :load_tags, :dump_tags, :domain_types def initialize @@ -727,7 +756,29 @@ module Psych Ractor.current[:PsychConfig] ||= Config.new end - def_delegators :config, :load_tags, :dump_tags, :domain_types, :load_tags=, :dump_tags=, :domain_types= + def load_tags + config.load_tags + end + + def dump_tags + config.dump_tags + end + + def domain_types + config.domain_types + end + + def load_tags=(value) + config.load_tags = value + end + + def dump_tags=(value) + config.dump_tags = value + end + + def domain_types=(value) + config.domain_types = value + end else attr_accessor :load_tags attr_accessor :dump_tags @@ -739,3 +790,5 @@ module Psych self.domain_types = {} # :startdoc: end + +require_relative 'psych/core_ext' diff --git a/ext/psych/lib/psych/class_loader.rb b/ext/psych/lib/psych/class_loader.rb index 50efc35ee2..c8f509720a 100644 --- a/ext/psych/lib/psych/class_loader.rb +++ b/ext/psych/lib/psych/class_loader.rb @@ -6,6 +6,7 @@ module Psych class ClassLoader # :nodoc: BIG_DECIMAL = 'BigDecimal' COMPLEX = 'Complex' + DATA = 'Data' unless RUBY_VERSION < "3.2" DATE = 'Date' DATE_TIME = 'DateTime' EXCEPTION = 'Exception' diff --git a/ext/psych/lib/psych/core_ext.rb b/ext/psych/lib/psych/core_ext.rb index 0721a133c3..6dfd0f1696 100644 --- a/ext/psych/lib/psych/core_ext.rb +++ b/ext/psych/lib/psych/core_ext.rb @@ -14,6 +14,23 @@ class Object end end -if defined?(::IRB) - require_relative 'y' +# Up to Ruby 3.4, Set was a regular object and was dumped as such +# by Pysch. +# Starting from Ruby 4.0 it's a core class written in C, so we have to implement +# #encode_with / #init_with to preserve backward compatibility. +if defined?(::Set) && Set.new.instance_variables.empty? + class Set + def encode_with(coder) + hash = {} + each do |m| + hash[m] = true + end + coder["hash"] = hash + coder + end + + def init_with(coder) + replace(coder["hash"].keys) + end + end end diff --git a/ext/psych/lib/psych/nodes/node.rb b/ext/psych/lib/psych/nodes/node.rb index f44fce5f05..fc27448f2e 100644 --- a/ext/psych/lib/psych/nodes/node.rb +++ b/ext/psych/lib/psych/nodes/node.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require 'stringio' require_relative '../class_loader' require_relative '../scalar_scanner' @@ -46,8 +45,8 @@ module Psych # Convert this node to Ruby. # # See also Psych::Visitors::ToRuby - def to_ruby(symbolize_names: false, freeze: false, strict_integer: false) - Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer).accept(self) + def to_ruby(symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true) + Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer, parse_symbols: parse_symbols).accept(self) end alias :transform :to_ruby @@ -56,6 +55,8 @@ module Psych # # See also Psych::Visitors::Emitter def yaml io = nil, options = {} + require "stringio" unless defined?(StringIO) + real_io = io || StringIO.new(''.encode('utf-8')) Visitors::Emitter.new(real_io, options).accept self diff --git a/ext/psych/lib/psych/scalar_scanner.rb b/ext/psych/lib/psych/scalar_scanner.rb index 3cb4bf3c7e..6a556fb3b8 100644 --- a/ext/psych/lib/psych/scalar_scanner.rb +++ b/ext/psych/lib/psych/scalar_scanner.rb @@ -11,26 +11,27 @@ module Psych # Base 60, [-+]inf and NaN are handled separately FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x - # Taken from http://yaml.org/type/int.html - INTEGER_STRICT = /^(?:[-+]?0b[0-1_]+ (?# base 2) - |[-+]?0[0-7_]+ (?# base 8) - |[-+]?(0|[1-9][0-9_]*) (?# base 10) - |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x + # Taken from http://yaml.org/type/int.html and modified to ensure at least one numerical symbol exists + INTEGER_STRICT = /^(?:[-+]?0b[_]*[0-1][0-1_]* (?# base 2) + |[-+]?0[_]*[0-7][0-7_]* (?# base 8) + |[-+]?(0|[1-9][0-9_]*) (?# base 10) + |[-+]?0x[_]*[0-9a-fA-F][0-9a-fA-F_]* (?# base 16))$/x # Same as above, but allows commas. # Not to YML spec, but kept for backwards compatibility - INTEGER_LEGACY = /^(?:[-+]?0b[0-1_,]+ (?# base 2) - |[-+]?0[0-7_,]+ (?# base 8) + INTEGER_LEGACY = /^(?:[-+]?0b[_,]*[0-1][0-1_,]* (?# base 2) + |[-+]?0[_,]*[0-7][0-7_,]* (?# base 8) |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10) - |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x + |[-+]?0x[_,]*[0-9a-fA-F][0-9a-fA-F_,]* (?# base 16))$/x attr_reader :class_loader # Create a new scanner - def initialize class_loader, strict_integer: false + def initialize class_loader, strict_integer: false, parse_symbols: true @symbol_cache = {} @class_loader = class_loader @strict_integer = strict_integer + @parse_symbols = parse_symbols end # Tokenize +string+ returning the Ruby object @@ -61,7 +62,6 @@ module Psych string end elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/) - require 'date' begin class_loader.date.strptime(string, '%F', Date::GREGORIAN) rescue ArgumentError @@ -73,7 +73,7 @@ module Psych -Float::INFINITY elsif string.match?(/^\.nan$/i) Float::NAN - elsif string.match?(/^:./) + elsif @parse_symbols && string.match?(/^:./) if string =~ /^:(["'])(.*)\1/ @symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, '')) else diff --git a/ext/psych/lib/psych/versions.rb b/ext/psych/lib/psych/versions.rb index a592a6916c..6c1679bf65 100644 --- a/ext/psych/lib/psych/versions.rb +++ b/ext/psych/lib/psych/versions.rb @@ -2,9 +2,9 @@ module Psych # The version of Psych you are using - VERSION = '5.0.1' + VERSION = '5.4.0' if RUBY_ENGINE == 'jruby' - DEFAULT_SNAKEYAML_VERSION = '1.33'.freeze + DEFAULT_SNAKEYAML_VERSION = '2.10'.freeze end end diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb index 8614251ca9..475444e589 100644 --- a/ext/psych/lib/psych/visitors/to_ruby.rb +++ b/ext/psych/lib/psych/visitors/to_ruby.rb @@ -12,9 +12,13 @@ module Psych ### # This class walks a YAML AST, converting each node to Ruby class ToRuby < Psych::Visitors::Visitor - def self.create(symbolize_names: false, freeze: false, strict_integer: false) + unless RUBY_VERSION < "3.2" + DATA_INITIALIZE = Data.instance_method(:initialize) + end + + def self.create(symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true) class_loader = ClassLoader.new - scanner = ScalarScanner.new class_loader, strict_integer: strict_integer + scanner = ScalarScanner.new class_loader, strict_integer: strict_integer, parse_symbols: parse_symbols new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze) end @@ -36,7 +40,7 @@ module Psych unless @domain_types.empty? || !target.tag key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:') - key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/ + key = "tag:#{key}" unless key.match?(/^(?:tag:|x-private)/) if @domain_types.key? key value, block = @domain_types[key] @@ -79,7 +83,6 @@ module Psych class_loader.big_decimal._load o.value when "!ruby/object:DateTime" class_loader.date_time - require 'date' unless defined? DateTime t = @ss.parse_time(o.value) DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) + (t.subsec/86400) @@ -97,11 +100,11 @@ module Psych Float(@ss.tokenize(o.value)) when "!ruby/regexp" klass = class_loader.regexp - o.value =~ /^\/(.*)\/([mixn]*)$/m - source = $1 + matches = /^\/(?<string>.*)\/(?<options>[mixn]*)$/m.match(o.value) + source = matches[:string].gsub('\/', '/') options = 0 lang = nil - ($2 || '').split('').each do |option| + matches[:options].each_char do |option| case option when 'x' then options |= Regexp::EXTENDED when 'i' then options |= Regexp::IGNORECASE @@ -198,6 +201,32 @@ module Psych s end + when /^!ruby\/data(-with-ivars)?(?::(.*))?$/ + data = register(o, resolve_class($2).allocate) if $2 + members = {} + + if $1 # data-with-ivars + ivars = {} + o.children.each_slice(2) do |type, vars| + case accept(type) + when 'members' + revive_data_members(members, vars) + data ||= allocate_anon_data(o, members) + when 'ivars' + revive_hash(ivars, vars) + end + end + ivars.each do |ivar, v| + data.instance_variable_set ivar, v + end + else + revive_data_members(members, o) + end + data ||= allocate_anon_data(o, members) + DATA_INITIALIZE.bind_call(data, **members) + data.freeze + data + when /^!ruby\/object:?(.*)?$/ name = $1 || 'Object' @@ -341,6 +370,20 @@ module Psych list end + def allocate_anon_data node, members + klass = class_loader.data.define(*members.keys) + register(node, klass.allocate) + end + + def revive_data_members hash, o + o.children.each_slice(2) do |k,v| + name = accept(k) + value = accept(v) + hash[class_loader.symbolize(name)] = value + end + hash + end + def revive_hash hash, o, tagged= false o.children.each_slice(2) { |k,v| key = accept(k) diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb index 31858798e4..b6c86f4c94 100644 --- a/ext/psych/lib/psych/visitors/yaml_tree.rb +++ b/ext/psych/lib/psych/visitors/yaml_tree.rb @@ -15,30 +15,25 @@ module Psych class YAMLTree < Psych::Visitors::Visitor class Registrar # :nodoc: def initialize - @obj_to_id = {} - @obj_to_node = {} - @targets = [] + @obj_to_id = {}.compare_by_identity + @obj_to_node = {}.compare_by_identity @counter = 0 end def register target, node - return unless target.respond_to? :object_id - @targets << target - @obj_to_node[target.object_id] = node + @obj_to_node[target] = node end def key? target - @obj_to_node.key? target.object_id - rescue NoMethodError - false + @obj_to_node.key? target end def id_for target - @obj_to_id[target.object_id] ||= (@counter += 1) + @obj_to_id[target] ||= (@counter += 1) end def node_for target - @obj_to_node[target.object_id] + @obj_to_node[target] end end @@ -70,6 +65,7 @@ module Psych fail(ArgumentError, "Invalid line_width #{@line_width}, must be non-negative or -1 for unlimited.") end end + @stringify_names = options[:stringify_names] @coders = [] @dispatch_cache = Hash.new do |h,klass| @@ -77,7 +73,7 @@ module Psych method = respond_to?(method) ? method : h[klass.superclass] - raise(TypeError, "Can't dump #{target.class}") unless method + raise(TypeError, "can't dump #{klass.name}") unless method h[klass] = method end.compare_by_identity @@ -166,6 +162,44 @@ module Psych alias :visit_Delegator :visit_Object + def visit_Data o + ivars = o.instance_variables + if ivars.empty? + tag = ['!ruby/data', o.class.name].compact.join(':') + register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) + o.members.each do |member| + @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY + accept o.send member + end + @emitter.end_mapping + + else + tag = ['!ruby/data-with-ivars', o.class.name].compact.join(':') + node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK) + register(o, node) + + # Dump the members + accept 'members' + @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK + o.members.each do |member| + @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY + accept o.send member + end + @emitter.end_mapping + + # Dump the ivars + accept 'ivars' + @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK + ivars.each do |ivar| + accept ivar.to_s + accept o.instance_variable_get ivar + end + @emitter.end_mapping + + @emitter.end_mapping + end + end unless RUBY_VERSION < "3.2" + def visit_Struct o tag = ['!ruby/struct', o.class.name].compact.join(':') @@ -193,7 +227,8 @@ module Psych end def visit_Date o - register o, visit_Integer(o.gregorian) + formatted = format_date o + register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY) end def visit_DateTime o @@ -265,20 +300,20 @@ module Psych style = Nodes::Scalar::LITERAL plain = false quote = false - elsif o =~ /\n(?!\Z)/ # match \n except blank line at the end of string + elsif o.match?(/\n(?!\Z)/) # match \n except blank line at the end of string style = Nodes::Scalar::LITERAL elsif o == '<<' style = Nodes::Scalar::SINGLE_QUOTED tag = 'tag:yaml.org,2002:str' plain = false quote = false - elsif o == 'y' || o == 'n' + elsif o == 'y' || o == 'Y' || o == 'n' || o == 'N' style = Nodes::Scalar::DOUBLE_QUOTED elsif @line_width && o.length > @line_width style = Nodes::Scalar::FOLDED - elsif o =~ /^[^[:word:]][^"]*$/ + elsif o.match?(/^[^[:word:]][^"]*$/) style = Nodes::Scalar::DOUBLE_QUOTED - elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/ =~ o + elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/.match?(o) style = Nodes::Scalar::SINGLE_QUOTED end @@ -328,7 +363,7 @@ module Psych if o.class == ::Hash register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| - accept k + accept(@stringify_names && Symbol === k ? k.to_s : k) accept v end @emitter.end_mapping @@ -341,7 +376,7 @@ module Psych register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| - accept k + accept(@stringify_names && Symbol === k ? k.to_s : k) accept v end @@ -490,6 +525,10 @@ module Psych end end + def format_date date + date.strftime("%Y-%m-%d") + end + def register target, yaml_obj @st.register target, yaml_obj yaml_obj @@ -568,7 +607,7 @@ module Psych raise BadAlias, "Tried to dump an aliased object" end - unless @permitted_classes[target.class] + unless Symbol === target || @permitted_classes[target.class] raise DisallowedClass.new('dump', target.class.name || target.class.inspect) end @@ -576,7 +615,7 @@ module Psych end def visit_Symbol sym - unless @permitted_symbols[sym] + unless @permitted_classes[Symbol] || @permitted_symbols[sym] raise DisallowedClass.new('dump', "Symbol(#{sym.inspect})") end diff --git a/ext/psych/psych.c b/ext/psych/psych.c index 8af0bb6a5a..afbd7a3571 100644 --- a/ext/psych/psych.c +++ b/ext/psych/psych.c @@ -23,7 +23,7 @@ VALUE mPsych; void Init_psych(void) { #ifdef HAVE_RB_EXT_RACTOR_SAFE - RB_EXT_RACTOR_SAFE(true); + RB_EXT_RACTOR_SAFE(true); #endif mPsych = rb_define_module("Psych"); @@ -34,4 +34,3 @@ void Init_psych(void) Init_psych_to_ruby(); Init_psych_yaml_tree(); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/psych/psych.gemspec b/ext/psych/psych.gemspec index a5dfc76f76..a32f79bc16 100644 --- a/ext/psych/psych.gemspec +++ b/ext/psych/psych.gemspec @@ -21,28 +21,41 @@ DESCRIPTION s.licenses = ["MIT"] s.require_paths = ["lib"] - # for ruby core repository. It was generated by `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + # for ruby core repository. + # It was generated by + # `git ls-files -z`.split("\x0").reject { |f| + # f.match(%r{^\.git|^(test|spec|features|bin|tool)/|^[A-Z]\w+file$|/extlibs$|\.(gemspec|java)$|jar}) + # } s.files = [ - ".gitignore", "Gemfile", "LICENSE", "Mavenfile", "README.md", "Rakefile", "bin/console", - "bin/setup", "ext/psych/depend", "ext/psych/extconf.rb", "ext/psych/psych.c", "ext/psych/psych.h", - "ext/psych/psych_emitter.c", "ext/psych/psych_emitter.h", "ext/psych/psych_parser.c", "ext/psych/psych_parser.h", - "ext/psych/psych_to_ruby.c", "ext/psych/psych_to_ruby.h", "ext/psych/psych_yaml_tree.c", "ext/psych/psych_yaml_tree.h", - "lib/psych.rb", "lib/psych/class_loader.rb", "lib/psych/coder.rb", "lib/psych/core_ext.rb", "lib/psych/exception.rb", - "lib/psych/handler.rb", "lib/psych/handlers/document_stream.rb", "lib/psych/handlers/recorder.rb", - "lib/psych/json/ruby_events.rb", "lib/psych/json/stream.rb", "lib/psych/json/tree_builder.rb", - "lib/psych/json/yaml_events.rb", "lib/psych/nodes.rb", "lib/psych/nodes/alias.rb", "lib/psych/nodes/document.rb", - "lib/psych/nodes/mapping.rb", "lib/psych/nodes/node.rb", "lib/psych/nodes/scalar.rb", "lib/psych/nodes/sequence.rb", - "lib/psych/nodes/stream.rb", "lib/psych/omap.rb", "lib/psych/parser.rb", "lib/psych/scalar_scanner.rb", - "lib/psych/set.rb", "lib/psych/stream.rb", "lib/psych/streaming.rb", "lib/psych/syntax_error.rb", - "lib/psych/tree_builder.rb", "lib/psych/versions.rb", "lib/psych/visitors.rb","lib/psych/visitors/depth_first.rb", - "lib/psych/visitors/emitter.rb", "lib/psych/visitors/json_tree.rb", "lib/psych/visitors/to_ruby.rb", - "lib/psych/visitors/visitor.rb", "lib/psych/visitors/yaml_tree.rb", "lib/psych/y.rb", "psych.gemspec" + "CONTRIBUTING.md", "LICENSE", "README.md", "ext/psych/depend", + "ext/psych/extconf.rb", "ext/psych/psych.c", "ext/psych/psych.h", + "ext/psych/psych_emitter.c", "ext/psych/psych_emitter.h", + "ext/psych/psych_parser.c", "ext/psych/psych_parser.h", + "ext/psych/psych_to_ruby.c", "ext/psych/psych_to_ruby.h", + "ext/psych/psych_yaml_tree.c", "ext/psych/psych_yaml_tree.h", + "lib/psych.rb", "lib/psych/class_loader.rb", "lib/psych/coder.rb", + "lib/psych/core_ext.rb", "lib/psych/exception.rb", "lib/psych/handler.rb", + "lib/psych/handlers/document_stream.rb", "lib/psych/handlers/recorder.rb", + "lib/psych/json/ruby_events.rb", "lib/psych/json/stream.rb", + "lib/psych/json/tree_builder.rb", "lib/psych/json/yaml_events.rb", + "lib/psych/nodes.rb", "lib/psych/nodes/alias.rb", + "lib/psych/nodes/document.rb", "lib/psych/nodes/mapping.rb", + "lib/psych/nodes/node.rb", "lib/psych/nodes/scalar.rb", + "lib/psych/nodes/sequence.rb", "lib/psych/nodes/stream.rb", + "lib/psych/omap.rb", "lib/psych/parser.rb", "lib/psych/scalar_scanner.rb", + "lib/psych/set.rb", "lib/psych/stream.rb", "lib/psych/streaming.rb", + "lib/psych/syntax_error.rb", "lib/psych/tree_builder.rb", + "lib/psych/versions.rb", "lib/psych/visitors.rb", + "lib/psych/visitors/depth_first.rb", "lib/psych/visitors/emitter.rb", + "lib/psych/visitors/json_tree.rb", "lib/psych/visitors/to_ruby.rb", + "lib/psych/visitors/visitor.rb", "lib/psych/visitors/yaml_tree.rb", + "lib/psych/y.rb" ] s.rdoc_options = ["--main", "README.md"] s.extra_rdoc_files = ["README.md"] - s.required_ruby_version = Gem::Requirement.new(">= 2.4.0") + s.required_ruby_version = Gem::Requirement.new(">= 2.5.0") s.required_rubygems_version = Gem::Requirement.new(">= 0") if RUBY_ENGINE == 'jruby' @@ -52,17 +65,18 @@ DESCRIPTION "ext/java/org/jruby/ext/psych/PsychLibrary.java", "ext/java/org/jruby/ext/psych/PsychParser.java", "ext/java/org/jruby/ext/psych/PsychToRuby.java", - "ext/java/org/jruby/ext/psych/PsychYamlTree.java", "lib/psych_jars.rb", "lib/psych.jar" ] - s.requirements = "jar org.yaml:snakeyaml, #{version_module::Psych::DEFAULT_SNAKEYAML_VERSION}" + s.requirements = "jar org.snakeyaml:snakeyaml-engine, #{version_module::Psych::DEFAULT_SNAKEYAML_VERSION}" s.add_dependency 'jar-dependencies', '>= 0.1.7' else s.extensions = ["ext/psych/extconf.rb"] s.add_dependency 'stringio' end - s.metadata['msys2_mingw_dependencies'] = 'libyaml' + s.add_dependency 'date' + s.metadata['msys2_mingw_dependencies'] = 'libyaml' + s.metadata['changelog_uri'] = s.homepage + '/releases' end diff --git a/ext/psych/psych_emitter.c b/ext/psych/psych_emitter.c index 022ffa0946..624ab7c528 100644 --- a/ext/psych/psych_emitter.c +++ b/ext/psych/psych_emitter.c @@ -17,7 +17,7 @@ static ID id_canonical; static void emit(yaml_emitter_t * emitter, yaml_event_t * event) { if(!yaml_emitter_emit(emitter, event)) - rb_raise(rb_eRuntimeError, "%s", emitter->problem); + rb_raise(rb_eRuntimeError, "%s", emitter->problem); } static int writer(void *ctx, unsigned char *buffer, size_t size) @@ -82,13 +82,13 @@ static VALUE initialize(int argc, VALUE *argv, VALUE self) TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); if (rb_scan_args(argc, argv, "11", &io, &options) == 2) { - line_width = rb_funcall(options, id_line_width, 0); - indent = rb_funcall(options, id_indentation, 0); - canonical = rb_funcall(options, id_canonical, 0); + line_width = rb_funcall(options, id_line_width, 0); + indent = rb_funcall(options, id_indentation, 0); + canonical = rb_funcall(options, id_canonical, 0); - yaml_emitter_set_width(emitter, NUM2INT(line_width)); - yaml_emitter_set_indent(emitter, NUM2INT(indent)); - yaml_emitter_set_canonical(emitter, Qtrue == canonical ? 1 : 0); + yaml_emitter_set_width(emitter, NUM2INT(line_width)); + yaml_emitter_set_indent(emitter, NUM2INT(indent)); + yaml_emitter_set_canonical(emitter, Qtrue == canonical ? 1 : 0); } rb_ivar_set(self, id_io, io); @@ -136,84 +136,118 @@ static VALUE end_stream(VALUE self) return self; } -/* call-seq: emitter.start_document(version, tags, implicit) - * - * Start a document emission with YAML +version+, +tags+, and an +implicit+ - * start. - * - * See Psych::Handler#start_document - */ -static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp) +struct start_document_data { + VALUE self; + VALUE version; + VALUE tags; + VALUE imp; + + yaml_tag_directive_t * head; +}; + +static VALUE start_document_try(VALUE d) { + struct start_document_data * data = (struct start_document_data *)d; + VALUE self = data->self; + VALUE version = data->version; + VALUE tags = data->tags; + VALUE imp = data->imp; + yaml_emitter_t * emitter; - yaml_tag_directive_t * head = NULL; yaml_tag_directive_t * tail = NULL; yaml_event_t event; yaml_version_directive_t version_directive; TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); - Check_Type(version, T_ARRAY); if(RARRAY_LEN(version) > 0) { - VALUE major = rb_ary_entry(version, (long)0); - VALUE minor = rb_ary_entry(version, (long)1); + VALUE major = rb_ary_entry(version, (long)0); + VALUE minor = rb_ary_entry(version, (long)1); - version_directive.major = NUM2INT(major); - version_directive.minor = NUM2INT(minor); + version_directive.major = NUM2INT(major); + version_directive.minor = NUM2INT(minor); } if(RTEST(tags)) { - long i = 0; - long len; - rb_encoding * encoding = rb_utf8_encoding(); - - Check_Type(tags, T_ARRAY); - - len = RARRAY_LEN(tags); - head = xcalloc((size_t)len, sizeof(yaml_tag_directive_t)); - tail = head; - - for(i = 0; i < len && i < RARRAY_LEN(tags); i++) { - VALUE tuple = RARRAY_AREF(tags, i); - VALUE name; - VALUE value; - - Check_Type(tuple, T_ARRAY); - - if(RARRAY_LEN(tuple) < 2) { - xfree(head); - rb_raise(rb_eRuntimeError, "tag tuple must be of length 2"); - } - name = RARRAY_AREF(tuple, 0); - value = RARRAY_AREF(tuple, 1); - StringValue(name); - StringValue(value); - name = rb_str_export_to_enc(name, encoding); - value = rb_str_export_to_enc(value, encoding); - - tail->handle = (yaml_char_t *)StringValueCStr(name); - tail->prefix = (yaml_char_t *)StringValueCStr(value); - - tail++; - } + long i = 0; + long len; + rb_encoding * encoding = rb_utf8_encoding(); + + Check_Type(tags, T_ARRAY); + + len = RARRAY_LEN(tags); + data->head = xcalloc((size_t)len, sizeof(yaml_tag_directive_t)); + tail = data->head; + + for(i = 0; i < len && i < RARRAY_LEN(tags); i++) { + VALUE tuple = RARRAY_AREF(tags, i); + VALUE name; + VALUE value; + + Check_Type(tuple, T_ARRAY); + + if(RARRAY_LEN(tuple) < 2) { + rb_raise(rb_eRuntimeError, "tag tuple must be of length 2"); + } + + name = RARRAY_AREF(tuple, 0); + value = RARRAY_AREF(tuple, 1); + StringValue(name); + StringValue(value); + name = rb_str_export_to_enc(name, encoding); + value = rb_str_export_to_enc(value, encoding); + + tail->handle = (yaml_char_t *)StringValueCStr(name); + tail->prefix = (yaml_char_t *)StringValueCStr(value); + + tail++; + } } yaml_document_start_event_initialize( - &event, - (RARRAY_LEN(version) > 0) ? &version_directive : NULL, - head, - tail, - imp ? 1 : 0 - ); + &event, + (RARRAY_LEN(version) > 0) ? &version_directive : NULL, + data->head, + tail, + imp ? 1 : 0 + ); emit(emitter, &event); - if(head) xfree(head); - return self; } +static VALUE start_document_ensure(VALUE d) +{ + struct start_document_data * data = (struct start_document_data *)d; + + xfree(data->head); + + return Qnil; +} + +/* call-seq: emitter.start_document(version, tags, implicit) + * + * Start a document emission with YAML +version+, +tags+, and an +implicit+ + * start. + * + * See Psych::Handler#start_document + */ +static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp) +{ + struct start_document_data data = { + .self = self, + .version = version, + .tags = tags, + .imp = imp, + + .head = NULL, + }; + + return rb_ensure(start_document_try, (VALUE)&data, start_document_ensure, (VALUE)&data); +} + /* call-seq: emitter.end_document(implicit) * * End a document emission with an +implicit+ ending. @@ -241,14 +275,14 @@ static VALUE end_document(VALUE self, VALUE imp) * See Psych::Handler#scalar */ static VALUE scalar( - VALUE self, - VALUE value, - VALUE anchor, - VALUE tag, - VALUE plain, - VALUE quoted, - VALUE style - ) { + VALUE self, + VALUE value, + VALUE anchor, + VALUE tag, + VALUE plain, + VALUE quoted, + VALUE style + ) { yaml_emitter_t * emitter; yaml_event_t event; rb_encoding *encoding; @@ -261,25 +295,26 @@ static VALUE scalar( value = rb_str_export_to_enc(value, encoding); if(!NIL_P(anchor)) { - Check_Type(anchor, T_STRING); - anchor = rb_str_export_to_enc(anchor, encoding); + Check_Type(anchor, T_STRING); + anchor = rb_str_export_to_enc(anchor, encoding); } if(!NIL_P(tag)) { - Check_Type(tag, T_STRING); - tag = rb_str_export_to_enc(tag, encoding); + Check_Type(tag, T_STRING); + tag = rb_str_export_to_enc(tag, encoding); } + const char *value_ptr = StringValuePtr(value); yaml_scalar_event_initialize( - &event, - (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), - (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), - (yaml_char_t*)StringValuePtr(value), - (int)RSTRING_LEN(value), - plain ? 1 : 0, - quoted ? 1 : 0, - (yaml_scalar_style_t)NUM2INT(style) - ); + &event, + (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), + (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), + (yaml_char_t*)value_ptr, + (int)RSTRING_LEN(value), + plain ? 1 : 0, + quoted ? 1 : 0, + (yaml_scalar_style_t)NUM2INT(style) + ); emit(emitter, &event); @@ -294,36 +329,36 @@ static VALUE scalar( * See Psych::Handler#start_sequence */ static VALUE start_sequence( - VALUE self, - VALUE anchor, - VALUE tag, - VALUE implicit, - VALUE style - ) { + VALUE self, + VALUE anchor, + VALUE tag, + VALUE implicit, + VALUE style + ) { yaml_emitter_t * emitter; yaml_event_t event; rb_encoding * encoding = rb_utf8_encoding(); if(!NIL_P(anchor)) { - Check_Type(anchor, T_STRING); - anchor = rb_str_export_to_enc(anchor, encoding); + Check_Type(anchor, T_STRING); + anchor = rb_str_export_to_enc(anchor, encoding); } if(!NIL_P(tag)) { - Check_Type(tag, T_STRING); - tag = rb_str_export_to_enc(tag, encoding); + Check_Type(tag, T_STRING); + tag = rb_str_export_to_enc(tag, encoding); } TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); yaml_sequence_start_event_initialize( - &event, - (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), - (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), - implicit ? 1 : 0, - (yaml_sequence_style_t)NUM2INT(style) - ); + &event, + (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), + (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), + implicit ? 1 : 0, + (yaml_sequence_style_t)NUM2INT(style) + ); emit(emitter, &event); @@ -357,12 +392,12 @@ static VALUE end_sequence(VALUE self) * See Psych::Handler#start_mapping */ static VALUE start_mapping( - VALUE self, - VALUE anchor, - VALUE tag, - VALUE implicit, - VALUE style - ) { + VALUE self, + VALUE anchor, + VALUE tag, + VALUE implicit, + VALUE style + ) { yaml_emitter_t * emitter; yaml_event_t event; rb_encoding *encoding; @@ -372,22 +407,22 @@ static VALUE start_mapping( encoding = rb_utf8_encoding(); if(!NIL_P(anchor)) { - Check_Type(anchor, T_STRING); - anchor = rb_str_export_to_enc(anchor, encoding); + Check_Type(anchor, T_STRING); + anchor = rb_str_export_to_enc(anchor, encoding); } if(!NIL_P(tag)) { - Check_Type(tag, T_STRING); - tag = rb_str_export_to_enc(tag, encoding); + Check_Type(tag, T_STRING); + tag = rb_str_export_to_enc(tag, encoding); } yaml_mapping_start_event_initialize( - &event, - (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), - (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), - implicit ? 1 : 0, - (yaml_mapping_style_t)NUM2INT(style) - ); + &event, + (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), + (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), + implicit ? 1 : 0, + (yaml_mapping_style_t)NUM2INT(style) + ); emit(emitter, &event); @@ -426,14 +461,14 @@ static VALUE alias(VALUE self, VALUE anchor) TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); if(!NIL_P(anchor)) { - Check_Type(anchor, T_STRING); - anchor = rb_str_export_to_enc(anchor, rb_utf8_encoding()); + Check_Type(anchor, T_STRING); + anchor = rb_str_export_to_enc(anchor, rb_utf8_encoding()); } yaml_alias_event_initialize( - &event, - (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)) - ); + &event, + (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)) + ); emit(emitter, &event); @@ -552,4 +587,3 @@ void Init_psych_emitter(void) id_indentation = rb_intern("indentation"); id_canonical = rb_intern("canonical"); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/psych/psych_parser.c b/ext/psych/psych_parser.c index 9c5179cc44..00a2207b58 100644 --- a/ext/psych/psych_parser.c +++ b/ext/psych/psych_parser.c @@ -32,9 +32,20 @@ static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read) *read = 0; if(! NIL_P(string)) { - void * str = (void *)StringValuePtr(string); - *read = (size_t)RSTRING_LEN(string); - memcpy(buf, str, *read); + char * str = StringValuePtr(string); + size_t len = (size_t)RSTRING_LEN(string); + + /* IO#read(size) is documented to return at most `size` bytes, but a + * misbehaving IO-like object may return more. Clamp the copy to the + * buffer libyaml gave us to avoid writing past its end, rounding down + * to a character boundary so a multibyte character is never split. */ + if(len > size) { + rb_encoding * enc = rb_enc_get(string); + len = (size_t)(rb_enc_left_char_head(str, str + size, str + len, enc) - str); + } + + *read = len; + memcpy(buf, str, len); } return 1; @@ -80,23 +91,23 @@ static VALUE allocate(VALUE klass) static VALUE make_exception(yaml_parser_t * parser, VALUE path) { if (parser->error == YAML_MEMORY_ERROR) { - return rb_eNoMemError; + return rb_eNoMemError; } else { - size_t line, column; - VALUE ePsychSyntaxError; + size_t line, column; + VALUE ePsychSyntaxError; - line = parser->context_mark.line + 1; - column = parser->context_mark.column + 1; + line = parser->context_mark.line + 1; + column = parser->context_mark.column + 1; - ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError")); + ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError")); - return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6, - path, - SIZET2NUM(line), - SIZET2NUM(column), - SIZET2NUM(parser->problem_offset), - parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil, - parser->context ? rb_usascii_str_new2(parser->context) : Qnil); + return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6, + path, + SIZET2NUM(line), + SIZET2NUM(column), + SIZET2NUM(parser->problem_offset), + parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil, + parser->context ? rb_usascii_str_new2(parser->context) : Qnil); } } @@ -108,18 +119,18 @@ static VALUE transcode_string(VALUE src, int * parser_encoding) int source_encoding = rb_enc_get_index(src); if (source_encoding == utf8) { - *parser_encoding = YAML_UTF8_ENCODING; - return src; + *parser_encoding = YAML_UTF8_ENCODING; + return src; } if (source_encoding == utf16le) { - *parser_encoding = YAML_UTF16LE_ENCODING; - return src; + *parser_encoding = YAML_UTF16LE_ENCODING; + return src; } if (source_encoding == utf16be) { - *parser_encoding = YAML_UTF16BE_ENCODING; - return src; + *parser_encoding = YAML_UTF16BE_ENCODING; + return src; } src = rb_str_export_to_enc(src, rb_utf8_encoding()); @@ -138,36 +149,36 @@ static VALUE transcode_io(VALUE src, int * parser_encoding) /* if no encoding is returned, assume ascii8bit. */ if (NIL_P(io_external_encoding)) { - io_external_enc_index = rb_ascii8bit_encindex(); + io_external_enc_index = rb_ascii8bit_encindex(); } else { - io_external_enc_index = rb_to_encoding_index(io_external_encoding); + io_external_enc_index = rb_to_encoding_index(io_external_encoding); } /* Treat US-ASCII as utf_8 */ if (io_external_enc_index == rb_usascii_encindex()) { - *parser_encoding = YAML_UTF8_ENCODING; - return src; + *parser_encoding = YAML_UTF8_ENCODING; + return src; } if (io_external_enc_index == rb_utf8_encindex()) { - *parser_encoding = YAML_UTF8_ENCODING; - return src; + *parser_encoding = YAML_UTF8_ENCODING; + return src; } if (io_external_enc_index == rb_enc_find_index("UTF-16LE")) { - *parser_encoding = YAML_UTF16LE_ENCODING; - return src; + *parser_encoding = YAML_UTF16LE_ENCODING; + return src; } if (io_external_enc_index == rb_enc_find_index("UTF-16BE")) { - *parser_encoding = YAML_UTF16BE_ENCODING; - return src; + *parser_encoding = YAML_UTF16BE_ENCODING; + return src; } /* Just guess on ASCII-8BIT */ if (io_external_enc_index == rb_ascii8bit_encindex()) { - *parser_encoding = YAML_ANY_ENCODING; - return src; + *parser_encoding = YAML_ANY_ENCODING; + return src; } /* If the external encoding is something we don't know how to handle, @@ -261,238 +272,238 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path) yaml_parser_initialize(parser); if (rb_respond_to(yaml, id_read)) { - yaml = transcode_io(yaml, &parser_encoding); - yaml_parser_set_encoding(parser, parser_encoding); - yaml_parser_set_input(parser, io_reader, (void *)yaml); + yaml = transcode_io(yaml, &parser_encoding); + yaml_parser_set_encoding(parser, parser_encoding); + yaml_parser_set_input(parser, io_reader, (void *)yaml); } else { - StringValue(yaml); - yaml = transcode_string(yaml, &parser_encoding); - yaml_parser_set_encoding(parser, parser_encoding); - yaml_parser_set_input_string( - parser, - (const unsigned char *)RSTRING_PTR(yaml), - (size_t)RSTRING_LEN(yaml) - ); + StringValue(yaml); + yaml = transcode_string(yaml, &parser_encoding); + yaml_parser_set_encoding(parser, parser_encoding); + yaml_parser_set_input_string( + parser, + (const unsigned char *)RSTRING_PTR(yaml), + (size_t)RSTRING_LEN(yaml) + ); } while(!done) { - VALUE event_args[5]; - VALUE start_line, start_column, end_line, end_column; - - if(parser->error || !yaml_parser_parse(parser, &event)) { - VALUE exception; - - exception = make_exception(parser, path); - yaml_parser_delete(parser); - yaml_parser_initialize(parser); - - rb_exc_raise(exception); - } - - start_line = SIZET2NUM(event.start_mark.line); - start_column = SIZET2NUM(event.start_mark.column); - end_line = SIZET2NUM(event.end_mark.line); - end_column = SIZET2NUM(event.end_mark.column); - - event_args[0] = handler; - event_args[1] = start_line; - event_args[2] = start_column; - event_args[3] = end_line; - event_args[4] = end_column; - rb_protect(protected_event_location, (VALUE)event_args, &state); - - switch(event.type) { - case YAML_STREAM_START_EVENT: - { - VALUE args[2]; - - args[0] = handler; - args[1] = INT2NUM(event.data.stream_start.encoding); - rb_protect(protected_start_stream, (VALUE)args, &state); - } - break; - case YAML_DOCUMENT_START_EVENT: - { - VALUE args[4]; - /* Get a list of tag directives (if any) */ - VALUE tag_directives = rb_ary_new(); - /* Grab the document version */ - VALUE version = event.data.document_start.version_directive ? - rb_ary_new3( - (long)2, - INT2NUM(event.data.document_start.version_directive->major), - INT2NUM(event.data.document_start.version_directive->minor) - ) : rb_ary_new(); - - if(event.data.document_start.tag_directives.start) { - yaml_tag_directive_t *start = - event.data.document_start.tag_directives.start; - yaml_tag_directive_t *end = - event.data.document_start.tag_directives.end; - for(; start != end; start++) { - VALUE handle = Qnil; - VALUE prefix = Qnil; - if(start->handle) { - handle = rb_str_new2((const char *)start->handle); - PSYCH_TRANSCODE(handle, encoding, internal_enc); - } - - if(start->prefix) { - prefix = rb_str_new2((const char *)start->prefix); - PSYCH_TRANSCODE(prefix, encoding, internal_enc); - } - - rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix)); - } - } - args[0] = handler; - args[1] = version; - args[2] = tag_directives; - args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse; - rb_protect(protected_start_document, (VALUE)args, &state); - } - break; - case YAML_DOCUMENT_END_EVENT: - { - VALUE args[2]; - - args[0] = handler; - args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse; - rb_protect(protected_end_document, (VALUE)args, &state); - } - break; - case YAML_ALIAS_EVENT: - { - VALUE args[2]; - VALUE alias = Qnil; - if(event.data.alias.anchor) { - alias = rb_str_new2((const char *)event.data.alias.anchor); - PSYCH_TRANSCODE(alias, encoding, internal_enc); - } - - args[0] = handler; - args[1] = alias; - rb_protect(protected_alias, (VALUE)args, &state); - } - break; - case YAML_SCALAR_EVENT: - { - VALUE args[7]; - VALUE anchor = Qnil; - VALUE tag = Qnil; - VALUE plain_implicit, quoted_implicit, style; - VALUE val = rb_str_new( - (const char *)event.data.scalar.value, - (long)event.data.scalar.length - ); - - PSYCH_TRANSCODE(val, encoding, internal_enc); - - if(event.data.scalar.anchor) { - anchor = rb_str_new2((const char *)event.data.scalar.anchor); - PSYCH_TRANSCODE(anchor, encoding, internal_enc); - } - - if(event.data.scalar.tag) { - tag = rb_str_new2((const char *)event.data.scalar.tag); - PSYCH_TRANSCODE(tag, encoding, internal_enc); - } - - plain_implicit = - event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue; - - quoted_implicit = - event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue; - - style = INT2NUM(event.data.scalar.style); - - args[0] = handler; - args[1] = val; - args[2] = anchor; - args[3] = tag; - args[4] = plain_implicit; - args[5] = quoted_implicit; - args[6] = style; - rb_protect(protected_scalar, (VALUE)args, &state); - } - break; - case YAML_SEQUENCE_START_EVENT: - { - VALUE args[5]; - VALUE anchor = Qnil; - VALUE tag = Qnil; - VALUE implicit, style; - if(event.data.sequence_start.anchor) { - anchor = rb_str_new2((const char *)event.data.sequence_start.anchor); - PSYCH_TRANSCODE(anchor, encoding, internal_enc); - } - - tag = Qnil; - if(event.data.sequence_start.tag) { - tag = rb_str_new2((const char *)event.data.sequence_start.tag); - PSYCH_TRANSCODE(tag, encoding, internal_enc); - } - - implicit = - event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue; - - style = INT2NUM(event.data.sequence_start.style); - - args[0] = handler; - args[1] = anchor; - args[2] = tag; - args[3] = implicit; - args[4] = style; - - rb_protect(protected_start_sequence, (VALUE)args, &state); - } - break; - case YAML_SEQUENCE_END_EVENT: - rb_protect(protected_end_sequence, handler, &state); - break; - case YAML_MAPPING_START_EVENT: - { - VALUE args[5]; - VALUE anchor = Qnil; - VALUE tag = Qnil; - VALUE implicit, style; - if(event.data.mapping_start.anchor) { - anchor = rb_str_new2((const char *)event.data.mapping_start.anchor); - PSYCH_TRANSCODE(anchor, encoding, internal_enc); - } - - if(event.data.mapping_start.tag) { - tag = rb_str_new2((const char *)event.data.mapping_start.tag); - PSYCH_TRANSCODE(tag, encoding, internal_enc); - } - - implicit = - event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue; - - style = INT2NUM(event.data.mapping_start.style); - - args[0] = handler; - args[1] = anchor; - args[2] = tag; - args[3] = implicit; - args[4] = style; - - rb_protect(protected_start_mapping, (VALUE)args, &state); - } - break; - case YAML_MAPPING_END_EVENT: - rb_protect(protected_end_mapping, handler, &state); - break; - case YAML_NO_EVENT: - rb_protect(protected_empty, handler, &state); - break; - case YAML_STREAM_END_EVENT: - rb_protect(protected_end_stream, handler, &state); - done = 1; - break; - } - yaml_event_delete(&event); - if (state) rb_jump_tag(state); + VALUE event_args[5]; + VALUE start_line, start_column, end_line, end_column; + + if(parser->error || !yaml_parser_parse(parser, &event)) { + VALUE exception; + + exception = make_exception(parser, path); + yaml_parser_delete(parser); + yaml_parser_initialize(parser); + + rb_exc_raise(exception); + } + + start_line = SIZET2NUM(event.start_mark.line); + start_column = SIZET2NUM(event.start_mark.column); + end_line = SIZET2NUM(event.end_mark.line); + end_column = SIZET2NUM(event.end_mark.column); + + event_args[0] = handler; + event_args[1] = start_line; + event_args[2] = start_column; + event_args[3] = end_line; + event_args[4] = end_column; + rb_protect(protected_event_location, (VALUE)event_args, &state); + + switch(event.type) { + case YAML_STREAM_START_EVENT: + { + VALUE args[2]; + + args[0] = handler; + args[1] = INT2NUM(event.data.stream_start.encoding); + rb_protect(protected_start_stream, (VALUE)args, &state); + } + break; + case YAML_DOCUMENT_START_EVENT: + { + VALUE args[4]; + /* Get a list of tag directives (if any) */ + VALUE tag_directives = rb_ary_new(); + /* Grab the document version */ + VALUE version = event.data.document_start.version_directive ? + rb_ary_new3( + (long)2, + INT2NUM(event.data.document_start.version_directive->major), + INT2NUM(event.data.document_start.version_directive->minor) + ) : rb_ary_new(); + + if(event.data.document_start.tag_directives.start) { + yaml_tag_directive_t *start = + event.data.document_start.tag_directives.start; + yaml_tag_directive_t *end = + event.data.document_start.tag_directives.end; + for(; start != end; start++) { + VALUE handle = Qnil; + VALUE prefix = Qnil; + if(start->handle) { + handle = rb_str_new2((const char *)start->handle); + PSYCH_TRANSCODE(handle, encoding, internal_enc); + } + + if(start->prefix) { + prefix = rb_str_new2((const char *)start->prefix); + PSYCH_TRANSCODE(prefix, encoding, internal_enc); + } + + rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix)); + } + } + args[0] = handler; + args[1] = version; + args[2] = tag_directives; + args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse; + rb_protect(protected_start_document, (VALUE)args, &state); + } + break; + case YAML_DOCUMENT_END_EVENT: + { + VALUE args[2]; + + args[0] = handler; + args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse; + rb_protect(protected_end_document, (VALUE)args, &state); + } + break; + case YAML_ALIAS_EVENT: + { + VALUE args[2]; + VALUE alias = Qnil; + if(event.data.alias.anchor) { + alias = rb_str_new2((const char *)event.data.alias.anchor); + PSYCH_TRANSCODE(alias, encoding, internal_enc); + } + + args[0] = handler; + args[1] = alias; + rb_protect(protected_alias, (VALUE)args, &state); + } + break; + case YAML_SCALAR_EVENT: + { + VALUE args[7]; + VALUE anchor = Qnil; + VALUE tag = Qnil; + VALUE plain_implicit, quoted_implicit, style; + VALUE val = rb_str_new( + (const char *)event.data.scalar.value, + (long)event.data.scalar.length + ); + + PSYCH_TRANSCODE(val, encoding, internal_enc); + + if(event.data.scalar.anchor) { + anchor = rb_str_new2((const char *)event.data.scalar.anchor); + PSYCH_TRANSCODE(anchor, encoding, internal_enc); + } + + if(event.data.scalar.tag) { + tag = rb_str_new2((const char *)event.data.scalar.tag); + PSYCH_TRANSCODE(tag, encoding, internal_enc); + } + + plain_implicit = + event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue; + + quoted_implicit = + event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue; + + style = INT2NUM(event.data.scalar.style); + + args[0] = handler; + args[1] = val; + args[2] = anchor; + args[3] = tag; + args[4] = plain_implicit; + args[5] = quoted_implicit; + args[6] = style; + rb_protect(protected_scalar, (VALUE)args, &state); + } + break; + case YAML_SEQUENCE_START_EVENT: + { + VALUE args[5]; + VALUE anchor = Qnil; + VALUE tag = Qnil; + VALUE implicit, style; + if(event.data.sequence_start.anchor) { + anchor = rb_str_new2((const char *)event.data.sequence_start.anchor); + PSYCH_TRANSCODE(anchor, encoding, internal_enc); + } + + tag = Qnil; + if(event.data.sequence_start.tag) { + tag = rb_str_new2((const char *)event.data.sequence_start.tag); + PSYCH_TRANSCODE(tag, encoding, internal_enc); + } + + implicit = + event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue; + + style = INT2NUM(event.data.sequence_start.style); + + args[0] = handler; + args[1] = anchor; + args[2] = tag; + args[3] = implicit; + args[4] = style; + + rb_protect(protected_start_sequence, (VALUE)args, &state); + } + break; + case YAML_SEQUENCE_END_EVENT: + rb_protect(protected_end_sequence, handler, &state); + break; + case YAML_MAPPING_START_EVENT: + { + VALUE args[5]; + VALUE anchor = Qnil; + VALUE tag = Qnil; + VALUE implicit, style; + if(event.data.mapping_start.anchor) { + anchor = rb_str_new2((const char *)event.data.mapping_start.anchor); + PSYCH_TRANSCODE(anchor, encoding, internal_enc); + } + + if(event.data.mapping_start.tag) { + tag = rb_str_new2((const char *)event.data.mapping_start.tag); + PSYCH_TRANSCODE(tag, encoding, internal_enc); + } + + implicit = + event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue; + + style = INT2NUM(event.data.mapping_start.style); + + args[0] = handler; + args[1] = anchor; + args[2] = tag; + args[3] = implicit; + args[4] = style; + + rb_protect(protected_start_mapping, (VALUE)args, &state); + } + break; + case YAML_MAPPING_END_EVENT: + rb_protect(protected_end_mapping, handler, &state); + break; + case YAML_NO_EVENT: + rb_protect(protected_empty, handler, &state); + break; + case YAML_STREAM_END_EVENT: + rb_protect(protected_end_stream, handler, &state); + done = 1; + break; + } + yaml_event_delete(&event); + if (state) rb_jump_tag(state); } return self; @@ -562,4 +573,3 @@ void Init_psych_parser(void) id_end_mapping = rb_intern("end_mapping"); id_event_location = rb_intern("event_location"); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/psych/psych_to_ruby.c b/ext/psych/psych_to_ruby.c index b388ff7754..3ab0138b52 100644 --- a/ext/psych/psych_to_ruby.c +++ b/ext/psych/psych_to_ruby.c @@ -10,7 +10,11 @@ static VALUE build_exception(VALUE self, VALUE klass, VALUE mesg) { VALUE e = rb_obj_alloc(klass); +#ifdef TRUFFLERUBY + rb_exc_set_message(e, mesg); +#else rb_iv_set(e, "mesg", mesg); +#endif return e; } @@ -36,4 +40,3 @@ void Init_psych_to_ruby(void) rb_define_private_method(cPsychVisitorsToRuby, "build_exception", build_exception, 2); rb_define_private_method(class_loader, "path2class", path2class, 1); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/psych/psych_yaml_tree.c b/ext/psych/psych_yaml_tree.c index 225655d127..bbd93f874d 100644 --- a/ext/psych/psych_yaml_tree.c +++ b/ext/psych/psych_yaml_tree.c @@ -9,4 +9,3 @@ void Init_psych_yaml_tree(void) VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject); cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor); } -/* vim: set noet sws=4 sw=4: */ |
