Skip to content

Commit fa88905

Browse files
committed
improved function slice for invalid cases, added new invalid test cases
1 parent a733bc3 commit fa88905

File tree

2 files changed

+53
-28
lines changed

2 files changed

+53
-28
lines changed

src/stdlib_strings.f90

+26-13
Original file line numberDiff line numberDiff line change
@@ -318,18 +318,19 @@ end function slice_string
318318
pure function slice_char(string, first, last, stride) result(sliced_string)
319319
character(len=*), intent(in) :: string
320320
integer, intent(in), optional :: first, last, stride
321-
integer :: first_index, last_index, stride_vector, n, i, j
321+
integer :: first_index, last_index, stride_vector, strides_taken, length_string, i, j
322322
character(len=:), allocatable :: sliced_string
323323

324-
if (len(string) > 0) then
324+
length_string = len(string)
325+
if (length_string > 0) then
325326
first_index = 1
326-
last_index = len(string)
327+
last_index = length_string
327328
stride_vector = 1
328329

329330
if (present(stride)) then
330331
if (stride /= 0) then
331332
if (stride < 0) then
332-
first_index = len(string)
333+
first_index = length_string
333334
last_index = 1
334335
end if
335336
stride_vector = stride
@@ -343,20 +344,32 @@ pure function slice_char(string, first, last, stride) result(sliced_string)
343344
end if
344345

345346
if (present(first)) then
346-
first_index = clip(first, 1, len(string))
347+
first_index = first
347348
end if
348349
if (present(last)) then
349-
last_index = clip(last, 1, len(string))
350+
last_index = last
350351
end if
351352

352-
n = int((last_index - first_index) / stride_vector)
353-
allocate(character(len=max(0, n + 1)) :: sliced_string)
353+
strides_taken = floor( real(last_index - first_index) / real(stride_vector) )
354354

355-
j = 1
356-
do i = first_index, last_index, stride_vector
357-
sliced_string(j:j) = string(i:i)
358-
j = j + 1
359-
end do
355+
if (strides_taken < 0 .or. &
356+
((first_index < 1 .and. last_index < 1) .or. &
357+
(first_index > length_string .and. last_index > length_string))) then
358+
359+
sliced_string = ""
360+
else
361+
first_index = clip(first_index, 1, length_string)
362+
last_index = clip(last_index, 1, length_string)
363+
364+
strides_taken = (last_index - first_index) / stride_vector
365+
allocate(character(len=strides_taken + 1) :: sliced_string)
366+
367+
j = 1
368+
do i = first_index, last_index, stride_vector
369+
sliced_string(j:j) = string(i:i)
370+
j = j + 1
371+
end do
372+
end if
360373
else
361374
sliced_string = ""
362375
end if

src/tests/string/test_string_functions.f90

+27-15
Original file line numberDiff line numberDiff line change
@@ -60,36 +60,48 @@ subroutine test_slice_string
6060
test_char = "abcdefghijklmnopqrstuvwxyz"
6161

6262
call check(slice(test_string, 2, 16, 3) == "behkn", &
63-
'function slice failed', warn=.true.)
64-
call check(slice(test_char, 15, stride=-1) == "onmlkjihgfedcba", &
65-
'function slice failed', warn=.true.)
63+
'function slice failed', warn=.false.)
64+
call check(slice(test_char, first=15, stride=-1) == "onmlkjihgfedcba", &
65+
'function slice failed', warn=.false.)
6666
call check(slice(test_string, last=22, stride=-1) == "zyxwv", &
67-
'function slice failed', warn=.true.)
67+
'function slice failed', warn=.false.)
6868
call check(slice(test_char, 7, 2) == "gfedcb", &
69-
'function slice failed', warn=.true.)
69+
'function slice failed', warn=.false.)
7070
call check(slice(test_string, 7, 2, 1) == "", &
71-
'function slice failed', warn=.true.)
71+
'function slice failed', warn=.false.)
7272
call check(slice(test_char, 2, 6, -1) == "", &
73-
'function slice failed', warn=.true.)
73+
'function slice failed', warn=.false.)
7474
call check(slice(test_string, stride=-1) == "zyxwvutsrqponmlkjihgfedcba", &
75-
'function slice failed', warn=.true.)
75+
'function slice failed', warn=.false.)
7676
call check(slice(test_string, 7, 7, -4) == "g", &
77-
'function slice failed', warn=.true.)
77+
'function slice failed', warn=.false.)
7878
call check(slice(test_char, 7, 7, 3) == "g", &
79-
'function slice failed', warn=.true.)
79+
'function slice failed', warn=.false.)
8080
call check(slice(test_string, 7, 7, 3) == "g", &
81-
'function slice failed', warn=.true.)
81+
'function slice failed', warn=.false.)
8282
call check(slice(test_char, 7, -10) == "gfedcba", &
83-
'function slice failed', warn=.true.)
83+
'function slice failed', warn=.false.)
8484
call check(slice(test_string, 500, 22) == "zyxwv", &
85-
'function slice failed', warn=.true.)
85+
'function slice failed', warn=.false.)
86+
call check(slice(test_char, 50, 27) == "", &
87+
'function slice failed', warn=.false.)
88+
call check(slice(test_string, -20, -200) == "", &
89+
'function slice failed', warn=.false.)
90+
call check(slice(test_char, first=0, stride=-1) == "", &
91+
'function slice failed', warn=.false.)
92+
call check(slice(test_string, last=27, stride=-2) == "", &
93+
'function slice failed', warn=.false.)
94+
call check(slice(test_char, first=27, stride=2) == "", &
95+
'function slice failed', warn=.false.)
96+
call check(slice(test_string, -500, 500) == "abcdefghijklmnopqrstuvwxyz", &
97+
'function slice failed', warn=.false.)
8698

8799
test_string = ""
88100
test_char = ""
89101
call check(slice(test_string, 2, 16, 3) == "", &
90-
'function slice failed', warn=.true.)
102+
'function slice failed', warn=.false.)
91103
call check(slice(test_char, 2, 16, 3) == "", &
92-
'function slice failed', warn=.true.)
104+
'function slice failed', warn=.false.)
93105

94106
end subroutine test_slice_string
95107

0 commit comments

Comments
 (0)