[m-rev.] for review: Simplify string.split implementation.

Peter Wang novalazy at gmail.com
Wed Oct 23 15:02:09 AEDT 2019


library/string.m:
    Replace foreign code implementations with Mercury code.
---
 library/string.m | 109 ++++-------------------------------------------
 1 file changed, 9 insertions(+), 100 deletions(-)

diff --git a/library/string.m b/library/string.m
index 8cc572d9c..97b005841 100644
--- a/library/string.m
+++ b/library/string.m
@@ -679,8 +679,8 @@
 
     % split(String, Index, LeftSubstring, RightSubstring):
     %
-    % Split a string into two substrings, at the code unit `Index'.
-    % (If `Count' is out of the range [0, length of `String'], it is treated
+    % Split a string into two substrings at the code unit offset `Index'.
+    % (If `Index' is out of the range [0, length of `String'], it is treated
     % as if it were the nearest end-point of that range.)
     %
 :- pred split(string::in, int::in, string::out, string::out) is det.
@@ -4138,110 +4138,19 @@ join_list_loop(Sep, [H | T]) = Sep ++ H ++ join_list_loop(Sep, T).
 ").
 
 %---------------------%
-%
-% For some Str and Count inputs, we may return Str as either Left or Right.
-% Since Str has mode `in', both Left or Right must have mode 'out', not `uo'.
-%
-
-:- pragma foreign_proc("C",
-    split(Str::in, Count::in, Left::out, Right::out),
-    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
-        does_not_affect_liveness, may_not_duplicate],
-"{
-    MR_Integer  len;
-
-    if (Count <= 0) {
-        MR_make_aligned_string(Left, """");
-        Right = Str;
-    } else {
-        len = strlen(Str);
 
-        if (Count > len) {
-            Count = len;
-        }
-
-        MR_allocate_aligned_string_msg(Left, Count, MR_ALLOC_ID);
-        MR_memcpy(Left, Str, Count);
-        Left[Count] = '\\0';
-        // We need to make a copy to ensure that the pointer is word-aligned.
-        MR_allocate_aligned_string_msg(Right, len - Count, MR_ALLOC_ID);
-        strcpy(Right, Str + Count);
-    }
-}").
-:- pragma foreign_proc("C#",
-    split(Str::in, Count::in, Left::out, Right::out),
-    [will_not_call_mercury, promise_pure, thread_safe],
-"{
-    int len;
-
-    if (Count <= 0) {
-        Left = """";
-        Right = Str;
-    } else {
-        len = Str.Length;
-        if (Count > len) {
-            Count = len;
-        }
-        Left = Str.Substring(0, Count);
-        Right = Str.Substring(Count);
-    }
-}").
-:- pragma foreign_proc("Java",
-    split(Str::in, Count::in, Left::out, Right::out),
-    [will_not_call_mercury, promise_pure, thread_safe],
-"
-    if (Count <= 0) {
-        Left = """";
-        Right = Str;
-    } else {
-        int len = Str.length();
-        if (Count > len) {
-            Count = len;
-        }
-        Left = Str.substring(0, Count);
-        Right = Str.substring(Count);
-    }
-").
-:- pragma foreign_proc("Erlang",
-    split(Str::in, Count::in, Left::out, Right::out),
-    [will_not_call_mercury, promise_pure, thread_safe],
-"
-    if
-        Count =< 0 ->
-            Left = <<>>,
-            Right = Str;
-        Count > size(Str) ->
-            Left = Str,
-            Right = <<>>;
-        true ->
-            << Left:Count/binary, Right/binary >> = Str
-    end
-").
-
-    % XXX ILSEQ from_code_unit_list refuses to create strings containing
-    % ill-formed sequences.
-    %
-split(Str, Count, Left, Right) :-
-    ( if Count =< 0 then
+split(Str, Index, Left, Right) :-
+    ( if Index =< 0 then
         Left = "",
         Right = Str
     else
-        to_code_unit_list(Str, List),
         Len = length(Str),
-        ( if Count > Len then
-            Num = Len
-        else
-            Num = Count
-        ),
-        ( if
-            list.split_list(Num, List, LeftList, RightList),
-            from_code_unit_list(LeftList, LeftPrime),
-            from_code_unit_list(RightList, RightPrime)
-        then
-            Left = LeftPrime,
-            Right = RightPrime
+        ( if Index >= Len then
+            Left = Str,
+            Right = ""
         else
-            unexpected($pred, "split_list failed")
+            unsafe_between(Str, 0, Index, Left),
+            unsafe_between(Str, Index, Len, Right)
         )
     ).
 
-- 
2.23.0



More information about the reviews mailing list