dbf 5.1.1 → 5.3.0
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 +13 -0
- data/README.md +19 -9
- data/bin/dbf +2 -54
- data/dbf.gemspec +6 -9
- data/lib/dbf/cli.rb +95 -0
- data/lib/dbf/column.rb +17 -15
- data/lib/dbf/column_builder.rb +31 -0
- data/lib/dbf/column_type.rb +66 -16
- data/lib/dbf/database/foxpro.rb +19 -32
- data/lib/dbf/encoder.rb +116 -0
- data/lib/dbf/encodings.rb +8 -0
- data/lib/dbf/file_handler.rb +36 -0
- data/lib/dbf/find.rb +54 -0
- data/lib/dbf/header.rb +5 -8
- data/lib/dbf/memo/base.rb +2 -0
- data/lib/dbf/memo/dbase3.rb +2 -2
- data/lib/dbf/memo/dbase4.rb +2 -2
- data/lib/dbf/memo/foxpro.rb +14 -7
- data/lib/dbf/record.rb +60 -34
- data/lib/dbf/record_context.rb +5 -0
- data/lib/dbf/record_iterator.rb +35 -0
- data/lib/dbf/schema.rb +21 -21
- data/lib/dbf/table.rb +50 -181
- data/lib/dbf/version.rb +1 -1
- data/lib/dbf/version_config.rb +79 -0
- data/lib/dbf.rb +8 -0
- metadata +17 -64
- data/spec/dbf/column_spec.rb +0 -287
- data/spec/dbf/database/foxpro_spec.rb +0 -53
- data/spec/dbf/encoding_spec.rb +0 -49
- data/spec/dbf/file_formats_spec.rb +0 -221
- data/spec/dbf/record_spec.rb +0 -116
- data/spec/dbf/table_spec.rb +0 -377
- data/spec/fixtures/cp1251.dbf +0 -0
- data/spec/fixtures/cp1251_summary.txt +0 -12
- data/spec/fixtures/dbase_02.dbf +0 -0
- data/spec/fixtures/dbase_02_summary.txt +0 -23
- data/spec/fixtures/dbase_03.dbf +0 -0
- data/spec/fixtures/dbase_03_cyrillic.dbf +0 -0
- data/spec/fixtures/dbase_03_cyrillic_summary.txt +0 -11
- data/spec/fixtures/dbase_03_summary.txt +0 -40
- data/spec/fixtures/dbase_30.dbf +0 -0
- data/spec/fixtures/dbase_30.fpt +0 -0
- data/spec/fixtures/dbase_30_summary.txt +0 -154
- data/spec/fixtures/dbase_31.dbf +0 -0
- data/spec/fixtures/dbase_31_summary.txt +0 -20
- data/spec/fixtures/dbase_32.dbf +0 -0
- data/spec/fixtures/dbase_32_summary.txt +0 -11
- data/spec/fixtures/dbase_83.dbf +0 -0
- data/spec/fixtures/dbase_83.dbt +0 -0
- data/spec/fixtures/dbase_83_missing_memo.dbf +0 -0
- data/spec/fixtures/dbase_83_missing_memo_record_0.yml +0 -16
- data/spec/fixtures/dbase_83_record_0.yml +0 -16
- data/spec/fixtures/dbase_83_record_9.yml +0 -23
- data/spec/fixtures/dbase_83_schema_ar.txt +0 -19
- data/spec/fixtures/dbase_83_schema_sq.txt +0 -21
- data/spec/fixtures/dbase_83_schema_sq_lim.txt +0 -21
- data/spec/fixtures/dbase_83_summary.txt +0 -24
- data/spec/fixtures/dbase_8b.dbf +0 -0
- data/spec/fixtures/dbase_8b.dbt +0 -0
- data/spec/fixtures/dbase_8b_summary.txt +0 -15
- data/spec/fixtures/dbase_8c.dbf +0 -0
- data/spec/fixtures/dbase_f5.dbf +0 -0
- data/spec/fixtures/dbase_f5.fpt +0 -0
- data/spec/fixtures/dbase_f5_summary.txt +0 -68
- data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DBC +0 -0
- data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DCT +0 -0
- data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DCX +0 -0
- data/spec/fixtures/foxprodb/calls.CDX +0 -0
- data/spec/fixtures/foxprodb/calls.FPT +0 -0
- data/spec/fixtures/foxprodb/calls.dbf +0 -0
- data/spec/fixtures/foxprodb/contacts.CDX +0 -0
- data/spec/fixtures/foxprodb/contacts.FPT +0 -0
- data/spec/fixtures/foxprodb/contacts.dbf +0 -0
- data/spec/fixtures/foxprodb/setup.CDX +0 -0
- data/spec/fixtures/foxprodb/setup.dbf +0 -0
- data/spec/fixtures/foxprodb/types.CDX +0 -0
- data/spec/fixtures/foxprodb/types.dbf +0 -0
- data/spec/fixtures/polygon.dbf +0 -0
- data/spec/spec_helper.rb +0 -35
data/lib/dbf/table.rb
CHANGED
|
@@ -13,42 +13,9 @@ module DBF
|
|
|
13
13
|
extend Forwardable
|
|
14
14
|
include Enumerable
|
|
15
15
|
include ::DBF::Schema
|
|
16
|
+
include ::DBF::Find
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
DBASE3_HEADER_SIZE = 32
|
|
19
|
-
DBASE7_HEADER_SIZE = 68
|
|
20
|
-
|
|
21
|
-
VERSIONS = {
|
|
22
|
-
'02' => 'FoxBase',
|
|
23
|
-
'03' => 'dBase III without memo file',
|
|
24
|
-
'04' => 'dBase IV without memo file',
|
|
25
|
-
'05' => 'dBase V without memo file',
|
|
26
|
-
'07' => 'Visual Objects 1.x',
|
|
27
|
-
'30' => 'Visual FoxPro',
|
|
28
|
-
'32' => 'Visual FoxPro with field type Varchar or Varbinary',
|
|
29
|
-
'31' => 'Visual FoxPro with AutoIncrement field',
|
|
30
|
-
'43' => 'dBASE IV SQL table files, no memo',
|
|
31
|
-
'63' => 'dBASE IV SQL system files, no memo',
|
|
32
|
-
'7b' => 'dBase IV with memo file',
|
|
33
|
-
'83' => 'dBase III with memo file',
|
|
34
|
-
'87' => 'Visual Objects 1.x with memo file',
|
|
35
|
-
'8b' => 'dBase IV with memo file',
|
|
36
|
-
'8c' => 'dBase 7',
|
|
37
|
-
'8e' => 'dBase IV with SQL table',
|
|
38
|
-
'cb' => 'dBASE IV SQL table files, with memo',
|
|
39
|
-
'f5' => 'FoxPro with memo file',
|
|
40
|
-
'fb' => 'FoxPro without memo file'
|
|
41
|
-
}.freeze
|
|
42
|
-
|
|
43
|
-
FOXPRO_VERSIONS = {
|
|
44
|
-
'30' => 'Visual FoxPro',
|
|
45
|
-
'31' => 'Visual FoxPro with AutoIncrement field',
|
|
46
|
-
'f5' => 'FoxPro with memo file',
|
|
47
|
-
'fb' => 'FoxPro without memo file'
|
|
48
|
-
}.freeze
|
|
49
|
-
|
|
50
|
-
attr_accessor :encoding
|
|
51
|
-
attr_writer :name
|
|
18
|
+
attr_reader :encoding
|
|
52
19
|
|
|
53
20
|
def_delegator :header, :header_length
|
|
54
21
|
def_delegator :header, :record_count
|
|
@@ -76,10 +43,12 @@ module DBF
|
|
|
76
43
|
# @param data [String, StringIO] data Path to the dbf file or a StringIO object
|
|
77
44
|
# @param memo [optional String, StringIO] memo Path to the memo file or a StringIO object
|
|
78
45
|
# @param encoding [optional String, Encoding] encoding Name of the encoding or an Encoding object
|
|
79
|
-
def initialize(data, memo = nil, encoding = nil)
|
|
80
|
-
@data = open_data(data)
|
|
81
|
-
@
|
|
82
|
-
@
|
|
46
|
+
def initialize(data, memo = nil, encoding = nil, name: nil)
|
|
47
|
+
@data = FileHandler.open_data(data)
|
|
48
|
+
@user_encoding = encoding
|
|
49
|
+
@encoding = determine_encoding
|
|
50
|
+
@memo = FileHandler.open_memo(data, memo, version_config.memo_class, version)
|
|
51
|
+
@name = name
|
|
83
52
|
yield self if block_given?
|
|
84
53
|
end
|
|
85
54
|
|
|
@@ -93,11 +62,7 @@ module DBF
|
|
|
93
62
|
|
|
94
63
|
# @return [TrueClass, FalseClass]
|
|
95
64
|
def closed?
|
|
96
|
-
|
|
97
|
-
@data.closed? && @memo.closed?
|
|
98
|
-
else
|
|
99
|
-
@data.closed?
|
|
100
|
-
end
|
|
65
|
+
@data.closed? && (!@memo || @memo.closed?)
|
|
101
66
|
end
|
|
102
67
|
|
|
103
68
|
# Column names
|
|
@@ -107,6 +72,20 @@ module DBF
|
|
|
107
72
|
@column_names ||= columns.map(&:name)
|
|
108
73
|
end
|
|
109
74
|
|
|
75
|
+
# Cumulative byte offsets for each column within a record
|
|
76
|
+
#
|
|
77
|
+
# @return [Array<Integer>]
|
|
78
|
+
def column_offsets
|
|
79
|
+
@column_offsets ||= begin
|
|
80
|
+
sum = 0
|
|
81
|
+
columns.map { |col| sum.tap { sum += col.length } }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def record_context
|
|
86
|
+
@record_context ||= RecordContext.new(columns:, version:, memo: @memo, column_offsets:)
|
|
87
|
+
end
|
|
88
|
+
|
|
110
89
|
# All columns
|
|
111
90
|
#
|
|
112
91
|
# @return [Array]
|
|
@@ -118,53 +97,16 @@ module DBF
|
|
|
118
97
|
# if the record has been marked as deleted.
|
|
119
98
|
#
|
|
120
99
|
# @yield [nil, DBF::Record]
|
|
121
|
-
def each
|
|
122
|
-
|
|
100
|
+
def each(&)
|
|
101
|
+
return enum_for(:each) unless block_given?
|
|
102
|
+
return if columns.empty?
|
|
103
|
+
|
|
104
|
+
RecordIterator.new(@data, record_context, header_length, record_length, record_count).each(&)
|
|
123
105
|
end
|
|
124
106
|
|
|
125
107
|
# @return [String]
|
|
126
108
|
def filename
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
File.basename(@data.path)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# Find records using a simple ActiveRecord-like syntax.
|
|
133
|
-
#
|
|
134
|
-
# Examples:
|
|
135
|
-
# table = DBF::Table.new 'mydata.dbf'
|
|
136
|
-
#
|
|
137
|
-
# # Find record number 5
|
|
138
|
-
# table.find(5)
|
|
139
|
-
#
|
|
140
|
-
# # Find all records for Keith Morrison
|
|
141
|
-
# table.find :all, first_name: "Keith", last_name: "Morrison"
|
|
142
|
-
#
|
|
143
|
-
# # Find first record
|
|
144
|
-
# table.find :first, first_name: "Keith"
|
|
145
|
-
#
|
|
146
|
-
# The <b>command</b> may be a record index, :all, or :first.
|
|
147
|
-
# <b>options</b> is optional and, if specified, should be a hash where the
|
|
148
|
-
# keys correspond to column names in the database. The values will be
|
|
149
|
-
# matched exactly with the value in the database. If you specify more
|
|
150
|
-
# than one key, all values must match in order for the record to be
|
|
151
|
-
# returned. The equivalent SQL would be "WHERE key1 = 'value1'
|
|
152
|
-
# AND key2 = 'value2'".
|
|
153
|
-
#
|
|
154
|
-
# @param command [Integer, Symbol] command
|
|
155
|
-
# @param options [optional, Hash] options Hash of search parameters
|
|
156
|
-
# @yield [optional, DBF::Record, NilClass]
|
|
157
|
-
def find(command, options = {}, &block)
|
|
158
|
-
case command
|
|
159
|
-
when Integer
|
|
160
|
-
record(command)
|
|
161
|
-
when Array
|
|
162
|
-
command.map { |i| record(i) }
|
|
163
|
-
when :all
|
|
164
|
-
find_all(options, &block)
|
|
165
|
-
when :first
|
|
166
|
-
find_first(options)
|
|
167
|
-
end
|
|
109
|
+
File.basename(@data.path) if @data.is_a?(File)
|
|
168
110
|
end
|
|
169
111
|
|
|
170
112
|
# @return [TrueClass, FalseClass]
|
|
@@ -190,7 +132,7 @@ module DBF
|
|
|
190
132
|
return nil if deleted_record?
|
|
191
133
|
|
|
192
134
|
record_data = @data.read(record_length)
|
|
193
|
-
DBF::Record.new(record_data,
|
|
135
|
+
DBF::Record.new(record_data, record_context)
|
|
194
136
|
end
|
|
195
137
|
|
|
196
138
|
alias row record
|
|
@@ -198,10 +140,14 @@ module DBF
|
|
|
198
140
|
# Dumps all records to a CSV file. If no filename is given then CSV is
|
|
199
141
|
# output to STDOUT.
|
|
200
142
|
#
|
|
201
|
-
# @param [optional String] path
|
|
202
|
-
def to_csv(
|
|
203
|
-
|
|
204
|
-
|
|
143
|
+
# @param [optional String, IO] path_or_io String path, IO-like object, or nil for STDOUT
|
|
144
|
+
def to_csv(path_or_io = nil)
|
|
145
|
+
io = case path_or_io
|
|
146
|
+
when nil then $stdout
|
|
147
|
+
when String then File.open(path_or_io, 'w')
|
|
148
|
+
else path_or_io
|
|
149
|
+
end
|
|
150
|
+
csv = CSV.new(io, force_quotes: true)
|
|
205
151
|
csv << column_names
|
|
206
152
|
each { |record| csv << record.to_a }
|
|
207
153
|
end
|
|
@@ -210,7 +156,7 @@ module DBF
|
|
|
210
156
|
#
|
|
211
157
|
# @return [String]
|
|
212
158
|
def version_description
|
|
213
|
-
|
|
159
|
+
version_config.version_description
|
|
214
160
|
end
|
|
215
161
|
|
|
216
162
|
# Encode string
|
|
@@ -218,7 +164,7 @@ module DBF
|
|
|
218
164
|
# @param [String] string
|
|
219
165
|
# @return [String]
|
|
220
166
|
def encode_string(string) # :nodoc:
|
|
221
|
-
|
|
167
|
+
Encoder.encode(string, @encoding)
|
|
222
168
|
end
|
|
223
169
|
|
|
224
170
|
# Encoding specified in the file header
|
|
@@ -230,104 +176,27 @@ module DBF
|
|
|
230
176
|
|
|
231
177
|
private
|
|
232
178
|
|
|
233
|
-
def
|
|
234
|
-
|
|
235
|
-
@data.seek(header_size)
|
|
236
|
-
[].tap do |columns|
|
|
237
|
-
until end_of_record?
|
|
238
|
-
args = case version
|
|
239
|
-
when '02'
|
|
240
|
-
[self, *@data.read(header_size * 2).unpack('A11 a C'), 0]
|
|
241
|
-
when '04', '8c'
|
|
242
|
-
[self, *@data.read(48).unpack('A32 a C C x13')]
|
|
243
|
-
else
|
|
244
|
-
[self, *@data.read(header_size).unpack('A11 a x4 C2')]
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
columns << Column.new(*args)
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
end
|
|
179
|
+
def version_config
|
|
180
|
+
@version_config ||= VersionConfig.new(version)
|
|
251
181
|
end
|
|
252
182
|
|
|
253
|
-
def
|
|
254
|
-
|
|
255
|
-
when '02'
|
|
256
|
-
DBASE2_HEADER_SIZE
|
|
257
|
-
when '04', '8c'
|
|
258
|
-
DBASE7_HEADER_SIZE
|
|
259
|
-
else
|
|
260
|
-
DBASE3_HEADER_SIZE
|
|
261
|
-
end
|
|
183
|
+
def determine_encoding
|
|
184
|
+
@user_encoding || header.encoding || Encoding.default_external
|
|
262
185
|
end
|
|
263
186
|
|
|
264
|
-
def
|
|
265
|
-
|
|
266
|
-
flag ? flag.unpack1('a') == '*' : true
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
def end_of_record? # :nodoc:
|
|
270
|
-
safe_seek { @data.read(1).ord == 13 }
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
def find_all(options) # :nodoc:
|
|
274
|
-
select do |record|
|
|
275
|
-
next unless record&.match?(options)
|
|
276
|
-
|
|
277
|
-
yield record if block_given?
|
|
278
|
-
record
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
def find_first(options) # :nodoc:
|
|
283
|
-
detect { |record| record&.match?(options) }
|
|
187
|
+
def build_columns # :nodoc:
|
|
188
|
+
ColumnBuilder.new(self, @data, version_config).build
|
|
284
189
|
end
|
|
285
190
|
|
|
286
|
-
def
|
|
287
|
-
|
|
191
|
+
def deleted_record? # :nodoc:
|
|
192
|
+
flag = @data.read(1)
|
|
193
|
+
flag ? flag.getbyte(0) == 0x2A : true
|
|
288
194
|
end
|
|
289
195
|
|
|
290
196
|
def header # :nodoc:
|
|
291
197
|
@header ||= safe_seek do
|
|
292
198
|
@data.seek(0)
|
|
293
|
-
Header.new(@data.read(DBASE3_HEADER_SIZE))
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
def memo_class # :nodoc:
|
|
298
|
-
@memo_class ||= if foxpro?
|
|
299
|
-
Memo::Foxpro
|
|
300
|
-
else
|
|
301
|
-
version == '83' ? Memo::Dbase3 : Memo::Dbase4
|
|
302
|
-
end
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
def memo_search_path(io) # :nodoc:
|
|
306
|
-
dirname = File.dirname(io)
|
|
307
|
-
basename = File.basename(io, '.*')
|
|
308
|
-
"#{dirname}/#{basename}*.{fpt,FPT,dbt,DBT}"
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
def open_data(data) # :nodoc:
|
|
312
|
-
case data
|
|
313
|
-
when StringIO
|
|
314
|
-
data
|
|
315
|
-
when String
|
|
316
|
-
File.open(data, 'rb')
|
|
317
|
-
else
|
|
318
|
-
raise ArgumentError, 'data must be a file path or StringIO object'
|
|
319
|
-
end
|
|
320
|
-
rescue Errno::ENOENT
|
|
321
|
-
raise DBF::FileNotFoundError, "file not found: #{data}"
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
def open_memo(data, memo = nil) # :nodoc:
|
|
325
|
-
if memo
|
|
326
|
-
meth = memo.is_a?(StringIO) ? :new : :open
|
|
327
|
-
memo_class.send(meth, memo, version)
|
|
328
|
-
elsif !data.is_a?(StringIO)
|
|
329
|
-
files = Dir.glob(memo_search_path(data))
|
|
330
|
-
files.any? ? memo_class.open(files.first, version) : nil
|
|
199
|
+
Header.new(@data.read(VersionConfig::DBASE3_HEADER_SIZE))
|
|
331
200
|
end
|
|
332
201
|
end
|
|
333
202
|
|
data/lib/dbf/version.rb
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DBF
|
|
4
|
+
class VersionConfig
|
|
5
|
+
DBASE2_HEADER_SIZE = 8
|
|
6
|
+
DBASE3_HEADER_SIZE = 32
|
|
7
|
+
DBASE7_HEADER_SIZE = 68
|
|
8
|
+
|
|
9
|
+
VERSIONS = {
|
|
10
|
+
'02' => 'FoxBase',
|
|
11
|
+
'03' => 'dBase III without memo file',
|
|
12
|
+
'04' => 'dBase IV without memo file',
|
|
13
|
+
'05' => 'dBase V without memo file',
|
|
14
|
+
'07' => 'Visual Objects 1.x',
|
|
15
|
+
'30' => 'Visual FoxPro',
|
|
16
|
+
'32' => 'Visual FoxPro with field type Varchar or Varbinary',
|
|
17
|
+
'31' => 'Visual FoxPro with AutoIncrement field',
|
|
18
|
+
'43' => 'dBASE IV SQL table files, no memo',
|
|
19
|
+
'63' => 'dBASE IV SQL system files, no memo',
|
|
20
|
+
'7b' => 'dBase IV with memo file',
|
|
21
|
+
'83' => 'dBase III with memo file',
|
|
22
|
+
'87' => 'Visual Objects 1.x with memo file',
|
|
23
|
+
'8b' => 'dBase IV with memo file',
|
|
24
|
+
'8c' => 'dBase 7',
|
|
25
|
+
'8e' => 'dBase IV with SQL table',
|
|
26
|
+
'cb' => 'dBASE IV SQL table files, with memo',
|
|
27
|
+
'f5' => 'FoxPro with memo file',
|
|
28
|
+
'fb' => 'FoxPro without memo file'
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
FOXPRO_VERSIONS = {
|
|
32
|
+
'30' => 'Visual FoxPro',
|
|
33
|
+
'31' => 'Visual FoxPro with AutoIncrement field',
|
|
34
|
+
'f5' => 'FoxPro with memo file',
|
|
35
|
+
'fb' => 'FoxPro without memo file'
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
attr_reader :version
|
|
39
|
+
|
|
40
|
+
def initialize(version)
|
|
41
|
+
@version = version
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def version_description
|
|
45
|
+
VERSIONS[version]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def header_size
|
|
49
|
+
case version
|
|
50
|
+
when '02'
|
|
51
|
+
DBASE2_HEADER_SIZE
|
|
52
|
+
when '04', '8c'
|
|
53
|
+
DBASE7_HEADER_SIZE
|
|
54
|
+
else
|
|
55
|
+
DBASE3_HEADER_SIZE
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def foxpro?
|
|
60
|
+
FOXPRO_VERSIONS.key?(version)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def memo_class
|
|
64
|
+
if foxpro?
|
|
65
|
+
Memo::Foxpro
|
|
66
|
+
else
|
|
67
|
+
version == '83' ? Memo::Dbase3 : Memo::Dbase4
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def read_column_args(table, io)
|
|
72
|
+
case version
|
|
73
|
+
when '02' then [table, *io.read(header_size * 2).unpack('A11 a C'), 0]
|
|
74
|
+
when '04', '8c' then [table, *io.read(48).unpack('A32 a C C x13')]
|
|
75
|
+
else [table, *io.read(header_size).unpack('A11 a x4 C2')]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/lib/dbf.rb
CHANGED
|
@@ -8,14 +8,22 @@ require 'time'
|
|
|
8
8
|
|
|
9
9
|
require 'dbf/version'
|
|
10
10
|
require 'dbf/schema'
|
|
11
|
+
require 'dbf/find'
|
|
11
12
|
require 'dbf/record'
|
|
13
|
+
require 'dbf/record_context'
|
|
12
14
|
require 'dbf/column_type'
|
|
13
15
|
require 'dbf/column'
|
|
14
16
|
require 'dbf/encodings'
|
|
17
|
+
require 'dbf/encoder'
|
|
15
18
|
require 'dbf/header'
|
|
19
|
+
require 'dbf/version_config'
|
|
20
|
+
require 'dbf/file_handler'
|
|
21
|
+
require 'dbf/column_builder'
|
|
22
|
+
require 'dbf/record_iterator'
|
|
16
23
|
require 'dbf/table'
|
|
17
24
|
require 'dbf/memo/base'
|
|
18
25
|
require 'dbf/memo/dbase3'
|
|
19
26
|
require 'dbf/memo/dbase4'
|
|
20
27
|
require 'dbf/memo/foxpro'
|
|
21
28
|
require 'dbf/database/foxpro'
|
|
29
|
+
require 'dbf/cli'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dbf
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Keith Morrison
|
|
@@ -29,10 +29,7 @@ email: keithm@infused.org
|
|
|
29
29
|
executables:
|
|
30
30
|
- dbf
|
|
31
31
|
extensions: []
|
|
32
|
-
extra_rdoc_files:
|
|
33
|
-
- CHANGELOG.md
|
|
34
|
-
- LICENSE
|
|
35
|
-
- README.md
|
|
32
|
+
extra_rdoc_files: []
|
|
36
33
|
files:
|
|
37
34
|
- CHANGELOG.md
|
|
38
35
|
- LICENSE
|
|
@@ -40,93 +37,49 @@ files:
|
|
|
40
37
|
- bin/dbf
|
|
41
38
|
- dbf.gemspec
|
|
42
39
|
- lib/dbf.rb
|
|
40
|
+
- lib/dbf/cli.rb
|
|
43
41
|
- lib/dbf/column.rb
|
|
42
|
+
- lib/dbf/column_builder.rb
|
|
44
43
|
- lib/dbf/column_type.rb
|
|
45
44
|
- lib/dbf/database/foxpro.rb
|
|
45
|
+
- lib/dbf/encoder.rb
|
|
46
46
|
- lib/dbf/encodings.rb
|
|
47
|
+
- lib/dbf/file_handler.rb
|
|
48
|
+
- lib/dbf/find.rb
|
|
47
49
|
- lib/dbf/header.rb
|
|
48
50
|
- lib/dbf/memo/base.rb
|
|
49
51
|
- lib/dbf/memo/dbase3.rb
|
|
50
52
|
- lib/dbf/memo/dbase4.rb
|
|
51
53
|
- lib/dbf/memo/foxpro.rb
|
|
52
54
|
- lib/dbf/record.rb
|
|
55
|
+
- lib/dbf/record_context.rb
|
|
56
|
+
- lib/dbf/record_iterator.rb
|
|
53
57
|
- lib/dbf/schema.rb
|
|
54
58
|
- lib/dbf/table.rb
|
|
55
59
|
- lib/dbf/version.rb
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
- spec/dbf/encoding_spec.rb
|
|
59
|
-
- spec/dbf/file_formats_spec.rb
|
|
60
|
-
- spec/dbf/record_spec.rb
|
|
61
|
-
- spec/dbf/table_spec.rb
|
|
62
|
-
- spec/fixtures/cp1251.dbf
|
|
63
|
-
- spec/fixtures/cp1251_summary.txt
|
|
64
|
-
- spec/fixtures/dbase_02.dbf
|
|
65
|
-
- spec/fixtures/dbase_02_summary.txt
|
|
66
|
-
- spec/fixtures/dbase_03.dbf
|
|
67
|
-
- spec/fixtures/dbase_03_cyrillic.dbf
|
|
68
|
-
- spec/fixtures/dbase_03_cyrillic_summary.txt
|
|
69
|
-
- spec/fixtures/dbase_03_summary.txt
|
|
70
|
-
- spec/fixtures/dbase_30.dbf
|
|
71
|
-
- spec/fixtures/dbase_30.fpt
|
|
72
|
-
- spec/fixtures/dbase_30_summary.txt
|
|
73
|
-
- spec/fixtures/dbase_31.dbf
|
|
74
|
-
- spec/fixtures/dbase_31_summary.txt
|
|
75
|
-
- spec/fixtures/dbase_32.dbf
|
|
76
|
-
- spec/fixtures/dbase_32_summary.txt
|
|
77
|
-
- spec/fixtures/dbase_83.dbf
|
|
78
|
-
- spec/fixtures/dbase_83.dbt
|
|
79
|
-
- spec/fixtures/dbase_83_missing_memo.dbf
|
|
80
|
-
- spec/fixtures/dbase_83_missing_memo_record_0.yml
|
|
81
|
-
- spec/fixtures/dbase_83_record_0.yml
|
|
82
|
-
- spec/fixtures/dbase_83_record_9.yml
|
|
83
|
-
- spec/fixtures/dbase_83_schema_ar.txt
|
|
84
|
-
- spec/fixtures/dbase_83_schema_sq.txt
|
|
85
|
-
- spec/fixtures/dbase_83_schema_sq_lim.txt
|
|
86
|
-
- spec/fixtures/dbase_83_summary.txt
|
|
87
|
-
- spec/fixtures/dbase_8b.dbf
|
|
88
|
-
- spec/fixtures/dbase_8b.dbt
|
|
89
|
-
- spec/fixtures/dbase_8b_summary.txt
|
|
90
|
-
- spec/fixtures/dbase_8c.dbf
|
|
91
|
-
- spec/fixtures/dbase_f5.dbf
|
|
92
|
-
- spec/fixtures/dbase_f5.fpt
|
|
93
|
-
- spec/fixtures/dbase_f5_summary.txt
|
|
94
|
-
- spec/fixtures/foxprodb/FOXPRO-DB-TEST.DBC
|
|
95
|
-
- spec/fixtures/foxprodb/FOXPRO-DB-TEST.DCT
|
|
96
|
-
- spec/fixtures/foxprodb/FOXPRO-DB-TEST.DCX
|
|
97
|
-
- spec/fixtures/foxprodb/calls.CDX
|
|
98
|
-
- spec/fixtures/foxprodb/calls.FPT
|
|
99
|
-
- spec/fixtures/foxprodb/calls.dbf
|
|
100
|
-
- spec/fixtures/foxprodb/contacts.CDX
|
|
101
|
-
- spec/fixtures/foxprodb/contacts.FPT
|
|
102
|
-
- spec/fixtures/foxprodb/contacts.dbf
|
|
103
|
-
- spec/fixtures/foxprodb/setup.CDX
|
|
104
|
-
- spec/fixtures/foxprodb/setup.dbf
|
|
105
|
-
- spec/fixtures/foxprodb/types.CDX
|
|
106
|
-
- spec/fixtures/foxprodb/types.dbf
|
|
107
|
-
- spec/fixtures/polygon.dbf
|
|
108
|
-
- spec/spec_helper.rb
|
|
109
|
-
homepage: http://github.com/infused/dbf
|
|
60
|
+
- lib/dbf/version_config.rb
|
|
61
|
+
homepage: https://github.com/infused/dbf
|
|
110
62
|
licenses:
|
|
111
63
|
- MIT
|
|
112
64
|
metadata:
|
|
113
65
|
rubygems_mfa_required: 'true'
|
|
114
|
-
|
|
115
|
-
|
|
66
|
+
source_code_uri: https://github.com/infused/dbf
|
|
67
|
+
changelog_uri: https://github.com/infused/dbf/blob/main/CHANGELOG.md
|
|
68
|
+
rdoc_options: []
|
|
116
69
|
require_paths:
|
|
117
70
|
- lib
|
|
118
71
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
72
|
requirements:
|
|
120
73
|
- - ">="
|
|
121
74
|
- !ruby/object:Gem::Version
|
|
122
|
-
version: 3.
|
|
75
|
+
version: 3.3.0
|
|
123
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
77
|
requirements:
|
|
125
78
|
- - ">="
|
|
126
79
|
- !ruby/object:Gem::Version
|
|
127
|
-
version:
|
|
80
|
+
version: '0'
|
|
128
81
|
requirements: []
|
|
129
|
-
rubygems_version:
|
|
82
|
+
rubygems_version: 4.0.10
|
|
130
83
|
specification_version: 4
|
|
131
84
|
summary: Read xBase files
|
|
132
85
|
test_files: []
|