|
@@ -10,7 +10,7 @@ module Sitef
|
|
|
# with a : and is followed by a : the value starts after the second :
|
|
|
# A multiline key / value needs a key that starts with . and ends with .
|
|
|
# the end of the value is a pair of dots .. by itself
|
|
|
- # Keys may not be nested, however, une could use spaces or dots,
|
|
|
+ # Keys may not be nested, however, you could use spaces or dots,
|
|
|
# or array indexes to emulate nexted keys.
|
|
|
# A # at the start optionally after whitespace is a comment
|
|
|
#
|
|
@@ -25,14 +25,13 @@ module Sitef
|
|
|
until file.eof?
|
|
|
lineno += 1
|
|
|
line = file.gets(256)
|
|
|
- # XXX does eof? even work???
|
|
|
break if line.nil?
|
|
|
next if line.empty?
|
|
|
# new record
|
|
|
if line[0,2] == '--'
|
|
|
# Store last key used if any.
|
|
|
- if key
|
|
|
- record[key.downcase] = value.chomp
|
|
|
+ if key
|
|
|
+ record[key] = value.chomp
|
|
|
key = nil
|
|
|
end
|
|
|
results << record
|
|
@@ -41,19 +40,25 @@ module Sitef
|
|
|
# Comments start with #
|
|
|
elsif line[0] == ':'
|
|
|
# a key/value pair
|
|
|
- key, value = line[1,line.size].split(':', 2)
|
|
|
- record[key.downcase] = value.chomp
|
|
|
+ key, value = line[1,line.size].split(':', 2)
|
|
|
+ record[key] = value.chomp
|
|
|
key = value = nil
|
|
|
elsif line[0, 2] == '..'
|
|
|
# end of multiline value
|
|
|
- record[key.downcase] = value.chomp
|
|
|
+ record[key] = value.chomp
|
|
|
key = value = nil
|
|
|
elsif (line[0] == '.') && key.nil?
|
|
|
# Multiline key/value starts here (but is ignored
|
|
|
# until .. is encountered)
|
|
|
key = line[1, line.size]
|
|
|
+ key.chomp!
|
|
|
value = ""
|
|
|
+ # multiline value
|
|
|
elsif key
|
|
|
+ if line[0] == '\\'
|
|
|
+ # remove any escapes
|
|
|
+ line.slice!(0)
|
|
|
+ end
|
|
|
# continue the value
|
|
|
value << line
|
|
|
else
|
|
@@ -62,8 +67,8 @@ module Sitef
|
|
|
end
|
|
|
end
|
|
|
# Store last key used if any.
|
|
|
- if key
|
|
|
- record[key.downcase] = value.chomp
|
|
|
+ if key
|
|
|
+ record[key] = value.chomp
|
|
|
end
|
|
|
# store last record
|
|
|
results << record unless record.empty?
|
|
@@ -71,7 +76,7 @@ module Sitef
|
|
|
end
|
|
|
|
|
|
def self.load_filename(filename)
|
|
|
- results , errors, warnings = nil, nil, nil;
|
|
|
+ results, errors = nil, nil, nil;
|
|
|
file = File.open(filename, 'rt')
|
|
|
return nil, ["Could not open #{filename}"] unless file
|
|
|
begin
|
|
@@ -82,36 +87,82 @@ module Sitef
|
|
|
return results, errors
|
|
|
end
|
|
|
|
|
|
+ # Loads a Sitef fileas obejcts. Uses the ruby_klass atribute to load the object
|
|
|
+ # If that is missing, uses defklass
|
|
|
+ def self.load_objects(filename, defklass=nil)
|
|
|
+ results, errors = load_filename(filename)
|
|
|
+ p filename, results, errors
|
|
|
+ unless errors.nil? || errors.empty?
|
|
|
+ return nil, errors
|
|
|
+ end
|
|
|
+
|
|
|
+ objres = []
|
|
|
+ results.each do | result |
|
|
|
+ klassname = result['ruby_class'] || defklass
|
|
|
+ return nil unless klassname
|
|
|
+ klass = klassname.split('::').inject(Kernel) { |klass, name| klass.const_get(name) rescue nil }
|
|
|
+ return nil unless klass
|
|
|
+ if klass.respond_to? :from_sitef
|
|
|
+ objres << klass.from_sitef(result)
|
|
|
+ else
|
|
|
+ objres << klass.new(result)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ return objres, errors
|
|
|
+ end
|
|
|
+
|
|
|
+
|
|
|
+ # Saves a single field to a file in Sitef format.
|
|
|
def self.save_field(file, key, value)
|
|
|
- sval = value.to_s
|
|
|
+ if value.is_a? String
|
|
|
+ sval = value.dup
|
|
|
+ else
|
|
|
+ sval = value.to_s
|
|
|
+ end
|
|
|
if sval["\n"]
|
|
|
file.puts(".#{key}\n")
|
|
|
- file.puts(sval)
|
|
|
- file.puts("\n..\n")
|
|
|
+ # Escape everything that could be misinterpreted with a \\
|
|
|
+ sval.gsub!(/\n([\.\-\:\#\\]+)/, "\n\\\\\\1")
|
|
|
+ sval.gsub!(/\A([\.\-\:\#\\]+)/, "\\\\\\1")
|
|
|
+ file.printf("%s", sval)
|
|
|
+ file.printf("\n..\n")
|
|
|
else
|
|
|
- file.puts(":#{key}:#{sval}\n")
|
|
|
+ file.printf(":#{key}:#{sval}\n")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ def self.save_object(file, object, *fields)
|
|
|
+ save_field(file, :ruby_class, object.class.to_s)
|
|
|
+ fields.each do | field |
|
|
|
+ value = object.send(field.to_sym)
|
|
|
+ save_field(file, field, value)
|
|
|
end
|
|
|
end
|
|
|
|
|
|
- def self.save_record(file, record)
|
|
|
+ def self.save_record(file, record, *fields)
|
|
|
record.each do | key, value |
|
|
|
+ next if fields && !fields.empty? && !fields.member?(key)
|
|
|
save_field(file, key, value)
|
|
|
end
|
|
|
end
|
|
|
|
|
|
- def self.save_file(file, records)
|
|
|
+ def self.save_file(file, records, *fields)
|
|
|
records.each do | record |
|
|
|
- save_record(file, record)
|
|
|
+ if record.is_a? Hash
|
|
|
+ save_record(file, record, *fields)
|
|
|
+ else
|
|
|
+ save_object(file, record, *fields)
|
|
|
+ end
|
|
|
file.puts("--\n")
|
|
|
end
|
|
|
end
|
|
|
|
|
|
- def self.save_filename(filename, records)
|
|
|
+ def self.save_filename(filename, records, *fields)
|
|
|
results , errors = nil, nil
|
|
|
file = File.open(filename, 'wt')
|
|
|
return false, ["Could not open #{filename}"] unless file
|
|
|
begin
|
|
|
- save_file(file, records)
|
|
|
+ save_file(file, records, *fields)
|
|
|
ensure
|
|
|
file.close
|
|
|
end
|