mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/soap/property.rb (SOAP::Property#load): new method for loading
property value into existing property tree. * test/soap/test_property.rb: add test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5220 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a15cdb7512
commit
c1e9ce9ca6
3 changed files with 154 additions and 70 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
Fri Dec 19 22:56:46 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
|
||||||
|
|
||||||
|
* lib/soap/property.rb (SOAP::Property#load): new method for loading
|
||||||
|
property value into existing property tree.
|
||||||
|
|
||||||
|
* test/soap/test_property.rb: add test.
|
||||||
|
|
||||||
Fri Dec 19 19:21:49 2003 akira yamada <akira@ruby-lang.org>
|
Fri Dec 19 19:21:49 2003 akira yamada <akira@ruby-lang.org>
|
||||||
|
|
||||||
* lib/runit/cui/testrunner.rb (RUNIT::CUI::TestRunner::run):
|
* lib/runit/cui/testrunner.rb (RUNIT::CUI::TestRunner::run):
|
||||||
|
|
|
@ -9,29 +9,34 @@
|
||||||
module SOAP
|
module SOAP
|
||||||
|
|
||||||
|
|
||||||
|
# Property stream format:
|
||||||
|
#
|
||||||
|
# line separator is \r?\n. 1 line per a property.
|
||||||
|
# line which begins with '#' is a comment line. empty line is ignored, too.
|
||||||
|
# key/value separator is ':' or '='.
|
||||||
|
# '\' as escape character. but line separator cannot be escaped.
|
||||||
|
# \s at the head/tail of key/value are trimmed.
|
||||||
|
#
|
||||||
|
# '[' + key + ']' indicates property section. for example,
|
||||||
|
#
|
||||||
|
# [aaa.bbb]
|
||||||
|
# ccc = ddd
|
||||||
|
# eee.fff = ggg
|
||||||
|
# []
|
||||||
|
# aaa.hhh = iii
|
||||||
|
#
|
||||||
|
# is the same as;
|
||||||
|
#
|
||||||
|
# aaa.bbb.ccc = ddd
|
||||||
|
# aaa.bbb.eee.fff = ggg
|
||||||
|
# aaa.hhh = iii
|
||||||
|
#
|
||||||
class Property
|
class Property
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
# Property file format:
|
|
||||||
# line separator is \r?\n. 1 line per a property.
|
|
||||||
# line which begins with '#' is comment line. empty line is ignored.
|
|
||||||
# key/value separator is ':', '=', or \s.
|
|
||||||
# '\' as escape character. but line separator cannot be escaped.
|
|
||||||
# \s at the head/tail of key/value are trimmed.
|
|
||||||
def self.load(stream)
|
def self.load(stream)
|
||||||
prop = new
|
prop = new
|
||||||
stream.each_with_index do |line, lineno|
|
prop.load(stream)
|
||||||
line.sub!(/\r?\n\z/, '')
|
|
||||||
next if /^(#.*|)$/ =~ line
|
|
||||||
if /^\s*([^=:\s\\]+(?:\\.[^=:\s\\]*)*)\s*[=:\s]\s*(.*)$/ =~ line
|
|
||||||
key, value = $1, $2
|
|
||||||
key = eval("\"#{key}\"")
|
|
||||||
value = eval("\"#{value.strip}\"")
|
|
||||||
prop[key] = value
|
|
||||||
else
|
|
||||||
raise TypeError.new("property format error at line #{lineno + 1}: `#{line}'")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
prop
|
prop
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -41,6 +46,7 @@ class Property
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# find property from $:.
|
||||||
def self.loadproperty(propname)
|
def self.loadproperty(propname)
|
||||||
$:.each do |path|
|
$:.each do |path|
|
||||||
if File.file?(file = File.join(path, propname))
|
if File.file?(file = File.join(path, propname))
|
||||||
|
@ -57,6 +63,34 @@ class Property
|
||||||
@locked = false
|
@locked = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
KEY_REGSRC = '([^=:\\\\]*(?:\\\\.[^=:\\\\]*)*)'
|
||||||
|
DEF_REGSRC = '\\s*' + KEY_REGSRC + '\\s*[=:]\\s*(.*)'
|
||||||
|
COMMENT_REGEXP = Regexp.new('^(?:#.*|)$')
|
||||||
|
CATDEF_REGEXP = Regexp.new("^\\[\\s*#{KEY_REGSRC}\\s*\\]$")
|
||||||
|
LINE_REGEXP = Regexp.new("^#{DEF_REGSRC}$")
|
||||||
|
def load(stream)
|
||||||
|
key_prefix = ""
|
||||||
|
stream.each_with_index do |line, lineno|
|
||||||
|
line.sub!(/\r?\n\z/, '')
|
||||||
|
case line
|
||||||
|
when COMMENT_REGEXP
|
||||||
|
next
|
||||||
|
when CATDEF_REGEXP
|
||||||
|
key_prefix = $1.strip
|
||||||
|
when LINE_REGEXP
|
||||||
|
key, value = $1.strip, $2.strip
|
||||||
|
key = "#{key_prefix}.#{key}" unless key_prefix.empty?
|
||||||
|
key = eval("\"#{key}\"")
|
||||||
|
value = eval("\"#{value}\"")
|
||||||
|
self[key] = value
|
||||||
|
else
|
||||||
|
raise TypeError.new(
|
||||||
|
"property format error at line #{lineno + 1}: `#{line}'")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
# name: a Symbol, String or an Array
|
# name: a Symbol, String or an Array
|
||||||
def [](name)
|
def [](name)
|
||||||
referent(name_to_a(name))
|
referent(name_to_a(name))
|
||||||
|
@ -133,50 +167,6 @@ class Property
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def referent(ary)
|
|
||||||
key, rest = location_pair(ary)
|
|
||||||
if rest.empty?
|
|
||||||
local_referent(key)
|
|
||||||
else
|
|
||||||
deref_key(key).referent(rest)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# returns: Array of hook
|
|
||||||
def assign(ary, value)
|
|
||||||
key, rest = location_pair(ary)
|
|
||||||
if rest.empty?
|
|
||||||
local_assign(key, value)
|
|
||||||
local_hook(key)
|
|
||||||
else
|
|
||||||
local_hook(key) + deref_key(key).assign(rest, value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def assign_hook(ary, hook)
|
|
||||||
key, rest = location_pair(ary)
|
|
||||||
if rest.empty?
|
|
||||||
local_assign_hook(key, hook)
|
|
||||||
else
|
|
||||||
deref_key(key).assign_hook(rest, hook)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def assign_self_hook(hook)
|
|
||||||
check_lock(nil)
|
|
||||||
@self_hook << hook
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def each_key
|
|
||||||
self.each do |key, value|
|
|
||||||
if propkey?(value)
|
|
||||||
yield(value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def deref_key(key)
|
def deref_key(key)
|
||||||
check_lock(key)
|
check_lock(key)
|
||||||
ref = @store[key] ||= self.class.new
|
ref = @store[key] ||= self.class.new
|
||||||
|
@ -206,15 +196,56 @@ private
|
||||||
@store[key] = value
|
@store[key] = value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def local_hook(key)
|
||||||
|
@self_hook + (@hook[key] || NO_HOOK)
|
||||||
|
end
|
||||||
|
|
||||||
def local_assign_hook(key, hook)
|
def local_assign_hook(key, hook)
|
||||||
check_lock(key)
|
check_lock(key)
|
||||||
@store[key] ||= nil
|
@store[key] ||= nil
|
||||||
(@hook[key] ||= []) << hook
|
(@hook[key] ||= []) << hook
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
NO_HOOK = [].freeze
|
NO_HOOK = [].freeze
|
||||||
def local_hook(key)
|
|
||||||
@self_hook + (@hook[key] || NO_HOOK)
|
def referent(ary)
|
||||||
|
ary[0..-2].inject(self) { |ref, name|
|
||||||
|
ref.deref_key(to_key(name))
|
||||||
|
}.local_referent(to_key(ary.last))
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign(ary, value)
|
||||||
|
ref = self
|
||||||
|
hook = NO_HOOK
|
||||||
|
ary[0..-2].each do |name|
|
||||||
|
key = to_key(name)
|
||||||
|
hook += ref.local_hook(key)
|
||||||
|
ref = ref.deref_key(key)
|
||||||
|
end
|
||||||
|
last_key = to_key(ary.last)
|
||||||
|
ref.local_assign(last_key, value)
|
||||||
|
hook + ref.local_hook(last_key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_hook(ary, hook)
|
||||||
|
ary[0..-2].inject(self) { |ref, name|
|
||||||
|
ref.deref_key(to_key(name))
|
||||||
|
}.local_assign_hook(to_key(ary.last), hook)
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_self_hook(hook)
|
||||||
|
check_lock(nil)
|
||||||
|
@self_hook << hook
|
||||||
|
end
|
||||||
|
|
||||||
|
def each_key
|
||||||
|
self.each do |key, value|
|
||||||
|
if propkey?(value)
|
||||||
|
yield(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_lock(key)
|
def check_lock(key)
|
||||||
|
@ -240,12 +271,6 @@ private
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def location_pair(ary)
|
|
||||||
name, *rest = *ary
|
|
||||||
key = to_key(name)
|
|
||||||
return key, rest
|
|
||||||
end
|
|
||||||
|
|
||||||
def normalize_name(name)
|
def normalize_name(name)
|
||||||
name_to_a(name).collect { |key| to_key(key) }.join('.')
|
name_to_a(name).collect { |key| to_key(key) }.join('.')
|
||||||
end
|
end
|
||||||
|
@ -269,3 +294,17 @@ end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# for ruby/1.6.
|
||||||
|
unless Enumerable.instance_methods.include?('inject')
|
||||||
|
module Enumerable
|
||||||
|
def inject(init)
|
||||||
|
result = init
|
||||||
|
each do |item|
|
||||||
|
result = yield(result, item)
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -32,6 +32,14 @@ client.protocol.http.protocol_version = 1.0
|
||||||
foo\\:bar\\=baz = qux
|
foo\\:bar\\=baz = qux
|
||||||
foo\\\\.bar.baz=\tq\\\\ux\ttab
|
foo\\\\.bar.baz=\tq\\\\ux\ttab
|
||||||
a\\ b = 1
|
a\\ b = 1
|
||||||
|
[ppp.qqq.rrr]
|
||||||
|
sss = 3
|
||||||
|
ttt.uuu = 4
|
||||||
|
|
||||||
|
[ sss.ttt.uuu ]
|
||||||
|
vvv.www = 5
|
||||||
|
[ ]
|
||||||
|
xxx.yyy.zzz = 6
|
||||||
__EOP__
|
__EOP__
|
||||||
prop = Property.load(propstr)
|
prop = Property.load(propstr)
|
||||||
assert_equal(["1", "2", "3"], prop["a.b"].values.sort)
|
assert_equal(["1", "2", "3"], prop["a.b"].values.sort)
|
||||||
|
@ -41,8 +49,38 @@ __EOP__
|
||||||
assert_equal("1.0", prop["client.protocol.http.protocol_version"])
|
assert_equal("1.0", prop["client.protocol.http.protocol_version"])
|
||||||
assert_equal("q\\ux\ttab", prop['foo\.bar.baz'])
|
assert_equal("q\\ux\ttab", prop['foo\.bar.baz'])
|
||||||
assert_equal("1", prop['a b'])
|
assert_equal("1", prop['a b'])
|
||||||
|
assert_equal("3", prop['ppp.qqq.rrr.sss'])
|
||||||
|
assert_equal("4", prop['ppp.qqq.rrr.ttt.uuu'])
|
||||||
|
assert_equal("5", prop['sss.ttt.uuu.vvv.www'])
|
||||||
|
assert_equal("6", prop['xxx.yyy.zzz'])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_load
|
||||||
|
prop = Property.new
|
||||||
|
hooked = false
|
||||||
|
prop.add_hook("foo.bar.baz") do |name, value|
|
||||||
|
assert_equal("foo.bar.baz", name)
|
||||||
|
assert_equal("123", value)
|
||||||
|
hooked = true
|
||||||
|
end
|
||||||
|
prop.lock
|
||||||
|
prop["foo.bar"].lock
|
||||||
|
prop.load("foo.bar.baz = 123")
|
||||||
|
assert(hooked)
|
||||||
|
assert_raises(TypeError) do
|
||||||
|
prop.load("foo.bar.qux = 123")
|
||||||
|
end
|
||||||
|
prop.load("foo.baz = 456")
|
||||||
|
assert_equal("456", prop["foo.baz"])
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_initialize
|
||||||
|
prop = ::SOAP::Property.new
|
||||||
|
# store is empty
|
||||||
|
assert_nil(prop["a"])
|
||||||
|
# does hook work?
|
||||||
|
assert_equal(1, prop["a"] = 1)
|
||||||
|
end
|
||||||
def test_initialize
|
def test_initialize
|
||||||
prop = ::SOAP::Property.new
|
prop = ::SOAP::Property.new
|
||||||
# store is empty
|
# store is empty
|
||||||
|
|
Loading…
Add table
Reference in a new issue