;+
; NAME:
; VALID_NUM()
; PURPOSE:
; Check if a string is a valid number representation.
; EXPLANATION:
; The input string is parsed for characters that may possibly
; form a valid number. It is more robust than simply checking
; for an IDL conversion error because that allows strings such
; as '22.3qwert' to be returned as the valid number 22.3
;
; This function had a major rewrite in August 2008 to use STREGEX
; and allow vector input. It should be backwards compatible.
; CALLING SEQUENCE:
; IDL> status = valid_num(string [,value] [,/integer])
;
; INPUTS:
; string - the string to be tested, scalar or array
;
; RETURNS
; status - byte scalar or array, same size as the input string
; set to 1 where the string is a valid number, 0 for invalid
; OPTIONAL OUTPUT:
; value - The value the string decodes to, same size as input string.
; This will be returned as a double precision number unless
; /INTEGER is present, in which case a long integer is returned.
;
; OPTIONAL INPUT KEYWORD:
; /INTEGER - if present code checks specifically for an integer.
; EXAMPLES:
; (1) IDL> print,valid_num(3.2,/integer)
; --> 0 ;Since 3.2 is not an integer
; (2) IDL> str =['-0.03','2.3g', '3.2e12']
; IDL> test = valid_num(str,val)
; test = [1,0,1] & val = [-0.030000000 ,NaN ,3.2000000e+12]
; REVISION HISTORY:
; Version 1, C D Pike, RAL, 24-May-93
; Version 2, William Thompson, GSFC, 14 October 1994
; Added optional output parameter VALUE to allow
; VALID_NUM to replace STRNUMBER in FITS routines.
; Version 3 Wayne Landsman rewrite to use STREGEX, vectorize
; Version 4 W.L. (fix from C. Markwardt) Better Stregex expression,
; was missing numbers like '134.' before Jan 1 2010
;-
FUNCTION valid_num, string, value, INTEGER=integer
On_error,2
compile_opt idl2
; A derivation of the regular expressions below can be found on
; http://wiki.tcl.tk/989
if keyword_set(INTEGER) then $
st = '^[-+]?[0-9][0-9]*$' else $ ;Integer
st = '^[-+]?([0-9]+\.?[0-9]*|\.[0-9]+)([eEdD][-+]?[0-9]+)?$' ;F.P.
;Simple return if we just need a boolean test.
if N_params() EQ 1 then return, stregex(strtrim(string,2),st,/boolean)
vv = stregex(strtrim(string,2),st,/boolean)
if size(string,/N_dimen) EQ 0 then begin ;Scalar
if vv then $
value= keyword_set(integer) ? long(string) : double(string)
endif else begin ;Array
g = where(vv,Ng)
if Ng GT 0 then begin ;Need to create output vector
if keyword_set(integer) then begin
value = vv*0L
value[g] = long(string[g])
endif else begin
value = replicate(!VALUES.D_NAN,N_elements(vv))
value[g] = double(string[g])
endelse
endif
endelse
return,vv
end