Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions to convert integer/logical values to character values #336

Merged
merged 8 commits into from
Apr 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions doc/specs/stdlib_ascii.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,42 @@ program demo_reverse
print'(a)', reverse("Hello, World!") ! returns "!dlroW ,olleH"
end program demo_reverse
```


### `to_string`

#### Status

Experimental

#### Description

Create a character string representing the value of the provided variable.

#### Syntax

`res = [[stdlib_ascii(module):to_string(interface)]] (string)`

#### Class

Pure function.

#### Argument

`val`: shall be an intrinsic integer or logical type. It is an `intent(in)` argument.

#### Result value

The result is an intrinsic character type.

#### Example

```fortran
program demo_string_value
use stdlib_ascii, only : to_string
implicit none
print'(a)', to_string(-3) ! returns "-3"
print'(a)', to_string(.true.) ! returns "T"
print'(a)', to_string(42) ! returns "42"
end program demo_string_value
```
86 changes: 85 additions & 1 deletion doc/specs/stdlib_string_type.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,90 @@ end program demo
```


<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
### Constructor from integer scalar

#### Description

The module defines a constructor to create a string type from an integer scalar.

#### Syntax

`res = [[stdlib_string_type(module):string_type(interface)]] (string)`

#### Status

Experimental

#### Class

Elemental function.

#### Argument

`val`: shall be a scalar integer value. It is an `intent(in)` argument.

#### Result value

The result is an instance of `string_type`.

#### Example

```fortran
program demo
use stdlib_string_type
implicit none
type(string_type) :: string
string = string_type(42)
! len(string) == 2
string = string_type(-289)
! len(string) == 4
end program demo
```


<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
### Constructor from logical scalar

#### Description

The module defines a constructor to create a string type from a logical scalar.

#### Syntax

`res = [[stdlib_string_type(module):string_type(interface)]] (string)`

#### Status

Experimental

#### Class

Elemental function.

#### Argument

`val`: shall be a scalar logical value. It is an `intent(in)` argument.

#### Result value

The result is an instance of `string_type`.

#### Example

```fortran
program demo
use stdlib_string_type
implicit none
type(string_type) :: string
string = string_type(.true.)
! len(string) == 1
string = string_type(.false.)
! len(string) == 1
end program demo
```


<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
### Assignment of character scalar

Expand All @@ -143,7 +227,7 @@ Experimental

#### Class

Elemntal subroutine, `assignment(=)`.
Elemental subroutine, `assignment(=)`.

#### Example

