Class: Ephem::Excerpt::DAFWriter

Inherits:
Object
  • Object
show all
Defined in:
lib/ephem/excerpt.rb

Overview

Helper class for writing DAF files This class handles the low-level details of DAF file format

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, debug = false) ⇒ DAFWriter

Returns a new instance of DAFWriter.



252
253
254
255
256
# File 'lib/ephem/excerpt.rb', line 252

def initialize(file, debug = false)
  @file = file
  @debug = debug
  @mutex = Mutex.new
end

Instance Attribute Details

#bwardObject

Returns the value of attribute bward.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def bward
  @bward
end

#double_formatObject

Returns the value of attribute double_format.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def double_format
  @double_format
end

#endiannessObject

Returns the value of attribute endianness.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def endianness
  @endianness
end

#fileObject (readonly)

Returns the value of attribute file.



237
238
239
# File 'lib/ephem/excerpt.rb', line 237

def file
  @file
end

#freeObject

Returns the value of attribute free.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def free
  @free
end

#fwardObject

Returns the value of attribute fward.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def fward
  @fward
end

#int_formatObject

Returns the value of attribute int_format.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def int_format
  @int_format
end

#ndObject

Returns the value of attribute nd.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def nd
  @nd
end

#niObject

Returns the value of attribute ni.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def ni
  @ni
end

#summaries_per_recordObject

Returns the value of attribute summaries_per_record.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def summaries_per_record
  @summaries_per_record
end

#summary_control_formatObject

Returns the value of attribute summary_control_format.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def summary_control_format
  @summary_control_format
end

#summary_formatObject

Returns the value of attribute summary_format.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def summary_format
  @summary_format
end

#summary_lengthObject

Returns the value of attribute summary_length.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def summary_length
  @summary_length
end

#summary_stepObject

Returns the value of attribute summary_step.



238
239
240
# File 'lib/ephem/excerpt.rb', line 238

def summary_step
  @summary_step
end

Instance Method Details

#add_array(name, values, array) ⇒ Object



327
328
329
330
331
332
333
334
335
336
337
338
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
377
378
379
380
381
382
383
384
# File 'lib/ephem/excerpt.rb', line 327

def add_array(name, values, array)
  record_number = @bward
  data = read_record(record_number).dup

  control_data = data[0, 24].unpack(@summary_control_format)
  next_record = control_data[0].to_i
  previous_record = control_data[1].to_i
  n_summaries = control_data[2].to_i

  if n_summaries < @summaries_per_record
    # Add to the existing record
    summary_record = record_number
    data[0, 24] = [next_record, previous_record, n_summaries + 1]
      .pack(@summary_control_format)
    write_record(summary_record, data)
  else
    # Create a new record
    summary_record = ((@free - 1) * 8 + 1023) / 1024 + 1
    name_record = summary_record + 1
    free_record = summary_record + 2

    data[0, 24] = [summary_record, previous_record, n_summaries]
      .pack(@summary_control_format)
    write_record(record_number, data)

    n_summaries = 0
    summaries = [0, record_number, 1]
      .pack(@summary_control_format)
      .ljust(RECORD_SIZE, "\0")
    names = " ".ljust(RECORD_SIZE, "\0")
    write_record(summary_record, summaries)
    write_record(name_record, names)

    @bward = summary_record
    @free = (free_record - 1) * RECORD_SIZE / 8 + 1
  end

  # Convert array to binary data
  array_data = array.pack("#{@double_format}*")

  start_word = @free
  @file.seek((start_word - 1) * 8)
  @file.write(array_data)
  end_word = @file.tell / 8

  @free = end_word + 1
  write_file_record

  # Using values up to nd+ni-2, then adding start_word and end_word
  new_values = values[0, @nd + @ni - 2] + [start_word, end_word]

  base = RECORD_SIZE * (summary_record - 1)
  offset = n_summaries * @summary_step
  @file.seek(base + 24 + offset)  # 24 is summary_control_struct size
  @file.write(new_values.pack(@summary_format))
  @file.seek(base + RECORD_SIZE + offset)
  @file.write(name[0, @summary_length].ljust(@summary_step, " "))
end

#read_record(n) ⇒ Object



313
314
315
316
317
318
# File 'lib/ephem/excerpt.rb', line 313

def read_record(n)
  @mutex.synchronize do
    @file.seek(n * RECORD_SIZE - RECORD_SIZE)
    @file.read(RECORD_SIZE)
  end
end

#setup_formats(nd, ni) ⇒ Object



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/ephem/excerpt.rb', line 258

def setup_formats(nd, ni)
  @nd = nd
  @ni = ni

  # Double is always 8 bytes, int is always 4 bytes
  double_size = 8
  int_size = 4

  # Set formats based on endianness
  if @endianness == :little
    @double_format = "E"  # Little-endian double
    @int_format = "l"     # Little-endian signed long (32-bit)
  else
    @double_format = "G"  # Big-endian double
    @int_format = "l>"    # Big-endian signed long (32-bit)
  end

  # Create formats for summary structures
  @summary_control_format =
    "#{@double_format}#{@double_format}#{@double_format}"
  @summary_format = @double_format.to_s * @nd + @int_format.to_s * @ni

  # Calculate segment summary sizes
  @summary_length = double_size * @nd + int_size * @ni

  # Pad to 8 bytes
  @summary_step = @summary_length + (-@summary_length % 8)

  @summaries_per_record = (RECORD_SIZE - 8 * 3) / @summary_step
end

#write_file_recordObject



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/ephem/excerpt.rb', line 289

def write_file_record
  @file.seek(0)
  data = @file.read(RECORD_SIZE)

  # Update pointers directly in the data buffer
  fward_pos = 76
  bward_pos = 80
  free_pos = 84

  if @endianness == :little
    data[fward_pos, 4] = [@fward].pack("l")
    data[bward_pos, 4] = [@bward].pack("l")
    data[free_pos, 4] = [@free].pack("l")
  else
    data[fward_pos, 4] = [@fward].pack("N")
    data[bward_pos, 4] = [@bward].pack("N")
    data[free_pos, 4] = [@free].pack("N")
  end

  # Write the updated record back to the file
  @file.seek(0)
  @file.write(data)
end

#write_record(n, data) ⇒ Object



320
321
322
323
324
325
# File 'lib/ephem/excerpt.rb', line 320

def write_record(n, data)
  @mutex.synchronize do
    @file.seek(n * RECORD_SIZE - RECORD_SIZE)
    @file.write(data)
  end
end