dbf 2.0.10 → 2.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +28 -25
- data/lib/dbf/column/base.rb +85 -59
- data/lib/dbf/column/foxpro.rb +1 -1
- data/lib/dbf/database/foxpro.rb +43 -26
- data/lib/dbf/encodings.rb +59 -59
- data/lib/dbf/header.rb +1 -1
- data/lib/dbf/memo/base.rb +7 -7
- data/lib/dbf/memo/dbase3.rb +6 -5
- data/lib/dbf/memo/dbase4.rb +2 -2
- data/lib/dbf/memo/foxpro.rb +4 -4
- data/lib/dbf/record.rb +18 -16
- data/lib/dbf/schema.rb +1 -0
- data/lib/dbf/table.rb +61 -76
- data/lib/dbf/version.rb +1 -1
- data/spec/dbf/column_spec.rb +19 -12
- data/spec/dbf/table_spec.rb +38 -37
- metadata +2 -2
data/lib/dbf/encodings.rb
CHANGED
@@ -1,63 +1,63 @@
|
|
1
1
|
module DBF
|
2
2
|
ENCODINGS = {
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
3
|
+
'01' => 'cp437', # U.S. MS-DOS
|
4
|
+
'02' => 'cp850', # International MS-DOS
|
5
|
+
'03' => 'cp1252', # Windows ANSI
|
6
|
+
'08' => 'cp865', # Danish OEM
|
7
|
+
'09' => 'cp437', # Dutch OEM
|
8
|
+
'0a' => 'cp850', # Dutch OEM*
|
9
|
+
'0b' => 'cp437', # Finnish OEM
|
10
|
+
'0d' => 'cp437', # French OEM
|
11
|
+
'0e' => 'cp850', # French OEM*
|
12
|
+
'0f' => 'cp437', # German OEM
|
13
|
+
'10' => 'cp850', # German OEM*
|
14
|
+
'11' => 'cp437', # Italian OEM
|
15
|
+
'12' => 'cp850', # Italian OEM*
|
16
|
+
'13' => 'cp932', # Japanese Shift-JIS
|
17
|
+
'14' => 'cp850', # Spanish OEM*
|
18
|
+
'15' => 'cp437', # Swedish OEM
|
19
|
+
'16' => 'cp850', # Swedish OEM*
|
20
|
+
'17' => 'cp865', # Norwegian OEM
|
21
|
+
'18' => 'cp437', # Spanish OEM
|
22
|
+
'19' => 'cp437', # English OEM (Britain)
|
23
|
+
'1a' => 'cp850', # English OEM (Britain)*
|
24
|
+
'1b' => 'cp437', # English OEM (U.S.)
|
25
|
+
'1c' => 'cp863', # French OEM (Canada)
|
26
|
+
'1d' => 'cp850', # French OEM*
|
27
|
+
'1f' => 'cp852', # Czech OEM
|
28
|
+
'22' => 'cp852', # Hungarian OEM
|
29
|
+
'23' => 'cp852', # Polish OEM
|
30
|
+
'24' => 'cp860', # Portuguese OEM
|
31
|
+
'25' => 'cp850', # Portuguese OEM*
|
32
|
+
'26' => 'cp866', # Russian OEM
|
33
|
+
'37' => 'cp850', # English OEM (U.S.)*
|
34
|
+
'40' => 'cp852', # Romanian OEM
|
35
|
+
'4d' => 'cp936', # Chinese GBK (PRC)
|
36
|
+
'4e' => 'cp949', # Korean (ANSI/OEM)
|
37
|
+
'4f' => 'cp950', # Chinese Big5 (Taiwan)
|
38
|
+
'50' => 'cp874', # Thai (ANSI/OEM)
|
39
|
+
'57' => 'cp1252', # ANSI
|
40
|
+
'58' => 'cp1252', # Western European ANSI
|
41
|
+
'59' => 'cp1252', # Spanish ANSI
|
42
|
+
'64' => 'cp852', # Eastern European MS-DOS
|
43
|
+
'65' => 'cp866', # Russian MS-DOS
|
44
|
+
'66' => 'cp865', # Nordic MS-DOS
|
45
|
+
'67' => 'cp861', # Icelandic MS-DOS
|
46
|
+
'6a' => 'cp737', # Greek MS-DOS (437G)
|
47
|
+
'6b' => 'cp857', # Turkish MS-DOS
|
48
|
+
'6c' => 'cp863', # French-Canadian MS-DOS
|
49
|
+
'78' => 'cp950', # Taiwan Big 5
|
50
|
+
'79' => 'cp949', # Hangul (Wansung)
|
51
|
+
'7a' => 'cp936', # PRC GBK
|
52
|
+
'7b' => 'cp932', # Japanese Shift-JIS
|
53
|
+
'7c' => 'cp874', # Thai Windows/MS-DOS
|
54
|
+
'86' => 'cp737', # Greek OEM
|
55
|
+
'87' => 'cp852', # Slovenian OEM
|
56
|
+
'88' => 'cp857', # Turkish OEM
|
57
|
+
'c8' => 'cp1250', # Eastern European Windows
|
58
|
+
'c9' => 'cp1251', # Russian Windows
|
59
|
+
'ca' => 'cp1254', # Turkish Windows
|
60
|
+
'cb' => 'cp1253', # Greek Windows
|
61
|
+
'cc' => 'cp1257', # Baltic Windows
|
62
62
|
}
|
63
63
|
end
|
data/lib/dbf/header.rb
CHANGED
data/lib/dbf/memo/base.rb
CHANGED
@@ -9,13 +9,13 @@ module DBF
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def initialize(data, version)
|
12
|
-
@data
|
12
|
+
@data = data
|
13
|
+
@version = version
|
13
14
|
end
|
14
15
|
|
15
16
|
def get(start_block)
|
16
|
-
|
17
|
-
|
18
|
-
end
|
17
|
+
return nil unless start_block > 0
|
18
|
+
build_memo start_block
|
19
19
|
end
|
20
20
|
|
21
21
|
def close
|
@@ -28,15 +28,15 @@ module DBF
|
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
|
-
def offset(start_block) #nodoc
|
31
|
+
def offset(start_block) # nodoc
|
32
32
|
start_block * block_size
|
33
33
|
end
|
34
34
|
|
35
|
-
def content_size(memo_size) #nodoc
|
35
|
+
def content_size(memo_size) # nodoc
|
36
36
|
(memo_size - block_size) + BLOCK_HEADER_SIZE
|
37
37
|
end
|
38
38
|
|
39
|
-
def block_content_size #nodoc
|
39
|
+
def block_content_size # nodoc
|
40
40
|
@block_content_size ||= block_size - BLOCK_HEADER_SIZE
|
41
41
|
end
|
42
42
|
|
data/lib/dbf/memo/dbase3.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
module DBF
|
2
2
|
module Memo
|
3
3
|
class Dbase3 < Base
|
4
|
-
def build_memo(start_block) #nodoc
|
4
|
+
def build_memo(start_block) # nodoc
|
5
5
|
@data.seek offset(start_block)
|
6
|
-
memo_string =
|
7
|
-
|
6
|
+
memo_string = ''
|
7
|
+
loop do
|
8
8
|
block = @data.read(BLOCK_SIZE).gsub(/(\000|\032)/, '')
|
9
9
|
memo_string << block
|
10
|
-
|
10
|
+
break if block.size < BLOCK_SIZE
|
11
|
+
end
|
11
12
|
memo_string
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
15
|
-
end
|
16
|
+
end
|
data/lib/dbf/memo/dbase4.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module DBF
|
2
2
|
module Memo
|
3
3
|
class Dbase4 < Base
|
4
|
-
def build_memo(start_block) #nodoc
|
4
|
+
def build_memo(start_block) # nodoc
|
5
5
|
@data.seek offset(start_block)
|
6
|
-
@data.read(@data.read(BLOCK_HEADER_SIZE).unpack(
|
6
|
+
@data.read(@data.read(BLOCK_HEADER_SIZE).unpack('x4L').first)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
data/lib/dbf/memo/foxpro.rb
CHANGED
@@ -3,10 +3,10 @@ module DBF
|
|
3
3
|
class Foxpro < Base
|
4
4
|
FPT_HEADER_SIZE = 512
|
5
5
|
|
6
|
-
def build_memo(start_block) #nodoc
|
6
|
+
def build_memo(start_block) # nodoc
|
7
7
|
@data.seek offset(start_block)
|
8
8
|
|
9
|
-
memo_type, memo_size, memo_string = @data.read(block_size).unpack(
|
9
|
+
memo_type, memo_size, memo_string = @data.read(block_size).unpack('NNa*')
|
10
10
|
return nil unless memo_type == 1 && memo_size > 0
|
11
11
|
|
12
12
|
if memo_size > block_content_size
|
@@ -22,7 +22,7 @@ module DBF
|
|
22
22
|
|
23
23
|
private
|
24
24
|
|
25
|
-
def block_size #nodoc
|
25
|
+
def block_size # nodoc
|
26
26
|
@block_size ||= begin
|
27
27
|
@data.rewind
|
28
28
|
@data.read(FPT_HEADER_SIZE).unpack('x6n').first || 0
|
@@ -30,4 +30,4 @@ module DBF
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
|
-
end
|
33
|
+
end
|
data/lib/dbf/record.rb
CHANGED
@@ -9,7 +9,9 @@ module DBF
|
|
9
9
|
# @memo [DBF::Memo]
|
10
10
|
def initialize(data, columns, version, memo)
|
11
11
|
@data = StringIO.new(data)
|
12
|
-
@columns
|
12
|
+
@columns = columns
|
13
|
+
@version = version
|
14
|
+
@memo = memo
|
13
15
|
end
|
14
16
|
|
15
17
|
# Equality
|
@@ -24,7 +26,7 @@ module DBF
|
|
24
26
|
#
|
25
27
|
# @return [Array]
|
26
28
|
def to_a
|
27
|
-
@columns.map {|column| attributes[column.name]}
|
29
|
+
@columns.map { |column| attributes[column.name] }
|
28
30
|
end
|
29
31
|
|
30
32
|
# Do all search parameters match?
|
@@ -32,17 +34,17 @@ module DBF
|
|
32
34
|
# @param [Hash] options
|
33
35
|
# @return [Boolean]
|
34
36
|
def match?(options)
|
35
|
-
options.all? {|key, value| self[key] == value}
|
37
|
+
options.all? { |key, value| self[key] == value }
|
36
38
|
end
|
37
39
|
|
38
40
|
# Reads attributes by column name
|
39
41
|
#
|
40
42
|
# @param [String, Symbol] key
|
41
|
-
def [](
|
42
|
-
key =
|
43
|
-
if attributes.
|
43
|
+
def [](name)
|
44
|
+
key = name.to_s
|
45
|
+
if attributes.key?(key)
|
44
46
|
attributes[key]
|
45
|
-
elsif index = underscored_column_names.index(key)
|
47
|
+
elsif (index = underscored_column_names.index(key))
|
46
48
|
attributes[@columns[index].name]
|
47
49
|
end
|
48
50
|
end
|
@@ -51,7 +53,8 @@ module DBF
|
|
51
53
|
#
|
52
54
|
# @return [Hash]
|
53
55
|
def attributes
|
54
|
-
@attributes ||=
|
56
|
+
@attributes ||=
|
57
|
+
Hash[@columns.map { |column| [column.name, init_attribute(column)] }]
|
55
58
|
end
|
56
59
|
|
57
60
|
# Overrides standard Object.respond_to? to return true if a
|
@@ -69,8 +72,8 @@ module DBF
|
|
69
72
|
|
70
73
|
private
|
71
74
|
|
72
|
-
def method_missing(method, *args) #nodoc
|
73
|
-
if index = underscored_column_names.index(method.to_s)
|
75
|
+
def method_missing(method, *args) # nodoc
|
76
|
+
if (index = underscored_column_names.index(method.to_s))
|
74
77
|
attributes[@columns[index].name]
|
75
78
|
else
|
76
79
|
super
|
@@ -78,15 +81,15 @@ module DBF
|
|
78
81
|
end
|
79
82
|
|
80
83
|
def underscored_column_names # nodoc
|
81
|
-
@underscored_column_names ||= @columns.map
|
84
|
+
@underscored_column_names ||= @columns.map(&:underscored_name)
|
82
85
|
end
|
83
86
|
|
84
|
-
def init_attribute(column) #nodoc
|
87
|
+
def init_attribute(column) # nodoc
|
85
88
|
value = column.memo? ? memo(column) : unpack_data(column)
|
86
89
|
column.type_cast(value)
|
87
90
|
end
|
88
91
|
|
89
|
-
def memo(column) #nodoc
|
92
|
+
def memo(column) # nodoc
|
90
93
|
if @memo
|
91
94
|
@memo.get(memo_start_block(column))
|
92
95
|
else
|
@@ -96,15 +99,14 @@ module DBF
|
|
96
99
|
end
|
97
100
|
end
|
98
101
|
|
99
|
-
def memo_start_block(column) #nodoc
|
102
|
+
def memo_start_block(column) # nodoc
|
100
103
|
format = 'V' if %w(30 31).include?(@version)
|
101
104
|
unpack_data(column, format).to_i
|
102
105
|
end
|
103
106
|
|
104
|
-
def unpack_data(column, format=nil) #nodoc
|
107
|
+
def unpack_data(column, format = nil) # nodoc
|
105
108
|
format ||= "a#{column.length}"
|
106
109
|
@data.read(column.length).unpack(format).first
|
107
110
|
end
|
108
|
-
|
109
111
|
end
|
110
112
|
end
|
data/lib/dbf/schema.rb
CHANGED
data/lib/dbf/table.rb
CHANGED
@@ -11,33 +11,33 @@ module DBF
|
|
11
11
|
DBF_HEADER_SIZE = 32
|
12
12
|
|
13
13
|
VERSIONS = {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
14
|
+
'02' => 'FoxBase',
|
15
|
+
'03' => 'dBase III without memo file',
|
16
|
+
'04' => 'dBase IV without memo file',
|
17
|
+
'05' => 'dBase V without memo file',
|
18
|
+
'07' => 'Visual Objects 1.x',
|
19
|
+
'30' => 'Visual FoxPro',
|
20
|
+
'31' => 'Visual FoxPro with AutoIncrement field',
|
21
|
+
'43' => 'dBASE IV SQL table files, no memo',
|
22
|
+
'63' => 'dBASE IV SQL system files, no memo',
|
23
|
+
'7b' => 'dBase IV with memo file',
|
24
|
+
'83' => 'dBase III with memo file',
|
25
|
+
'87' => 'Visual Objects 1.x with memo file',
|
26
|
+
'8b' => 'dBase IV with memo file',
|
27
|
+
'8e' => 'dBase IV with SQL table',
|
28
|
+
'cb' => 'dBASE IV SQL table files, with memo',
|
29
|
+
'f5' => 'FoxPro with memo file',
|
30
|
+
'fb' => 'FoxPro without memo file'
|
31
31
|
}
|
32
32
|
|
33
33
|
FOXPRO_VERSIONS = {
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
'30' => 'Visual FoxPro',
|
35
|
+
'31' => 'Visual FoxPro with AutoIncrement field',
|
36
|
+
'f5' => 'FoxPro with memo file',
|
37
|
+
'fb' => 'FoxPro without memo file'
|
38
38
|
}
|
39
39
|
|
40
|
-
attr_reader
|
40
|
+
attr_reader :header
|
41
41
|
attr_accessor :encoding # Source encoding (for ex. :cp1251)
|
42
42
|
|
43
43
|
# Opens a DBF::Table
|
@@ -62,16 +62,14 @@ module DBF
|
|
62
62
|
# @param [optional String, StringIO] memo Path to the memo file or a StringIO object
|
63
63
|
# @param [optional String, Encoding] encoding Name of the encoding or an Encoding object
|
64
64
|
def initialize(data, memo = nil, encoding = nil)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
raise DBF::FileNotFoundError.new("file not found: #{data}")
|
74
|
-
end
|
65
|
+
@data = open_data(data)
|
66
|
+
@data.rewind
|
67
|
+
@header = Header.new(@data.read(DBF_HEADER_SIZE), supports_encoding?)
|
68
|
+
@encoding = encoding || header.encoding
|
69
|
+
@memo = open_memo(data, memo)
|
70
|
+
yield self if block_given?
|
71
|
+
rescue Errno::ENOENT
|
72
|
+
raise DBF::FileNotFoundError, "file not found: #{data}"
|
75
73
|
end
|
76
74
|
|
77
75
|
# @return [TrueClass, FalseClass]
|
@@ -106,7 +104,7 @@ module DBF
|
|
106
104
|
#
|
107
105
|
# @yield [nil, DBF::Record]
|
108
106
|
def each
|
109
|
-
header.record_count.times {|i| yield record(i)}
|
107
|
+
header.record_count.times { |i| yield record(i) }
|
110
108
|
end
|
111
109
|
|
112
110
|
# Retrieve a record by index number.
|
@@ -117,9 +115,8 @@ module DBF
|
|
117
115
|
# @return [DBF::Record, NilClass]
|
118
116
|
def record(index)
|
119
117
|
seek_to_record(index)
|
120
|
-
if
|
121
|
-
|
122
|
-
end
|
118
|
+
return nil if deleted_record?
|
119
|
+
DBF::Record.new(@data.read(header.record_length), columns, version, @memo)
|
123
120
|
end
|
124
121
|
|
125
122
|
alias_method :row, :record
|
@@ -171,10 +168,11 @@ module DBF
|
|
171
168
|
# table.find :first, :first_name => "Keith"
|
172
169
|
#
|
173
170
|
# The <b>command</b> may be a record index, :all, or :first.
|
174
|
-
# <b>options</b> is optional and, if specified, should be a hash where the
|
175
|
-
# to column names in the database. The values will be
|
176
|
-
# in the database. If you specify more
|
177
|
-
#
|
171
|
+
# <b>options</b> is optional and, if specified, should be a hash where the
|
172
|
+
# keys correspond to column names in the database. The values will be
|
173
|
+
# matched exactly with the value in the database. If you specify more
|
174
|
+
# than one key, all values must match in order for the record to be
|
175
|
+
# returned. The equivalent SQL would be "WHERE key1 = 'value1'
|
178
176
|
# AND key2 = 'value2'".
|
179
177
|
#
|
180
178
|
# @param [Fixnum, Symbol] command
|
@@ -185,7 +183,7 @@ module DBF
|
|
185
183
|
when Fixnum
|
186
184
|
record(command)
|
187
185
|
when Array
|
188
|
-
command.map {|i| record(i)}
|
186
|
+
command.map { |i| record(i) }
|
189
187
|
when :all
|
190
188
|
find_all(options, &block)
|
191
189
|
when :first
|
@@ -204,7 +202,7 @@ module DBF
|
|
204
202
|
#
|
205
203
|
# @return [String]
|
206
204
|
def column_names
|
207
|
-
columns.map
|
205
|
+
columns.map(&:name)
|
208
206
|
end
|
209
207
|
|
210
208
|
# Is string encoding supported?
|
@@ -219,7 +217,7 @@ module DBF
|
|
219
217
|
''.respond_to?(:encoding)
|
220
218
|
end
|
221
219
|
|
222
|
-
def supports_iconv? #nodoc
|
220
|
+
def supports_iconv? # nodoc
|
223
221
|
require 'iconv'
|
224
222
|
true
|
225
223
|
rescue
|
@@ -228,10 +226,10 @@ module DBF
|
|
228
226
|
|
229
227
|
private
|
230
228
|
|
231
|
-
def build_columns #nodoc
|
229
|
+
def build_columns # nodoc
|
232
230
|
columns = []
|
233
231
|
@data.seek(DBF_HEADER_SIZE)
|
234
|
-
|
232
|
+
until ["\0", "\r"].include?(first_byte = @data.read(1))
|
235
233
|
column_data = first_byte + @data.read(DBF_HEADER_SIZE - 1)
|
236
234
|
name, type, length, decimal = column_data.unpack('a10 x a x4 C2')
|
237
235
|
columns << column_class.new(self, name, type, length, decimal)
|
@@ -239,55 +237,43 @@ module DBF
|
|
239
237
|
columns
|
240
238
|
end
|
241
239
|
|
242
|
-
|
243
|
-
def foxpro? #nodoc
|
240
|
+
def foxpro? # nodoc
|
244
241
|
FOXPRO_VERSIONS.keys.include? version
|
245
242
|
end
|
246
243
|
|
247
|
-
def column_class #nodoc
|
244
|
+
def column_class # nodoc
|
248
245
|
@column_class ||= foxpro? ? Column::Foxpro : Column::Dbase
|
249
246
|
end
|
250
247
|
|
251
|
-
def memo_class #nodoc
|
248
|
+
def memo_class # nodoc
|
252
249
|
@memo_class ||= if foxpro?
|
253
250
|
Memo::Foxpro
|
254
251
|
else
|
255
|
-
|
256
|
-
Memo::Dbase3
|
257
|
-
else
|
258
|
-
Memo::Dbase4
|
259
|
-
end
|
252
|
+
version == '83' ? Memo::Dbase3 : Memo::Dbase4
|
260
253
|
end
|
261
254
|
end
|
262
255
|
|
263
|
-
def
|
264
|
-
@column_count ||= ((header.header_length - DBF_HEADER_SIZE + 1) / DBF_HEADER_SIZE).to_i
|
265
|
-
end
|
266
|
-
|
267
|
-
def open_data(data) #nodoc
|
256
|
+
def open_data(data) # nodoc
|
268
257
|
data.is_a?(StringIO) ? data : File.open(data, 'rb')
|
269
258
|
end
|
270
259
|
|
271
|
-
def open_memo(data, memo = nil) #nodoc
|
272
|
-
if memo
|
273
|
-
|
274
|
-
|
275
|
-
memo_class.open(memo, version)
|
260
|
+
def open_memo(data, memo = nil) # nodoc
|
261
|
+
if memo
|
262
|
+
meth = memo.is_a?(StringIO) ? :new : :open
|
263
|
+
memo_class.send(meth, memo, version)
|
276
264
|
elsif !data.is_a? StringIO
|
277
|
-
files = Dir.glob(memo_search_path
|
265
|
+
files = Dir.glob(memo_search_path data)
|
278
266
|
files.any? ? memo_class.open(files.first, version) : nil
|
279
|
-
else
|
280
|
-
nil
|
281
267
|
end
|
282
268
|
end
|
283
269
|
|
284
|
-
def memo_search_path(io) #nodoc
|
270
|
+
def memo_search_path(io) # nodoc
|
285
271
|
dirname = File.dirname(io)
|
286
272
|
basename = File.basename(io, '.*')
|
287
273
|
"#{dirname}/#{basename}*.{fpt,FPT,dbt,DBT}"
|
288
274
|
end
|
289
275
|
|
290
|
-
def find_all(options) #nodoc
|
276
|
+
def find_all(options) # nodoc
|
291
277
|
map do |record|
|
292
278
|
if record && record.match?(options)
|
293
279
|
yield record if block_given?
|
@@ -296,25 +282,24 @@ module DBF
|
|
296
282
|
end.compact
|
297
283
|
end
|
298
284
|
|
299
|
-
def find_first(options) #nodoc
|
300
|
-
detect {|record| record && record.match?(options)}
|
285
|
+
def find_first(options) # nodoc
|
286
|
+
detect { |record| record && record.match?(options) }
|
301
287
|
end
|
302
288
|
|
303
|
-
def deleted_record? #nodoc
|
289
|
+
def deleted_record? # nodoc
|
304
290
|
@data.read(1).unpack('a') == ['*']
|
305
291
|
end
|
306
292
|
|
307
|
-
def seek(offset) #nodoc
|
293
|
+
def seek(offset) # nodoc
|
308
294
|
@data.seek header.header_length + offset
|
309
295
|
end
|
310
296
|
|
311
|
-
def seek_to_record(index) #nodoc
|
297
|
+
def seek_to_record(index) # nodoc
|
312
298
|
seek(index * header.record_length)
|
313
299
|
end
|
314
300
|
|
315
|
-
def csv_class #nodoc
|
301
|
+
def csv_class # nodoc
|
316
302
|
@csv_class ||= CSV.const_defined?(:Reader) ? FCSV : CSV
|
317
303
|
end
|
318
304
|
end
|
319
|
-
|
320
305
|
end
|