databrick 0.1.1 → 0.2.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 (3) hide show
  1. data/databrick.rb +71 -8
  2. data/test.rb +15 -0
  3. metadata +4 -4
@@ -109,7 +109,9 @@ class DataBrick
109
109
 
110
110
  # returns a stringy representation of this DataBrick's unique content
111
111
  def inspect
112
- "<#{self.class.name}##{position}: #{parts.map {|p| val = self.send(p); ".#{p}: #{val.is_a?(DataBrick) ? val.micro_inspect : val.inspect}" }.join(', ')}>"
112
+ "<#{self.class.name}##{position}: #{parts.map {|p|
113
+ val = self.send(p); ".#{p}: #{val.is_a?(DataBrick) ? val.micro_inspect : val.inspect}"
114
+ }.join(', ')}>"
113
115
  end
114
116
 
115
117
  def micro_inspect; "<#{self.class.name}##{position}>"; end
@@ -119,27 +121,36 @@ class DataBrick
119
121
  PointerDefaults = {:bits => 32, :nil_if => 0xFFFFFFFF}
120
122
 
121
123
  # defines a simple string - defaults 8 bit length, :bits => 16 or 32 for longer strings!
122
- def self.define_one_string(name, opts = {})
124
+ def self.define_one_string(name, opts)
123
125
  define_piece "#{name}_length", :string_length, {:string_name => name}.merge(opts)
124
126
  define_piece name, :raw_string, {:length_from => "#{name}_length".to_sym}.merge(opts)
125
127
  end
126
128
 
129
+ # shortcut to raw string (fixed sounds nicer than raw, I think?)
130
+ def self.define_one_fixed_string(name, opts)
131
+ define_piece name, :raw_string, opts
132
+ end
133
+
127
134
  # Thing readers!
128
135
  IntPacker = {8 => 'C', 16 => 'n', 32 => 'N', 64 => 'Q'}
129
- def read_integer(io, options = {}); options = {:bits => 8}.merge(options)
136
+ def read_integer(io, options); options = {:bits => 8}.merge(options)
130
137
  source.read(options[:bits] / 8).unpack(IntPacker[options[:bits]]).first
131
138
  end
132
139
 
133
- def read_raw_string(io, options = {}); io.read(send(options[:length_from])); end
140
+ def read_raw_string(io, options); io.read(options[:length] || send(options[:length_from])); end
134
141
  alias_method :read_string_length, :read_integer
135
142
 
136
- def read_pointer(io, options = {})
143
+ def read_pointer(io, options)
137
144
  options = PointerDefaults.merge(options)
138
145
  ref = read_integer(io, options)
139
146
  return nil if ref == options[:nil_if]
140
147
  (options[:type] || self.class).new(io, ref)
141
148
  end
142
149
 
150
+ def read_array(io, options)
151
+ FixedArray.new(io, options, self)
152
+ end
153
+
143
154
 
144
155
  # Thing blobbers!
145
156
  def self.blob_integer(int, props, options = {})
@@ -147,7 +158,8 @@ class DataBrick
147
158
  end
148
159
 
149
160
  def self.blob_raw_string(str, props, options = {})
150
- str.to_s
161
+ if options[:length] then (str.to_s + ("\000" * options[:length]))[0 ... options[:length]]
162
+ else str.to_s end
151
163
  end
152
164
 
153
165
  def self.blob_pointer(pointee, props, options = {})
@@ -161,12 +173,58 @@ class DataBrick
161
173
  self.blob_integer(props[options[:string_name]].to_s.length, props, options)
162
174
  end
163
175
 
176
+ def self.blob_array(arr, props, options = {})
177
+ accumulate = ''; options[:length].times do |i|
178
+ accumulate += send("blob_#{options[:innards]}", arr[i], props, options[:innards_options]).to_s
179
+ end; return accumulate
180
+ end
181
+
164
182
  # lengths for offset calculation
165
183
  def type_length_integer(opts); (opts[:bits] || 8) / 8; end
166
184
  def type_length_pointer(opts); (opts[:bits] || 32) / 8; end
167
- def type_length_raw_string(opts); send(opts[:length_from]); end
185
+ def type_length_raw_string(opts); opts[:length] || send(opts[:length_from]); end
168
186
  alias_method :type_length_string_length, :type_length_integer
187
+ def type_length_array(opts)
188
+ (opts[:length] || send(opts[:length_from])) * send("type_length_#{opts[:innards]}", opts[:innards_options] || {})
189
+ end
190
+ end
191
+
192
+ class DataBrick::FixedArray
193
+ def initialize(io, options, parent); @io = io; @start = io.tell; @options = options; @parent = parent; end
194
+ attr_reader :io, :start, :options
195
+ include Enumerable
169
196
 
197
+ # get a part of the array. :)
198
+ def [] key
199
+ was_at = @io.tell; seek_to key
200
+ return @parent.send("read_#{@options[:innards]}", @io, @options[:innards_options] || {})
201
+ ensure @io.seek was_at end
202
+
203
+ # set a part of the array. :)
204
+ def []= key, value
205
+ was_at = @source.tell
206
+ seek_to key
207
+ @io.write @parent.class.send("blob_#{@options[:innards]}", value, {}, @options[:innards_options] || {})
208
+ ensure @io.seek was_at end
209
+
210
+ # Implementing #each makes Enumerable happy!
211
+ def each &blk
212
+ (0 ... length).each { |index| blk.call(self[index]) }
213
+ end
214
+
215
+ def size; @options[:length] || @options[:length_from]; end
216
+ alias_method :length, :size
217
+
218
+ def inspect; "<#{self.class.name}:#{@start}*#{length}>"; end
219
+
220
+ protected
221
+ def seek_to key
222
+ raise 'Key must be an integer.' unless key.is_a?(Integer)
223
+ raise 'Index must not be negative.' if key < 0
224
+ raise 'Key must be less than length.' if key >= length
225
+ chunk_size = @parent.send("type_length_#{@options[:innards]}", @options[:innards_options] || {})
226
+ @io.seek @start + (chunk_size * key)
227
+ end
170
228
  end
171
229
 
172
230
  # -=- BrickFu Lessons! -=-
@@ -205,11 +263,16 @@ end
205
263
  # catman = catman.next
206
264
  # end until catman == nil
207
265
  #
266
+ #### Notes:
267
+ # Arrays can only currently contain statically lengthed things,
268
+ # numbers, pointers, and fixed_strings are great examples.
269
+ # If you want to see how more of the types work, look in the
270
+ # test.rb file at how it does it. :)
271
+ #
208
272
 
209
273
  #### TODO:
210
274
  # @ Add float types
211
275
  # @ Maybe something for signed numbers?
212
- # @ An Array type?
213
276
  # @ Booleans type! (length = bools / 8)
214
277
  #
215
278
 
data/test.rb CHANGED
@@ -32,3 +32,18 @@ until catman == nil
32
32
  catman = catman.next
33
33
  end
34
34
 
35
+ File.unlink('cats.db')
36
+ #### TEST ARRAYS!
37
+
38
+ class ArrThing < DataBrick
39
+ define_piece :words, :array, :innards => :raw_string, :innards_options => {:length => 4}, :length => 10
40
+ end
41
+
42
+ file = open('arr-thing.db', 'w+')
43
+ thing = ArrThing.create({
44
+ :words => ['cats', 'bats', 'cake', 'macs', 'chat', 'wave', 'four', 'tofu', 'echo', 'flop']
45
+ }, file)
46
+
47
+ puts "\nThese are a few of my favourite things:"
48
+ thing.words.each { |word| puts word }
49
+ file.close
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: databrick
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Bluebie