00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 module shr_string_mod
00023
00024
00025
00026 use shr_kind_mod
00027 use shr_sys_mod
00028 use shr_cal_mod
00029 use shr_timer_mod, only : shr_timer_get, shr_timer_start, shr_timer_stop
00030 use shr_log_mod, only : s_loglev => shr_log_Level
00031 use shr_log_mod, only : s_logunit => shr_log_Unit
00032
00033 implicit none
00034 private
00035
00036
00037
00038
00039
00040
00041
00042 public :: shr_string_countChar
00043 public :: shr_string_toUpper
00044 public :: shr_string_toLower
00045 public :: shr_string_getParentDir
00046 public :: shr_string_lastIndex
00047 public :: shr_string_endIndex
00048 public :: shr_string_leftAlign
00049 public :: shr_string_alphanum
00050 public :: shr_string_betweenTags
00051 public :: shr_string_parseCFtunit
00052 public :: shr_string_clean
00053
00054 public :: shr_string_listIsValid
00055 public :: shr_string_listGetNum
00056 public :: shr_string_listGetIndex
00057 public :: shr_string_listGetIndexF
00058 public :: shr_string_listGetName
00059 public :: shr_string_listIntersect
00060 public :: shr_string_listUnion
00061 public :: shr_string_listMerge
00062 public :: shr_string_listAppend
00063 public :: shr_string_listPrepend
00064 public :: shr_string_listSetDel
00065 public :: shr_string_listGetDel
00066
00067 public :: shr_string_setAbort
00068 public :: shr_string_setDebug
00069
00070
00071
00072
00073
00074
00075
00076 character(len=1) ,save :: listDel = ":"
00077 character(len=2) ,save :: listDel2 = "::"
00078 logical ,save :: doabort = .true.
00079 integer(SHR_KIND_IN),save :: debug = 0
00080
00081
00082 contains
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 integer function shr_string_countChar(str,char,rc)
00101
00102
00103 implicit none
00104
00105
00106
00107 character(*) ,intent(in) :: str
00108 character(1) ,intent(in) :: char
00109 integer(SHR_KIND_IN),intent(out),optional :: rc
00110
00111
00112
00113
00114 integer(SHR_KIND_IN) :: count
00115 integer(SHR_KIND_IN) :: n
00116 integer(SHR_KIND_IN) :: t01 = 0
00117
00118
00119 character(*),parameter :: subName = "(shr_string_countChar) "
00120 character(*),parameter :: F00 = "('(shr_string_countChar) ',4a)"
00121
00122
00123
00124
00125
00126 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00127 if (debug>1) call shr_timer_start(t01)
00128
00129 count = 0
00130 do n = 1, len_trim(str)
00131 if (str(n:n) == char) count = count + 1
00132 end do
00133 shr_string_countChar = count
00134
00135 if (present(rc)) rc = 0
00136
00137 if (debug>1) call shr_timer_stop (t01)
00138
00139 end function shr_string_countChar
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 function shr_string_toUpper(str)
00155
00156 implicit none
00157
00158
00159 character(len=*), intent(in) :: str
00160 character(len=len(str)) :: shr_string_toUpper
00161
00162
00163 integer(SHR_KIND_IN) :: i
00164 integer(SHR_KIND_IN) :: aseq
00165 integer(SHR_KIND_IN) :: LowerToUpper
00166 character(len=1) :: ctmp
00167 integer(SHR_KIND_IN) :: t01 = 0
00168
00169
00170 character(*),parameter :: subName = "(shr_string_toUpper) "
00171 character(*),parameter :: F00 = "('(shr_string_toUpper) ',4a)"
00172
00173
00174
00175
00176
00177 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00178 if (debug>1) call shr_timer_start(t01)
00179
00180 LowerToUpper = iachar("A") - iachar("a")
00181
00182 do i = 1, len(str)
00183 ctmp = str(i:i)
00184 aseq = iachar(ctmp)
00185 if ( aseq >= iachar("a") .and. aseq <= iachar("z") ) &
00186 ctmp = achar(aseq + LowertoUpper)
00187 shr_string_toUpper(i:i) = ctmp
00188 end do
00189
00190 if (debug>1) call shr_timer_stop (t01)
00191
00192 end function shr_string_toUpper
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 function shr_string_toLower(str)
00207
00208 implicit none
00209
00210
00211 character(len=*), intent(in) :: str
00212 character(len=len(str)) :: shr_string_toLower
00213
00214
00215 integer(SHR_KIND_IN) :: i
00216 integer(SHR_KIND_IN) :: aseq
00217 integer(SHR_KIND_IN) :: UpperToLower
00218 character(len=1) :: ctmp
00219 integer(SHR_KIND_IN) :: t01 = 0
00220
00221
00222 character(*),parameter :: subName = "(shr_string_toLower) "
00223 character(*),parameter :: F00 = "('(shr_string_toLower) ',4a)"
00224
00225
00226
00227
00228
00229 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00230 if (debug>1) call shr_timer_start(t01)
00231
00232 UpperToLower = iachar("a") - iachar("A")
00233
00234 do i = 1, len(str)
00235 ctmp = str(i:i)
00236 aseq = iachar(ctmp)
00237 if ( aseq >= iachar("A") .and. aseq <= iachar("Z") ) &
00238 ctmp = achar(aseq + UpperToLower)
00239 shr_string_toLower(i:i) = ctmp
00240 end do
00241
00242 if (debug>1) call shr_timer_stop (t01)
00243
00244 end function shr_string_toLower
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 function shr_string_getParentDir(str)
00259
00260 implicit none
00261
00262
00263 character(len=*), intent(in) :: str
00264 character(len=len(str)) :: shr_string_getParentDir
00265
00266
00267 integer(SHR_KIND_IN) :: i
00268 integer(SHR_KIND_IN) :: nlen
00269 integer(SHR_KIND_IN) :: t01 = 0
00270
00271
00272 character(*),parameter :: subName = "(shr_string_getParentDir) "
00273 character(*),parameter :: F00 = "('(shr_string_getParentDir) ',4a)"
00274
00275
00276
00277
00278
00279 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00280 if (debug>1) call shr_timer_start(t01)
00281
00282 nlen = len_trim(str)
00283 if ( str(nlen:nlen) == "/" ) nlen = nlen - 1
00284 i = index( str(1:nlen), "/", back=.true. )
00285 if ( i == 0 )then
00286 shr_string_getParentDir = str
00287 else
00288 shr_string_getParentDir = str(1:i-1)
00289 end if
00290
00291 if (debug>1) call shr_timer_stop (t01)
00292
00293 end function shr_string_getParentDir
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 integer function shr_string_lastIndex(string,substr,rc)
00312
00313 implicit none
00314
00315
00316
00317 character(*) ,intent(in) :: string
00318 character(*) ,intent(in) :: substr
00319 integer(SHR_KIND_IN),intent(out),optional :: rc
00320
00321
00322
00323
00324 integer(SHR_KIND_IN) :: t01 = 0
00325
00326
00327 character(*),parameter :: subName = "(shr_string_lastIndex) "
00328 character(*),parameter :: F00 = "('(shr_string_lastIndex) ',4a)"
00329
00330
00331
00332
00333
00334
00335 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00336 if (debug>1) call shr_timer_start(t01)
00337
00338 shr_string_lastIndex = index(string,substr,.true.)
00339
00340 if (present(rc)) rc = 0
00341
00342 if (debug>1) call shr_timer_stop (t01)
00343
00344 end function shr_string_lastIndex
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 integer function shr_string_endIndex(string,substr,rc)
00362
00363 implicit none
00364
00365
00366
00367 character(*) ,intent(in) :: string
00368 character(*) ,intent(in) :: substr
00369 integer(SHR_KIND_IN),intent(out),optional :: rc
00370
00371
00372
00373
00374 integer(SHR_KIND_IN) :: i
00375 integer(SHR_KIND_IN) :: t01 = 0
00376
00377
00378 character(*),parameter :: subName = "(shr_string_endIndex) "
00379 character(*),parameter :: F00 = "('(shr_string_endIndex) ',4a)"
00380
00381
00382
00383
00384
00385
00386
00387
00388 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00389 if (debug>1) call shr_timer_start(t01)
00390
00391 i = index(trim(string),trim(substr))
00392 if ( i == 0 ) then
00393 shr_string_endIndex = 0
00394 else
00395 shr_string_endIndex = i + len_trim(substr) - 1
00396 end if
00397
00398
00399
00400
00401
00402
00403
00404 if (present(rc)) rc = 0
00405
00406 if (debug>1) call shr_timer_stop (t01)
00407
00408 end function shr_string_endIndex
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 subroutine shr_string_leftAlign(str,rc)
00426
00427 implicit none
00428
00429
00430
00431 character(*) ,intent(inout) :: str
00432 integer(SHR_KIND_IN),intent(out) ,optional :: rc
00433
00434
00435
00436
00437 integer(SHR_KIND_IN) :: rCode
00438 integer(SHR_KIND_IN) :: t01 = 0
00439
00440
00441 character(*),parameter :: subName = "(shr_string_leftAlign) "
00442 character(*),parameter :: F00 = "('(shr_string_leftAlign) ',4a)"
00443
00444
00445
00446
00447
00448
00449 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00450 if (debug>1) call shr_timer_start(t01)
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 str = adjustL(str)
00463 if (present(rc)) rc = 0
00464
00465 if (debug>1) call shr_timer_stop (t01)
00466
00467 end subroutine shr_string_leftAlign
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 subroutine shr_string_alphanum(str,rc)
00485
00486 implicit none
00487
00488
00489
00490 character(*) ,intent(inout) :: str
00491 integer(SHR_KIND_IN),intent(out) ,optional :: rc
00492
00493
00494
00495
00496 integer(SHR_KIND_IN) :: rCode
00497 integer(SHR_KIND_IN) :: n,icnt
00498 integer(SHR_KIND_IN) :: t01 = 0
00499
00500
00501 character(*),parameter :: subName = "(shr_string_alphaNum) "
00502 character(*),parameter :: F00 = "('(shr_string_alphaNum) ',4a)"
00503
00504
00505
00506
00507
00508 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00509 if (debug>1) call shr_timer_start(t01)
00510
00511 icnt = 0
00512 do n=1,len_trim(str)
00513 if ((str(n:n) >= 'a' .and. str(n:n) <= 'z') .or. &
00514 (str(n:n) >= 'A' .and. str(n:n) <= 'Z') .or. &
00515 (str(n:n) >= '0' .and. str(n:n) <= '9')) then
00516 icnt = icnt + 1
00517 str(icnt:icnt) = str(n:n)
00518 endif
00519 enddo
00520 do n=icnt+1,len(str)
00521 str(n:n) = ' '
00522 enddo
00523
00524 if (present(rc)) rc = 0
00525
00526 if (debug>1) call shr_timer_stop (t01)
00527
00528 end subroutine shr_string_alphanum
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 subroutine shr_string_betweenTags(string,startTag,endTag,substr,rc)
00546
00547 implicit none
00548
00549
00550
00551 character(*) ,intent(in) :: string
00552 character(*) ,intent(in) :: startTag
00553 character(*) ,intent(in) :: endTag
00554 character(*) ,intent(out) :: substr
00555 integer(SHR_KIND_IN),intent(out),optional :: rc
00556
00557
00558
00559
00560 integer(SHR_KIND_IN) :: iStart
00561 integer(SHR_KIND_IN) :: iEnd
00562 integer(SHR_KIND_IN) :: rCode
00563 integer(SHR_KIND_IN) :: t01 = 0
00564
00565
00566 character(*),parameter :: subName = "(shr_string_betweenTags) "
00567 character(*),parameter :: F00 = "('(shr_string_betweenTags) ',4a)"
00568
00569
00570
00571
00572
00573
00574 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00575 if (debug>1) call shr_timer_start(t01)
00576
00577 iStart = shr_string_endIndex(string,trim(adjustL(startTag)))
00578 iEnd = index(string,trim(adjustL(endTag )))
00579
00580 rCode = 0
00581 substr = ""
00582
00583 if (iStart < 1) then
00584 if (s_loglev > 0) then
00585 write(s_logunit,F00) "ERROR: can't find start tag in string"
00586 write(s_logunit,F00) "ERROR: start tag = ",trim(startTag)
00587 write(s_logunit,F00) "ERROR: string = ",trim(string)
00588 endif
00589 rCode = 1
00590 else if (iEnd < 1) then
00591 if (s_loglev > 0) then
00592 write(s_logunit,F00) "ERROR: can't find end tag in string"
00593 write(s_logunit,F00) "ERROR: end tag = ",trim( endTag)
00594 write(s_logunit,F00) "ERROR: string = ",trim(string)
00595 endif
00596 rCode = 2
00597 else if ( iEnd <= iStart) then
00598 if (s_loglev > 0) then
00599 write(s_logunit,F00) "ERROR: start tag not before end tag"
00600 write(s_logunit,F00) "ERROR: start tag = ",trim(startTag)
00601 write(s_logunit,F00) "ERROR: end tag = ",trim( endTag)
00602 write(s_logunit,F00) "ERROR: string = ",trim(string)
00603 endif
00604 rCode = 3
00605 else if ( iStart+1 == iEnd ) then
00606 substr = ""
00607 if (s_loglev > 0) write(s_logunit,F00) "WARNING: zero-length substring found in ",trim(string)
00608 else
00609 substr = string(iStart+1:iEnd-1)
00610 if (len_trim(substr) == 0 .and. s_loglev > 0) &
00611 & write(s_logunit,F00) "WARNING: white-space substring found in ",trim(string)
00612 end if
00613
00614 if (present(rc)) rc = rCode
00615
00616 if (debug>1) call shr_timer_stop (t01)
00617
00618 end subroutine shr_string_betweenTags
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 subroutine shr_string_parseCFtunit(string,unit,bdate,bsec,rc)
00643
00644 implicit none
00645
00646
00647
00648 character(*) ,intent(in) :: string
00649 character(*) ,intent(out) :: unit
00650 integer(SHR_KIND_IN),intent(out) :: bdate
00651 real(SHR_KIND_R8) ,intent(out) :: bsec
00652 integer(SHR_KIND_IN),intent(out),optional :: rc
00653
00654
00655
00656
00657 integer(SHR_KIND_IN) :: i,i1,i2
00658 character(SHR_KIND_CL) :: tbase
00659 character(SHR_KIND_CL) :: lstr
00660 integer(SHR_KIND_IN) :: yr,mo,da,hr,min
00661 real(SHR_KIND_R8) :: sec
00662 integer(SHR_KIND_IN) :: t01 = 0
00663
00664
00665 character(*),parameter :: subName = "(shr_string_parseCFtunit) "
00666 character(*),parameter :: F00 = "('(shr_string_parseCFtunit) ',4a)"
00667
00668
00669
00670
00671
00672
00673
00674 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00675 if (debug>1) call shr_timer_start(t01)
00676
00677 unit = 'none'
00678 bdate = 0
00679 bsec = 0.0_SHR_KIND_R8
00680
00681 i = shr_string_lastIndex(string,'days ')
00682 if (i > 0) unit = 'days'
00683 i = shr_string_lastIndex(string,'hours ')
00684 if (i > 0) unit = 'hours'
00685 i = shr_string_lastIndex(string,'minutes ')
00686 if (i > 0) unit = 'minutes'
00687 i = shr_string_lastIndex(string,'seconds ')
00688 if (i > 0) unit = 'seconds'
00689
00690 if (trim(unit) == 'none') then
00691 write(s_logunit,F00) ' ERROR time unit unknown'
00692 call shr_string_abort(subName//' time unit unknown')
00693 endif
00694
00695 i = shr_string_lastIndex(string,' since ')
00696 if (i < 1) then
00697 write(s_logunit,F00) ' ERROR since does not appear in unit attribute for time '
00698 call shr_string_abort(subName//' no since in attr name')
00699 endif
00700 tbase = trim(string(i+6:))
00701 call shr_string_leftAlign(tbase)
00702
00703 if (debug > 0 .and. s_logunit > 0) then
00704 write(s_logunit,*) trim(subName)//' '//'unit '//trim(unit)
00705 write(s_logunit,*) trim(subName)//' '//'tbase '//trim(tbase)
00706 endif
00707
00708 yr=0; mo=0; da=0; hr=0; min=0; sec=0
00709 i1 = 1
00710
00711 i2 = index(tbase,'-') - 1
00712 lstr = tbase(i1:i2)
00713 read(lstr,*,ERR=200,END=200) yr
00714 tbase = tbase(i2+2:)
00715 call shr_string_leftAlign(tbase)
00716
00717 i2 = index(tbase,'-') - 1
00718 lstr = tbase(i1:i2)
00719 read(lstr,*,ERR=200,END=200) mo
00720 tbase = tbase(i2+2:)
00721 call shr_string_leftAlign(tbase)
00722
00723 i2 = index(tbase,' ') - 1
00724 lstr = tbase(i1:i2)
00725 read(lstr,*,ERR=200,END=200) da
00726 tbase = tbase(i2+2:)
00727 call shr_string_leftAlign(tbase)
00728
00729 i2 = index(tbase,':') - 1
00730 lstr = tbase(i1:i2)
00731 read(lstr,*,ERR=200,END=100) hr
00732 tbase = tbase(i2+2:)
00733 call shr_string_leftAlign(tbase)
00734
00735 i2 = index(tbase,':') - 1
00736 lstr = tbase(i1:i2)
00737 read(lstr,*,ERR=200,END=100) min
00738 tbase = tbase(i2+2:)
00739 call shr_string_leftAlign(tbase)
00740
00741 i2 = index(tbase,' ') - 1
00742 lstr = tbase(i1:i2)
00743 read(lstr,*,ERR=200,END=100) sec
00744
00745 100 continue
00746
00747 if (debug > 0 .and. s_loglev > 0) write(s_logunit,*) trim(subName),'ymdhms:',yr,mo,da,hr,min,sec
00748
00749 call shr_cal_ymd2date(yr,mo,da,bdate)
00750 bsec = real(hr*3600 + min*60,SHR_KIND_R8) + sec
00751
00752 if (present(rc)) rc = 0
00753
00754 if (debug>1) call shr_timer_stop (t01)
00755 return
00756
00757 200 continue
00758 write(s_logunit,F00) 'ERROR 200 on char num read '
00759 call shr_string_abort(subName//' ERROR on char num read')
00760 if (debug>1) call shr_timer_stop (t01)
00761 return
00762
00763 end subroutine shr_string_parseCFtunit
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780 subroutine shr_string_clean(string,rc)
00781
00782 implicit none
00783
00784
00785
00786 character(*) ,intent(inout) :: string
00787 integer(SHR_KIND_IN),optional,intent(out) :: rc
00788
00789
00790
00791
00792 integer(SHR_KIND_IN) :: n
00793 integer(SHR_KIND_IN) :: rCode
00794 integer(SHR_KIND_IN) :: t01 = 0
00795
00796
00797 character(*),parameter :: subName = "(shr_string_clean) "
00798 character(*),parameter :: F00 = "('(shr_string_clean) ',4a)"
00799
00800
00801
00802
00803
00804 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00805 if (debug>1) call shr_timer_start(t01)
00806
00807 rCode = 0
00808 string = ' '
00809 if (present(rc)) rc = rCode
00810 if (debug>1) call shr_timer_stop (t01)
00811
00812 end subroutine shr_string_clean
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 logical function shr_string_listIsValid(list,rc)
00830
00831 implicit none
00832
00833
00834
00835 character(*) ,intent(in) :: list
00836 integer(SHR_KIND_IN),optional,intent(out) :: rc
00837
00838
00839
00840
00841 integer (SHR_KIND_IN) :: nChar
00842 integer (SHR_KIND_IN) :: rCode
00843 integer (SHR_KIND_IN) :: t01 = 0
00844
00845
00846 character(*),parameter :: subName = "(shr_string_listIsValid) "
00847 character(*),parameter :: F00 = "('(shr_string_listIsValid) ',4a)"
00848
00849
00850
00851
00852
00853 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00854 if (debug>1) call shr_timer_start(t01)
00855
00856 rCode = 0
00857 shr_string_listIsValid = .true.
00858
00859 nChar = len_trim(list)
00860 if (nChar < 1) then
00861 rCode = 1
00862 else if ( list(1:1) == listDel ) then
00863 rCode = 2
00864 else if (list(nChar:nChar) == listDel ) then
00865 rCode = 3
00866 else if (index(trim(list)," " ) > 0) then
00867 rCode = 4
00868 else if (index(trim(list),listDel2) > 0) then
00869 rCode = 5
00870 end if
00871
00872 if (rCode /= 0) then
00873 shr_string_listIsValid = .false.
00874 if (s_loglev > 0) write(s_logunit,F00) "WARNING: invalid list = ",trim(list)
00875 endif
00876
00877 if (present(rc)) rc = rCode
00878 if (debug>1) call shr_timer_stop (t01)
00879
00880 end function shr_string_listIsValid
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 subroutine shr_string_listGetName(list,k,name,rc)
00898
00899 implicit none
00900
00901
00902
00903 character(*) ,intent(in) :: list
00904 integer(SHR_KIND_IN) ,intent(in) :: k
00905 character(*) ,intent(out) :: name
00906 integer(SHR_KIND_IN),optional,intent(out) :: rc
00907
00908
00909
00910
00911 integer(SHR_KIND_IN) :: i,j,n
00912 integer(SHR_KIND_IN) :: kFlds
00913 integer(SHR_KIND_IN) :: i0,i1
00914 integer(SHR_KIND_IN) :: rCode
00915 integer(SHR_KIND_IN) :: t01 = 0
00916
00917
00918 character(*),parameter :: subName = "(shr_string_listGetName) "
00919 character(*),parameter :: F00 = "('(shr_string_listGetName) ',4a)"
00920
00921
00922
00923
00924
00925 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
00926 if (debug>1) call shr_timer_start(t01)
00927
00928 rCode = 0
00929
00930
00931 if (.not. shr_string_listIsValid(list,rCode) ) then
00932 write(s_logunit,F00) "ERROR: invalid list = ",trim(list)
00933 call shr_string_abort(subName//" ERROR: invalid list = "//trim(list))
00934 end if
00935
00936
00937 kFlds = shr_string_listGetNum(list)
00938 if (k<1 .or. kFlds<k) then
00939 write(s_logunit,*) subName,"ERROR: invalid index = ",k
00940 write(s_logunit,*) subName,"ERROR: list = ",trim(list)
00941 call shr_string_abort(subName//" ERROR: invalid index")
00942 end if
00943
00944
00945 i0 = 1
00946 i1 = len_trim(list)
00947
00948
00949 do n=2,k
00950 i = index(list(i0:i1),listDel)
00951 i0 = i0 + i
00952 end do
00953
00954
00955 if ( k < kFlds ) then
00956 i = index(list(i0:i1),listDel)
00957 i1 = i0 + i - 2
00958 end if
00959
00960
00961 name = list(i0:i1)//" "
00962
00963 if (present(rc)) rc = rCode
00964 if (debug>1) call shr_timer_stop (t01)
00965
00966 end subroutine shr_string_listGetName
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 subroutine shr_string_listIntersect(list1,list2,listout,rc)
00984
00985 implicit none
00986
00987
00988
00989 character(*) ,intent(in) :: list1
00990 character(*) ,intent(in) :: list2
00991 character(*) ,intent(out) :: listout
00992 integer(SHR_KIND_IN),optional,intent(out) :: rc
00993
00994
00995
00996
00997 integer(SHR_KIND_IN) :: nf,n1,n2
00998 character(SHR_KIND_CS) :: name
00999 integer(SHR_KIND_IN) :: rCode
01000 integer(SHR_KIND_IN) :: t01 = 0
01001
01002
01003 character(*),parameter :: subName = "(shr_string_listIntersect) "
01004 character(*),parameter :: F00 = "('(shr_string_listIntersect) ',4a)"
01005
01006
01007
01008
01009
01010 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01011 if (debug>1) call shr_timer_start(t01)
01012
01013 rCode = 0
01014
01015 nf = shr_string_listGetNum(list1)
01016 call shr_string_clean(listout)
01017 do n1 = 1,nf
01018 call shr_string_listGetName(list1,n1,name,rCode)
01019 n2 = shr_string_listGetIndexF(list2,name)
01020 if (n2 > 0) then
01021 call shr_string_listAppend(listout,name)
01022 endif
01023 enddo
01024
01025 if (present(rc)) rc = rCode
01026 if (debug>1) call shr_timer_stop (t01)
01027
01028 end subroutine shr_string_listIntersect
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045 subroutine shr_string_listUnion(list1,list2,listout,rc)
01046
01047 implicit none
01048
01049
01050
01051 character(*) ,intent(in) :: list1
01052 character(*) ,intent(in) :: list2
01053 character(*) ,intent(out) :: listout
01054 integer(SHR_KIND_IN),optional,intent(out) :: rc
01055
01056
01057
01058
01059 integer(SHR_KIND_IN) :: nf,n1,n2
01060 character(SHR_KIND_CS) :: name
01061 integer(SHR_KIND_IN) :: rCode
01062 integer(SHR_KIND_IN) :: t01 = 0
01063
01064
01065 character(*),parameter :: subName = "(shr_string_listUnion) "
01066 character(*),parameter :: F00 = "('(shr_string_listUnion) ',4a)"
01067
01068
01069
01070
01071
01072 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01073 if (debug>1) call shr_timer_start(t01)
01074 rCode = 0
01075
01076 call shr_string_clean(listout)
01077
01078 nf = shr_string_listGetNum(list1)
01079 do n1 = 1,nf
01080 call shr_string_listGetName(list1,n1,name,rCode)
01081 n2 = shr_string_listGetIndexF(listout,name)
01082 if (n2 < 1) then
01083 call shr_string_listAppend(listout,name)
01084 endif
01085 enddo
01086
01087 nf = shr_string_listGetNum(list2)
01088 do n1 = 1,nf
01089 call shr_string_listGetName(list2,n1,name,rCode)
01090 n2 = shr_string_listGetIndexF(listout,name)
01091 if (n2 < 1) then
01092 call shr_string_listAppend(listout,name)
01093 endif
01094 enddo
01095
01096 if (present(rc)) rc = rCode
01097 if (debug>1) call shr_timer_stop (t01)
01098
01099 end subroutine shr_string_listUnion
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 subroutine shr_string_listMerge(list1,list2,listout,rc)
01118
01119 implicit none
01120
01121
01122 character(*) ,intent(in) :: list1
01123 character(*) ,intent(in) :: list2
01124 character(*) ,intent(out) :: listout
01125 integer(SHR_KIND_IN),optional,intent(out) :: rc
01126
01127
01128
01129
01130 character(SHR_KIND_CX) :: l1,l2
01131 integer(SHR_KIND_IN) :: rCode
01132 integer(SHR_KIND_IN) :: t01 = 0
01133
01134
01135 character(*),parameter :: subName = "(shr_string_listMerge) "
01136 character(*),parameter :: F00 = "('(shr_string_listMerge) ',4a)"
01137
01138
01139
01140
01141
01142
01143 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01144 if (debug>1) call shr_timer_start(t01)
01145 rCode = 0
01146
01147
01148 if ( (len(l1) < len_trim(list1)) .or. (len(l2) < len_trim(list2))) then
01149 call shr_string_abort(subName//'ERROR: temp string not large enough')
01150 end if
01151
01152 call shr_string_clean(l1)
01153 call shr_string_clean(l2)
01154 call shr_string_clean(listout)
01155 l1 = trim(list1)
01156 l2 = trim(list2)
01157 call shr_string_leftAlign(l1,rCode)
01158 call shr_string_leftAlign(l2,rCode)
01159 if (len_trim(l1)+len_trim(l2)+1 > len(listout)) &
01160 call shr_string_abort(subName//'ERROR: output list string not large enough')
01161 if (len_trim(l1) == 0) then
01162 listout = trim(l2)
01163 else
01164 listout = trim(l1)//":"//trim(l2)
01165 endif
01166
01167 if (present(rc)) rc = rCode
01168 if (debug>1) call shr_timer_stop (t01)
01169
01170 end subroutine shr_string_listMerge
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187 subroutine shr_string_listAppend(list,listadd,rc)
01188
01189 implicit none
01190
01191
01192
01193 character(*) ,intent(inout) :: list
01194 character(*) ,intent(in) :: listadd
01195 integer(SHR_KIND_IN),optional,intent(out) :: rc
01196
01197
01198
01199
01200 character(SHR_KIND_CX) :: l1
01201 integer(SHR_KIND_IN) :: rCode
01202 integer(SHR_KIND_IN) :: t01 = 0
01203
01204
01205 character(*),parameter :: subName = "(shr_string_listAppend) "
01206 character(*),parameter :: F00 = "('(shr_string_listAppend) ',4a)"
01207
01208
01209
01210
01211
01212
01213 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01214 if (debug>1) call shr_timer_start(t01)
01215 rCode = 0
01216
01217
01218 if (len(l1) < len_trim(listAdd)) then
01219 call shr_string_abort(subName//'ERROR: temp string not large enough')
01220 end if
01221
01222 call shr_string_clean(l1)
01223 l1 = trim(listadd)
01224 call shr_string_leftAlign(l1,rCode)
01225 if (len_trim(list)+len_trim(l1)+1 > len(list)) &
01226 call shr_string_abort(subName//'ERROR: output list string not large enough')
01227 if (len_trim(list) == 0) then
01228 list = trim(l1)
01229 else
01230 list = trim(list)//":"//trim(l1)
01231 endif
01232
01233 if (present(rc)) rc = rCode
01234 if (debug>1) call shr_timer_stop (t01)
01235
01236 end subroutine shr_string_listAppend
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 subroutine shr_string_listPrepend(listadd,list,rc)
01256
01257 implicit none
01258
01259
01260
01261 character(*) ,intent(in) :: listadd
01262 character(*) ,intent(inout) :: list
01263 integer(SHR_KIND_IN),optional,intent(out) :: rc
01264
01265
01266
01267
01268 character(SHR_KIND_CX) :: l1
01269 integer(SHR_KIND_IN) :: rCode
01270 integer(SHR_KIND_IN) :: t01 = 0
01271
01272
01273 character(*),parameter :: subName = "(shr_string_listPrepend) "
01274 character(*),parameter :: F00 = "('(shr_string_listPrepend) ',4a)"
01275
01276
01277
01278
01279
01280
01281 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01282 if (debug>1) call shr_timer_start(t01)
01283 rCode = 0
01284
01285
01286 if (len(l1) < len_trim(listAdd)) then
01287 call shr_string_abort(subName//'ERROR: temp string not large enough')
01288 end if
01289
01290 call shr_string_clean(l1)
01291 l1 = trim(listadd)
01292 call shr_string_leftAlign(l1,rCode)
01293 call shr_string_leftAlign(list,rCode)
01294 if (len_trim(list)+len_trim(l1)+1 > len(list)) &
01295 call shr_string_abort(subName//'ERROR: output list string not large enough')
01296 if (len_trim(l1) == 0) then
01297 list = trim(list)
01298 else
01299 list = trim(l1)//":"//trim(list)
01300 endif
01301
01302 if (present(rc)) rc = rCode
01303 if (debug>1) call shr_timer_stop (t01)
01304
01305 end subroutine shr_string_listPrepend
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 integer function shr_string_listGetIndexF(string,fldStr)
01323
01324 implicit none
01325
01326
01327
01328 character(*),intent(in) :: string
01329 character(*),intent(in) :: fldStr
01330
01331
01332
01333
01334 integer(SHR_KIND_IN) :: k
01335 integer(SHR_KIND_IN) :: rc
01336 integer(SHR_KIND_IN) :: t01 = 0
01337
01338
01339 character(*),parameter :: subName = "(shr_string_listGetIndexF) "
01340 character(*),parameter :: F00 = "('(shr_string_listGetIndexF) ',4a)"
01341
01342
01343
01344 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01345 if (debug>1) call shr_timer_start(t01)
01346
01347 call shr_string_listGetIndex(string,fldStr,k,print=.false.,rc=rc)
01348 shr_string_listGetIndexF = k
01349
01350 if (debug>1) call shr_timer_stop (t01)
01351
01352 end function shr_string_listGetIndexF
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369 subroutine shr_string_listGetIndex(string,fldStr,kFld,print,rc)
01370
01371 implicit none
01372
01373
01374
01375 character(*) ,intent(in) :: string
01376 character(*) ,intent(in) :: fldStr
01377 integer(SHR_KIND_IN),intent(out) :: kFld
01378 logical ,intent(in) ,optional :: print
01379 integer(SHR_KIND_IN),intent(out),optional :: rc
01380
01381
01382
01383
01384 integer(SHR_KIND_IN) :: n
01385 integer(SHR_KIND_IN) :: k
01386 integer(SHR_KIND_IN) :: nFields
01387 integer(SHR_KIND_IN) :: i0,i1
01388 integer(SHR_KIND_IN) :: j0,j1
01389 logical :: found
01390 logical :: lprint
01391 integer(SHR_KIND_IN) :: t01 = 0
01392
01393
01394 character(*),parameter :: subName = "(shr_string_listGetIndex) "
01395 character(*),parameter :: F00 = "('(shr_string_listGetIndex) ',4a)"
01396
01397
01398
01399
01400
01401
01402
01403
01404 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01405 if (debug>1) call shr_timer_start(t01)
01406 if (present(rc)) rc = 0
01407
01408 lprint = .false.
01409 if (present(print)) lprint = print
01410
01411
01412 if (len_trim(fldStr) < 1) then
01413 if (lprint) write(s_logunit,F00) "ERROR: input field name has 0 length"
01414 call shr_string_abort(subName//"invalid field name")
01415 end if
01416
01417
01418 found = .false.
01419 kFld = 0
01420 i0 = 1
01421 i1 = -1
01422 j0 = -1
01423 j1 = len_trim(string)
01424 nFields = shr_string_listGetNum(string)
01425 do k = 1,nFields
01426
01427
01428
01429
01430 n = index(string(i0:len_trim(string)),listDel)
01431 if (n > 0) then
01432 i1 = i0 + n - 2
01433 else
01434 i1 = len_trim(string)
01435 endif
01436
01437
01438
01439
01440
01441 if (trim(fldStr) == string(i0:i1)) then
01442 found = .true.
01443 kFld = k
01444 exit
01445 endif
01446 i0 = i1 + 2
01447
01448
01449
01450
01451 n = index(string(1:j1),listDel,back=.true.)
01452 j0 = n + 1
01453
01454
01455
01456
01457
01458 if (trim(fldStr) == string(j0:j1)) then
01459 found = .true.
01460 kFld = nFields + 1 - k
01461 exit
01462 endif
01463 j1 = j0 - 2
01464
01465
01466
01467 if (2*k >= nFields) exit
01468 end do
01469
01470
01471 if (.not. found) then
01472 kFld = 0
01473 if (lprint .and. s_loglev > 0) write(s_logunit,F00) "FYI: field ",trim(fldStr)," not found in list ",trim(string)
01474 if (present(rc)) rc = 1
01475 end if
01476
01477 if (debug>1) call shr_timer_stop (t01)
01478
01479 end subroutine shr_string_listGetIndex
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494 integer function shr_string_listGetNum(str)
01495
01496 implicit none
01497
01498
01499
01500 character(*),intent(in) :: str
01501
01502
01503
01504
01505 integer(SHR_KIND_IN) :: count
01506 integer(SHR_KIND_IN) :: t01 = 0
01507
01508
01509 character(*),parameter :: subName = "(shr_string_listGetNum) "
01510 character(*),parameter :: F00 = "('(shr_string_listGetNum) ',4a)"
01511
01512
01513
01514
01515
01516 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01517 if (debug>1) call shr_timer_start(t01)
01518
01519 shr_string_listGetNum = 0
01520
01521 if (len_trim(str) > 0) then
01522 count = shr_string_countChar(str,listDel)
01523 shr_string_listGetNum = count + 1
01524 endif
01525
01526 if (debug>1) call shr_timer_stop (t01)
01527
01528 end function shr_string_listGetNum
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545 subroutine shr_string_listSetDel(cflag)
01546
01547 implicit none
01548
01549
01550
01551 character(len=1),intent(in) :: cflag
01552
01553
01554
01555 integer(SHR_KIND_IN) :: t01 = 0
01556
01557
01558 character(*),parameter :: subName = "(shr_string_listSetDel) "
01559 character(*),parameter :: F00 = "('(shr_string_listSetDel) ',a) "
01560
01561
01562
01563 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01564 if (debug>1) call shr_timer_start(t01)
01565
01566 if (debug > 0 .and. s_loglev > 0) write(s_logunit,F00) 'changing listDel from '//trim(listDel)//' to '//trim(cflag)
01567 listDel = trim(cflag)
01568 listDel2 = listDel//listDel
01569
01570 if (debug>1) call shr_timer_stop (t01)
01571
01572 end subroutine shr_string_listSetDel
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589 subroutine shr_string_listGetDel(del)
01590
01591 implicit none
01592
01593
01594
01595 character(*),intent(out) :: del
01596
01597
01598
01599 integer(SHR_KIND_IN) :: t01 = 0
01600
01601
01602 character(*),parameter :: subName = "(shr_string_listGetDel) "
01603 character(*),parameter :: F00 = "('(shr_string_listGetDel) ',a) "
01604
01605
01606
01607 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01608 if (debug>1) call shr_timer_start(t01)
01609
01610 del = trim(listDel)
01611
01612 if (debug>1) call shr_timer_stop (t01)
01613
01614 end subroutine shr_string_listGetDel
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631 subroutine shr_string_setAbort(flag)
01632
01633 implicit none
01634
01635
01636
01637 logical,intent(in) :: flag
01638
01639
01640
01641 integer(SHR_KIND_IN) :: t01 = 0
01642
01643
01644 character(*),parameter :: subName = "(shr_string_setAbort) "
01645 character(*),parameter :: F00 = "('(shr_string_setAbort) ',a) "
01646
01647
01648
01649 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01650 if (debug>1) call shr_timer_start(t01)
01651
01652 if (debug > 0 .and. s_loglev > 0) then
01653 if (flag) then
01654 write(s_logunit,F00) 'setting abort to true'
01655 else
01656 write(s_logunit,F00) 'setting abort to false'
01657 endif
01658 endif
01659
01660 doabort = flag
01661
01662 if (debug>1) call shr_timer_stop (t01)
01663
01664 end subroutine shr_string_setAbort
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681 subroutine shr_string_setDebug(iFlag)
01682
01683 implicit none
01684
01685
01686
01687 integer(SHR_KIND_IN),intent(in) :: iFlag
01688
01689
01690
01691
01692 integer(SHR_KIND_IN) :: t01 = 0
01693
01694
01695 character(*),parameter :: subName = "(shr_string_setDebug) "
01696 character(*),parameter :: F00 = "('(shr_string_setDebug) ',a) "
01697 character(*),parameter :: F01 = "('(shr_string_setDebug) ',a,i3,a,i3) "
01698
01699
01700
01701
01702
01703 if (iFlag>1 .and. t01<1) call shr_timer_get(t01,subName)
01704 if (iFlag>1) call shr_timer_start(t01)
01705
01706
01707 debug = iFlag
01708
01709 if (iFlag>1) call shr_timer_stop (t01)
01710
01711 end subroutine shr_string_setDebug
01712
01713
01714
01715
01716 subroutine shr_string_abort(string)
01717
01718 implicit none
01719
01720
01721
01722 character(*),optional,intent(in) :: string
01723
01724
01725
01726 integer(SHR_KIND_IN) :: t01 = 0
01727
01728
01729 character(SHR_KIND_CX) :: lstring
01730 character(*),parameter :: subName = "(shr_string_abort)"
01731 character(*),parameter :: F00 = "('(shr_string_abort) ',a)"
01732
01733
01734
01735
01736
01737
01738 if (debug>1 .and. t01<1) call shr_timer_get(t01,subName)
01739 if (debug>1) call shr_timer_start(t01)
01740
01741 lstring = ''
01742 if (present(string)) lstring = string
01743
01744 if (doabort) then
01745 call shr_sys_abort(trim(lstring))
01746 else
01747 write(s_logunit,F00) ' no abort:'//trim(lstring)
01748 endif
01749
01750 if (debug>1) call shr_timer_stop (t01)
01751
01752 end subroutine shr_string_abort
01753
01754
01755
01756
01757 end module shr_string_mod