Skip to content

Commit 3621b03

Browse files
authored
Add functions to convert integer/logical values to character values (#336)
2 parents 0886501 + 8b1d71a commit 3621b03

8 files changed

+311
-11
lines changed

doc/specs/stdlib_ascii.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,42 @@ program demo_reverse
169169
print'(a)', reverse("Hello, World!") ! returns "!dlroW ,olleH"
170170
end program demo_reverse
171171
```
172+
173+
174+
### `to_string`
175+
176+
#### Status
177+
178+
Experimental
179+
180+
#### Description
181+
182+
Create a character string representing the value of the provided variable.
183+
184+
#### Syntax
185+
186+
`res = [[stdlib_ascii(module):to_string(interface)]] (string)`
187+
188+
#### Class
189+
190+
Pure function.
191+
192+
#### Argument
193+
194+
`val`: shall be an intrinsic integer or logical type. It is an `intent(in)` argument.
195+
196+
#### Result value
197+
198+
The result is an intrinsic character type.
199+
200+
#### Example
201+
202+
```fortran
203+
program demo_string_value
204+
use stdlib_ascii, only : to_string
205+
implicit none
206+
print'(a)', to_string(-3) ! returns "-3"
207+
print'(a)', to_string(.true.) ! returns "T"
208+
print'(a)', to_string(42) ! returns "42"
209+
end program demo_string_value
210+
```

doc/specs/stdlib_string_type.md

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,90 @@ end program demo
123123
```
124124

125125

126+
<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
127+
### Constructor from integer scalar
128+
129+
#### Description
130+
131+
The module defines a constructor to create a string type from an integer scalar.
132+
133+
#### Syntax
134+
135+
`res = [[stdlib_string_type(module):string_type(interface)]] (string)`
136+
137+
#### Status
138+
139+
Experimental
140+
141+
#### Class
142+
143+
Elemental function.
144+
145+
#### Argument
146+
147+
`val`: shall be a scalar integer value. It is an `intent(in)` argument.
148+
149+
#### Result value
150+
151+
The result is an instance of `string_type`.
152+
153+
#### Example
154+
155+
```fortran
156+
program demo
157+
use stdlib_string_type
158+
implicit none
159+
type(string_type) :: string
160+
string = string_type(42)
161+
! len(string) == 2
162+
string = string_type(-289)
163+
! len(string) == 4
164+
end program demo
165+
```
166+
167+
168+
<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
169+
### Constructor from logical scalar
170+
171+
#### Description
172+
173+
The module defines a constructor to create a string type from a logical scalar.
174+
175+
#### Syntax
176+
177+
`res = [[stdlib_string_type(module):string_type(interface)]] (string)`
178+
179+
#### Status
180+
181+
Experimental
182+
183+
#### Class
184+
185+
Elemental function.
186+
187+
#### Argument
188+
189+
`val`: shall be a scalar logical value. It is an `intent(in)` argument.
190+
191+
#### Result value
192+
193+
The result is an instance of `string_type`.
194+
195+
#### Example
196+
197+
```fortran
198+
program demo
199+
use stdlib_string_type
200+
implicit none
201+
type(string_type) :: string
202+
string = string_type(.true.)
203+
! len(string) == 1
204+
string = string_type(.false.)
205+
! len(string) == 1
206+
end program demo
207+
```
208+
209+
126210
<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
127211
### Assignment of character scalar
128212

@@ -143,7 +227,7 @@ Experimental
143227

144228
#### Class
145229

146-
Elemntal subroutine, `assignment(=)`.
230+
Elemental subroutine, `assignment(=)`.
147231

148232
#### Example
149233

src/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# Create a list of the files to be preprocessed
44
set(fppFiles
5+
stdlib_ascii.fypp
56
stdlib_bitsets.fypp
67
stdlib_bitsets_64.fypp
78
stdlib_bitsets_large.fypp
@@ -22,6 +23,7 @@ set(fppFiles
2223
stdlib_quadrature_trapz.fypp
2324
stdlib_quadrature_simps.fypp
2425
stdlib_stats_distribution_PRNG.fypp
26+
stdlib_string_type.fypp
2527
)
2628

2729

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

3941
set(SRC
40-
stdlib_ascii.f90
4142
stdlib_error.f90
4243
stdlib_kinds.f90
4344
stdlib_logger.f90
44-
stdlib_string_type.f90
4545
stdlib_strings.f90
4646
stdlib_system.F90
4747
${outFiles}

src/Makefile.manual

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
SRCFYPP =\
2+
stdlib_ascii.fypp \
23
stdlib_bitsets_64.fypp \
34
stdlib_bitsets_large.fypp \
45
stdlib_bitsets.fypp \
@@ -18,15 +19,14 @@ SRCFYPP =\
1819
stdlib_stats_moment_mask.fypp \
1920
stdlib_stats_moment_scalar.fypp \
2021
stdlib_stats_var.fypp \
21-
stdlib_stats_distribution_PRNG.fypp
22+
stdlib_stats_distribution_PRNG.fypp \
23+
stdlib_string_type.fypp
2224

2325
SRC = f18estop.f90 \
24-
stdlib_ascii.f90 \
2526
stdlib_error.f90 \
2627
stdlib_kinds.f90 \
2728
stdlib_logger.f90 \
2829
stdlib_strings.f90 \
29-
stdlib_string_type.f90 \
3030
$(SRCGEN)
3131

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

5656
# Fortran module dependencies
5757
f18estop.o: stdlib_error.o
58+
stdlib_ascii.o: stdlib_kinds.o
5859
stdlib_bitsets.o: stdlib_kinds.o
5960
stdlib_bitsets_64.o: stdlib_bitsets.o
6061
stdlib_bitsets_large.o: stdlib_bitsets.o
@@ -110,5 +111,5 @@ stdlib_stats_var.o: \
110111
stdlib_stats_distribution_PRNG.o: \
111112
stdlib_kinds.o \
112113
stdlib_error.o
113-
stdlib_string_type.o: stdlib_ascii.o
114+
stdlib_string_type.o: stdlib_ascii.o stdlib_kinds.o
114115
stdlib_strings.o: stdlib_ascii.o stdlib_string_type.o

src/stdlib_ascii.f90 renamed to src/stdlib_ascii.fypp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
#:include "common.fypp"
2+
13
!> The `stdlib_ascii` module provides procedures for handling and manipulating
24
!> intrinsic character variables and constants.
35
!>
46
!> The specification of this module is available [here](../page/specs/stdlib_ascii.html).
57
module stdlib_ascii
8+
use stdlib_kinds, only : int8, int16, int32, int64
69

710
implicit none
811
private
@@ -17,6 +20,17 @@ module stdlib_ascii
1720

1821
! Character conversion functions
1922
public :: to_lower, to_upper, to_title, reverse
23+
public :: to_string
24+
25+
!> Version: experimental
26+
!>
27+
!> Create a character string representing the value of the provided variable.
28+
interface to_string
29+
#:for kind in INT_KINDS
30+
module procedure :: to_string_integer_${kind}$
31+
module procedure :: to_string_logical_${kind}$
32+
#:endfor
33+
end interface to_string
2034

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

313327
end function reverse
314328

329+
#:for kind in INT_KINDS
330+
!> Represent an integer of kind ${kind}$ as character sequence
331+
pure function to_string_integer_${kind}$(val) result(string)
332+
integer, parameter :: ik = ${kind}$
333+
integer(ik), intent(in) :: val
334+
character(len=:), allocatable :: string
335+
integer, parameter :: buffer_len = range(val)+2
336+
character(len=buffer_len) :: buffer
337+
integer :: pos
338+
integer(ik) :: n
339+
character(len=1), parameter :: numbers(0:9) = &
340+
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
341+
342+
if (val == 0_ik) then
343+
string = numbers(0)
344+
return
345+
end if
346+
347+
n = abs(val)
348+
buffer = ""
349+
350+
pos = buffer_len + 1
351+
do while (n > 0_ik)
352+
pos = pos - 1
353+
buffer(pos:pos) = numbers(mod(n, 10_ik))
354+
n = n/10_ik
355+
end do
356+
if (val < 0_ik) then
357+
pos = pos - 1
358+
buffer(pos:pos) = '-'
359+
end if
360+
361+
string = buffer(pos:)
362+
end function to_string_integer_${kind}$
363+
#:endfor
364+
365+
#:for kind in INT_KINDS
366+
!> Represent an logical of kind ${kind}$ as character sequence
367+
pure function to_string_logical_${kind}$(val) result(string)
368+
integer, parameter :: ik = ${kind}$
369+
logical(ik), intent(in) :: val
370+
character(len=1) :: string
371+
372+
string = merge("T", "F", val)
373+
end function to_string_logical_${kind}$
374+
#:endfor
375+
315376
end module stdlib_ascii

src/stdlib_string_type.f90 renamed to src/stdlib_string_type.fypp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
! SPDX-Identifier: MIT
2+
#:include "common.fypp"
23

34
!> Implementation of a string type to hold an arbitrary sequence of characters.
45
!>
@@ -13,8 +14,8 @@
1314
!> The specification of this module is available [here](../page/specs/stdlib_string_type.html).
1415
module stdlib_string_type
1516
use stdlib_ascii, only: to_lower_ => to_lower, to_upper_ => to_upper, &
16-
to_title_ => to_title, reverse_ => reverse
17-
17+
& to_title_ => to_title, reverse_ => reverse, to_string
18+
use stdlib_kinds, only : int8, int16, int32, int64
1819
implicit none
1920
private
2021

@@ -44,6 +45,10 @@ module stdlib_string_type
4445
!> Constructor for new string instances
4546
interface string_type
4647
module procedure :: new_string
48+
#:for kind in INT_KINDS
49+
module procedure :: new_string_from_integer_${kind}$
50+
module procedure :: new_string_from_logical_${kind}$
51+
#:endfor
4752
end interface string_type
4853

4954

@@ -351,6 +356,24 @@ elemental function new_string(string) result(new)
351356
end if
352357
end function new_string
353358

359+
#:for kind in INT_KINDS
360+
!> Constructor for new string instances from an integer of kind ${kind}$.
361+
elemental function new_string_from_integer_${kind}$(val) result(new)
362+
integer(${kind}$), intent(in) :: val
363+
type(string_type) :: new
364+
new%raw = to_string(val)
365+
end function new_string_from_integer_${kind}$
366+
#:endfor
367+
368+
#:for kind in INT_KINDS
369+
!> Constructor for new string instances from a logical of kind ${kind}$.
370+
elemental function new_string_from_logical_${kind}$(val) result(new)
371+
logical(${kind}$), intent(in) :: val
372+
type(string_type) :: new
373+
new%raw = to_string(val)
374+
end function new_string_from_logical_${kind}$
375+
#:endfor
376+
354377

355378
!> Assign a character sequence to a string.
356379
elemental subroutine assign_string_char(lhs, rhs)

0 commit comments

Comments
 (0)