#!/usr/bin/ruby require 'optparse' require 'rubygems' require 'bindata' require 'xtmfile/xtmheader' class XtmJoin class XtmJoinArgumentError < ArgumentError ; end attr_reader :opts BUFFER_MAX_SIZE = 4096 * 4096 def initialize args @args = [] @input_filename = nil parse_command_line args end def parse_command_line args @args = args.clone @opts = OptionParser.new do |opts| opts.banner = "Usage: #{File.basename $0} [options]\n" opts.separator "" opts.separator "Mandatory options" opts.on("-i", "--input FILE", "Input XTM file") do |r| @input_filename = r end opts.separator "" opts.separator "General options:" opts.on("-h", "--help", "Show this help") do |h| @help = h end opts.on("-v", "--verbose", "Show warnings too") do |v| @verbose = v end opts.separator "" end end def validate! @opts.parse! raise XtmJoinArgumentError, "No input XTM file specified!" if @input_filename.nil? raise RuntimeError, "Current input XTM does not exist!" unless File.exist? @input_filename raise RuntimeError, "Current input XTML is not a file!" unless File.file? @input_filename @input_filename = File.expand_path @input_filename end def run validate! output_file = nil # initial file in_xtm = File.open @input_filename, "rb" header = XtmHeader::read in_xtm output_file = header.filename_str puts "Writing data to %s" % output_file # FIXME: prevent overwriting out_xtm = File.open output_file, "wb" cur_xtm = @input_filename is_first = true cur_size = header.filesize print "\x1b[s" while cur_size > 0 do unless is_first then cur_xtm = _nextfile cur_xtm puts "Opening %s" % cur_xtm in_xtm = File.open cur_xtm, "rb" end while cur_size > 0 and (not in_xtm.eof?) do pcent = ((header.filesize - cur_size) * 100 / header.filesize) STDOUT.print "\x1b[uProgress : %s %" % pcent STDOUT.flush read_size = if cur_size > BUFFER_MAX_SIZE then BUFFER_MAX_SIZE else cur_size end buffer = in_xtm.read read_size cur_size = cur_size - buffer.length out_xtm.write buffer.slice(0, buffer.length) end is_first = false in_xtm.close end out_xtm.close STDOUT.puts "" # remaining files end def _nextfile curfile result = nil cur_idx = 0 cur_len = 0 case curfile when /\.([0-9]+)\.xtm$/ then cur_idx = $1.to_i cur_len = $1.length next_idx = cur_idx + 1 result = curfile.gsub(/\.([0-9]+)\.xtm$/, ".%0#{cur_len}d.xtm" % next_idx) when /\.xtm\.([0-9]+)$/ then cur_idx = $1.to_i cur_len = $1.length next_idx = cur_idx + 1 result = curfile.gsub(/\.xtm\.([0-9]+)$/, ".xtm.%0#{cur_len}d" % next_idx) else raise "Unable to detect a naming patterng for file sequence!" end return result end def self.main args xj = nil begin xj = XtmJoin.new args xj.run exit 0 rescue XtmJoinArgumentError => e STDERR.puts "%s" % xj.opts STDERR.puts "error: %s" % e.message exit 1 rescue SystemExit => e raise e rescue Exception => e STDERR.puts "error: %s" % e.message exit 1 end end end XtmJoin.main ARGV