LCOV - code coverage report
Current view: top level - src - mo_string_utils.f90 (source / functions) Hit Total Coverage
Test: forces coverage Lines: 123 163 75.5 %
Date: 2024-03-13 19:03:28 Functions: 18 20 90.0 %

          Line data    Source code
       1             : !> \file mo_string_utils.f90
       2             : !> \brief \copybrief mo_string_utils
       3             : !> \details \copydetails mo_string_utils
       4             : 
       5             : !> \brief String utilities
       6             : !> \details This module provides string conversion and checking utilities.
       7             : !> \authors Matthias Cuntz, Matthias Zink, Giovanni Dalmasso, David Schaefer
       8             : !> \date Dec 2011
       9             : !> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
      10             : !! FORCES is released under the LGPLv3+ license \license_note
      11             : MODULE mo_string_utils
      12             : 
      13             :   USE mo_kind, ONLY: i4, i8, sp, dp
      14             : 
      15             :   IMPLICIT NONE
      16             : 
      17             :   PUBLIC :: compress      ! Conversion   : 'A b C x Y z' -> 'AbCxYz'
      18             :   PUBLIC :: divide_string ! split string in substring with the help of delimiter
      19             :   PUBLIC :: equalStrings  ! compares two strings
      20             :   PUBLIC :: nonull        ! Check if string is still NULL
      21             :   PUBLIC :: num2str       ! Convert a number to a string
      22             :   PUBLIC :: separator     ! Format string: '-----...-----'
      23             :   PUBLIC :: splitString   ! splits string at given delimiter
      24             :   PUBLIC :: startswith    ! checks if string starts with a certain prefix
      25             :   PUBLIC :: endswith      ! checks if string ends with a certain suffix
      26             :   PUBLIC :: str2num       ! Converts string into an array of its numerical representation
      27             :   PUBLIC :: tolower       ! Conversion   : 'ABCXYZ' -> 'abcxyz'
      28             :   PUBLIC :: toupper       ! Conversion   : 'abcxyz' -> 'ABCXYZ'
      29             :   PUBLIC :: Replace_Text  ! replaces all text occurences in string
      30             :   PUBLIC :: replace_word  ! replaces all word occurences in string
      31             :   PUBLIC :: index_word    ! yields starting position of word in string or 0
      32             :   PUBLIC :: is_blank
      33             : 
      34             :   ! public :: numarray2str
      35             : 
      36             :   ! ------------------------------------------------------------------
      37             : 
      38             :   !>    \brief Convert to string.
      39             : 
      40             :   !>    \details Convert a number or logical to a string with an optional format.
      41             :   !!
      42             :   !!    \b Example
      43             :   !!
      44             :   !!    \code{.f90}
      45             :   !!    str = num2str(3.1415217_i4,'(F3.1)')
      46             :   !!    \endcode
      47             :   !!    See also example in test directory.
      48             : 
      49             :   !>    \param[in] "integer(i4/i8)/real(sp/dp)/logical :: num"  Number or logical
      50             :   !>    \param[in] "character(len=*), optional :: form"         Format string\n
      51             :   !!                                                            Defaults are:\n
      52             :   !!                                                            i4    - '(I10)'\n
      53             :   !!                                                            i8    - '(I20)'\n
      54             :   !!                                                            sp/dp - '(G32.5)'\n
      55             :   !!                                                            log   - '(L10)'
      56             :   !>    \retval "character(len=X) :: str"                       String of formatted input number or logical\n
      57             :   !!                                                            Output length X is:\n
      58             :   !!                                                            i4    - 10\n
      59             :   !!                                                            i8    - 20\n
      60             :   !!                                                            sp/dp - 32\n
      61             :   !!                                                            log   - 10
      62             : 
      63             :   !>    \note
      64             :   !!    Uses WRITE to write into string. Recursive write is not permitted before Fortran 2003
      65             :   !!    so that one cannot use\n
      66             :   !!    \code{.f90}
      67             :   !!    write(*,*) 'A='//num2str(a)
      68             :   !!    \endcode
      69             :   !!    Use 'call message' from mo_messages.f90
      70             :   !!    \code{.f90}
      71             :   !!    use mo_messages, only message
      72             :   !!    call message('A=', trim(num2str(a)))
      73             :   !!    \endcode
      74             :   !!    or write into another string first:
      75             :   !!    \code{.f90}
      76             :   !!    str = 'A='//num2str(a)
      77             :   !!    write(*,*) trim(str)
      78             :   !!    \endcode
      79             : 
      80             :   !>    \author Matthias Cuntz
      81             :   !>    \date Dec 2011
      82             :   !!        - modified from Echam5, (C) MPI-MET, Hamburg, Germany
      83             :   INTERFACE num2str
      84             :      MODULE PROCEDURE i42str, i82str, sp2str, dp2str, log2str
      85             :   END INTERFACE num2str
      86             : 
      87             : 
      88             :   ! ------------------------------------------------------------------
      89             : 
      90             :   !>    \brief Convert to string.
      91             : 
      92             :   !>    \details Convert a array of numbers or logicals to a string.
      93             :   !!
      94             :   !!    \b Example
      95             :   !!
      96             :   !!    \code{.f90}
      97             :   !!    str = numarray2str(num)
      98             :   !!    \endcode
      99             : 
     100             :   !>    \param[in] "integer(i4/i8)/real(sp/dp)/logical :: num(:)"    Array of numbers or logicals
     101             :   !>    \retval "character(len=X) :: str"                            String of formatted input number or logical\n
     102             : 
     103             :   !>    \author Matthias Cuntz
     104             :   !>    \date Dec 2011
     105             :   !!        - modified from Echam5, (C) MPI-MET, Hamburg, Germany
     106             :   INTERFACE numarray2str
     107             :      MODULE PROCEDURE i4array2str
     108             :   END INTERFACE numarray2str
     109             : 
     110             :   ! ------------------------------------------------------------------
     111             : 
     112             :   PRIVATE
     113             : 
     114             :   ! ------------------------------------------------------------------
     115             :   !> separator string (line)
     116             :   CHARACTER(len=*), PARAMETER :: separator = repeat('-',70)
     117             : 
     118             :   ! ------------------------------------------------------------------
     119             : 
     120             : CONTAINS
     121             : 
     122             :   !> \brief   Check for blank characters.
     123             :   !> \details Checks whether or not `c` is a blank character, namely a space and tab character.
     124             :   !> \return  Truth value if `c` is a blank.
     125          18 :   pure logical function is_blank(c)
     126             : 
     127             :     character(len=1), intent(in) :: c !< The character to test.
     128             :     integer :: ic
     129             : 
     130          18 :     ic = iachar(c)             ! TAB
     131          18 :     is_blank = (c == ' ') .or. (ic == int(z'09'));
     132             : 
     133          18 :   end function is_blank
     134             : 
     135             :   ! ------------------------------------------------------------------
     136             : 
     137             :   !>    \brief Remove white spaces
     138             : 
     139             :   !>    \details Return a copy of an input string with all whitespace (spaces and tabs) removed
     140             :   !!
     141             :   !!    \b Example
     142             :   !!
     143             :   !!    Returns 'Hallo'
     144             :   !!    \code{.f90}
     145             :   !!    noSpaces = whiteSpaces = compress('H a l l o')
     146             :   !!    \endcode
     147             : 
     148             :   !>     \param[in] "character(len=*) :: whiteSpaces"             String
     149             :   !>     \param[out] "integer(i4), optional :: n"                 Integer
     150             :   !>     \retval "character(len = len(whiteSpaces)) :: compress"  String where all all whitespace (spaces and tabs) are removed
     151             : 
     152             :   !>     \author Giovanni Dalmasso
     153             :   !>     \date Jan 2013
     154             :   !!        - modified from Paul van Delst, CIMSS/SSEC 18-Oct-1999
     155             : 
     156          34 :   function compress( whiteSpaces, n )
     157             : 
     158          18 :         use mo_kind,    only : i4
     159             : 
     160             :         implicit none
     161             : 
     162             :         character(len=*),               intent(in)  :: whiteSpaces
     163             :         integer(i4),        optional,   intent(out) :: n
     164             : 
     165             :         character(len(whiteSpaces))                 ::  compress
     166             : 
     167             :         ! Local parameters
     168             :         integer(i4),    parameter                   :: iachar_space = 32_i4
     169             :         integer(i4),    parameter                   :: iachar_tab   = 9_i4
     170             : 
     171             :         ! Local variables
     172             :         integer(i4)                                 :: i, j
     173             :         integer(i4)                                 :: iachar_character
     174             : 
     175             :         ! Setup
     176             : 
     177             :         ! Initialise compress
     178          34 :         compress = ' '
     179             :         ! Initialise counter
     180             :         j = 0_i4
     181             : 
     182             :         ! Loop over string
     183         418 :         do i = 1, len(whiteSpaces)
     184             :             ! Convert the current character to its position
     185         384 :             iachar_character = iachar(whiteSpaces(i:i))
     186             : 
     187             :             ! If the character is NOT a space ' ' or a tab '->|' copy it to the output string.
     188         418 :             if ( iachar_character /= iachar_space .and. iachar_character /= iachar_tab )    then
     189         137 :                 j = j + 1
     190         137 :                 compress(j:j) = whiteSpaces(i:i)
     191             :             end if
     192             :         end do
     193             : 
     194             :         ! Save the non-whitespace count
     195          34 :         if ( present(n) ) n = j
     196             : 
     197          68 :     end function compress
     198             : 
     199             :     ! replaces text
     200             :     ! e.g. replace_text('our hour', 'our', 'their') --> 'their htheir'
     201           1 :     function replace_text (s,text,rep)  result(outs)
     202             :       character(*)        :: s,text,rep
     203             :       character(len(s)+100) :: outs     ! provide outs with extra 100 char len
     204             :       integer             :: i, nt, nr
     205             : 
     206           1 :       outs = s ; nt = len_trim(text) ; nr = len_trim(rep)
     207           1 :       if (text == rep) return
     208           2 :       do
     209           3 :          i = index(outs,text(:nt)) ; if (i == 0) exit
     210           3 :          outs = outs(:i-1) // rep(:nr) // outs(i+nt:)
     211             :       end do
     212          35 :     end function replace_text
     213             : 
     214             :     !> \brief replaces words in a string
     215             :     !> \details replaces proper words only, e.g. replace_word('our hour', 'our', 'their') --> 'their hour'
     216             :     !> \author Robert Schweppe
     217             :     !> \date Nov 2018
     218           0 :     function replace_word(s, word, rep, check_negative_number_arg)  result(outs)
     219             :       character(*) :: s, word, rep
     220             :       logical, optional  :: check_negative_number_arg
     221             :       character(len(s)+100) :: outs     ! provide outs with extra 100 char len
     222             :       integer               :: i, nt, nr
     223             : 
     224           0 :       outs = s ; nt = len_trim(word) ; nr = len_trim(rep)
     225           0 :       if (word == rep) return
     226           0 :       do
     227           0 :         i = index_word(outs, word(:nt), check_negative_number_arg)
     228           0 :         if (i == 0) exit
     229           0 :         outs = outs(:i-1) // rep(:nr) // outs(i+nt:)
     230             :       end do
     231           1 :     end function replace_word
     232             : 
     233             :     !> \brief find index in word
     234             :     !> \author Robert Schweppe
     235             :     !> \date Nov 2018
     236           0 :     function index_word(s, text, check_negative_number_arg) result(out_index)
     237             :     CHARACTER(*)       :: s
     238             :     CHARACTER(*)       :: text
     239             :     logical, optional  :: check_negative_number_arg
     240             :     integer :: out_index
     241             : 
     242             :     integer :: i, nw, ns, i_add
     243             :     logical :: is_begin_not_word, check_negative_number_default
     244             :     character(63), parameter :: word_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
     245             :     character(10), parameter :: digit_chars = '0123456789'
     246             : 
     247           0 :     check_negative_number_default = .false.
     248           0 :     if (present(check_negative_number_arg)) then
     249           0 :       check_negative_number_default = check_negative_number_arg
     250             :     end if
     251             : 
     252           0 :     nw = LEN_TRIM(text) ; ns = LEN_TRIM(s)
     253           0 :     out_index = 0
     254           0 :     i = 1
     255           0 :     scan_loop: DO
     256             :       ! find index of the first character of word in string that has not been scanned so far
     257           0 :       i_add = scan(s(i:ns), text(1:1))
     258           0 :       i = i + i_add - 1
     259           0 :       if (i_add == 0 .or. i+nw-1 > ns) then
     260             :         ! the word cannot be in string as the first char is not even contained or
     261             :         ! the word cannot be in string starting at i as it would be too long
     262             :         exit
     263           0 :       else if (s(i:i+nw-1) == trim(text)) then
     264             :         ! charachter matches the word
     265           0 :         is_begin_not_word = .true.
     266           0 :         if (i-1 > 0) then
     267             :           ! is the word preceded by a alphanumeric character?
     268           0 :           if (scan(s(i-1:i-1), word_chars) == 1) then
     269             :             is_begin_not_word = .false.
     270             :           else if (check_negative_number_default .and. &
     271           0 :                    scan(s(i-1:i-1), '-') == 1 .and. &
     272             :                    scan(digit_chars, text(1:1)) > 0 ) then
     273             :             is_begin_not_word = .false.
     274             :           end if
     275             :         end if
     276             :         if (is_begin_not_word) then
     277             :           ! is the word succeeded by a alphanumeric character?
     278           0 :           if (scan(s(i+nw:i+nw), word_chars) == 1) then
     279             :             ! word boundary end is violated, continue
     280             :             i = i + 1
     281             :           else
     282             :             ! index is found and word boundaries are checked
     283           0 :             out_index = i
     284           0 :             exit scan_loop
     285             :           end if
     286             :         else
     287             :           ! word boundary start is violated, continue
     288             :           i = i + 1
     289             :         end if
     290             :       else
     291             :         ! word does not match, continue
     292             :         i = i + 1
     293             :       end if
     294             :     END DO scan_loop
     295             : 
     296           0 :   end function index_word
     297             : 
     298             :   ! ------------------------------------------------------------------
     299             : 
     300             :   !>    \brief Divide string in substrings.
     301             : 
     302             :   !>    \details Divides a string in several substrings (array of strings) with the help of a user
     303             :   !!    specified delimiter.
     304             :   !!
     305             :   !!    \b Example
     306             :   !!
     307             :   !!    Divide string into 'I', 'want', 'to', ...
     308             :   !!    \code{.f90}
     309             :   !!    divide_string('I want to test this routine!', ' ', strArr(:))
     310             :   !!    \endcode
     311             : 
     312             :   !>    \param[in] "CHARACTER(len=*), INTENT(IN) :: string"     - string to be divided
     313             :   !>    \param[in] "CHARACTER(len=*), INTENT(IN) :: delim"      - delimiter specifying places for division
     314             :   !>    \param[out] "CHARACTER(len=*), DIMENSION(:), ALLOCATABLE,  INTENT(OUT) :: strArr"
     315             :   !!                 Array of substrings, has to be allocateable and is handed to the routine unallocated
     316             : 
     317             :   !>    \note
     318             :   !!    only character types allowed.\n
     319             :   !!    output array should be allocateable array, which is unallocated handed to the subroutine.
     320             :   !!    allocation is done in in devide_string.
     321             : 
     322             :   !>    \author Matthias Zink
     323             :   !>    \date Oct 2012
     324             : 
     325          23 :   SUBROUTINE divide_string(string, delim, strArr)
     326             : 
     327             :     IMPLICIT NONE
     328             : 
     329             :     CHARACTER(len=*)             , INTENT(IN)        :: string
     330             :     CHARACTER(len=*)             , INTENT(IN)        :: delim
     331             :     CHARACTER(len=*), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: strArr
     332             : 
     333             :     CHARACTER(256)                                   :: stringDummy   ! string in fisrt place but cutted in pieces
     334          23 :     CHARACTER(256), DIMENSION(:) , ALLOCATABLE       :: strDummyArr   ! Dummy arr until number of substrings is known
     335             :     INTEGER(i4)                                      :: pos           ! position of dilimiter
     336             :     INTEGER(i4)                                      :: nosubstr      ! number of substrings in string
     337             : 
     338          23 :     stringDummy = string
     339             : 
     340          69 :     allocate(strDummyArr(len_trim(stringDummy)))
     341          23 :     pos=999_i4
     342          23 :     nosubstr=0_i4
     343             :     ! search for substrings and theirs count
     344             :     do
     345          78 :        pos = index(trim(adjustl(stringDummy)), delim)
     346             :        ! exit if no more delimiter is find and save the last part of the string
     347          78 :        if (pos == 0_i4) then
     348          23 :           nosubstr = nosubstr + 1_i4
     349          23 :           StrDummyArr(nosubstr) = trim(stringDummy)
     350             :           exit
     351             :        end if
     352             : 
     353          55 :        nosubstr = nosubstr + 1_i4
     354          55 :        strDummyArr(nosubstr) = stringDummy(1:pos-1)
     355          55 :        stringDummy = stringDummy(pos+1:len_trim(stringDummy))
     356             :     end do
     357             :     ! hand over results to strArr
     358          23 :     if (nosubstr == 0_i4) then
     359           0 :        print*, '***WARNING: string does not contain delimiter. There are no substrings. (subroutine DIVIDE_STRING)'
     360           0 :        return
     361             :     else
     362          69 :        allocate(strArr(nosubstr))
     363         124 :        strArr = StrDummyArr(1:nosubstr)
     364             :     end if
     365             : 
     366          23 :     deallocate(strDummyArr)
     367             : 
     368          23 :   END SUBROUTINE divide_string
     369             : 
     370             :     ! ------------------------------------------------------------------
     371             : 
     372             :   !>    \brief Checks if two string are equal
     373             : 
     374             :   !>    \details Returns true if the given string arguments are equal
     375             :   !!
     376             :   !!    \b Example
     377             :   !!
     378             :   !!    \code{.f90}
     379             :   !!    isequal = equalString(string1,string2)
     380             :   !!    \endcode
     381             : 
     382             :   !>    \param[in] "character(len=*) :: string1"    String
     383             :   !>    \param[in] "character(len=*) :: string2"    String
     384             :   !>    \retval "logical :: eq" Logical value if string equal
     385             : 
     386             :   !>    \author David Schaefer
     387             :   !>    \date Mar 2015
     388             : 
     389           4 :   function equalStrings(string1,string2)
     390             :     implicit none
     391             : 
     392             :     character(len=*), intent(in)     :: string1, string2
     393           4 :     integer(i4),      allocatable    :: array1(:), array2(:)
     394             :     integer(i4)                      :: i
     395             :     logical                          :: equalStrings
     396             : 
     397          30 :     array1 = str2num(trim(string1))
     398          29 :     array2 = str2num(trim(string2))
     399           4 :     equalStrings = .false.
     400             : 
     401           4 :     if (size(array1) == size(array2)) then
     402          17 :        equalStrings = .true.
     403          17 :        do i=1, size(array1)
     404          17 :           if (array1(i) /= array2(i)) then
     405             :              equalStrings = .false.
     406             :              exit
     407             :           end if
     408             :        end do
     409             :     end if
     410             : 
     411          23 :   end function equalStrings
     412             : 
     413             :   ! ------------------------------------------------------------------
     414             : 
     415             :   !>    \brief Checks if string was already used
     416             : 
     417             :   !>    \details Checks if string was already used, i.e. does not contain NULL character anymore.
     418             :   !!
     419             :   !!    \b Example
     420             :   !!
     421             :   !!    Trim if string is used.
     422             :   !!    \code{.f90}
     423             :   !!    if (nonull(str)) write(*,*) trim(str)
     424             :   !!    \endcode
     425             : 
     426             :   !>    \param[in] "character(len=*) :: str"    String
     427             :   !>    \retval "logical :: used"               .true.: string was already set; .false.: string still in initialised state
     428             : 
     429             :   !>    \author Matthias Cuntz
     430             :   !>    \date Jan 2012
     431             : 
     432           2 :   FUNCTION nonull(str)
     433             : 
     434             :     IMPLICIT NONE
     435             : 
     436             :     CHARACTER(LEN=*), INTENT(in) :: str
     437             :     LOGICAL                      :: nonull
     438             : 
     439           2 :     if (scan(str, achar(0)) == 0) then
     440             :        nonull = .true.
     441             :     else
     442           1 :        nonull = .false.
     443             :     end if
     444             : 
     445           4 :   END FUNCTION nonull
     446             : 
     447             :   ! ------------------------------------------------------------------
     448             : 
     449             :   !>    \brief split string at delimiter
     450             : 
     451             :   !>    \details Split string at delimiter an return an array of strings
     452             :   !!
     453             :   !!    \b Example
     454             :   !!
     455             :   !!    \code{.f90}
     456             :   !!    string_parts = splitString(string,delim)
     457             :   !!    \endcode
     458             : 
     459             :   !>    \param[in] "character(len=*) :: string"    String
     460             :   !>    \param[in] "character(len=*) :: delim"     String
     461             :   !>    \retval "character(len=245) :: out(:)"     Array of splitted strings
     462             : 
     463             :   !>    \author David Schaefer
     464             :   !>    \date Mar 2015
     465             : 
     466           4 :   function splitString(string,delim) result(out)
     467             : 
     468           2 :     use mo_append, only : append
     469             :     implicit none
     470             : 
     471             :     character(len=*),   intent(in)        :: string
     472             :     character(len=*),   intent(in)        :: delim
     473             :     character(len=256), allocatable       :: out(:)
     474           4 :     integer(i4),        allocatable       :: string_array(:), delim_array(:)
     475             :     integer(i4)                           :: i, start
     476             :     !
     477           0 :     if (allocated(out)) deallocate(out)
     478         143 :     string_array = str2num(string//delim)
     479           9 :     delim_array = str2num(delim)
     480           4 :     start = 1
     481             : 
     482         142 :     do i=1, size(string_array) - size(delim_array) + 1
     483         167 :        if (all(string_array(i:i+size(delim_array)-1) == delim_array)) then
     484          20 :           call append(out, numarray2str(string_array(start:i-1)))
     485          20 :           start = i + size(delim_array)
     486             :        end if
     487             :     end do
     488             :     !
     489           4 :   end function splitString
     490             : 
     491             :   ! ------------------------------------------------------------------
     492             : 
     493             :   !>    \brief Checks if string starts with character(s)
     494             :   !>    \details Returns true if string starts with given characters, flase otherwise
     495             :   !>    \author David Schaefer
     496             :   !>    \date Mar 2015
     497         116 :   logical function startswith(string, start, strip)
     498             : 
     499             :     implicit none
     500             : 
     501             :     character(len=*), intent(in)     :: string !< string to check
     502             :     character(len=*), intent(in)     :: start  !< starting string
     503             :     logical, optional, intent(in)    :: strip  !< whether to strip trailing white-spaces (.false. by default)
     504             : 
     505             :     integer(i4) :: i
     506             :     logical :: strip_
     507             : 
     508         116 :     strip_ = .false.
     509         116 :     if ( present(strip) ) strip_ = strip
     510             : 
     511           0 :     if (strip_) then
     512           0 :       i = index(trim(string), trim(start))
     513             :     else
     514         116 :       i = index(string, start)
     515             :     end if
     516             : 
     517         116 :     startswith = i == 1
     518             : 
     519           4 :   end function startswith
     520             : 
     521             :   ! ------------------------------------------------------------------
     522             : 
     523             :   !>    \brief Checks if (maybe trimmed) string ends with given character(s)
     524             :   !>    \retval "endswith" if string ends with given end
     525             :   !>    \author Sebastian Müller
     526             :   !>    \date Mar 2023
     527          95 :   logical function endswith(string, suffix, strip)
     528             : 
     529             :     implicit none
     530             : 
     531             :     character(len=*), intent(in)     :: string !< string to check
     532             :     character(len=*), intent(in)     :: suffix !< ending string
     533             :     logical, optional, intent(in)    :: strip  !< whether to strip trailing white-spaces (.true. by default)
     534             : 
     535             :     integer(i4) :: i, ref
     536             :     logical :: strip_
     537             : 
     538          95 :     strip_ = .true.
     539          95 :     if ( present(strip) ) strip_ = strip
     540             : 
     541           0 :     if (strip_) then
     542          95 :       i = index(trim(string), trim(suffix), back=.true.)
     543          95 :       ref = len_trim(string) - len_trim(suffix) + 1_i4
     544             :     else
     545           0 :       i = index(string, suffix, back=.true.)
     546           0 :       ref = len(string) - len(suffix) + 1_i4
     547             :     end if
     548             : 
     549          95 :     endswith = i == ref
     550             : 
     551         116 :   end function endswith
     552             : 
     553             :   ! ------------------------------------------------------------------
     554             : 
     555             :   !>    \brief Convert to lower case
     556             : 
     557             :   !>    \details Convert all upper case letters in string to lower case letters.
     558             :   !!
     559             :   !!    \b Example
     560             :   !!
     561             :   !!    Returns 'hallo'
     562             :   !!    \code{.f90}
     563             :   !!    low = tolower('Hallo')
     564             :   !!    \endcode
     565             : 
     566             :   !>    \param[in] "character(len=*) :: upper"                String
     567             :   !>    \retval    "character(len=len_trim(upper)) :: low"    String where all uppercase in input is converted to lowercase
     568             : 
     569             :   !>    \author Matthias Cuntz
     570             :   !>    \date Dec 2011
     571             :   !!        - modified from Echam5, (C) MPI-MET, Hamburg, Germany
     572             : 
     573          28 :   FUNCTION tolower(upper)
     574             : 
     575             :     IMPLICIT NONE
     576             : 
     577             :     CHARACTER(LEN=*)              ,INTENT(in) :: upper
     578             :     CHARACTER(LEN=LEN_TRIM(upper))            :: tolower
     579             : 
     580             :     INTEGER            :: i
     581             :     INTEGER ,PARAMETER :: idel = ICHAR('a')-ICHAR('A')
     582             : 
     583         102 :     DO i=1,LEN_TRIM(upper)
     584          74 :        IF (ICHAR(upper(i:i)) >= ICHAR('A') .AND. &
     585          28 :             ICHAR(upper(i:i)) <= ICHAR('Z')) THEN
     586           1 :           tolower(i:i) = CHAR( ICHAR(upper(i:i)) + idel )
     587             :        ELSE
     588          73 :           tolower(i:i) = upper(i:i)
     589             :        END IF
     590             :     END DO
     591             : 
     592          95 :   END FUNCTION tolower
     593             : 
     594             :   ! ------------------------------------------------------------------
     595             : 
     596             :   !>    \brief Convert to upper case
     597             : 
     598             :   !>    \details Convert all lower case letters in string to upper case letters.
     599             :   !!
     600             :   !!    \b Example
     601             :   !!
     602             :   !!    Returns 'HALLO'
     603             :   !!    \code{.f90}
     604             :   !!    up = toupper('Hallo')
     605             :   !!    \endcode
     606             : 
     607             :   !>    \param[in] "character(len=*) :: lower"            String
     608             :   !>    \retval "character(len=len_trim(lower)) :: up"    String where all lowercase in input is converted to uppercase
     609             : 
     610             :   !>    \author Matthias Cuntz
     611             :   !>    \date Dec 2011
     612             :   !!        - modified from Echam5, (C) MPI-MET, Hamburg, Germany
     613             : 
     614          41 :   FUNCTION toupper (lower)
     615             : 
     616             :     IMPLICIT NONE
     617             : 
     618             :     CHARACTER(LEN=*)              ,INTENT(in) :: lower
     619             :     CHARACTER(LEN=LEN_TRIM(lower))            :: toupper
     620             : 
     621             :     INTEGER            :: i
     622             :     INTEGER, PARAMETER :: idel = ICHAR('A')-ICHAR('a')
     623             : 
     624         798 :     DO i=1,LEN_TRIM(lower)
     625         757 :        IF (ICHAR(lower(i:i)) >= ICHAR('a') .AND. &
     626          41 :             ICHAR(lower(i:i)) <= ICHAR('z')) THEN
     627           4 :           toupper(i:i) = CHAR( ICHAR(lower(i:i)) + idel )
     628             :        ELSE
     629         753 :           toupper(i:i) = lower(i:i)
     630             :        END IF
     631             :     END DO
     632             : 
     633          28 :   END FUNCTION toupper
     634             : 
     635             : 
     636             :   ! -----------------------------------------------------------
     637             :   ! PRIVATE ROUTINES
     638             :   ! (no "template" documentation required)
     639             :   ! -----------------------------------------------------------
     640             : 
     641          34 :   PURE FUNCTION i42str(nn,form)
     642             :     ! returns integer nn as a string (often needed in printing messages)
     643             :     IMPLICIT NONE
     644             :     INTEGER(i4),      INTENT(IN)           :: nn
     645             :     CHARACTER(len=*), INTENT(IN), OPTIONAL :: form
     646             :     CHARACTER(len=10) :: i42str
     647             : 
     648          34 :     if (present(form)) then
     649          34 :        write(i42str,form) nn
     650             :     else
     651           0 :        write(i42str,'(I10)') nn
     652             :     end if
     653             :     !i42str = adjustl(i42str)
     654             : 
     655          41 :   END FUNCTION i42str
     656             : 
     657             : 
     658           1 :   PURE FUNCTION i82str(nn,form)
     659             :     ! returns integer nn as a string (often needed in printing messages)
     660             :     IMPLICIT NONE
     661             :     INTEGER(i8),      INTENT(IN)           :: nn
     662             :     CHARACTER(len=*), INTENT(IN), OPTIONAL :: form
     663             :     CHARACTER(len=20) :: i82str
     664             : 
     665           1 :     if (present(form)) then
     666           1 :        write(i82str,form) nn
     667             :     else
     668           0 :        write(i82str,'(I20)') nn
     669             :     end if
     670             :     !i82str = adjustl(i82str)
     671             : 
     672          34 :   END FUNCTION i82str
     673             : 
     674             : 
     675           1 :   PURE FUNCTION sp2str(rr,form)
     676             :     ! returns real rr as a string (often needed in printing messages)
     677             :     IMPLICIT NONE
     678             :     REAL(sp),         INTENT(IN)           :: rr
     679             :     CHARACTER(len=*), INTENT(IN), OPTIONAL :: form
     680             :     CHARACTER(len=32) :: sp2str
     681             : 
     682           1 :     if (present(form)) then
     683           1 :        write(sp2str,form) rr
     684             :     else
     685           0 :        write(sp2str,'(G32.5)') rr
     686             :     end if
     687             :     !sp2str = adjustl(sp2str)
     688             : 
     689           1 :   END FUNCTION sp2str
     690             : 
     691             : 
     692           1 :   PURE FUNCTION dp2str(rr,form)
     693             :     ! returns real rr as a string (often needed in printing messages)
     694             :     IMPLICIT NONE
     695             :     REAL(dp),         INTENT(IN)           :: rr
     696             :     CHARACTER(len=*), INTENT(IN), OPTIONAL :: form
     697             :     CHARACTER(len=32) :: dp2str
     698             : 
     699           1 :     if (present(form)) then
     700           1 :        write(dp2str,form) rr
     701             :     else
     702           0 :        write(dp2str,'(G32.5)') rr
     703             :     end if
     704             :     !dp2str = adjustl(dp2str)
     705             : 
     706           1 :   END FUNCTION dp2str
     707             : 
     708             : 
     709           1 :   PURE FUNCTION log2str(ll,form)
     710             :     ! returns logical ll as a string (often needed in printing messages)
     711             :     IMPLICIT NONE
     712             :     LOGICAL,          INTENT(in)           :: ll
     713             :     CHARACTER(len=*), INTENT(IN), OPTIONAL :: form
     714             :     CHARACTER(len=10) :: log2str
     715             : 
     716           1 :     if (present(form)) then
     717           1 :        write(log2str,form) ll
     718             :     else
     719           0 :        write(log2str,'(L10)') ll
     720             :     end if
     721             :     !log2str = adjustl(log2str)
     722             : 
     723           1 :   END FUNCTION log2str
     724             : 
     725          20 :   function i4array2str(arr) result(out)
     726             : 
     727             :     integer(i4), intent(in)     :: arr(:)
     728             :     integer(i4)                 :: ii
     729             :     character(len=size(arr))    :: out
     730             : 
     731          20 :     out = " "
     732         135 :     do ii=1,size(arr)
     733         135 :        out(ii:ii) = char(arr(ii))
     734             :     end do
     735             : 
     736           1 :   end function i4array2str
     737             : 
     738             :   ! ------------------------------------------------------------------
     739             : 
     740             :   !>    \brief Converts string into an array of its numerical representation
     741             : 
     742             :   !>    \details Converts string into an integer array of the numerical values of the letters
     743             :   !!
     744             :   !!    \b Example
     745             :   !!
     746             :   !!    Convert is string into numerical array of the letters
     747             :   !!    \code{.f90}
     748             :   !!    num = str2num(string)
     749             :   !!    \endcode
     750             : 
     751             :   !>    \param[in] "character(len=*) :: string"    String
     752             :   !>    \retval "integer  :: out(:)"               Numerical array of letters
     753             : 
     754             :   !>    \author David Schaefer
     755             :   !>    \date Mar 2015
     756             : 
     757          16 :   function str2num(string) result(out)
     758             : 
     759             :     implicit none
     760             : 
     761             :     character(len=*), intent(in)       :: string
     762             :     integer(i4), allocatable           :: out(:)
     763             :     integer(i4)                        :: i
     764             : 
     765          16 :     if (allocated(out)) deallocate(out)
     766          48 :     allocate(out(len(string)))
     767             : 
     768         211 :     do i=1,len(string)
     769         211 :        out(i) = ichar(string(i:i))
     770             :     end do
     771             : 
     772          20 :   end function str2num
     773             : 
     774             : 
     775             : END MODULE mo_string_utils

Generated by: LCOV version 1.16