[m-rev.] for review: Add case-insensitive string compare predicate.
Peter Wang
novalazy at gmail.com
Mon Jun 20 14:13:14 AEST 2016
Suggestions for a better name?
---
library/string.m:
Add string.compare_ci_ascii predicate,
i.e. case-insensitive in the ASCII range.
NEWS:
Announce addition.
---
NEWS | 1 +
library/string.m | 45 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 46 insertions(+)
diff --git a/NEWS b/NEWS
index 99bb129..32423b5 100644
--- a/NEWS
+++ b/NEWS
@@ -256,6 +256,7 @@ Changes to the Mercury standard library:
- from_utf8_code_unit_list/2
- from_utf16_code_unit_list/2
- det_remove_prefix/3
+ - compare_ci_ascii/3
* The following predicates have been added to the map module:
diff --git a/library/string.m b/library/string.m
index c13f7d4..36d0c37 100644
--- a/library/string.m
+++ b/library/string.m
@@ -456,6 +456,15 @@
%
:- pred contains_char(string::in, char::in) is semidet.
+ % compare_ci_ascii(Res, X, Y):
+ %
+ % Compare two strings by code point order, ignoring the case of letters
+ % (A-Z, a-z) in the ASCII range.
+ % Equivalent to `compare(Res, to_lower(X), to_lower(Y))'
+ % but more efficient.
+ %
+:- pred compare_ci_ascii(comparison_result::uo, string::in, string::in) is det.
+
% prefix_length(Pred, String):
%
% The length (in code units) of the maximal prefix of `String' consisting
@@ -3143,6 +3152,42 @@ contains_char(Str, Char, I) :-
%---------------------%
+compare_ci_ascii(Res, X, Y) :-
+ compare_ci_ascii_loop(X, Y, 0, Res).
+
+:- pred compare_ci_ascii_loop(string::in, string::in, int::in,
+ comparison_result::uo) is det.
+
+compare_ci_ascii_loop(X, Y, I, Res) :-
+ ( if unsafe_index_next(X, I, IX, CharX) then
+ ( if unsafe_index_next(Y, I, _IY, CharY) then
+ char.to_lower(CharX, LowerCharX),
+ char.to_lower(CharY, LowerCharY),
+ compare(CharRes, LowerCharX, LowerCharY),
+ (
+ CharRes = (=),
+ % CharX = CharY, or both are in the ASCII range.
+ % In either case, we must have IX = IY.
+ compare_ci_ascii_loop(X, Y, IX, Res)
+ ;
+ ( CharRes = (<)
+ ; CharRes = (>)
+ ),
+ Res = CharRes
+ )
+ else
+ % X longer than Y.
+ Res = (>)
+ )
+ else if unsafe_index_next(Y, I, _IY, _CharY) then
+ % X shorter than Y.
+ Res = (<)
+ else
+ Res = (=)
+ ).
+
+%---------------------%
+
prefix_length(P, S) = Index :-
prefix_length_loop(P, S, 0, Index).
--
2.6.4
More information about the reviews
mailing list