aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb')
-rw-r--r--actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb185
1 files changed, 185 insertions, 0 deletions
diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb
new file mode 100644
index 0000000000..119bf12646
--- /dev/null
+++ b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb
@@ -0,0 +1,185 @@
+require 'set'
+
+# Multiset implements a collection of unordered values and
+# allows duplicates.
+#
+# == Example
+#
+# require 'multiset'
+# s1 = Multiset.new [1, 2] # -> #<Multiset: {1, 2}>
+# s1.add(2) # -> #<Multiset: {1, 2, 2}>
+# s1.merge([2, 6]) # -> #<Multiset: {1, 2, 2, 2, 3}>
+# s1.multiplicity(2) # -> 3
+# s1.multiplicity(3) # -> 1
+class Multiset < Set
+ def initialize(*args, &block) #:nodoc:
+ @hash = Hash.new(0)
+ super
+ end
+
+ # Returns the number of times an element belongs to the multiset.
+ def multiplicity(e)
+ @hash[e]
+ end
+
+ # Returns the total number of elements in a multiset, including
+ # repeated memberships
+ def cardinality
+ @hash.inject(0) { |s, (e, m)| s += m }
+ end
+ alias_method :size, :cardinality
+ alias_method :length, :cardinality
+
+ # Converts the set to an array. The order of elements is uncertain.
+ def to_a
+ inject([]) { |ary, (key, _)| ary << key }
+ end
+
+ # Returns true if the set is a superset of the given set.
+ def superset?(set)
+ set.is_a?(self.class) or raise ArgumentError, "value must be a set"
+ return false if cardinality < set.cardinality
+ set.all? { |o| set.multiplicity(o) <= multiplicity(o) }
+ end
+
+ # Returns true if the set is a proper superset of the given set.
+ def proper_superset?(set)
+ set.is_a?(self.class) or raise ArgumentError, "value must be a set"
+ return false if cardinality <= set.cardinality
+ set.all? { |o| set.multiplicity(o) <= multiplicity(o) }
+ end
+
+ # Returns true if the set is a subset of the given set.
+ def subset?(set)
+ set.is_a?(self.class) or raise ArgumentError, "value must be a set"
+ return false if set.cardinality < cardinality
+ all? { |o| multiplicity(o) <= set.multiplicity(o) }
+ end
+
+ # Returns true if the set is a proper subset of the given set.
+ def proper_subset?(set)
+ set.is_a?(self.class) or raise ArgumentError, "value must be a set"
+ return false if set.cardinality <= cardinality
+ all? { |o| multiplicity(o) <= set.multiplicity(o) }
+ end
+
+ # Calls the given block once for each element in the set, passing
+ # the element as parameter. Returns an enumerator if no block is
+ # given.
+ def each
+ @hash.each_pair do |key, multiplicity|
+ multiplicity.times do
+ yield(key)
+ end
+ end
+ self
+ end
+
+ # Adds the given object to the set and returns self. Use +merge+ to
+ # add many elements at once.
+ def add(o)
+ @hash[o] ||= 0
+ @hash[o] += 1
+ self
+ end
+ alias << add
+
+ undef :add?
+
+ # Deletes all the identical object from the set and returns self.
+ # If +n+ is given, it will remove that amount of identical objects
+ # from the set. Use +subtract+ to delete many different items at
+ # once.
+ def delete(o, n = nil)
+ if n
+ @hash[o] ||= 0
+ @hash[o] -= n if @hash[o] > 0
+ @hash.delete(o) if @hash[o] == 0
+ else
+ @hash.delete(o)
+ end
+ self
+ end
+
+ undef :delete?
+
+ # Deletes every element of the set for which block evaluates to
+ # true, and returns self.
+ def delete_if
+ each { |o| delete(o) if yield(o) }
+ self
+ end
+
+ # Merges the elements of the given enumerable object to the set and
+ # returns self.
+ def merge(enum)
+ enum.each { |o| add(o) }
+ self
+ end
+
+ # Deletes every element that appears in the given enumerable object
+ # and returns self.
+ def subtract(enum)
+ enum.each { |o| delete(o, 1) }
+ self
+ end
+
+ # Returns a new set containing elements common to the set and the
+ # given enumerable object.
+ def &(enum)
+ s = dup
+ n = self.class.new
+ enum.each { |o|
+ if s.include?(o)
+ s.delete(o, 1)
+ n.add(o)
+ end
+ }
+ n
+ end
+ alias intersection &
+
+ # Returns a new set containing elements exclusive between the set
+ # and the given enumerable object. (set ^ enum) is equivalent to
+ # ((set | enum) - (set & enum)).
+ def ^(enum)
+ n = self.class.new(enum)
+ each { |o| n.include?(o) ? n.delete(o, 1) : n.add(o) }
+ n
+ end
+
+ # Returns true if two sets are equal. Two multisets are equal if
+ # they have the same cardinalities and each element has the same
+ # multiplicity in both sets. The equality of each element inside
+ # the multiset is defined according to Object#eql?.
+ def eql?(set)
+ return true if equal?(set)
+ set = self.class.new(set) unless set.is_a?(self.class)
+ return false unless cardinality == set.cardinality
+ superset?(set) && subset?(set)
+ end
+ alias_method :==, :eql?
+
+ def marshal_dump #:nodoc:
+ @hash
+ end
+
+ def marshal_load(hash) #:nodoc:
+ @hash = hash
+ end
+
+ def to_yaml(opts = {}) #:nodoc:
+ YAML::quick_emit(self, opts) do |out|
+ out.map(taguri, to_yaml_style) do |map|
+ @hash.each do |k, v|
+ map.add(k, v)
+ end
+ end
+ end
+ end
+
+ def yaml_initialize(tag, val) #:nodoc:
+ @hash = val
+ self
+ end
+end