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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +19 -9
  4. data/bin/dbf +2 -54
  5. data/dbf.gemspec +6 -9
  6. data/lib/dbf/cli.rb +95 -0
  7. data/lib/dbf/column.rb +17 -15
  8. data/lib/dbf/column_builder.rb +31 -0
  9. data/lib/dbf/column_type.rb +66 -16
  10. data/lib/dbf/database/foxpro.rb +19 -32
  11. data/lib/dbf/encoder.rb +116 -0
  12. data/lib/dbf/encodings.rb +8 -0
  13. data/lib/dbf/file_handler.rb +36 -0
  14. data/lib/dbf/find.rb +54 -0
  15. data/lib/dbf/header.rb +5 -8
  16. data/lib/dbf/memo/base.rb +2 -0
  17. data/lib/dbf/memo/dbase3.rb +2 -2
  18. data/lib/dbf/memo/dbase4.rb +2 -2
  19. data/lib/dbf/memo/foxpro.rb +14 -7
  20. data/lib/dbf/record.rb +60 -34
  21. data/lib/dbf/record_context.rb +5 -0
  22. data/lib/dbf/record_iterator.rb +35 -0
  23. data/lib/dbf/schema.rb +21 -21
  24. data/lib/dbf/table.rb +50 -181
  25. data/lib/dbf/version.rb +1 -1
  26. data/lib/dbf/version_config.rb +79 -0
  27. data/lib/dbf.rb +8 -0
  28. metadata +17 -64
  29. data/spec/dbf/column_spec.rb +0 -287
  30. data/spec/dbf/database/foxpro_spec.rb +0 -53
  31. data/spec/dbf/encoding_spec.rb +0 -49
  32. data/spec/dbf/file_formats_spec.rb +0 -221
  33. data/spec/dbf/record_spec.rb +0 -116
  34. data/spec/dbf/table_spec.rb +0 -377
  35. data/spec/fixtures/cp1251.dbf +0 -0
  36. data/spec/fixtures/cp1251_summary.txt +0 -12
  37. data/spec/fixtures/dbase_02.dbf +0 -0
  38. data/spec/fixtures/dbase_02_summary.txt +0 -23
  39. data/spec/fixtures/dbase_03.dbf +0 -0
  40. data/spec/fixtures/dbase_03_cyrillic.dbf +0 -0
  41. data/spec/fixtures/dbase_03_cyrillic_summary.txt +0 -11
  42. data/spec/fixtures/dbase_03_summary.txt +0 -40
  43. data/spec/fixtures/dbase_30.dbf +0 -0
  44. data/spec/fixtures/dbase_30.fpt +0 -0
  45. data/spec/fixtures/dbase_30_summary.txt +0 -154
  46. data/spec/fixtures/dbase_31.dbf +0 -0
  47. data/spec/fixtures/dbase_31_summary.txt +0 -20
  48. data/spec/fixtures/dbase_32.dbf +0 -0
  49. data/spec/fixtures/dbase_32_summary.txt +0 -11
  50. data/spec/fixtures/dbase_83.dbf +0 -0
  51. data/spec/fixtures/dbase_83.dbt +0 -0
  52. data/spec/fixtures/dbase_83_missing_memo.dbf +0 -0
  53. data/spec/fixtures/dbase_83_missing_memo_record_0.yml +0 -16
  54. data/spec/fixtures/dbase_83_record_0.yml +0 -16
  55. data/spec/fixtures/dbase_83_record_9.yml +0 -23
  56. data/spec/fixtures/dbase_83_schema_ar.txt +0 -19
  57. data/spec/fixtures/dbase_83_schema_sq.txt +0 -21
  58. data/spec/fixtures/dbase_83_schema_sq_lim.txt +0 -21
  59. data/spec/fixtures/dbase_83_summary.txt +0 -24
  60. data/spec/fixtures/dbase_8b.dbf +0 -0
  61. data/spec/fixtures/dbase_8b.dbt +0 -0
  62. data/spec/fixtures/dbase_8b_summary.txt +0 -15
  63. data/spec/fixtures/dbase_8c.dbf +0 -0
  64. data/spec/fixtures/dbase_f5.dbf +0 -0
  65. data/spec/fixtures/dbase_f5.fpt +0 -0
  66. data/spec/fixtures/dbase_f5_summary.txt +0 -68
  67. data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DBC +0 -0
  68. data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DCT +0 -0
  69. data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DCX +0 -0
  70. data/spec/fixtures/foxprodb/calls.CDX +0 -0
  71. data/spec/fixtures/foxprodb/calls.FPT +0 -0
  72. data/spec/fixtures/foxprodb/calls.dbf +0 -0
  73. data/spec/fixtures/foxprodb/contacts.CDX +0 -0
  74. data/spec/fixtures/foxprodb/contacts.FPT +0 -0
  75. data/spec/fixtures/foxprodb/contacts.dbf +0 -0
  76. data/spec/fixtures/foxprodb/setup.CDX +0 -0
  77. data/spec/fixtures/foxprodb/setup.dbf +0 -0
  78. data/spec/fixtures/foxprodb/types.CDX +0 -0
  79. data/spec/fixtures/foxprodb/types.dbf +0 -0
  80. data/spec/fixtures/polygon.dbf +0 -0
  81. 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
- DBASE2_HEADER_SIZE = 8
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
- @encoding = encoding || header.encoding || Encoding.default_external
82
- @memo = open_memo(data, memo)
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
- if @memo
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
- record_count.times { |i| yield record(i) }
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
- return unless @data.respond_to?(:path)
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, columns, version, @memo)
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 Defaults to STDOUT
202
- def to_csv(path = nil)
203
- out_io = path ? File.open(path, 'w') : $stdout
204
- csv = CSV.new(out_io, force_quotes: true)
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
- VERSIONS[version]
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
- string.force_encoding(@encoding).encode(Encoding.default_external, undef: :replace, invalid: :replace)
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 build_columns # :nodoc:
234
- safe_seek do
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 header_size
254
- case version
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 deleted_record? # :nodoc:
265
- flag = @data.read(1)
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 foxpro? # :nodoc:
287
- FOXPRO_VERSIONS.key?(version)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DBF
4
- VERSION = '5.1.1'.freeze
4
+ VERSION = '5.3.0'
5
5
  end
@@ -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.1.1
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
- - spec/dbf/column_spec.rb
57
- - spec/dbf/database/foxpro_spec.rb
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
- rdoc_options:
115
- - "--charset=UTF-8"
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.1.0
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: 3.2.3
80
+ version: '0'
128
81
  requirements: []
129
- rubygems_version: 3.6.7
82
+ rubygems_version: 4.0.10
130
83
  specification_version: 4
131
84
  summary: Read xBase files
132
85
  test_files: []