;+ ; NAME: ; CMSV_WRAW ; ; AUTHOR: ; Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770 ; craigm@lheamail.gsfc.nasa.gov ; ; PURPOSE: ; Write raw SAVE data to output block ; ; CALLING SEQUENCE: ; CMSV_WRAW, BLOCK, POINTER, DATA, UNIT=UNIT, $ ; STRING=STRING, LONG=LONG, BYTE=BYTE, TYPE=TYPE, $ ; OFFSET=OFFSET, STATUS=STATUS, ERRMSG=ERRMSG ; ; DESCRIPTION: ; ; This procedure writes raw integer or string data to an IDL SAVE ; block in memory. This is the lowest level writing function in the ; library, intended for developers who are investigating new and ; existing SAVE file formats. ; ; The data to be written is specified by the DATA parameter. The ; data must be of type BYTE, LONG or STRING, and the type is ; determined automatically from the data itself. [ The mnemonic ; STRING LONG and BYTE keywords are accepted for programming clarity ; but ignored. ] ; ; This procedure accepts but currently ignores the UNIT keyword. It ; is the caller's responsibility to write the BLOCK data to disk ; when appropriate. ; ; ================================================================== ; Research Systems, Inc. has issued a separate license intended ; to resolve any potential conflict between this software and the ; IDL End User License Agreement. The text of that license ; can be found in the file LICENSE.RSI, included with this ; software library. ; ================================================================== ; ; ; BLOCK, POINTER, OFFSET ; ; This procedure writes data to a byte array only. The intent is ; for users to accumulate a significant amount of data in a BLOCK ; and then write it out with a single call to WRITEU. Users should ; be aware that the block can be larger than the buffered data, so ; they should use something like the following: ; ; WRITEU, UNIT, BLOCK(0:POINTER-1) ; ; When library routines do indeed write buffered BLOCK data to disk, ; they will appropriately reset the BLOCK and POINTER. Namely, ; BLOCK will be reset to empty, and POINTER will be reset to zero. ; OFFSET will be advanced the according number of bytes. ; ; The terminology is as follows: BLOCK is a byte array which ; represents a portion of, or an entire, IDL SAVE file. The block ; may be a cached portion of an on-disk file, or an entire in-memory ; SAVE file. POINTER is the current file pointer within BLOCK ; (i.e., the next byte to be written is BLOCK[POINTER]). Hence, a ; POINTER value of 0 refers to the start of the block. OFFSET is ; the file offset of the 0th byte of BLOCK; thus "POINT_LUN, ; OFFSET+POINTER" should point to the same byte as BLOCK[POINTER]. ; The following diagram shows the meanings for BLOCK, POINTER and ; OFFSET schematically: ; ; ; 0 <- OFFSET -> | ; FILE |----------------|------*--------|---------> ; ; BLOCK |------*--------| ; 0 ^ POINTER ; ; ; This procedure is part of the CMSVLIB SAVE library for IDL by ; Craig Markwardt. You must have the full CMSVLIB core package ; installed in order for this procedure to function properly. ; ; ; INPUTS: ; ; BLOCK - a byte array, a cache of the SAVE file. Users will ; usually not access this array directly. Users are advised ; to clear BLOCK after calling POINT_LUN or writing the ; block to disk. ; ; POINTER - a long integer, a pointer to the next byte to be written ; from BLOCK. CMSVLIB routines will automatically advance ; the pointer. ; ; DATA - the data to be written. Must of type STRING, BYTE or LONG. ; ; ; KEYWORDS: ; ; LONG - ignored (to be used for clarity) ; BYTE - ignored (to be used for clarity) ; STRING - ignored (to be used for clarity) ; ; UNIT - a file unit. Currently ignored. ; ; OFFSET - the file offset of byte zero of BLOCK. ; Upon output, if the file pointer is advanced, OFFSET will ; also be changed. ; (OFFSET is not currently used by this routine) ; Default: 0 ; ; STATUS - upon return, this keyword will contain 1 for success and ; 0 for failure. ; ; ERRMSG - upon return with a failure, this keyword will contain the ; error condition as a string. ; ; EXAMPLE: ; ; ; SEE ALSO: ; ; CMRESTORE, SAVE, RESTORE, CMSVLIB ; ; MODIFICATION HISTORY: ; Written, 2000 ; Documented, 24 Jan 2001 ; Added notification about RSI License, 13 May 2002, CM ; Fixed bug in writing of empty strings, 28 Mar 2006, CM ; Fixed bug when writing strings >128 characters, 2012-04-05, CM ; NOTE: remember to modify CMSVLIB.PRO when changing library! ; ; $Id: cmsv_wraw.pro,v 1.9 2012/04/05 20:43:09 cmarkwar Exp $ ; ;- ; Copyright (C) 2000-2001, 2006, 2012, Craig Markwardt ; This software is provided as is without any warranty whatsoever. ; Permission to use, copy, modify, and distribute modified or ; unmodified copies is granted, provided this copyright and disclaimer ; are included unchanged. ;- pro cmsv_enlarge, block, pointer, nbytes, status=status, errmsg=errmsg status = 1 diff = pointer+nbytes - n_elements(block) if diff GT 0 then begin if n_elements(block) GT 0 then $ block = [temporary(block), bytarr(diff + 1024L)] $ else $ block = bytarr(diff + 1024L) endif return end pro cmsv_wraw, block, pointer, value0, unit=unit, replen=replen, $ byte=byte, long=long, string=string, $ status=status, errmsg=errmsg if n_elements(pointer) EQ 0 then pointer = 0L sz = size(value0) tp = sz(sz(0)+1) if tp EQ 7 then begin ;; STRING DATA ;; STRING_DATA ;; LONG - STRLEN - string length in characters ;; BYTExSTRLEN - string characters, padded to next four-byte boundary if n_elements(pointer) EQ 0 then pointer = 0L ;; Compute number of bytes required to store this data replen1 = keyword_set(replen) len = strlen(value0) ;; Length in bytes of the string header llen = 4*(replen1*(len GT 0) + 1) stride = 4 ntotbytes = long( total(floor((len+3)/4)*4L + llen) ) if pointer+ntotbytes GT n_elements(block) then $ cmsv_enlarge, block, pointer, ntotbytes for i = 0L, n_elements(value0)-1 do begin name = value0(i) ;; Add string length hlen = len(i) byteorder, hlen, /HTONL block(pointer) = byte(hlen, 0, 4) if replen1 AND hlen NE 0 then block(pointer+4) = byte(hlen, 0, 4) pointer = pointer + stride + stride*replen1*(hlen NE 0) if len(i) GT 0 then begin ;; Add string contents nbytes = floor((len(i)+3)/4)*4L ;; Round up to next 4-bytes block(pointer) = byte(name) pointer = pointer + nbytes endif endfor status = 1 return endif status = 0 nelt = n_elements(value0) sz = size(value0) tp = sz(sz(0)+1) value = value0 if tp EQ 1 then begin nbytes = 1L ;; BYTE DATA endif else if tp EQ 3 then begin nbytes = 4L ;; LONG DATA endif else begin status = 0 errmsg = 'ERROR: CMSV_WRAW: data must byte BYTE, LONG or STRING' return endelse ntotbytes = nbytes * nelt if pointer+ntotbytes GT n_elements(block) then $ cmsv_enlarge, block, pointer, ntotbytes common cmsv_conv_common, lendian if n_elements(lendian) EQ 0 then begin ;; Little-endian? lendian = (long(['01'xb,'02'xb,'03'xb,'04'xb],0,1))(0) NE '01020304'xl endif ;; Convert values to net order from host endianness case nbytes of ; 1: dummy = 1 ; byte ; 2: byteorder, value, /HTONS ; int 4: byteorder, value, /HTONL ; long ; 8: if lendian then byteorder, value, /L64SWAP ; long64 else: endcase block(pointer) = byte(temporary(value), 0, ntotbytes) pointer = pointer + ntotbytes status = 1 return end