Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions ext/json/generator/generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ typedef struct JSON_Generator_StateStruct {

static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8;

static ID i_to_s, i_to_json, i_new, i_pack, i_unpack, i_create_id, i_extend, i_encode;
static ID i_to_s, i_to_json, i_new, i_encode;
static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan, sym_allow_duplicate_key,
sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_escape_slash, sym_strict, sym_as_json;

Expand Down Expand Up @@ -2173,10 +2173,6 @@ void Init_generator(void)
i_to_s = rb_intern("to_s");
i_to_json = rb_intern("to_json");
i_new = rb_intern("new");
i_pack = rb_intern("pack");
i_unpack = rb_intern("unpack");
i_create_id = rb_intern("create_id");
i_extend = rb_intern("extend");
i_encode = rb_intern("encode");

sym_indent = ID2SYM(rb_intern("indent"));
Expand Down
7 changes: 1 addition & 6 deletions ext/json/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
static VALUE mJSON, eNestingError, Encoding_UTF_8;
static VALUE CNaN, CInfinity, CMinusInfinity;

static ID i_chr, i_aset, i_aref,
i_leftshift, i_new, i_try_convert, i_uminus, i_encode;
static ID i_new, i_try_convert, i_uminus, i_encode;

static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_symbolize_names, sym_freeze,
sym_decimal_class, sym_on_load, sym_allow_duplicate_key;
Expand Down Expand Up @@ -1612,10 +1611,6 @@ void Init_parser(void)
sym_decimal_class = ID2SYM(rb_intern("decimal_class"));
sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key"));

i_chr = rb_intern("chr");
i_aset = rb_intern("[]=");
i_aref = rb_intern("[]");
i_leftshift = rb_intern("<<");
i_new = rb_intern("new");
i_try_convert = rb_intern("try_convert");
i_uminus = rb_intern("-@");
Expand Down
353 changes: 353 additions & 0 deletions lib/set/subclass_compatible.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
# frozen_string_literal: true

# :markup: markdown
#
# set/subclass_compatible.rb - Provides compatibility for set subclasses
#
# Copyright (c) 2002-2024 Akinori MUSHA <knu@iDaemons.org>
#
# Documentation by Akinori MUSHA and Gavin Sinclair.
#
# All rights reserved. You can redistribute and/or modify it under the same
# terms as Ruby.


class Set
# This module is automatically included in subclasses of Set, to
# make them backwards compatible with the pure-Ruby set implementation
# used before Ruby 4. Users who want to use Set subclasses without
# this compatibility layer should subclass from Set::CoreSet.
#
# Note that Set subclasses that access `@hash` are not compatible even
# with this support. Such subclasses must be updated to support Ruby 4.
module SubclassCompatible
module ClassMethods
def [](*ary)
new(ary)
end
end

# Creates a new set containing the elements of the given enumerable
# object.
#
# If a block is given, the elements of enum are preprocessed by the
# given block.
#
# Set.new([1, 2]) #=> #<Set: {1, 2}>
# Set.new([1, 2, 1]) #=> #<Set: {1, 2}>
# Set.new([1, 'c', :s]) #=> #<Set: {1, "c", :s}>
# Set.new(1..5) #=> #<Set: {1, 2, 3, 4, 5}>
# Set.new([1, 2, 3]) { |x| x * x } #=> #<Set: {1, 4, 9}>
def initialize(enum = nil, &block) # :yields: o
enum.nil? and return

if block
do_with_enum(enum) { |o| add(block[o]) }
else
merge(enum)
end
end

def do_with_enum(enum, &block) # :nodoc:
if enum.respond_to?(:each_entry)
enum.each_entry(&block) if block
elsif enum.respond_to?(:each)
enum.each(&block) if block
else
raise ArgumentError, "value must be enumerable"
end
end
private :do_with_enum

def replace(enum)
if enum.instance_of?(self.class)
super
else
do_with_enum(enum) # make sure enum is enumerable before calling clear
clear
merge(enum)
end
end

def to_set(*args, &block)
klass = if args.empty?
Set
else
warn "passing arguments to Enumerable#to_set is deprecated", uplevel: 1
args.shift
end
return self if instance_of?(Set) && klass == Set && block.nil? && args.empty?
klass.new(self, *args, &block)
end

def flatten_merge(set, seen = {}) # :nodoc:
set.each { |e|
if e.is_a?(Set)
case seen[e_id = e.object_id]
when true
raise ArgumentError, "tried to flatten recursive Set"
when false
next
end

seen[e_id] = true
flatten_merge(e, seen)
seen[e_id] = false
else
add(e)
end
}

self
end
protected :flatten_merge

def flatten
self.class.new.flatten_merge(self)
end

def flatten!
replace(flatten()) if any?(Set)
end

def superset?(set)
case
when set.instance_of?(self.class)
super
when set.is_a?(Set)
size >= set.size && set.all?(self)
else
raise ArgumentError, "value must be a set"
end
end
alias >= superset?

def proper_superset?(set)
case
when set.instance_of?(self.class)
super
when set.is_a?(Set)
size > set.size && set.all?(self)
else
raise ArgumentError, "value must be a set"
end
end
alias > proper_superset?

def subset?(set)
case
when set.instance_of?(self.class)
super
when set.is_a?(Set)
size <= set.size && all?(set)
else
raise ArgumentError, "value must be a set"
end
end
alias <= subset?

def proper_subset?(set)
case
when set.instance_of?(self.class)
super
when set.is_a?(Set)
size < set.size && all?(set)
else
raise ArgumentError, "value must be a set"
end
end
alias < proper_subset?

def <=>(set)
return unless set.is_a?(Set)

case size <=> set.size
when -1 then -1 if proper_subset?(set)
when +1 then +1 if proper_superset?(set)
else 0 if self.==(set)
end
end

def intersect?(set)
case set
when Set
if size < set.size
any?(set)
else
set.any?(self)
end
when Enumerable
set.any?(self)
else
raise ArgumentError, "value must be enumerable"
end
end

def disjoint?(set)
!intersect?(set)
end

def add?(o)
add(o) unless include?(o)
end

def delete?(o)
delete(o) if include?(o)
end

def delete_if(&block)
block_given? or return enum_for(__method__) { size }
select(&block).each { |o| delete(o) }
self
end

def keep_if(&block)
block_given? or return enum_for(__method__) { size }
reject(&block).each { |o| delete(o) }
self
end

def collect!
block_given? or return enum_for(__method__) { size }
set = self.class.new
each { |o| set << yield(o) }
replace(set)
end
alias map! collect!

def reject!(&block)
block_given? or return enum_for(__method__) { size }
n = size
delete_if(&block)
self if size != n
end

def select!(&block)
block_given? or return enum_for(__method__) { size }
n = size
keep_if(&block)
self if size != n
end

alias filter! select!

def merge(*enums, **nil)
enums.each do |enum|
if enum.instance_of?(self.class)
super(enum)
else
do_with_enum(enum) { |o| add(o) }
end
end

self
end

def subtract(enum)
do_with_enum(enum) { |o| delete(o) }
self
end

def |(enum)
dup.merge(enum)
end
alias + |
alias union |

def -(enum)
dup.subtract(enum)
end
alias difference -

def &(enum)
n = self.class.new
if enum.is_a?(Set)
if enum.size > size
each { |o| n.add(o) if enum.include?(o) }
else
enum.each { |o| n.add(o) if include?(o) }
end
else
do_with_enum(enum) { |o| n.add(o) if include?(o) }
end
n
end
alias intersection &

def ^(enum)
n = self.class.new(enum)
each { |o| n.add(o) unless n.delete?(o) }
n
end

def ==(other)
if self.equal?(other)
true
elsif other.instance_of?(self.class)
super
elsif other.is_a?(Set) && self.size == other.size
other.all? { |o| include?(o) }
else
false
end
end

def eql?(o) # :nodoc:
return false unless o.is_a?(Set)
super
end

def classify
block_given? or return enum_for(__method__) { size }

h = {}

each { |i|
(h[yield(i)] ||= self.class.new).add(i)
}

h
end

def join(separator=nil)
to_a.join(separator)
end

InspectKey = :__inspect_key__ # :nodoc:

# Returns a string containing a human-readable representation of the
# set ("#<Set: {element1, element2, ...}>").
def inspect
ids = (Thread.current[InspectKey] ||= [])

if ids.include?(object_id)
return sprintf('#<%s: {...}>', self.class.name)
end

ids << object_id
begin
return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
ensure
ids.pop
end
end

alias to_s inspect

def pretty_print(pp) # :nodoc:
pp.group(1, sprintf('#<%s:', self.class.name), '>') {
pp.breakable
pp.group(1, '{', '}') {
pp.seplist(self) { |o|
pp.pp o
}
}
}
end

def pretty_print_cycle(pp) # :nodoc:
pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
end
end
private_constant :SubclassCompatible
end
Loading