Class: Cabriolet::CAB::Extractor::BlockReader

Inherits:
Object
  • Object
show all
Defined in:
lib/cabriolet/cab/extractor.rb

Overview

BlockReader wraps cabinet file handles and reads CFDATA blocks Handles multi-part cabinets by following the FolderData chain

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io_system, folder_data, num_blocks, salvage) ⇒ BlockReader

Returns a new instance of BlockReader.



329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/cabriolet/cab/extractor.rb', line 329

def initialize(io_system, folder_data, num_blocks, salvage)
  @io_system = io_system
  @current_data = folder_data
  @num_blocks = num_blocks
  @salvage = salvage
  @current_block = 0
  @buffer = ""
  @buffer_pos = 0
  @cab_handle = nil

  # Cache ENV lookups once at initialization
  @debug_block = ENV.fetch("DEBUG_BLOCK", nil)

  # Open first cabinet and seek to data offset
  open_current_cabinet
end

Instance Attribute Details

#current_blockObject (readonly)

Returns the value of attribute current_block.



326
327
328
# File 'lib/cabriolet/cab/extractor.rb', line 326

def current_block
  @current_block
end

#current_dataObject (readonly)

Returns the value of attribute current_data.



326
327
328
# File 'lib/cabriolet/cab/extractor.rb', line 326

def current_data
  @current_data
end

#io_systemObject (readonly)

Returns the value of attribute io_system.



326
327
328
# File 'lib/cabriolet/cab/extractor.rb', line 326

def io_system
  @io_system
end

#num_blocksObject (readonly)

Returns the value of attribute num_blocks.



326
327
328
# File 'lib/cabriolet/cab/extractor.rb', line 326

def num_blocks
  @num_blocks
end

#salvageObject (readonly)

Returns the value of attribute salvage.



326
327
328
# File 'lib/cabriolet/cab/extractor.rb', line 326

def salvage
  @salvage
end

Instance Method Details

#closeObject



394
395
396
397
# File 'lib/cabriolet/cab/extractor.rb', line 394

def close
  @cab_handle&.close
  @cab_handle = nil
end

#read(bytes) ⇒ Object



346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/cabriolet/cab/extractor.rb', line 346

def read(bytes)
  # Early return if we've already exhausted all blocks and buffer
  if @current_block >= @num_blocks && @buffer_pos >= @buffer.bytesize
    if @debug_block
      warn "DEBUG BlockReader.read(#{bytes}): Already exhausted, returning empty"
    end
    return +""
  end

  result = +""

  if @debug_block
    warn "DEBUG BlockReader.read(#{bytes}): buffer_size=#{@buffer.bytesize} buffer_pos=#{@buffer_pos} block=#{@current_block}/#{@num_blocks}"
  end

  while result.bytesize < bytes
    # Read more data if buffer is empty
    if (@buffer_pos >= @buffer.bytesize) && !read_next_block
      if @debug_block
        warn "DEBUG BlockReader.read: EXHAUSTED at result.bytesize=#{result.bytesize} (wanted #{bytes})"
      end
      break
    end

    # Copy from buffer
    available = @buffer.bytesize - @buffer_pos
    to_copy = [available, bytes - result.bytesize].min

    result << @buffer[@buffer_pos, to_copy]
    @buffer_pos += to_copy
  end

  if @debug_block
    warn "DEBUG BlockReader.read: returning #{result.bytesize} bytes"
  end

  result
end

#seek(_offset, _whence) ⇒ Object



385
386
387
388
# File 'lib/cabriolet/cab/extractor.rb', line 385

def seek(_offset, _whence)
  # Not implemented for block reader
  0
end

#tellObject



390
391
392
# File 'lib/cabriolet/cab/extractor.rb', line 390

def tell
  0
end