lib/dbf/table.rb in dbf-4.1.3 vs lib/dbf/table.rb in dbf-4.1.4

- old
+ new

@@ -10,11 +10,12 @@ class Table extend Forwardable include Enumerable include ::DBF::Schema - DBF_HEADER_SIZE = 32 + DBASE2_HEADER_SIZE = 8 + DBASE3_HEADER_SIZE = 32 VERSIONS = { '02' => 'FoxBase', '03' => 'dBase III without memo file', '04' => 'dBase IV without memo file', @@ -65,13 +66,13 @@ # # # working with a dbf overriding specified in the dbf encoding # table = DBF::Table.new 'data.dbf', nil, 'cp437' # table = DBF::Table.new 'data.dbf', 'memo.dbt', Encoding::US_ASCII # - # @param [String, StringIO] data Path to the dbf file or a StringIO object - # @param [optional String, StringIO] memo Path to the memo file or a StringIO object - # @param [optional String, Encoding] encoding Name of the encoding or an Encoding object + # @param data [String, StringIO] data Path to the dbf file or a StringIO object + # @param memo [optional String, StringIO] memo Path to the memo file or a StringIO object + # @param encoding [optional String, Encoding] encoding Name of the encoding or an Encoding object def initialize(data, memo = nil, encoding = nil) @data = open_data(data) @encoding = encoding || header.encoding @memo = open_memo(data, memo) yield self if block_given? @@ -96,11 +97,11 @@ # Column names # # @return [String] def column_names - columns.map(&:name) + @column_names ||= columns.map(&:name) end # All columns # # @return [Array] @@ -143,12 +144,12 @@ # matched exactly with the value in the database. If you specify more # than one key, all values must match in order for the record to be # returned. The equivalent SQL would be "WHERE key1 = 'value1' # AND key2 = 'value2'". # - # @param [Integer, Symbol] command - # @param [optional, Hash] options Hash of search parameters + # @param command [Integer, Symbol] command + # @param options [optional, Hash] options Hash of search parameters # @yield [optional, DBF::Record, NilClass] def find(command, options = {}, &block) case command when Integer record(command) @@ -209,20 +210,33 @@ private def build_columns # :nodoc: safe_seek do - @data.seek(DBF_HEADER_SIZE) + @data.seek(header_size) [].tap do |columns| until end_of_record? - column_data = @data.read(DBF_HEADER_SIZE) - columns << Column.new(self, *column_data.unpack('a10 x a x4 C2')) + case version + when '02' + column_data = @data.read(header_size * 2) + columns << Column.new(self, *column_data.unpack('A11 a C'), 0) + else + column_data = @data.read(header_size) + columns << Column.new(self, *column_data.unpack('A11 a x4 C2')) + end end end end end + def header_size + header_size = case version + when '02' then DBASE2_HEADER_SIZE + else DBASE3_HEADER_SIZE + end + end + def deleted_record? # :nodoc: flag = @data.read(1) flag ? flag.unpack1('a') == '*' : true end @@ -248,10 +262,10 @@ end def header # :nodoc: @header ||= safe_seek do @data.seek(0) - Header.new(@data.read(DBF_HEADER_SIZE)) + Header.new(@data.read(DBASE3_HEADER_SIZE)) end end def memo_class # :nodoc: @memo_class ||= begin