rbase 0.1.2 → 0.1.3

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.
data/Rakefile CHANGED
@@ -7,11 +7,10 @@ desc 'Create a gem'
7
7
  task :gem do
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = 'rbase'
10
- s.version = '0.1.2'
10
+ s.version = '0.1.3'
11
11
  s.summary = 'Library to create/read/write to XBase databases (*.DBF files)'
12
12
  s.files = Dir.glob('**/*').delete_if { |item| item.include?('.svn') }
13
13
  s.require_path = 'lib'
14
- s.autorequire = 'rbase'
15
14
  s.authors = 'Maxim Kulkin, Leonardo Augusto Pires'
16
15
  s.email = 'maxim.kulkin@gmail.com, leonardo.pires@gmail.com'
17
16
  s.homepage = 'http://rbase.rubyforge.com/'
@@ -21,6 +20,5 @@ task :gem do
21
20
  s.required_ruby_version = '>= 1.8.2'
22
21
  end
23
22
 
24
- Gem.manage_gems
25
23
  Gem::Builder.new(spec).build
26
24
  end
@@ -1,5 +1,7 @@
1
1
  module RBase
2
2
  module Columns
3
+
4
+ require 'iconv'
3
5
 
4
6
  # Base class for all column types
5
7
  class Column
@@ -57,6 +59,10 @@ module RBase
57
59
  def unpack(value)
58
60
  throw "Not implemented"
59
61
  end
62
+
63
+ def inspect
64
+ "#{name}(type=#{type}, size=#{size})"
65
+ end
60
66
 
61
67
  protected
62
68
 
@@ -77,14 +83,27 @@ module RBase
77
83
  end
78
84
 
79
85
  super name, options.merge(:size => size)
86
+
87
+ if options[:encoding]
88
+ @unpack_converter = Iconv.new('utf-8', options[:encoding])
89
+ @pack_converter = Iconv.new(options[:encoding], 'utf-8')
90
+ end
80
91
  end
81
92
 
82
93
  def pack(value)
94
+ value = value.to_s
95
+ value = @pack_converter.iconv(value) if @pack_converter
83
96
  [value].pack("A#{size}")
84
97
  end
85
98
 
86
99
  def unpack(data)
87
- data.rstrip
100
+ value = data.rstrip
101
+ value = @unpack_converter.iconv(value) if @unpack_converter
102
+ value
103
+ end
104
+
105
+ def inspect
106
+ "#{name}(string #{size})"
88
107
  end
89
108
  end
90
109
 
@@ -100,17 +119,33 @@ module RBase
100
119
  end
101
120
 
102
121
  def pack(value)
103
- if decimal && decimal!=0
104
- [format("%-#{size-decimal-1}.#{decimal}f", value)].pack("A#{size}")
122
+ if value
123
+ if float?
124
+ [format("%#{size-decimal-1}.#{decimal}f", value)].pack("A#{size}")
125
+ else
126
+ [format("%#{size}d", value)].pack("A#{size}")
127
+ end
105
128
  else
106
- [format("%-#{size}d", value)].pack("A#{size}")
129
+ " "*size
107
130
  end
108
131
  end
109
132
 
110
133
  def unpack(data)
111
- return nil if data.rstrip == ''
134
+ return nil if data.strip == ''
112
135
  data.rstrip.to_i
113
136
  end
137
+
138
+ def inspect
139
+ if float?
140
+ "#{name}(decimal)"
141
+ else
142
+ "#{name}(integer)"
143
+ end
144
+ end
145
+
146
+ def float?
147
+ decimal && decimal != 0
148
+ end
114
149
  end
115
150
 
116
151
 
@@ -139,6 +174,10 @@ module RBase
139
174
  nil
140
175
  end
141
176
  end
177
+
178
+ def inspect
179
+ "#{name}(boolean)"
180
+ end
142
181
  end
143
182
 
144
183
 
@@ -157,6 +196,10 @@ module RBase
157
196
  return nil if data.rstrip == ''
158
197
  Date.new(*data.unpack("a4a2a2").map { |s| s.to_i})
159
198
  end
