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.



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/cabriolet/cab/extractor.rb', line 322

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.



319
320
321
# File 'lib/cabriolet/cab/extractor.rb', line 319

def current_block
  @current_block
end

#current_dataObject (readonly)

Returns the value of attribute current_data.



319
320
321
# File 'lib/cabriolet/cab/extractor.rb', line 319

def current_data
  @current_data
end

#io_systemObject (readonly)

Returns the value of attribute io_system.



319
320
321
# File 'lib/cabriolet/cab/extractor.rb', line 319

def io_system
  @io_system
end

#num_blocksObject (readonly)

Returns the value of attribute num_blocks.



319
320
321
# File 'lib/cabriolet/cab/extractor.rb', line 319

def num_blocks
  @num_blocks
end

#salvageObject (readonly)

Returns the value of attribute salvage.



319
320
321
# File 'lib/cabriolet/cab/extractor.rb', line 319

def salvage
  @salvage
end

Instance Method Details

#closeObject



387
388
389
390
# File 'lib/cabriolet/cab/extractor.rb', line 387

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

#read(bytes) ⇒ Object



339
340
341
342
343
344
345
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
# File 'lib/cabriolet/cab/extractor.rb', line 339

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



378
379
380
381
# File 'lib/cabriolet/cab/extractor.rb', line 378

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

#tellObject



383
384
385
# File 'lib/cabriolet/cab/extractor.rb', line 383

def tell
  0
end