Expand Down
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# Create a list of the files to be preprocessed
set(fppFiles
stdlib_ascii.fypp
stdlib_bitsets.fypp
stdlib_bitsets_64.fypp
stdlib_bitsets_large.fypp
Expand All @@ -22,6 +23,7 @@ set(fppFiles
stdlib_quadrature_trapz.fypp
stdlib_quadrature_simps.fypp
stdlib_stats_distribution_PRNG.fypp
stdlib_string_type.fypp
)


Expand All @@ -37,11 +39,9 @@ endif()
fypp_f90("${fyppFlags}" "${fppFiles}" outFiles)

set(SRC
stdlib_ascii.f90
stdlib_error.f90
stdlib_kinds.f90
stdlib_logger.f90
stdlib_string_type.f90
stdlib_strings.f90
stdlib_system.F90
${outFiles}
Expand Down
9 changes: 5 additions & 4 deletions src/Makefile.manual
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
SRCFYPP =\
stdlib_ascii.fypp \
stdlib_bitsets_64.fypp \
stdlib_bitsets_large.fypp \
stdlib_bitsets.fypp \
Expand All @@ -18,15 +19,14 @@ SRCFYPP =\
stdlib_stats_moment_mask.fypp \
stdlib_stats_moment_scalar.fypp \
stdlib_stats_var.fypp \
stdlib_stats_distribution_PRNG.fypp
stdlib_stats_distribution_PRNG.fypp \
stdlib_string_type.fypp

SRC = f18estop.f90 \
stdlib_ascii.f90 \
stdlib_error.f90 \
stdlib_kinds.f90 \
stdlib_logger.f90 \
stdlib_strings.f90 \
stdlib_string_type.f90 \
$(SRCGEN)

LIB = libstdlib.a
Expand Down Expand Up @@ -55,6 +55,7 @@ $(SRCGEN): %.f90: %.fypp common.fypp

# Fortran module dependencies
f18estop.o: stdlib_error.o
stdlib_ascii.o: stdlib_kinds.o
stdlib_bitsets.o: stdlib_kinds.o
stdlib_bitsets_64.o: stdlib_bitsets.o
stdlib_bitsets_large.o: stdlib_bitsets.o
Expand Down Expand Up @@ -110,5 +111,5 @@ stdlib_stats_var.o: \
stdlib_stats_distribution_PRNG.o: \
stdlib_kinds.o \
stdlib_error.o
stdlib_string_type.o: stdlib_ascii.o
stdlib_string_type.o: stdlib_ascii.o stdlib_kinds.o
stdlib_strings.o: stdlib_ascii.o stdlib_string_type.o
61 changes: 61 additions & 0 deletions src/stdlib_ascii.f90 → src/stdlib_ascii.fypp
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#:include "common.fypp"

!> The `stdlib_ascii` module provides procedures for handling and manipulating
!> intrinsic character variables and constants.
!>
!> The specification of this module is available [here](../page/specs/stdlib_ascii.html).
module stdlib_ascii
use stdlib_kinds, only : int8, int16, int32, int64

implicit none
private
Expand All @@ -17,6 +20,17 @@ module stdlib_ascii

! Character conversion functions
public :: to_lower, to_upper, to_title, reverse
public :: to_string

!> Version: experimental
!>
!> Create a character string representing the value of the provided variable.
interface to_string
#:for kind in INT_KINDS
module procedure :: to_string_integer_${kind}$
module procedure :: to_string_logical_${kind}$
#:endfor
end interface to_string

! All control characters in the ASCII table (see www.asciitable.com).
character(len=1), public, parameter :: NUL = achar(int(z'00')) !! Null
Expand Down Expand Up @@ -312,4 +326,51 @@ pure function reverse(string) result(reverse_string)

end function reverse

#:for kind in INT_KINDS
!> Represent an integer of kind ${kind}$ as character sequence
pure function to_string_integer_${kind}$(val) result(string)
integer, parameter :: ik = ${kind}$
integer(ik), intent(in) :: val
character(len=:), allocatable :: string
integer, parameter :: buffer_len = range(val)+2
character(len=buffer_len) :: buffer
integer :: pos
integer(ik) :: n
character(len=1), parameter :: numbers(0:9) = &
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]

if (val == 0_ik) then
string = numbers(0)
return
end if

n = abs(val)
buffer = ""

pos = buffer_len + 1
do while (n > 0_ik)
pos = pos - 1
buffer(pos:pos) = numbers(mod(n, 10_ik))
n = n/10_ik
end do
if (val < 0_ik) then
pos = pos - 1
buffer(pos:pos) = '-'
end if

string = buffer(pos:)
end function to_string_integer_${kind}$
#:endfor

#:for kind in INT_KINDS
!> Represent an logical of kind ${kind}$ as character sequence
pure function to_string_logical_${kind}$(val) result(string)
integer, parameter :: ik = ${kind}$
logical(ik), intent(in) :: val
Comment on lines +368 to +369
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just for improved clarity of the generated code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I didn't like the look with the ${kind}$ preprocessor all over the place

character(len=1) :: string

string = merge("T", "F", val)
end function to_string_logical_${kind}$
#:endfor

end module stdlib_ascii
27 changes: 25 additions & 2 deletions src/stdlib_string_type.f90 → src/stdlib_string_type.fypp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
! SPDX-Identifier: MIT
#:include "common.fypp"

!> Implementation of a string type to hold an arbitrary sequence of characters.
!>
Expand All @@ -13,8 +14,8 @@
!> The specification of this module is available [here](../page/specs/stdlib_string_type.html).
module stdlib_string_type
use stdlib_ascii, only: to_lower_ => to_lower, to_upper_ => to_upper, &
to_title_ => to_title, reverse_ => reverse

& to_title_ => to_title, reverse_ => reverse, to_string
use stdlib_kinds, only : int8, int16, int32, int64
implicit none
private

Expand Down Expand Up @@ -44,6 +45,10 @@ module stdlib_string_type
!> Constructor for new string instances
interface string_type
module procedure :: new_string
#:for kind in INT_KINDS
module procedure :: new_string_from_integer_${kind}$
module procedure :: new_string_from_logical_${kind}$
#:endfor
end interface string_type


Expand Down Expand Up @@ -351,6 +356,24 @@ elemental function new_string(string) result(new)
end if
end function new_string

#:for kind in INT_KINDS
!> Constructor for new string instances from an integer of kind ${kind}$.
elemental function new_string_from_integer_${kind}$(val) result(new)
integer(${kind}$), intent(in) :: val
type(string_type) :: new
new%raw = to_string(val)
end function new_string_from_integer_${kind}$
#:endfor

#:for kind in INT_KINDS
!> Constructor for new string instances from a logical of kind ${kind}$.
elemental function new_string_from_logical_${kind}$(val) result(new)
logical(${kind}$), intent(in) :: val
type(string_type) :: new
new%raw = to_string(val)
end function new_string_from_logical_${kind}$
#:endfor


!> Assign a character sequence to a string.
elemental subroutine assign_string_char(lhs, rhs)
Expand Down
Loading