# Sitef is a simple text format for serializing data to # It's intent is to be human readable and easy to # use for multi line text. module Sitef # All Sitef data is stored in files with one or more records. # Records are separated by separated by at least 2 dashes on a line. # Records contain key/value fields. The key starts in the first column # 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, # or array indexes to emulate nexted keys. # A # at the start optionally after whitespace is a comment # def self.parse_file(file) lineno = 0 results = [] errors = [] record = {} key = nil value = nil 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 key = nil end results << record record = {} elsif line[0] == '#' # 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 = nil elsif line[0, 2] == '..' # end of multiline value record[key.downcase] = 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] value = "" elsif key # continue the value value << line else # Not in a key, sntax error. errors << "#{lineno}: Don't know how to process line" end end # Store last key used if any. if key record[key.downcase] = value.chomp end # store last record results << record unless record.empty? return results, errors end def self.load_filename(filename) results , errors, warnings = nil, nil, nil; file = File.open(filename, 'rt') return nil, ["Could not open #{filename}"] unless file begin results, errors = parse_file(file) ensure file.close end return results, errors end def self.save_field(file, key, value) sval = value.to_s if sval["\n"] file.puts(".#{key}\n") file.puts(sval) file.puts("\n..\n") else file.puts(":#{key}:#{sval}\n") end end def self.save_record(file, record) record.each do | key, value | save_field(file, key, value) end end def self.save_file(file, records) records.each do | record | save_record(file, record) file.puts("--\n") end end def self.save_filename(filename, records) results , errors = nil, nil file = File.open(filename, 'wt') return false, ["Could not open #{filename}"] unless file begin save_file(file, records) ensure file.close end return true, [] end end