[go: up one dir, main page]

Menu

[r1]: / idl_lib / insert_record.pro  Maximize  Restore  History

Download this file

120 lines (105 with data), 3.2 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
;*************************** 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