[m-rev.] for review: Add string.unsafe_append_string_pieces.

Peter Wang novalazy at gmail.com
Thu Nov 7 15:21:15 AEDT 2019


library/string.m:
    Add unsafe_append_string_pieces/2 predicate.

NEWS:
    Announce addition.
---
 NEWS             |  1 +
 library/string.m | 64 ++++++++++++++++++++++++++++++++++--------------
 2 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/NEWS b/NEWS
index c8417526f..80e4504d3 100644
--- a/NEWS
+++ b/NEWS
@@ -432,6 +432,7 @@ Changes to the Mercury standard library:
    - unsafe_compare_substrings/6
    - nondet_append/3
    - append_string_pieces/2
+   - unsafe_append_string_pieces/2
 
   The following procedures in the string module have been deprecated:
 
diff --git a/library/string.m b/library/string.m
index 8b74b3e9c..ebcbc8a97 100644
--- a/library/string.m
+++ b/library/string.m
@@ -706,6 +706,14 @@
     %
 :- pred append_string_pieces(list(string_piece)::in, string::uo) is det.
 
+    % Same as append_string_pieces/2 but without range checks.
+    % WARNING: if any piece `substring(S, Start, End)' has `Start' or `End'
+    % outside the range [0, length(S)], or if `Start' > `End',
+    % then the behaviour is UNDEFINED. Use with care!
+    %
+:- pred unsafe_append_string_pieces(list(string_piece)::in, string::uo)
+    is det.
+
 %---------------------------------------------------------------------------%
 %
 % Splitting up strings.
@@ -4151,16 +4159,19 @@ copy_into_buffer(Dest0, Dest, DestOffset0, DestOffset, Src, SrcStart, SrcEnd)
 %---------------------%
 
 append_string_pieces(Pieces, String) :-
-    check_pieces_and_sum_length($pred, Pieces, 0, BufferLen),
-    alloc_buffer(BufferLen, Buffer0),
-    list.foldl2(copy_piece_into_buffer, Pieces, 0, End, Buffer0, Buffer),
-    expect(unify(End, BufferLen), $pred, "End != BufferLen"),
-    buffer_to_string(Buffer, String).
+    DoCheck = yes,
+    sum_piece_lengths($pred, DoCheck, Pieces, 0, BufferLen),
+    do_append_string_pieces(Pieces, BufferLen, String).
+
+unsafe_append_string_pieces(Pieces, String) :-
+    DoCheck = no,
+    sum_piece_lengths($pred, DoCheck, Pieces, 0, BufferLen),
+    do_append_string_pieces(Pieces, BufferLen, String).
 
-:- pred check_pieces_and_sum_length(string::in, list(string_piece)::in,
+:- pred sum_piece_lengths(string::in, bool::in, list(string_piece)::in,
     int::in, int::out) is det.
 
-check_pieces_and_sum_length(PredName, Pieces, Len0, Len) :-
+sum_piece_lengths(PredName, DoCheck, Pieces, Len0, Len) :-
     (
         Pieces = [],
         Len = Len0
@@ -4171,22 +4182,37 @@ check_pieces_and_sum_length(PredName, Pieces, Len0, Len) :-
             PieceLen = length(Str)
         ;
             Piece = substring(BaseStr, Start, End),
-            BaseLen = length(BaseStr),
-            ( if
-                Start >= 0,
-                Start =< BaseLen,
-                End >= Start,
-                End =< BaseLen
-            then
-                PieceLen = End - Start
-            else
-                unexpected(PredName, "substring index out of range")
-            )
+            (
+                DoCheck = yes,
+                BaseLen = length(BaseStr),
+                ( if
+                    Start >= 0,
+                    Start =< BaseLen,
+                    End >= Start,
+                    End =< BaseLen
+                then
+                    true
+                else
+                    unexpected(PredName, "substring index out of range")
+                )
+            ;
+                DoCheck = no
+            ),
+            PieceLen = End - Start
         ),
         Len1 = Len0 + PieceLen,
-        check_pieces_and_sum_length(PredName, TailPieces, Len1, Len)
+        sum_piece_lengths(PredName, DoCheck, TailPieces, Len1, Len)
     ).
 
+:- pred do_append_string_pieces(list(string_piece)::in, int::in, string::uo)
+    is det.
+
+do_append_string_pieces(Pieces, BufferLen, String) :-
+    alloc_buffer(BufferLen, Buffer0),
+    list.foldl2(copy_piece_into_buffer, Pieces, 0, End, Buffer0, Buffer),
+    expect(unify(End, BufferLen), $pred, "End != BufferLen"),
+    buffer_to_string(Buffer, String).
+
 :- pred copy_piece_into_buffer(string_piece::in, int::in, int::out,
     string_buffer::di, string_buffer::uo) is det.
 
-- 
2.23.0



More information about the reviews mailing list