199
+
200
+ def inspect
201
+ "#{name}(date)"
202
+ end
160
203
  end
161
204
 
162
205
 
@@ -175,6 +218,10 @@ module RBase
175
218
  def unpack(data)
176
219
  table.memo.read(data.to_i)
177
220
  end
221
+
222
+ def inspect
223
+ "#{name}(memo)"
224
+ end
178
225
  end
179
226
 
180
227
 
@@ -190,12 +237,16 @@ module RBase
190
237
  end
191
238
 
192
239
  def pack(value)
193
- [format("%-#{size-decimal-1}.#{decimal}f", value)].pack("A#{size}")
240
+ [format("%-#{size-decimal-1}.#{decimal}f", value || 0.0)].pack("A#{size}")
194
241
  end
195
242
 
196
243
  def unpack(data)
197
244
  data.rstrip.to_f
198
245
  end
246
+
247
+ def inspect
248
+ "#{name}(float)"
249
+ end
199
250
  end
200
251
 
201
252
  end
@@ -1,7 +1,8 @@
1
1
  module RBase
2
- class Error < Exception; end
3
2
 
4
- class UnknownColumnError < RBase::Error
3
+ class StandardError < Exception; end
4
+
5
+ class UnknownColumnError < StandardError
5
6
  attr_reader :name
6
7
 
7
8
  def initialize(name)
@@ -10,6 +11,15 @@ module RBase
10
11
  end
11
12
  end
12
13
 
14
+ class InvalidValueError < StandardError
15
+ attr_reader :column, :value
16
+
17
+ def initialize(column, value)
18
+ super("Invalid value #{value.inspect} for column #{column.inspect}")
19
+ @column, @value = column, value
20
+ end
21
+ end
22
+
13
23
  # Class that contains data for particular table row.
14
24
  # Should not be created explicitly (use Table#create to create records)
15
25
  #
@@ -68,7 +78,7 @@ module RBase
68
78
  @deleted ||= new_record? ? false : @data[0, 1] == '*'
69
79
  end
70
80
 
71
- # Returns cloned copy of current record
81
+ # Clone record.
72
82
  def clone
73
83
  c = self.class.new(@table, @values_changed)
74
84
  c.instance_variable_set("@values_cached", @values_cached)
@@ -95,7 +105,12 @@ module RBase
95
105
  @data[0, 1] = deleted? ? '*' : ' '
96
106
  @values_changed.each do |k, v|
97
107
  column = @table.column(k)
98
- @data[column.offset, column.size] = column.pack(v)
108
+ raise UnknownColumnError.new(k) unless column
109
+ begin
110
+ @data[column.offset, column.size] = column.pack(v)
111
+ rescue Object => e
112
+ raise InvalidValueError.new(column, v)
113
+ end
99
114
  @values_cached[k] = v
100
115
  end
101
116
  end
@@ -117,6 +132,7 @@ module RBase
117
132
  # Sets value of specified column.
118
133
  def set_value(name, value)
119
134
  name = name.to_s.upcase.to_sym
135
+ raise UnknownColumnError.new(name) unless @table.column(name)
120
136
  @values_changed[name] = value
121
137
  end
122
138
  end
@@ -3,6 +3,8 @@ module RBase
3
3
  class Table
4
4
  private_class_method :new
5
5
 
6
+ include Enumerable
7
+
6
8
  # Create new XBase table file. Table file name will be equal to name with ".dbf" suffix.
7
9
  #
8
10
  # Allowed options
@@ -58,9 +60,9 @@ module RBase
58
60
 
59
61
  # Open table with given name.
60
62
  # Table name should be like file name without ".dbf" suffix.
61
- def self.open(name)
63
+ def self.open(name, options = {})
62
64
  table = new
63
- table.instance_eval { open("#{name}.dbf") }
65
+ table.instance_eval { open("#{name}.dbf", options) }
64
66
  if block_given?
65
67
  result = yield table
66
68
  table.close
@@ -94,6 +96,16 @@ module RBase
94
96
  update_header
95
97
  end
96
98
 
