core/env.rb
module Rubinius
class EnvironmentVariables
include Enumerable
def [](key)
value = getenv(StringValue(key))
if value
value = set_encoding value
value.freeze
end
value
end
def []=(key, value)
key = StringValue(key)
if value.nil?
unsetenv(key)
else
if setenv(key, StringValue(value), 1) != 0
Errno.handle("setenv")
end
end
value
end
alias_method :store, :[]=
def each_key
return to_enum(:each_key) { size } unless block_given?
each { |k, v| yield k }
end
def each_value
return to_enum(:each_value) { size } unless block_given?
each { |k, v| yield v }
end
def each
return to_enum(:each) { size } unless block_given?
env = environ()
ptr_size = FFI.type_size FFI.find_type(:pointer)
offset = 0
cur = env + offset
until cur.read_pointer.null?
entry = cur.read_pointer.read_string
key, value = entry.split '=', 2
value.taint if value
key.taint if key
key = set_encoding key
value = set_encoding value
yield key, value
offset += ptr_size
cur = env + offset
end
self
end
alias_method :each_pair, :each
def delete(key)
existing_value = self[key]
if existing_value
self[key] = nil
elsif block_given?
yield key
end
existing_value
end
def delete_if(&block)
return to_enum(:delete_if) { size } unless block_given?
reject!(&block)
self
end
def include?(key)
!self[key].nil?
end
alias_method :has_key?, :include?
alias_method :key?, :include?
# More efficient than using the one from Enumerable
alias_method :member?, :include?
def fetch(key, absent=undefined)
if block_given? and !undefined.equal?(absent)
warn "block supersedes default value argument"
end
if value = self[key]
return value
end
if block_given?
return yield(key)
elsif undefined.equal?(absent)
raise KeyError, "key not found"
end
return absent
end
def to_s
"ENV"
end
def inspect
to_hash.inspect
end
def reject(&block)
to_hash.reject(&block)
end
def reject!
return to_enum(:reject!) { size } unless block_given?
# Avoid deleting from environ while iterating because the
# OS can handle that in a million different bad ways.
keys = []
each { |k, v| keys << k if yield(k, v) }
keys.each { |k| delete k }
keys.empty? ? nil : self
end
def clear
# Avoid deleting from environ while iterating because the
# OS can handle that in a million different bad ways.
keys = []
each { |k, v| keys << k }
keys.each { |k| delete k }
self
end
def has_value?(value)
each { |k, v| return true if v == value }
return false
end
alias_method :value?, :has_value?
def values_at(*params)
params.map{ |k| self[k] }
end
def index(value)
each do |k, v|
return k if v == value
end
nil
end
def invert
to_hash.invert
end
def key(value)
index(value)
end
def keys
keys = []
each { |k, v| keys << k }
keys
end
def values
vals = []
each { |k, v| vals << v }
vals
end
def empty?
each { return false }
return true
end
def length
sz = 0
each { |k, v| sz += 1 }
sz
end
alias_method :size, :length
def rehash
# No need to do anything, our keys are always strings
end
def replace(other)
clear
other.each { |k, v| self[k] = v }
end
def select(&blk)
return to_enum { size } unless block_given?
to_hash.select(&blk)
end
def shift
env = environ()
offset = 0
cur = env + offset
ptr = cur.read_pointer
return nil unless ptr
key, value = ptr.read_string.split "=", 2
return nil unless key
key.taint if key
value.taint if value
delete key
key = set_encoding key
value = set_encoding value
return [key, value]
end
def to_a
ary = []
each { |k, v| ary << [k, v] }
ary
end
def to_hash
hsh = {}
each { |k, v| hsh[k] = v }
hsh
end
alias_method :to_h, :to_hash
def update(other)
if block_given?
other.each { |k, v| self[k] = yield(k, self[k], v) }
else
other.each { |k, v| self[k] = v }
end
end
def keep_if(&block)
return to_enum(:keep_if) { size } unless block_given?
select!(&block)
self
end
def select!
return to_enum(:select!) { size } unless block_given?
reject! { |k, v| !yield(k, v) }
end
def assoc(key)
key = StringValue(key)
value = self[key]
value ? [key, value] : nil
end
def rassoc(value)
value = StringValue(value)
key = index(value)
key ? [key, value] : nil
end
def set_encoding(value)
return unless value.kind_of? String
if Encoding.default_internal && value.ascii_only?
value.encode Encoding.default_internal, Encoding.find("locale")
else
value.force_encoding Encoding.find("locale")
end
end
private :set_encoding
end
end