Class: FixWidthTable
- Inherits:
-
Object
- Object
- FixWidthTable
- Defined in:
- lib/rbbt/fix_width_table.rb
Constant Summary collapse
- CONNECTIONS =
{}
Instance Attribute Summary collapse
-
#file ⇒ Object
Returns the value of attribute file.
-
#filename ⇒ Object
Returns the value of attribute filename.
-
#range ⇒ Object
Returns the value of attribute range.
-
#record_size ⇒ Object
Returns the value of attribute record_size.
-
#size ⇒ Object
Returns the value of attribute size.
-
#value_size ⇒ Object
Returns the value of attribute value_size.
Class Method Summary collapse
Instance Method Summary collapse
- #[](pos) ⇒ Object
- #add(pos, value) ⇒ Object (also: #<<)
-
#add_point(data) ⇒ Object
{{{ Adding data.
- #add_range(data) ⇒ Object
- #chunked_values_at(keys, max = 5000) ⇒ Object
- #close ⇒ Object
-
#closest(pos) ⇒ Object
{{{ Searching.
- #dump ⇒ Object
- #format(pos, value) ⇒ Object
- #get_point(pos) ⇒ Object
- #get_range(pos) ⇒ Object
-
#initialize(filename, value_size = nil, range = nil, update = false, in_memory = true) ⇒ FixWidthTable
constructor
A new instance of FixWidthTable.
- #last_pos ⇒ Object
- #overlap(index) ⇒ Object
- #pos(index) ⇒ Object
- #pos_end(index) ⇒ Object
- #read ⇒ Object
- #unformat(format) ⇒ Object
- #value(index) ⇒ Object
- #values_at(*list) ⇒ Object
Constructor Details
#initialize(filename, value_size = nil, range = nil, update = false, in_memory = true) ⇒ FixWidthTable
Returns a new instance of FixWidthTable.
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 |
# File 'lib/rbbt/fix_width_table.rb', line 4 def initialize(filename, value_size = nil, range = nil, update = false, in_memory = true) @filename = filename if update or %w(memory stringio).include?(filename.to_s.downcase) or not File.exists?(filename) Log.debug "FixWidthTable create: #{ filename }" @value_size = value_size @range = range @record_size = @value_size + (@range ? 12 : 4) if %w(memory stringio).include? filename.to_s.downcase @filename = :memory @file = StringIO.new else FileUtils.rm @filename if File.exists? @filename @file = File.open(@filename, 'wb') end @file.write [value_size].pack("L") @file.write [@range ? 1 : 0 ].pack("C") @size = 0 else Log.debug "FixWidthTable up-to-date: #{ filename }" if in_memory @file = StringIO.new(Open.read(@filename, :mode => 'rb'), 'r') else @file = File.open(@filename, 'r') end @value_size = @file.read(4).unpack("L").first @range = @file.read(1).unpack("C").first == 1 @record_size = @value_size + (@range ? 12 : 4) @size = (File.size(@filename) - 5) / (@record_size) end end |
Instance Attribute Details
#file ⇒ Object
Returns the value of attribute file.
3 4 5 |
# File 'lib/rbbt/fix_width_table.rb', line 3 def file @file end |
#filename ⇒ Object
Returns the value of attribute filename.
3 4 5 |
# File 'lib/rbbt/fix_width_table.rb', line 3 def filename @filename end |
#range ⇒ Object
Returns the value of attribute range.
3 4 5 |
# File 'lib/rbbt/fix_width_table.rb', line 3 def range @range end |
#record_size ⇒ Object
Returns the value of attribute record_size.
3 4 5 |
# File 'lib/rbbt/fix_width_table.rb', line 3 def record_size @record_size end |
#size ⇒ Object
Returns the value of attribute size.
3 4 5 |
# File 'lib/rbbt/fix_width_table.rb', line 3 def size @size end |
#value_size ⇒ Object
Returns the value of attribute value_size.
3 4 5 |
# File 'lib/rbbt/fix_width_table.rb', line 3 def value_size @value_size end |
Class Method Details
.get(filename, value_size = nil, range = nil, update = false) ⇒ Object
40 41 42 43 44 45 46 47 48 |
# File 'lib/rbbt/fix_width_table.rb', line 40 def self.get(filename, value_size = nil, range = nil, update = false) return self.new(filename, value_size, range, update) if filename == :memory case when (!File.exists?(filename) or update or not CONNECTIONS.include?(filename)) CONNECTIONS[filename] = self.new(filename, value_size, range, update) end CONNECTIONS[filename] end |
Instance Method Details
#[](pos) ⇒ Object
237 238 239 240 241 242 243 244 |
# File 'lib/rbbt/fix_width_table.rb', line 237 def [](pos) return [] if size == 0 if range get_range(pos) else get_point(pos) end end |
#add(pos, value) ⇒ Object Also known as: <<
69 70 71 72 73 |
# File 'lib/rbbt/fix_width_table.rb', line 69 def add(pos, value) format = format(pos, value) @file.write format @size += 1 end |
#add_point(data) ⇒ Object
{{{ Adding data
122 123 124 125 126 |
# File 'lib/rbbt/fix_width_table.rb', line 122 def add_point(data) data.sort_by{|value, pos| pos }.each do |value, pos| add pos, value end end |
#add_range(data) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rbbt/fix_width_table.rb', line 128 def add_range(data) latest = [] data.sort_by{|value, pos| pos[0] }.each do |value, pos| while latest.any? and latest[0] < pos[0] latest.shift end overlap = latest.length add pos + [overlap], value latest << pos[1] end end |
#chunked_values_at(keys, max = 5000) ⇒ Object
252 253 254 255 256 257 258 |
# File 'lib/rbbt/fix_width_table.rb', line 252 def chunked_values_at(keys, max = 5000) Misc.ordered_divide(keys, max).inject([]) do |acc,c| new = self.values_at(*c) new.annotate acc if new.respond_to? :annotate and acc.empty? acc.concat(new) end end |
#close ⇒ Object
110 111 112 |
# File 'lib/rbbt/fix_width_table.rb', line 110 def close @file.close end |
#closest(pos) ⇒ Object
{{{ Searching
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/rbbt/fix_width_table.rb', line 144 def closest(pos) upper = size - 1 lower = 0 return -1 if upper < lower while(upper >= lower) do idx = lower + (upper - lower) / 2 pos_idx = pos(idx) case pos <=> pos_idx when 0 break when -1 upper = idx - 1 when 1 lower = idx + 1 end end if pos_idx > pos idx = idx - 1 end idx.to_i end |
#dump ⇒ Object
114 115 116 117 118 |
# File 'lib/rbbt/fix_width_table.rb', line 114 def dump read @file.rewind @file.read end |
#format(pos, value) ⇒ Object
50 51 52 53 54 55 56 57 |
# File 'lib/rbbt/fix_width_table.rb', line 50 def format(pos, value) padding = value_size - value.length if range (pos + [value + ("\0" * padding)]).pack("llla#{value_size}") else [pos, value + ("\0" * padding)].pack("la#{value_size}") end end |
#get_point(pos) ⇒ Object
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/rbbt/fix_width_table.rb', line 203 def get_point(pos) if Range === pos r_start = pos.begin r_end = pos.end else r_start = pos.to_i r_end = pos.to_i end idx = closest(r_start) return [] if idx >= size return [] if idx <0 and r_start == r_end idx = 0 if idx < 0 idx += 1 unless pos(idx) >= r_start return [] if idx >= size values = [] l_start = pos(idx) l_end = pos_end(idx) while l_start <= r_end values << value(idx) idx += 1 break if idx >= size l_start = pos(idx) l_end = pos_end(idx) end values end |
#get_range(pos) ⇒ Object
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/rbbt/fix_width_table.rb', line 171 def get_range(pos) if Range === pos r_start = pos.begin r_end = pos.end else r_start = pos.to_i r_end = pos.to_i end idx = closest(r_start) return [] if idx >= size return [] if idx <0 and r_start == r_end idx = 0 if idx < 0 idx -= overlap(idx) unless overlap(idx).nil? values = [] l_start = pos(idx) l_end = pos_end(idx) while l_start <= r_end values << value(idx) if l_end >= r_start idx += 1 break if idx >= size l_start = pos(idx) l_end = pos_end(idx) end values end |
#last_pos ⇒ Object
76 77 78 |
# File 'lib/rbbt/fix_width_table.rb', line 76 def last_pos pos(size - 1) end |
#overlap(index) ⇒ Object
92 93 94 95 96 |
# File 'lib/rbbt/fix_width_table.rb', line 92 def overlap(index) return nil if index < 0 or index >= size @file.seek(13 + (record_size) * index, IO::SEEK_SET) @file.read(4).unpack("l").first end |
#pos(index) ⇒ Object
80 81 82 83 84 |
# File 'lib/rbbt/fix_width_table.rb', line 80 def pos(index) return nil if index < 0 or index >= size @file.seek(5 + (record_size) * index, IO::SEEK_SET) @file.read(4).unpack("l").first end |
#pos_end(index) ⇒ Object
86 87 88 89 90 |
# File 'lib/rbbt/fix_width_table.rb', line 86 def pos_end(index) return nil if index < 0 or index >= size @file.seek(9 + (record_size) * index, IO::SEEK_SET) @file.read(4).unpack("l").first end |
#read ⇒ Object
104 105 106 107 108 |
# File 'lib/rbbt/fix_width_table.rb', line 104 def read return if @filename == :memory @file.close unless @file.closed? @file = File.open(@filename, 'r') end |
#unformat(format) ⇒ Object
59 60 61 62 63 64 65 66 67 |
# File 'lib/rbbt/fix_width_table.rb', line 59 def unformat(format) if range pos_start, pos_end, pos_overlap, value = format.unpack("llla#{value_size}") [[pos_start, pos_end, pos_overlap], value.strip] else pos, value = format.unpack("la#{value_size}") [pos, value.strip] end end |
#value(index) ⇒ Object
98 99 100 101 102 |
# File 'lib/rbbt/fix_width_table.rb', line 98 def value(index) return nil if index < 0 or index >= size @file.seek((range ? 17 : 9 ) + (record_size) * index, IO::SEEK_SET) @file.read(value_size).unpack("a#{value_size}").first.strip end |
#values_at(*list) ⇒ Object
246 247 248 249 250 |
# File 'lib/rbbt/fix_width_table.rb', line 246 def values_at(*list) list.collect{|pos| self[pos] } end |