99
+ def clear
100
+ file_end = @record_offset
101
+ @file.pos = file_end
102
+ @file.write "\x1a"
103
+ @file.truncate file_end+1
104
+
105
+ self.count = 0
106
+ update_header
107
+ end
108
+
97
109
  def close
98
110
  @file.close
99
111
  end
@@ -158,7 +170,7 @@ module RBase
158
170
 
159
171
  private
160
172
 
161
- def open(name)
173
+ def open(name, options = {})
162
174
  @name = File.basename(name, '.dbf')
163
175
  @file = File.open(name, "r+b")
164
176
  header = @file.read(32)
@@ -177,12 +189,14 @@ module RBase
177
189
 
178
190
  @columns = []
179
191
  @name_to_columns = {}
192
+ column_options = {}
193
+ column_options[:encoding] = options[:encoding] if options[:encoding]
180
194
  while true do
181
195
  column_data = @file.read(32)
182
196
  break if column_data[0, 1] == "\x0d"
183
197
  name, type, offset, size, decimal = *column_data.unpack('@0a11aLCC')
184
198
  name = name.strip
185
- @columns << Columns::Column.column_for(type).new(name, :offset => offset, :size => size, :decimal => decimal)
199
+ @columns << Columns::Column.column_for(type).new(name, options.merge(:offset => offset, :size => size, :decimal => decimal))
186
200
  @name_to_columns[name.upcase.to_sym] = @columns.last
187
201
  end
188
202
 
@@ -196,7 +210,8 @@ module RBase
196
210
  @file.pos = @record_offset + @record_size*count
197
211
  @file.write record.serialize
198
212
  @file.write [26].pack('c')
199
- self.count += 1
213
+ record.instance_variable_set(:@index, count)
214
+ self.count += 1
200
215
  else
201
216
  throw "Index out of bound" if record.index>=count
202
217
  @file.pos = @record_offset + @record_size*record.index
metadata CHANGED
@@ -1,56 +1,64 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.2
3
- specification_version: 1
4
2
  name: rbase
5
3
  version: !ruby/object:Gem::Version
6
- version: 0.1.2
7
- date: 2007-05-30 00:00:00 +04:00
8
- summary: Library to create/read/write to XBase databases (*.DBF files)
9
- require_paths:
10
- - lib
11
- email: maxim.kulkin@gmail.com, leonardo.pires@gmail.com
12
- homepage: http://rbase.rubyforge.com/
13
- rubyforge_project: rbase
14
- description:
15
- autorequire: rbase
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 1.8.2
24
- version:
4
+ version: 0.1.3
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
7
  - Maxim Kulkin, Leonardo Augusto Pires
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-28 00:00:00 +04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: maxim.kulkin@gmail.com, leonardo.pires@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
31
24
  files:
32
- - lib
33
- - Rakefile
34
- - lib/rbase
35
- - lib/rbase.rb
36
- - lib/rbase/record.rb
37
- - lib/rbase/columns.rb
38
- - lib/rbase/schema.rb
39
25
  - lib/rbase/builder.rb
40
- - lib/rbase/table.rb
26
+ - lib/rbase/columns.rb
41
27
  - lib/rbase/memo_file.rb
28
+ - lib/rbase/record.rb
29
+ - lib/rbase/schema.rb
42
30
  - lib/rbase/schema_dumper.rb
43
- test_files: []
31
+ - lib/rbase/table.rb
32
+ - lib/rbase.rb
33
+ - Rakefile
34
+ - rbase-0.1.3.gem
35
+ has_rdoc: true
36
+ homepage: http://rbase.rubyforge.com/
37
+ licenses: []
44
38
 
39
+ post_install_message:
45
40
  rdoc_options: []
46
41
 
47
- extra_rdoc_files: []
48
-
49
- executables: []
50
-
51
- extensions: []
52
-
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 1.8.2
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
53
56
  requirements: []
54
57
 
55
- dependencies: []
58
+ rubyforge_project: rbase
59
+ rubygems_version: 1.3.2
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Library to create/read/write to XBase databases (*.DBF files)
63
+ test_files: []
56
64