PRO flt_clean, StrIn, FmtIn, StrOut, FmtOut, nocheck=NoCheck, $ strcrumbs=StrCrumbs, numcrumbs=NumCrumbs ;+ ; NAME: ; flt_clean ; PURPOSE: ; Check a specified format against a specified string. ; CALLING SEQUENCE: ; flt_clean, StrIn, FmtIn, StrOut, FmtOut, /nocheck ; INPUTS: ; StrIn character string (usually a record read from file) ; FmtIn format to be matched against string ; OPTIONAL INPUTS: ; /nocheck see procedure ; OUTPUTS: ; StrOut reduced character string (see procedure) ; FmtOut reduced format; = '()' if the input format does not ; match the input string ; OPTIONAL OUTPUTS: ; StrCrumbs string array containing the discarded portions of the ; input string ; NumCrumbs # elements in StrCrumbs ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; InitVar ; PROCEDURE: ; The input format is searched for the character descriptor 'A'. All 'A' ; occurrences are removed from the format, and the corresponding ; substrings are removed from the input string. ; The reduced output format will contain only numeric format desciptors ; (I,F,D,E). ; If the input string does not adequately match the format, ; string '()' is returned as output format. This occurs if: ; > If the string is longer or shorter than the length implied by the ; input format, i.e. the lengths must match exactly ; > (Only if the keyword NoCheck is not set) ; If the substring for an 'A' descriptor contains a numerical digit (0..9) ; MODIFICATION HISTORY: ; MAY-1994, Paul Hick (ARC) ; SEP-2003, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Bug fix. If format would end with a string (e.g. A3) then this would not ; be cleaned up properly. ;- StrOut = StrIn FmtOut = FmtIn FmtL = strlen(FmtIn) IF FmtL EQ 0 THEN RETURN ; Empty input string InitVar, NoCheck, /key DoCheck = 1-NoCheck FmtOut = strmid( FmtOut, 1, FmtL-2 )+',' ; Remove brackets, add comma FmtL -= 1 StrA = ['0','1','2','3','4','5','6','7','8','9'] FmtList = ['A','I','F','E','D','.',','] FmtN = n_elements(FmtList) PosN = intarr(FmtN, /nozero) Ntot = 0 pos = 0 NumCrumbs = 0 WHILE pos LT FmtL DO BEGIN ; Pick up positions of FmtList chars FOR i=0,FmtN-1 DO PosN[i] = strpos( FmtOut, FmtList[i], pos ) p = where( PosN NE -1 ) posmin = min( PosN[p], pmin ) pmin = p[pmin] ch = FmtList[pmin] ; 1st FmtList char following 'pos' IF pmin GT 4 THEN message, 'should not have happened' CASE posmin OF ; Format counter pos : N = 1 ELSE: reads, strmid( FmtOut, pos, posmin-pos ), N ENDCASE pend = (PosN[where(FmtList EQ '.')])[0] ; Check for dot CASE pend EQ -1 OF 0: pend = min( [pend, PosN[ where(FmtList EQ ',') ] ] ) 1: pend = PosN[ where(FmtList EQ ',') ] ENDCASE pend = pend[0] m = 0 ; reads, S,M crashes if S is 1-char string and M doesn't exist CASE pend-posmin EQ 1 of ; Format length 0: reads, strmid( FmtOut, posmin+1, pend-posmin-1 ), M 1: message, 'Format specifier of undetermined length' ENDCASE CASE ch OF 'A': BEGIN ; 'AN' DETECTED IN FORMAT IF DoCheck THEN BEGIN ; If DoCheck is set .. StrDmp = strmid(StrOut,Ntot,M*N); .. Check whether the 'An' part ; .. of StrOut contains digits i = -1 REPEAT BEGIN i += 1 d = where( StrDmp EQ StrA[i] ) IF d[0] NE -1 THEN BEGIN ; Digit found i = n_elements(StrA) FmtOut = '' ; Format does not fit StrOut pos = FmtL ENDIF ENDREP until i ge n_elements(StrA)-1 ENDIF IF FmtOut NE '' THEN BEGIN ; Remove 'An' part from FmtOut FmtOut = strmid(FmtOut,0,pos)+strmid(FmtOut,pend+1) FmtL = strlen(FmtOut) IF Ntot+M*N GT strlen(StrOut) THEN BEGIN ; SEP-2003 bugfix: used to be 'ge' FmtOut = '' ; StrOut too short pos = FmtL ; Break while loop ENDIF ELSE BEGIN ; Remove 'An' substring from StrOut NumCrumbs += 1 CASE NumCrumbs EQ 1 OF ; Collect the 'An' substrings 0: StrCrumbs = [StrCrumbs,strmid(StrOut,Ntot,M*N)] 1: StrCrumbs = strmid(StrOut,Ntot,M*N) ENDCASE StrOut = strmid(StrOut,0,Ntot)+strmid(StrOut,Ntot+M*N) ENDELSE ENDIF END ELSE: BEGIN ; I,F,E,D detected in format Ntot += M*N ; # chars in StrOut IF strlen(StrOut) LT Ntot THEN BEGIN; StrOut too short FmtOut = '' pos = FmtL ; Break while loop ENDIF ELSE $ ; Set pos after I,F,E,D format pos = (PosN[ where(FmtList EQ ',') ])[0]+1 END ENDCASE ENDWHILE ; If not whole StrOut processed: format does not fit string IF FmtOut NE '' THEN IF Ntot LT strlen(StrOut) THEN FmtOut = '' ; Reconstruct valid format descriptor: remove comma, add brackets FmtOut = '('+strmid( FmtOut,0,strlen(FmtOut)-1 )+')' RETURN & END