| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718 |
- !> Character string manipulation methods
- !> These methods work generally on character strings, but also, more particularly
- !> on lists. A list is a character string that contains substrings separated by
- !> a delimeter. That delimeter can be set by the user but the default is ":".
- !> Colon delimeted lists are used in OASIS and MCT mainly to instantiate a list
- !> of fields, such as "temperature:humidity:zonal_velocity:meridiona_velocity".
- #define NEW_LGI_METHOD2a
- !!#define NEW_LGI_METHOD2b
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !MODULE: mod_oasis_string -- string and list methods
- !
- ! !DESCRIPTION:
- ! General string and specific list method. A list is a single string
- ! that is delimited by a character forming multiple fields, ie,
- ! character(len=*) :: mylist = "t:s:u1:v1:u2:v2:taux:tauy"
- ! The delimiter is called listDel in this module, is default ":",
- ! but can be set by a call to oasis_string_listSetDel.
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- module mod_oasis_string
- ! !USES:
- use mod_oasis_kinds
- use mod_oasis_parameters
- use mod_oasis_data
- use mod_oasis_sys
- use mod_oasis_timer
- implicit none
- private
- ! !PUBLIC TYPES:
- ! no public types
- ! !PUBLIC MEMBER FUNCTIONS:
- public :: oasis_string_countChar ! Count number of char in string, fn
- public :: oasis_string_toUpper ! Convert string to upper-case
- public :: oasis_string_toLower ! Convert string to lower-case
- public :: oasis_string_getParentDir ! For a pathname get the parent directory name
- public :: oasis_string_lastIndex ! Index of last substr in str
- public :: oasis_string_endIndex ! Index of end of substr in str
- public :: oasis_string_leftAlign ! remove leading white space
- public :: oasis_string_alphanum ! remove all non alpha-numeric characters
- public :: oasis_string_betweenTags ! get the substring between the two tags
- public :: oasis_string_parseCFtunit ! parse CF time units
- public :: oasis_string_clean ! Set string to all white space
- public :: oasis_string_listIsValid ! test for a valid "list"
- public :: oasis_string_listGetNum ! Get number of fields in list, fn
- public :: oasis_string_listGetIndex ! Get index of field
- public :: oasis_string_listGetIndexF ! function version of listGetIndex
- public :: oasis_string_listGetName ! get k-th field name
- public :: oasis_string_listIntersect ! get intersection of two field lists
- public :: oasis_string_listUnion ! get union of two field lists
- public :: oasis_string_listMerge ! merge two lists to form third
- public :: oasis_string_listAppend ! append list at end of another
- public :: oasis_string_listPrepend ! prepend list in front of another
- public :: oasis_string_listSetDel ! Set field delimeter in lists
- public :: oasis_string_listGetDel ! Get field delimeter in lists
- public :: oasis_string_setAbort ! set local abort flag
- public :: oasis_string_setDebug ! set local debug flag
- ! !PUBLIC DATA MEMBERS:
- ! no public data members
- !EOP
- character(len=1) ,save :: listDel = ":" ! note single exec implications
- character(len=2) ,save :: listDel2 = "::" ! note single exec implications
- logical ,save :: doabort = .true.
- integer(ip_i4_p),save :: debug = 0
- !===============================================================================
- contains
- !===============================================================================
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_countChar -- Count number of occurances of a character
- !
- ! !DESCRIPTION:
- !> Count number of occurances of a single character in a string
- ! \newline
- ! n = shr\_string\_countChar(string,character)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- integer function oasis_string_countChar(str,char,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: str !< string to search
- character(1) ,intent(in) :: char !< char to search for
- integer(ip_i4_p),intent(out),optional :: rc !< return code
- !EOP
- !----- local -----
- integer(ip_i4_p) :: count ! counts occurances of char
- integer(ip_i4_p) :: n ! generic index
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_countChar) "
- !-------------------------------------------------------------------------------
- ! Notes:
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- count = 0
- do n = 1, len_trim(str)
- if (str(n:n) == char) count = count + 1
- end do
- oasis_string_countChar = count
- if (present(rc)) rc = 0
- call oasis_debug_exit(subname)
- end function oasis_string_countChar
- !===============================================================================
- !BOP ===========================================================================
- ! !IROUTINE: oasis_string_toUpper -- Convert string to upper case
- !
- ! !DESCRIPTION:
- !> Convert the input string to upper-case.
- ! Use achar and iachar intrinsics to ensure use of ascii collating sequence.
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- function oasis_string_toUpper(str)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(len=*), intent(in) :: str !< input string to convert to upper case
- character(len=len(str)) :: oasis_string_toUpper !< output converted string
- !----- local -----
- integer(ip_i4_p) :: i ! Index
- integer(ip_i4_p) :: aseq ! ascii collating sequence
- integer(ip_i4_p) :: LowerToUpper ! integer to convert case
- character(len=1) :: ctmp ! Character temporary
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_toUpper) "
- !-------------------------------------------------------------------------------
- !
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- LowerToUpper = iachar("A") - iachar("a")
- do i = 1, len(str)
- ctmp = str(i:i)
- aseq = iachar(ctmp)
- if ( aseq >= iachar("a") .and. aseq <= iachar("z") ) &
- ctmp = achar(aseq + LowertoUpper)
- oasis_string_toUpper(i:i) = ctmp
- end do
- call oasis_debug_exit(subname)
- end function oasis_string_toUpper
- !===============================================================================
- !BOP ===========================================================================
- ! !IROUTINE: oasis_string_toLower -- Convert string to lower case
- !
- ! !DESCRIPTION:
- !> Convert the input string to lower-case.
- ! Use achar and iachar intrinsics to ensure use of ascii collating sequence.
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- function oasis_string_toLower(str)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(len=*), intent(in) :: str !< input string to convert to lower case
- character(len=len(str)) :: oasis_string_toLower !< output converted string
- !----- local -----
- integer(ip_i4_p) :: i ! Index
- integer(ip_i4_p) :: aseq ! ascii collating sequence
- integer(ip_i4_p) :: UpperToLower ! integer to convert case
- character(len=1) :: ctmp ! Character temporary
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_toLower) "
- !-------------------------------------------------------------------------------
- !
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- UpperToLower = iachar("a") - iachar("A")
- do i = 1, len(str)
- ctmp = str(i:i)
- aseq = iachar(ctmp)
- if ( aseq >= iachar("A") .and. aseq <= iachar("Z") ) &
- ctmp = achar(aseq + UpperToLower)
- oasis_string_toLower(i:i) = ctmp
- end do
- call oasis_debug_exit(subname)
- end function oasis_string_toLower
- !===============================================================================
- !BOP ===========================================================================
- ! !IROUTINE: oasis_string_getParentDir -- For pathname get the parent directory name
- !
- ! !DESCRIPTION:
- !> Get the parent directory pathname.
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- function oasis_string_getParentDir(str)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(len=*), intent(in) :: str !< input string
- character(len=len(str)) :: oasis_string_getParentDir !< return directory path
- !----- local -----
- integer(ip_i4_p) :: i ! Index
- integer(ip_i4_p) :: nlen ! Length of string
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_getParentDir) "
- !-------------------------------------------------------------------------------
- !
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- nlen = len_trim(str)
- if ( str(nlen:nlen) == "/" ) nlen = nlen - 1
- i = index( str(1:nlen), "/", back=.true. )
- if ( i == 0 )then
- oasis_string_getParentDir = str
- else
- oasis_string_getParentDir = str(1:i-1)
- end if
-
- call oasis_debug_exit(subname)
- end function oasis_string_getParentDir
- !===============================================================================
- !BOP ===========================================================================
- !
- !
- ! !IROUTINE: oasis_string_lastIndex -- Get index of last substr within string
- !
- ! !DESCRIPTION:
- !> Get the index of the last occurance of a substring within a string
- ! \newline
- ! n = shr\_string\_lastIndex(string,substring)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- integer function oasis_string_lastIndex(string,substr,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: string !< input string to search
- character(*) ,intent(in) :: substr !< sub-string to search for
- integer(ip_i4_p),intent(out),optional :: rc !< return code
- !EOP
- !--- local ---
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_lastIndex) "
- !-------------------------------------------------------------------------------
- ! Note:
- ! - "new" F90 back option to index function makes this home-grown solution obsolete
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- oasis_string_lastIndex = index(string,substr,.true.)
- if (present(rc)) rc = 0
- call oasis_debug_exit(subname)
- end function oasis_string_lastIndex
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_endIndex -- Get the ending index of substr within string
- !
- ! !DESCRIPTION:
- !> Get the ending index of the first occurance of a substring within string
- ! \newline
- ! n = shr\_string\_endIndex(string,substring)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- integer function oasis_string_endIndex(string,substr,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: string !< string to search
- character(*) ,intent(in) :: substr !< sub-string to search for
- integer(ip_i4_p),intent(out),optional :: rc !< return code
- !EOP
- !--- local ---
- integer(ip_i4_p) :: i ! generic index
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_endIndex) "
- !-------------------------------------------------------------------------------
- ! Notes:
- ! * returns zero if substring not found, uses len_trim() intrinsic
- ! * very similar to: i = index(str,substr,back=.true.)
- ! * do we need this function?
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- i = index(trim(string),trim(substr))
- if ( i == 0 ) then
- oasis_string_endIndex = 0 ! substr is not in string
- else
- oasis_string_endIndex = i + len_trim(substr) - 1
- end if
- ! -------------------------------------------------------------------
- ! i = index(trim(string),trim(substr),back=.true.)
- ! if (i == len(string)+1) i = 0
- ! oasis_string_endIndex = i
- ! -------------------------------------------------------------------
- if (present(rc)) rc = 0
- call oasis_debug_exit(subname)
- end function oasis_string_endIndex
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_leftAlign -- remove leading white space
- !
- ! !DESCRIPTION:
- !> Remove leading white space
- ! \newline
- ! call shr\_string\_leftAlign(string)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_leftAlign(str,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(inout) :: str !< input and returned string
- integer(ip_i4_p),intent(out) ,optional :: rc !< return code
- !EOP
- !----- local ----
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_leftAlign) "
- !-------------------------------------------------------------------------------
- ! note:
- ! * ?? this routine isn't needed, use the intrisic adjustL instead ??
- !-------------------------------------------------------------------------------
- ! -------------------------------------------------------------------
- ! --- used this until I discovered the intrinsic function below
- ! do while (len_trim(str) > 0 )
- ! if (str(1:1) /= ' ') exit
- ! str = str(2:len_trim(str))
- ! end do
- ! rCode = 0
- ! !! (len_trim(str) == 0 ) rCode = 1 ! ?? appropriate ??
- ! -------------------------------------------------------------------
- call oasis_debug_enter(subname)
- str = adjustL(str)
- if (present(rc)) rc = 0
- call oasis_debug_exit(subname)
- end subroutine oasis_string_leftAlign
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_alphanum -- remove non alpha numeric characters
- !
- ! !DESCRIPTION:
- !> Remove all non alpha numeric characters from string
- ! \newline
- ! call shr\_string\_alphanum(string)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_alphanum(str,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(inout) :: str !< input and output string
- integer(ip_i4_p),intent(out) ,optional :: rc !< return code
- !EOP
- !----- local ----
- integer(ip_i4_p) :: rCode ! return code
- integer(ip_i4_p) :: n,icnt ! counters
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_alphaNum) "
- !-------------------------------------------------------------------------------
- !
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- icnt = 0
- do n=1,len_trim(str)
- if ((str(n:n) >= 'a' .and. str(n:n) <= 'z') .or. &
- (str(n:n) >= 'A' .and. str(n:n) <= 'Z') .or. &
- (str(n:n) >= '0' .and. str(n:n) <= '9')) then
- icnt = icnt + 1
- str(icnt:icnt) = str(n:n)
- endif
- enddo
- do n=icnt+1,len(str)
- str(n:n) = ' '
- enddo
- if (present(rc)) rc = 0
- call oasis_debug_exit(subname)
- end subroutine oasis_string_alphanum
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_betweenTags -- Get the substring between the two tags.
- !
- ! !DESCRIPTION:
- !> Get the substring found between the start and end strings.
- ! \newline
- ! call shr\_string\_betweenTags(string,startTag,endTag,substring,rc)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_betweenTags(string,startTag,endTag,substr,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: string !< input string to search
- character(*) ,intent(in) :: startTag !< start string
- character(*) ,intent(in) :: endTag !< end string
- character(*) ,intent(out) :: substr !< output sub-string between tags
- integer(ip_i4_p),intent(out),optional :: rc !< return code
- !EOP
- !--- local ---
- integer(ip_i4_p) :: iStart ! substring start index
- integer(ip_i4_p) :: iEnd ! substring end index
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_betweenTags) "
- !-------------------------------------------------------------------------------
- ! Notes:
- ! * assumes the leading/trailing white space is not part of start & end tags
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- iStart = oasis_string_endIndex(string,trim(adjustL(startTag))) ! end of start tag
- iEnd = index(string,trim(adjustL(endTag ))) ! start of end tag
- rCode = 0
- substr = ""
- if (iStart < 1) then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,estr,"can't find start tag in string"
- WRITE(nulprt,*) subname,estr,"start tag = ",TRIM(startTag)
- WRITE(nulprt,*) subname,estr,"string = ",TRIM(string)
- CALL oasis_flush(nulprt)
- rCode = 1
- else if (iEnd < 1) then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,estr,"can't find end tag in string"
- WRITE(nulprt,*) subname,estr,"end tag = ",TRIM( endTag)
- WRITE(nulprt,*) subname,estr,"string = ",TRIM(string)
- CALL oasis_flush(nulprt)
- rCode = 2
- else if ( iEnd <= iStart) then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,estr,"start tag not before end tag"
- WRITE(nulprt,*) subname,estr,"start tag = ",TRIM(startTag)
- WRITE(nulprt,*) subname,estr,"end tag = ",TRIM( endTag)
- WRITE(nulprt,*) subname,estr,"string = ",TRIM(string)
- CALL oasis_flush(nulprt)
- rCode = 3
- else if ( iStart+1 == iEnd ) then
- substr = ""
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,wstr,"zero-length substring found in ",TRIM(string)
- CALL oasis_flush(nulprt)
- else
- substr = string(iStart+1:iEnd-1)
- IF (LEN_TRIM(substr) == 0) THEN
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,wstr,"white-space substring found in ",TRIM(string)
- CALL oasis_flush(nulprt)
- ENDIF
- end if
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end subroutine oasis_string_betweenTags
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_parseCFtunit -- Parse CF time unit
- !
- ! !DESCRIPTION:
- !> Parse CF time unit into a delta string name and a base time in yyyymmdd
- ! and seconds (nearest integer actually).
- ! \newline
- ! call shr\_string\_parseCFtunit(string,substring)
- ! \newline
- ! Input string is like "days since 0001-06-15 15:20:45.5 -6:00"
- ! - recognizes "days", "hours", "minutes", "seconds"
- ! - must have at least yyyy-mm-dd, hh:mm:ss.s is optional
- ! - expects a "since" in the string
- ! - ignores time zone part
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_parseCFtunit(string,unit,bdate,bsec,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: string !< string to search
- character(*) ,intent(out) :: unit !< delta time unit
- integer(ip_i4_p),intent(out) :: bdate !< base date yyyymmdd
- real(ip_r8_p) ,intent(out) :: bsec !< base seconds
- integer(ip_i4_p),intent(out),optional :: rc !< return code
- !EOP
- !--- local ---
- integer(ip_i4_p) :: i,i1,i2 ! generic index
- character(ic_long) :: tbase ! baseline time
- character(ic_long) :: lstr ! local string
- integer(ip_i4_p) :: yr,mo,da,hr,min ! time stuff
- real(ip_r8_p) :: sec ! time stuff
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_parseCFtunit) "
- !-------------------------------------------------------------------------------
- ! Notes:
- ! o assume length of CF-1.0 time attribute char string < ic_long
- ! This is a reasonable assumption.
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- unit = 'none'
- bdate = 0
- bsec = 0.0_ip_r8_p
- i = oasis_string_lastIndex(string,'days ')
- if (i > 0) unit = 'days'
- i = oasis_string_lastIndex(string,'hours ')
- if (i > 0) unit = 'hours'
- i = oasis_string_lastIndex(string,'minutes ')
- if (i > 0) unit = 'minutes'
- i = oasis_string_lastIndex(string,'seconds ')
- if (i > 0) unit = 'seconds'
- if (trim(unit) == 'none') then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,estr,'time unit unknown'
- CALL oasis_flush(nulprt)
- CALL oasis_string_abort(subName//' time unit unknown')
- endif
- i = oasis_string_lastIndex(string,' since ')
- if (i < 1) then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,estr,'since does not appear in unit attribute for time '
- CALL oasis_flush(nulprt)
- CALL oasis_string_abort(subName//' no since in attr name')
- endif
- tbase = trim(string(i+6:))
- call oasis_string_leftAlign(tbase)
- if (debug > 0 .and. nulprt > 0) then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) TRIM(subName)//' '//'unit '//TRIM(unit)
- WRITE(nulprt,*) TRIM(subName)//' '//'tbase '//TRIM(tbase)
- CALL oasis_flush(nulprt)
- endif
- yr=0; mo=0; da=0; hr=0; min=0; sec=0
- i1 = 1
- i2 = index(tbase,'-') - 1
- lstr = tbase(i1:i2)
- read(lstr,*,ERR=200,END=200) yr
- tbase = tbase(i2+2:)
- call oasis_string_leftAlign(tbase)
- i2 = index(tbase,'-') - 1
- lstr = tbase(i1:i2)
- read(lstr,*,ERR=200,END=200) mo
- tbase = tbase(i2+2:)
- call oasis_string_leftAlign(tbase)
- i2 = index(tbase,' ') - 1
- lstr = tbase(i1:i2)
- read(lstr,*,ERR=200,END=200) da
- tbase = tbase(i2+2:)
- call oasis_string_leftAlign(tbase)
- i2 = index(tbase,':') - 1
- lstr = tbase(i1:i2)
- read(lstr,*,ERR=200,END=100) hr
- tbase = tbase(i2+2:)
- call oasis_string_leftAlign(tbase)
- i2 = index(tbase,':') - 1
- lstr = tbase(i1:i2)
- read(lstr,*,ERR=200,END=100) min
- tbase = tbase(i2+2:)
- call oasis_string_leftAlign(tbase)
- i2 = index(tbase,' ') - 1
- lstr = tbase(i1:i2)
- read(lstr,*,ERR=200,END=100) sec
- 100 continue
- IF (debug > 0 ) THEN
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) TRIM(subName),'ymdhms:',yr,mo,da,hr,min,sec
- CALL oasis_flush(nulprt)
- ENDIF
- bdate = abs(yr)*10000 + mo*100 + da
- if (yr < 0) bdate = -bdate
- bsec = real(hr*3600 + min*60,ip_r8_p) + sec
- if (present(rc)) rc = 0
- call oasis_debug_exit(subname)
- return
- 200 continue
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- write(nulprt,*) subname,estr,'200 on char num read '
- CALL oasis_flush(nulprt)
- call oasis_string_abort(subName//estr//'on char num read')
- call oasis_debug_exit(subname)
- end subroutine oasis_string_parseCFtunit
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_clean -- Clean a string, set it to "blank"
- !
- ! !DESCRIPTION:
- !> Clean a string, set it to blank
- ! \newline
- ! call shr\_string\_clean(string,rc)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_clean(string,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(inout) :: string !< string
- integer(ip_i4_p),optional,intent(out) :: rc !< return code
- !EOP
- !----- local -----
- integer(ip_i4_p) :: n ! counter
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_clean) "
- !-------------------------------------------------------------------------------
- ! Notes:
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- rCode = 0
- string = ' '
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end subroutine oasis_string_clean
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listIsValid -- determine whether string is a valid list
- !
- ! !DESCRIPTION:
- !> Determine whether string is a valid list
- ! \newline
- ! logical_var = shr\_string\_listIsValid(list,rc)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- logical function oasis_string_listIsValid(list,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: list !< list/string
- integer(ip_i4_p),optional,intent(out) :: rc !< return code
- !EOP
- !----- local -----
- integer (ip_i4_p) :: nChar ! lenth of list
- integer (ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listIsValid) "
- !-------------------------------------------------------------------------------
- ! check that the list conforms to the list format
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- rCode = 0
- oasis_string_listIsValid = .true.
- nChar = len_trim(list)
- if (nChar < 1) then ! list is an empty string
- rCode = 1
- else if ( list(1:1) == listDel ) then ! first char is delimiter
- rCode = 2
- else if (list(nChar:nChar) == listDel ) then ! last char is delimiter
- rCode = 3
- else if (index(trim(list)," " ) > 0) then ! white-space in a field name
- rCode = 4
- else if (index(trim(list),listDel2) > 0) then ! found zero length field
- rCode = 5
- end if
-
- if (rCode /= 0) then
- oasis_string_listIsValid = .false.
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- write(nulprt,*) subname,wstr,"invalid list = ",trim(list)
- CALL oasis_flush(nulprt)
- endif
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end function oasis_string_listIsValid
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listGetName -- Get name of k-th field in list
- !
- ! !DESCRIPTION:
- !> Get name of k-th field in list
- ! \newline
- ! call shr\_string\_listGetName(list,k,name,rc)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listGetName(list,k,name,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: list !< input list
- integer(ip_i4_p) ,intent(in) :: k !< index of field
- character(*) ,intent(out) :: name !< k-th name in list
- integer(ip_i4_p),optional,intent(out) :: rc !< return code
- !EOP
- !----- local -----
- integer(ip_i4_p) :: i,j,n ! generic indecies
- integer(ip_i4_p) :: kFlds ! number of fields in list
- integer(ip_i4_p) :: i0,i1 ! name = list(i0:i1)
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listGetName) "
- !-------------------------------------------------------------------------------
- ! Notes:
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- rCode = 0
- !--- check that this is a valid list ---
- if (.not. oasis_string_listIsValid(list,rCode) ) then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- write(nulprt,*) subname,estr,"invalid list = ",trim(list)
- CALL oasis_flush(nulprt)
- call oasis_string_abort(subName//estr//"invalid list = "//trim(list))
- end if
- !--- check that this is a valid index ---
- kFlds = oasis_string_listGetNum(list)
- if (k<1 .or. kFlds<k) then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,estr,"invalid index = ",k
- WRITE(nulprt,*) subname,estr," list = ",TRIM(list)
- CALL oasis_flush(nulprt)
- CALL oasis_string_abort(subName//estr//"invalid index")
- end if
- !--- start with whole list, then remove fields before and after desired field ---
- i0 = 1
- i1 = len_trim(list)
- !--- remove field names before desired field ---
- do n=2,k
- i = index(list(i0:i1),listDel)
- i0 = i0 + i
- end do
- !--- remove field names after desired field ---
- if ( k < kFlds ) then
- i = index(list(i0:i1),listDel)
- i1 = i0 + i - 2
- end if
- !--- copy result into output variable ---
- name = list(i0:i1)//" "
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listGetName
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listIntersect -- Get intersection of two field lists
- !
- ! !DESCRIPTION:
- !> Get intersection of two fields lists, write into third list
- ! \newline
- ! call shr\_string\_listIntersect(list1,list2,listout)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listIntersect(list1,list2,listout,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: list1 !< input list 1
- character(*) ,intent(in) :: list2 !< input list 2
- character(*) ,intent(out) :: listout !< output list
- integer(ip_i4_p),optional,intent(out) :: rc !< return code
- !EOP
- !----- local -----
- integer(ip_i4_p) :: nf,n1,n2 ! counters
- character(ic_med) :: name ! field name
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listIntersect) "
- !-------------------------------------------------------------------------------
- ! Notes:
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- rCode = 0
- nf = oasis_string_listGetNum(list1)
- call oasis_string_clean(listout)
- do n1 = 1,nf
- call oasis_string_listGetName(list1,n1,name,rCode)
- n2 = oasis_string_listGetIndexF(list2,name)
- if (n2 > 0) then
- call oasis_string_listAppend(listout,name)
- endif
- enddo
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listIntersect
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listUnion -- Get union of two field lists
- !
- ! !DESCRIPTION:
- !> Get union of two fields lists, write into third list
- ! \newline
- ! call shr\_string\_listUnion(list1,list2,listout)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listUnion(list1,list2,listout,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: list1 !< input list 1
- character(*) ,intent(in) :: list2 !< input list 2
- character(*) ,intent(out) :: listout !< output list 3
- integer(ip_i4_p),optional,intent(out) :: rc !< return code
- !EOP
- !----- local -----
- integer(ip_i4_p) :: nf,n1,n2 ! counters
- character(ic_med) :: name ! field name
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listUnion) "
- !-------------------------------------------------------------------------------
- ! Notes:
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- rCode = 0
- call oasis_string_clean(listout)
- nf = oasis_string_listGetNum(list1)
- do n1 = 1,nf
- call oasis_string_listGetName(list1,n1,name,rCode)
- n2 = oasis_string_listGetIndexF(listout,name)
- if (n2 < 1) then
- call oasis_string_listAppend(listout,name)
- endif
- enddo
- nf = oasis_string_listGetNum(list2)
- do n1 = 1,nf
- call oasis_string_listGetName(list2,n1,name,rCode)
- n2 = oasis_string_listGetIndexF(listout,name)
- if (n2 < 1) then
- call oasis_string_listAppend(listout,name)
- endif
- enddo
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listUnion
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listMerge -- Merge lists two list to third
- !
- ! !DESCRIPTION:
- !> Merge two lists into a third list
- ! \newline
- ! call shr\_string\_listMerge(list1,list2,listout)
- ! call shr\_string\_listMerge(list1,list2,list1)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listMerge(list1,list2,listout,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: list1 !< input list 1
- character(*) ,intent(in) :: list2 !< input list 2
- character(*) ,intent(out) :: listout !< output list
- integer(ip_i4_p),optional,intent(out) :: rc !< return code
- !EOP
- !----- local -----
- character(ic_xl) :: l1,l2 ! local char strings
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listMerge) "
- !-------------------------------------------------------------------------------
- ! Notes:
- ! - no input or output string should be longer than ic_xl
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- rCode = 0
- !--- make sure temp strings are large enough ---
- if ( (len(l1) < len_trim(list1)) .or. (len(l2) < len_trim(list2))) then
- call oasis_string_abort(subName//estr//"temp string not large enough")
- end if
- call oasis_string_clean(l1)
- call oasis_string_clean(l2)
- call oasis_string_clean(listout)
- l1 = trim(list1)
- l2 = trim(list2)
- call oasis_string_leftAlign(l1,rCode)
- call oasis_string_leftAlign(l2,rCode)
- if (len_trim(l1)+len_trim(l2)+1 > len(listout)) &
- call oasis_string_abort(subName//estr//"output list string not large enough")
- if (len_trim(l1) == 0) then
- listout = trim(l2)
- else
- listout = trim(l1)//":"//trim(l2)
- endif
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listMerge
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listAppend -- Append one list to another
- !
- ! !DESCRIPTION:
- !> Append one list to another
- ! \newline
- ! call shr\_string\_listAppend(list,listadd)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listAppend(list,listadd,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(inout) :: list !< input and output list
- character(*) ,intent(in) :: listadd !< list to append
- integer(ip_i4_p),optional,intent(out) :: rc !< return code
- !EOP
- !----- local -----
- character(ic_xl) :: l1 ! local string
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listAppend) "
- !-------------------------------------------------------------------------------
- ! Notes:
- ! - no input or output string should be longer than ic_xl
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- rCode = 0
- !--- make sure temp string is large enough ---
- if (len(l1) < len_trim(listAdd)) then
- call oasis_string_abort(subName//estr//'temp string not large enough')
- end if
- call oasis_string_clean(l1)
- l1 = trim(listadd)
- call oasis_string_leftAlign(l1,rCode)
- if (len_trim(list)+len_trim(l1)+1 > len(list)) &
- call oasis_string_abort(subName//estr//'output list string not large enough')
- if (len_trim(list) == 0) then
- list = trim(l1)
- else
- list = trim(list)//":"//trim(l1)
- endif
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listAppend
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listPrepend -- Prepend one list to another
- !
- ! !DESCRIPTION:
- !> Prepend one list to another
- ! \newline
- ! call shr\_string\_listPrepend(listadd,list)
- ! \newline
- ! results in listadd:list
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listPrepend(listadd,list,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: listadd ! input and output list
- character(*) ,intent(inout) :: list ! list to prepend
- integer(ip_i4_p),optional,intent(out) :: rc ! return code
- !EOP
- !----- local -----
- character(ic_xl) :: l1 ! local string
- integer(ip_i4_p) :: rCode ! return code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listPrepend) "
- !-------------------------------------------------------------------------------
- ! Notes:
- ! - no input or output string should be longer than ic_xl
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- rCode = 0
- !--- make sure temp string is large enough ---
- if (len(l1) < len_trim(listAdd)) then
- call oasis_string_abort(subName//estr//'temp string not large enough')
- end if
- call oasis_string_clean(l1)
- l1 = trim(listadd)
- call oasis_string_leftAlign(l1,rCode)
- call oasis_string_leftAlign(list,rCode)
- if (len_trim(list)+len_trim(l1)+1 > len(list)) &
- call oasis_string_abort(subName//estr//"output list string not large enough")
- if (len_trim(l1) == 0) then
- list = trim(list)
- else
- list = trim(l1)//":"//trim(list)
- endif
- if (present(rc)) rc = rCode
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listPrepend
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listGetIndexF -- Get index of field in string
- !
- ! !DESCRIPTION:
- !> Get the index of a field in a list
- ! \newline
- ! k = shr\_string\_listGetIndex(str,"taux")
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- integer function oasis_string_listGetIndexF(string,fldStr)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*),intent(in) :: string !< input string
- character(*),intent(in) :: fldStr !< name of field
- !EOP
- !----- local -----
- integer(ip_i4_p) :: k ! local index variable
- integer(ip_i4_p) :: rc ! error code
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listGetIndexF) "
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- call oasis_string_listGetIndex(string,fldStr,k,print=.false.,rc=rc)
- oasis_string_listGetIndexF = k
- call oasis_debug_exit(subname)
- end function oasis_string_listGetIndexF
- #if (defined NEW_LGI_METHOD2a || defined NEW_LGI_METHOD2b)
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listGetIndex -- Get index of field in string
- !
- ! !DESCRIPTION:
- !> Get the index of a field in a string
- ! \newline
- ! call shr\_string\_listGetIndex(str,"taux",k,rc)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listGetIndex(string,fldStr,kFld,print,rc)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*) ,intent(in) :: string !< input list
- character(*) ,intent(in) :: fldStr !< name of field
- integer(ip_i4_p),intent(out) :: kFld !< index of field in list
- logical ,intent(in) ,optional :: print !< print switch
- integer(ip_i4_p),intent(out),optional :: rc !< return code
- !EOP
- !----- local -----
- integer(ip_i4_p) :: n,n1,n2 ! index for colon position
- integer(ip_i4_p) :: lens ! length of string
- logical :: found ! T => field found in fieldNames
- logical :: lprint ! local print flag
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listGetIndex) "
- !-------------------------------------------------------------------------------
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- ! call oasis_timer_start('tcx_slgi0')
- ! call oasis_timer_start('tcx_slgia')
- if (present(rc)) rc = 0
- kfld = 0
- found = .false.
- lprint = .false.
- if (present(print)) lprint = print
- !--- confirm proper size of input data ---
- if (len_trim(fldStr) < 1) then
- IF (lprint) THEN
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,estr,"input field name has 0 length"
- CALL oasis_flush(nulprt)
- ENDIF
- CALL oasis_string_abort(subName//"invalid field name")
- end if
- ! call oasis_timer_stop('tcx_slgia')
- ! call oasis_timer_start('tcx_slgib')
- lens = len_trim(string)
- ! write(nulprt,*) subname,' tcx1 ',string
- ! write(nulprt,*) subname,' tcx2 ',fldStr
- n = index(string,listDel,back=.false.)
- ! write(nulprt,*) subname,' tcx3 ',n
- ! call oasis_timer_start('tcx_slgib')
- ! call oasis_timer_start('tcx_slgic')
- if (n <= 0) then ! single field only
- ! call oasis_timer_start('tcx_slgic1')
- if (trim(fldStr) == string(1:lens)) then
- found = .true.
- kFld = 1
- endif
- ! call oasis_timer_stop('tcx_slgic1')
- ! write(nulprt,*) subname,' tcx4a ',found,kfld
- elseif (n > 0) then
- !--- check first string ---
- ! call oasis_timer_start('tcx_slgic2')
- if (trim(fldStr) == string(1:n-1)) then
- found = .true.
- kFld = 1
- endif
- ! write(nulprt,*) subname,' tcx4b ',found,kfld
- ! call oasis_timer_stop('tcx_slgic2')
- !--- check last string ---
- if (.not.found) then
- ! call oasis_timer_start('tcx_slgic3')
- n = index(string,listDel,back=.true.)
- if (trim(fldStr) == string(n+1:lens)) then
- found = .true.
- kFld = oasis_string_listGetNum(string)
- endif
- ! call oasis_timer_stop('tcx_slgic3')
- ! write(nulprt,*) subname,' tcx4c ',found,kfld
- endif
- !--- check other strings ---
- if (.not.found) then
- ! call oasis_timer_start('tcx_slgic4')
- n = index(string,':'//trim(fldStr)//':',back=.false.)
- ! write(nulprt,*) subname,' tcx5a ',n
- if (n > 0) then
- found = .true.
- #if defined NEW_LGI_METHOD2a
- if (n <= lens) then
- #endif
- #if defined NEW_LGI_METHOD2b
- if (n <= lens/2) then
- #endif
- ! call oasis_timer_start('tcx_slgic4a')
- n1 = 0
- kFld = 1
- do while (n1 < n)
- kFld = kFld + 1
- n2 = index(string(n1+1:lens),listDel,back=.false.)
- n1 = n1 + n2
- ! write(nulprt,*) subname,' tcx5b ',kfld,n2,n1,n
- enddo
- ! call oasis_timer_stop('tcx_slgic4a')
- else
- ! call oasis_timer_start('tcx_slgic4b')
- n1 = lens+1
- kFld = oasis_string_listGetNum(string) + 1
- ! call oasis_timer_stop('tcx_slgic4b')
- ! call oasis_timer_start('tcx_slgic4c')
- do while (n1 > n)
- kFld = kFld - 1
- n2 = index(string(1:n1-1),listDel,back=.true.)
- n1 = n2
- ! write(nulprt,*) subname,' tcx5c ',kfld,n2,n1,n
- enddo
- ! call oasis_timer_stop('tcx_slgic4c')
- endif
- endif
- ! write(nulprt,*) subname,' tcx4d ',found,kfld
- ! call oasis_timer_stop('tcx_slgic4')
- endif
- endif
- ! call oasis_timer_stop('tcx_slgic')
- ! call oasis_timer_start('tcx_slgid')
- !--- not finding a field is not a fatal error ---
- if (.not. found) then
- IF (lprint) THEN
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,"FYI: field ",TRIM(fldStr)," not found in list ",TRIM(string)
- CALL oasis_flush(nulprt)
- ENDIF
- if (present(rc)) rc = 1
- end if
- ! call oasis_timer_stop('tcx_slgid')
- ! call oasis_timer_stop('tcx_slgi0')
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listGetIndex
- #endif
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listGetNum -- get number of fields in a string list
- !
- ! !DESCRIPTION:
- !> return number of fields in string list
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- integer function oasis_string_listGetNum(str)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*),intent(in) :: str !< input list
- !EOP
- !----- local -----
- integer(ip_i4_p) :: count ! counts occurances of char
- !----- formats -----
- character(*),parameter :: subName = "(oasis_string_listGetNum) "
- !-------------------------------------------------------------------------------
- ! Notes:
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- oasis_string_listGetNum = 0
- if (len_trim(str) > 0) then
- count = oasis_string_countChar(str,listDel)
- oasis_string_listGetNum = count + 1
- endif
- call oasis_debug_exit(subname)
- end function oasis_string_listGetNum
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listSetDel -- Set list delimeter character
- !
- ! !DESCRIPTION:
- !> Set field delimeter character in lists
- ! \newline
- ! call shr\_string\_listSetDel(":")
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listSetDel(cflag)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(len=1),intent(in) :: cflag !< field delimeter
- !EOP
- !--- formats ---
- character(*),parameter :: subName = "(oasis_string_listSetDel) "
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- IF (debug > 0) THEN
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,' changing listDel from '//TRIM(listDel)//' to '//TRIM(cflag)
- CALL oasis_flush(nulprt)
- ENDIF
- listDel = trim(cflag)
- listDel2 = listDel//listDel
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listSetDel
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_listGetDel -- Get list delimeter character
- !
- ! !DESCRIPTION:
- !> Get field delimeter character in lists
- ! \newline
- ! call shr\_string\_listGetDel(del)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_listGetDel(del)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*),intent(out) :: del !< field delimeter
- !EOP
- !--- formats ---
- character(*),parameter :: subName = "(oasis_string_listGetDel) "
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- del = trim(listDel)
- call oasis_debug_exit(subname)
- end subroutine oasis_string_listGetDel
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_setAbort -- Set local oasis_string abort flag
- !
- ! !DESCRIPTION:
- !> Set local oasis_string abort flag, true = abort, false = print and continue
- ! \newline
- ! call shr\_string\_setAbort(.false.)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_setAbort(flag)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- logical,intent(in) :: flag !< abort flag
- !EOP
- !--- formats ---
- character(*),parameter :: subName = "(oasis_string_setAbort) "
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- if (debug > 0) then
- if (flag) then
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,' setting abort to true'
- CALL oasis_flush(nulprt)
- else
- WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
- WRITE(nulprt,*) subname,' setting abort to false'
- CALL oasis_flush(nulprt)
- endif
- endif
- doabort = flag
- call oasis_debug_exit(subname)
- end subroutine oasis_string_setAbort
- !===============================================================================
- !BOP ===========================================================================
- !
- ! !IROUTINE: oasis_string_setDebug -- Set local oasis_string debug level
- !
- ! !DESCRIPTION:
- !> Set local oasis_string debug level, 0 = production
- ! \newline
- ! call shr\_string\_setDebug(2)
- !
- !
- ! !INTERFACE: ------------------------------------------------------------------
- subroutine oasis_string_setDebug(iFlag)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- integer(ip_i4_p),intent(in) :: iFlag !< requested debug level
- !EOP
- !--- local ---
- !--- formats ---
- character(*),parameter :: subName = "(oasis_string_setDebug) "
- !-------------------------------------------------------------------------------
- ! NTOE: write statement can be expensive if called many times.
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- ! if (OASIS_debug > 0) write(nulprt,*) subname,' changing debug level from ',debug,' to ',iflag
- debug = iFlag
- call oasis_debug_exit(subname)
- end subroutine oasis_string_setDebug
- !===============================================================================
- !===============================================================================
- !> Supports aborts in the string module
- subroutine oasis_string_abort(string)
- implicit none
- ! !INPUT/OUTPUT PARAMETERS:
- character(*),optional,intent(in) :: string !< error string
- !EOP
- !--- local ---
- character(ic_xl) :: lstring
- character(*),parameter :: subName = "(oasis_string_abort)"
- !-------------------------------------------------------------------------------
- ! NOTE:
- ! - no input or output string should be longer than ic_xl
- !-------------------------------------------------------------------------------
- call oasis_debug_enter(subname)
- lstring = ''
- if (present(string)) lstring = string
- if (doabort) then
- WRITE(nulprt,*) subname,estr,'abort for ',TRIM(lstring)
- call oasis_abort()
- else
- write(nulprt,*) subname,wstr,'no abort for '//trim(lstring)
- CALL oasis_flush(nulprt)
- endif
- call oasis_debug_exit(subname)
- end subroutine oasis_string_abort
- !===============================================================================
- !===============================================================================
- end module mod_oasis_string
|