;*************************** insert_record *****************************
;
; usage: index=insert_record(file, rec, [n], [offset=start] [/swap_endian])
;
; purpose: General-purpose utility to insert a record into an ordered
; associated file at the correct location.
; The file is always maintained so that each record is sorted
; by the nth record. If the record exists, overwrites the
; existing record, otherwise it inserts it by shuffling
; the subsequent records forward. Returns the 0-based index
; of its final location in the file.
;
; arguments: file The associated binary file to modify
;
; rec The record to insert into the file.
;
; n The 0-based indexed of the field by which the file is sorted
; Assumes 0 if not supplied.
;
; keywords: offset Byte of the file at which the records start--
; in case there is a header.
;
; /swap_endian Indicates that the file was created with a
; machine with opposite "endian" binary represention.
; Simply passes the keyword to the "open" procedure.
;
; modification history: Created 2001-10-12 by Peter Mills (peter.mills@nrl.navy.mil)
; Based on the function "add_hiz"
;
;*******************************************************************
;Trying to insert some efficiency into this operation:
;This function adds a record at a particular
;rev number at the correct location by doing a binary search. If the rev number
;is not found, laboriously inserts it, otherwise overwrites the existing "rec" record.
;Returns the index value of its location in the associated file.
function insert_record, file, rec, n, offset=start, swap_endian=swap_endian
size=byte_size(rec)
if n_elements(n) eq 0 then n=0
rev=rec.(n)
on_ioerror, create
openu, lun, file, swap_endian=swap_endian, /get_lun
t=assoc(lun, rec, offset, /packed)
;special case in which the file does not exist:
goto, skip
create:
openw, lun, file, swap_endian=swap_endian, /get_lun
t=assoc(lun, rec, offset)
on_ioerror, NULL
skip:
filesize=(fstat(lun)).size
if n_elements(first) eq 0 then first=0
nrec=filesize/size
;special case in which there are no records in the file:
if nrec eq 0 then begin
t[0]=rec
free_lun, lun
return, 0
endif
last=nrec-1
fs=t[first]
ls=t[last]
index=-1
if rev eq fs.(n) then begin
index=first
last=first
endif
if ls.(n) eq rev then begin
index=last
last=first
endif
if rev lt fs.(n) then begin
last=first
endif
if rev gt ls.(n) then begin
first=last
last=last+1
endif
while last-first gt 1 do begin
mid=(first+last)/2
ms=t[mid]
if ms.(n) eq rev then begin
index=mid
break
endif
if rev gt ms.(n) then begin
first=mid
fs=ms
endif else begin
last=mid
ls=ms
endelse
endwhile
;if not found, insert record by uprooting all subsequent records and
;shifting them forward one spot:
if index eq -1 then begin
for i=nrec-1, last, -1 do t[i+1]=t[i]
t[last]=rec
index=last
endif else begin
;otherwise, just overwrite the existing record:
t[index]=rec
endelse
free_lun, lun
return, index
end