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.



247
248
249
250
251
# File 'lib/ephem/excerpt.rb', line 247

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

Instance Attribute Details

#bwardObject

Returns the value of attribute bward.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def bward
  @bward
end

#double_formatObject

Returns the value of attribute double_format.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def double_format
  @double_format
end

#endiannessObject

Returns the value of attribute endianness.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def endianness
  @endianness
end

#fileObject (readonly)

Returns the value of attribute file.



232
233
234
# File 'lib/ephem/excerpt.rb', line 232

def file
  @file
end

#freeObject

Returns the value of attribute free.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def free
  @free
end

#fwardObject

Returns the value of attribute fward.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def fward
  @fward
end

#int_formatObject

Returns the value of attribute int_format.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def int_format
  @int_format
end

#ndObject

Returns the value of attribute nd.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def nd
  @nd
end

#niObject

Returns the value of attribute ni.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def ni
  @ni
end

#summaries_per_recordObject

Returns the value of attribute summaries_per_record.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def summaries_per_record
  @summaries_per_record
end

#summary_control_formatObject

Returns the value of attribute summary_control_format.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def summary_control_format
  @summary_control_format
end

#summary_formatObject

Returns the value of attribute summary_format.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def summary_format
  @summary_format
end

#summary_lengthObject

Returns the value of attribute summary_length.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def summary_length
  @summary_length
end

#summary_stepObject

Returns the value of attribute summary_step.



233
234
235
# File 'lib/ephem/excerpt.rb', line 233

def summary_step
  @summary_step
end

Instance Method Details

#add_array(name, values, array) ⇒ Object



322
323
324
325
326
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
# File 'lib/ephem/excerpt.rb', line 322

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



308
309
310
311
312
313
# File 'lib/ephem/excerpt.rb', line 308

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



253
254
255
256
257
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
# File 'lib/ephem/excerpt.rb', line 253

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



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/ephem/excerpt.rb', line 284

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



315
316
317
318
319
320
# File 'lib/ephem/excerpt.rb', line 315

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