Евгений обнови решението на 09.11.2014 21:32 (преди около 10 години)
+module RBFS
+ class Directory
+ :directories
+ :files
+
+ def directories
+ @directories
+ end
+
+ def files
+ @files
+ end
+
+ def initialize
+ @directories = Hash.new
+ @files = Hash.new
+ end
+
+ def add_file(name, file)
+ files[name] = file
+ end
+
+ def add_directory(name, directory = Directory.new)
+ directories[name] = directory
+ end
+
+ def [](name)
+ if directories.has_key?(name)
+ directories[name]
+ elsif files.has_key?(name)
+ files[name]
+ else
+ nil
+ end
+ end
+
+ def serialize
+ serialized = Parse::recursive_serialization(@files)
+ serialized += Parse::recursive_serialization(@directories)
+ end
+
+ def self.parse(string_data)
+ output_dir = Directory.new
+ data, output_dir = Parse::parse_files(string_data, output_dir)
+ data, output_dir = Parse::parse_directories(data, output_dir)
+ output_dir
+ end
+ end
+
+ class File
+ :data
+
+ def data=(value)
+ @data = value
+ end
+
+ def data
+ @data
+ end
+
+ def data_type
+ case @data
+ when nil then :nil
+ when String then :string
+ when Symbol then :symbol
+ when Numeric then :number
+ when TrueClass, FalseClass then :boolean
+ end
+ end
+
+ def initialize (data = nil)
+ @data = data
+ end
+
+ def serialize
+ data_type.to_s + ':' + @data.to_s
+ end
+
+ def self.parse(string_data)
+ split_data = string_data.split(':', 2)
+ type = split_data[0]
+ value = split_data[1]
+
+ parsed_data = Parse::parse_to_type(type, value)
+
+ File.new(parsed_data)
+ end
+ end
+
+
+ # Helper classes
+ class Parse
+ def self.parse_to_type(type, value)
+ case type
+ when 'nil' then nil
+ when 'string' then value
+ when 'symbol' then value.to_sym
+ when 'number' then to_number(value)
+ when 'boolean' then value === 'true'
+ end
+ end
+
+ def self.to_number(number)
+ if number.to_f % 1.0 === 0
+ number.to_i
+ else
+ number.to_f
+ end
+ end
+
+ def self.recursive_serialization(container)
+ output = container.size.to_s + ':'
+ container.each do |name, obj|
+ content = obj.serialize
+ output += name + ':' + content.size.to_s + ':' + content
+ end
+ output
+ end
+
+ def self.parse_files(data, root_dir)
+ data = data.split(':', 2)
+ file_count = data[0].to_i
+ data = data[1]
+
+ for _ in 0...file_count
+ name, file, data = parse_file_data(data)
+ root_dir.add_file(name, file)
+ end
+ return data, root_dir
+ end
+
+ def self.parse_file_data(data)
+ data = data.split(':', 3)
+ name = data[0]
+ size = data[1].to_i
+ content = data[2][0...size]
+ file = File::parse(content)
+ return name, file, data[2][size..-1]
+ end
+
+ def self.parse_directories(data, root_dir)
+ data = data.split(':', 2)
+ dir_count = data[0].to_i
+ data = data[1]
+
+ for _ in 0...dir_count
+ name, dir, data = parse_directory_data(data)
+ root_dir.add_directory(name, dir)
+ end
+ return data, root_dir
+ end
+
+ def self.parse_directory_data(data)
+ data = data.split(':', 3)
+ name = data[0]
+ size = data[1].to_i
+ content = data[2][0...size]
+ directory = Directory::parse(content)
+ return name, directory, data[2][size..-1]
+ end
+ end
+end