class Tdms::Document
Attributes
channels[R]
file[R]
segments[R]
Public Class Methods
new(file)
click to toggle source
# File lib/tdms/document.rb, line 6 def initialize(file) @file = file parse_segments build_aggregates end
Private Instance Methods
build_aggregates()
click to toggle source
# File lib/tdms/document.rb, line 98 def build_aggregates @channels = [] channels_by_path = {} segments.each do |segment| segment.objects.select { |o| o.path.channel? }.each do |ch| (channels_by_path[ch.path.to_s] ||= []) << ch end end channels_by_path.each do |path, channels| @channels << AggregateChannel.new(channels) end end
parse_segments()
click to toggle source
# File lib/tdms/document.rb, line 14 def parse_segments @segments = [] until file.eof? segment = Tdms::Segment.new segment.prev_segment = @segments[-1] @segments << segment lead_in = @file.read(0x1C) metadata_pos = @file.pos unpacked = lead_in.unpack("a4VVQQ") tdms_tag = unpacked[0] # char[4] toc_flags = unpacked[1] # u32 tdms_version = unpacked[2] # u32 next_seg_pos = unpacked[3] + metadata_pos # u64 raw_data_pos = unpacked[4] + metadata_pos # u64 new_changed_objs = @file.read_u32 raw_data_pos_obj = raw_data_pos 1.upto(new_changed_objs) do |obj_index| path = Tdms::Path.new(:path => @file.read_utf8_string) index_block_len = @file.read_u32 if index_block_len == 0xFFFFFFFF # no index block elsif index_block_len == 0x000000 # index block is same as this channel in the last segment prev_chan = segment.prev_segment.objects.find {|o| o.path == path } chan = Tdms::Channel.new chan.file = @file chan.raw_data_pos = raw_data_pos_obj chan.path = prev_chan.path chan.data_type_id = prev_chan.data_type_id chan.dimension = prev_chan.dimension chan.num_values = prev_chan.num_values segment.objects << chan else # XXX why does the number of properties seem to be # included in the raw data index block size? # -4 is a hack index_block = @file.read(index_block_len - 4) decoded = index_block.unpack("VVQ") chan = Tdms::Channel.new chan.file = @file chan.raw_data_pos = raw_data_pos_obj chan.path = path chan.data_type_id = decoded[0] # first 4 bytes u32 chan.dimension = decoded[1] # next 4 bytes u32 chan.num_values = decoded[2] # next 8 bytes u64 data_type = Tdms::DataType.find_by_id(chan.data_type_id) fixed_length = data_type::LengthInBytes raw_data_pos_obj += if fixed_length chan.num_values * fixed_length else # if the values are variable length (strings only) then # the index block contains 8 additional bytes at the # end with the total length of the raw data in u64 index_block[-8,8].unpack("Q")[0] end segment.objects << chan end # TODO store properties num_props = @file.read_u32 1.upto(num_props) do |n| prop = @file.read_property end end @file.seek next_seg_pos end end