summaryrefslogtreecommitdiff
path: root/lib/soap
diff options
context:
space:
mode:
authornahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-12-19 13:59:27 +0000
committernahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-12-19 13:59:27 +0000
commitc1e9ce9ca6d888cc18d945c916db4f4acd685d6b (patch)
tree209c33fb227b88fc0dcf17a72beb292fb286e203 /lib/soap
parenta15cdb751223ba152ad73b4d39dbc30331c6168c (diff)
* 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
Diffstat (limited to 'lib/soap')
-rw-r--r--lib/soap/property.rb179
1 files changed, 109 insertions, 70 deletions
diff --git a/lib/soap/property.rb b/lib/soap/property.rb
index d2bae88825..e0516aa419 100644
--- a/lib/soap/property.rb
+++ b/lib/soap/property.rb
@@ -9,29 +9,34 @@
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
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)
prop = new
- stream.each_with_index do |line, lineno|
- 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.load(stream)
prop
end
@@ -41,6 +46,7 @@ class Property
end
end
+ # find property from $:.
def self.loadproperty(propname)
$:.each do |path|
if File.file?(file = File.join(path, propname))
@@ -57,6 +63,34 @@ class Property
@locked = false
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
def [](name)
referent(name_to_a(name))
@@ -133,50 +167,6 @@ class Property
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)
check_lock(key)
ref = @store[key] ||= self.class.new
@@ -206,15 +196,56 @@ private
@store[key] = value
end
+ def local_hook(key)
+ @self_hook + (@hook[key] || NO_HOOK)
+ end
+
def local_assign_hook(key, hook)
check_lock(key)
@store[key] ||= nil
(@hook[key] ||= []) << hook
end
+private
+
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
def check_lock(key)
@@ -240,12 +271,6 @@ private
end
end
- def location_pair(ary)
- name, *rest = *ary
- key = to_key(name)
- return key, rest
- end
-
def normalize_name(name)
name_to_a(name).collect { |key| to_key(key) }.join('.')
end
@@ -269,3 +294,17 @@ 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