[m-rev.] diff: java versions of string functions
Peter Wang
novalazy at gmail.com
Mon Jun 29 16:22:16 AEST 2009
Branches: main
library/string.m:
Add Java versions of string functions.
Fix integer overflow in slow version of substring/4, as can happen when
someone passes max_int for Count.
tests/hard_coded/Mmakefile:
tests/hard_coded/contains_char_2.exp:
tests/hard_coded/contains_char_2.m:
tests/hard_coded/string_append_iii.exp:
tests/hard_coded/string_append_iii.m:
tests/hard_coded/string_append_ioi.exp:
tests/hard_coded/string_append_ioi.m:
tests/hard_coded/string_append_ooi.exp:
tests/hard_coded/string_append_ooi.m:
tests/hard_coded/string_set_char.exp:
tests/hard_coded/string_set_char.m:
tests/hard_coded/string_split_2.exp:
tests/hard_coded/string_split_2.m:
tests/hard_coded/string_sub_string_search.exp:
tests/hard_coded/string_sub_string_search.m:
tests/hard_coded/string_substring.exp:
tests/hard_coded/string_substring.m:
Add some test cases.
diff --git a/library/string.m b/library/string.m
index e996100..f23329e 100644
--- a/library/string.m
+++ b/library/string.m
@@ -1334,6 +1334,19 @@ string.to_char_list(Str::uo, CharList::in) :-
}
}").
+:- pragma foreign_proc("Java",
+ string.to_char_list_2(Str::in, CharList::out),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+ does_not_affect_liveness, no_sharing],
+"
+ list.List_1 lst = new list.List_1.F_nil_0();
+ for (int i = Str.length() - 1; i >= 0; i--) {
+ char c = Str.charAt(i);
+ lst = new list.List_1.F_cons_2(c, lst);
+ }
+ CharList = lst;
+").
+
:- pragma foreign_proc("Erlang",
string.to_char_list_2(Str::in, CharList::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
@@ -1731,6 +1744,28 @@ string.append_list(Strs::in) = (Str::uo) :-
Str[len] = '\\0';
}").
+:- pragma foreign_proc("Java",
+ string.join_list(Sep::in, Strs::in) = (Str::uo),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+ does_not_affect_liveness],
+"
+ java.lang.StringBuilder sb = new java.lang.StringBuilder();
+ boolean add_sep = false;
+
+ while (Strs instanceof list.List_1.F_cons_2) {
+ list.List_1.F_cons_2 cons = (list.List_1.F_cons_2) Strs;
+ java.lang.String s = (java.lang.String) cons.F1;
+ if (add_sep) {
+ sb.append(Sep);
+ }
+ sb.append(s);
+ add_sep = true;
+ Strs = cons.F2;
+ }
+
+ Str = sb.toString();
+").
+
string.join_list(_, []) = "".
string.join_list(Sep, [H | T]) = H ++ string.join_list_2(Sep, T).
@@ -1796,6 +1831,15 @@ string.sub_string_search(WholeString, Pattern, Index) :-
SUCCESS_INDICATOR = (Index >= 0);
}").
+:- pragma foreign_proc("Java",
+ sub_string_search_start(WholeString::in, Pattern::in, BeginAt::in,
+ Index::out),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ Index = WholeString.indexOf(Pattern, BeginAt);
+ succeeded = (Index >= 0);
+").
+
:- pragma foreign_proc("Erlang",
sub_string_search_start(String::in, SubString::in, BeginAt::in,
Index::out),
[will_not_call_mercury, promise_pure, thread_safe],
@@ -3539,12 +3583,21 @@ count_extra_trailing_zeroes(FloatStr, I, N0) = N :-
"
SUCCESS_INDICATOR = (strchr(Str, Ch) != NULL) && Ch != '\\0';
").
+
:- pragma foreign_proc("C#",
string.contains_char(Str::in, Ch::in),
[will_not_call_mercury, promise_pure, thread_safe],
"
SUCCESS_INDICATOR = (Str.IndexOf(Ch) != -1);
").
+
+:- pragma foreign_proc("Java",
+ string.contains_char(Str::in, Ch::in),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ succeeded = (Str.indexOf(Ch) != -1);
+").
+
string.contains_char(String, Char) :-
string.contains_char(String, Char, 0, string.length(String)).
@@ -3716,6 +3769,20 @@ string.set_char(Char, Index, !Str) :-
SUCCESS_INDICATOR = true;
}
").
+:- pragma foreign_proc("Java",
+ string.set_char_2(Ch::in, Index::in, Str0::in, Str::out),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ if (Index < 0 || Index >= Str0.length()) {
+ Str = null;
+ succeeded = false;
+ } else {
+ java.lang.StringBuilder sb = new StringBuilder(Str0);
+ sb.setCharAt(Index, Ch);
+ Str = sb.toString();
+ succeeded = true;
+ }
+").
string.set_char_2(Ch, Index, Str0, Str) :-
string.to_char_list(Str0, List0),
list.replace_nth(List0, Index + 1, Ch, List),
@@ -3921,6 +3988,13 @@ string.append(S1::out, S2::out, S3::in) :-
SUCCESS_INDICATOR = S3.Equals(System.String.Concat(S1, S2));
}").
+:- pragma foreign_proc("Java",
+ string.append_iii(S1::in, S2::in, S3::in),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ succeeded = S3.equals(S1.concat(S2));
+").
+
:- pragma foreign_proc("Erlang",
string.append_iii(S1::in, S2::in, S3::in),
[will_not_call_mercury, promise_pure, thread_safe],
@@ -3975,6 +4049,19 @@ string.append_iii(X, Y, Z) :-
}
}").
+:- pragma foreign_proc("Java",
+ string.append_ioi(S1::in, S2::uo, S3::in),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ if (S3.startsWith(S1)) {
+ S2 = S3.substring(S1.length());
+ succeeded = true;
+ } else {
+ S2 = null;
+ succeeded = false;
+ }
+").
+
string.append_ioi(X, Y, Z) :-
string.mercury_append(X, Y, Z).
@@ -4000,6 +4087,13 @@ string.append_ioi(X, Y, Z) :-
S3 = System.String.Concat(S1, S2);
}").
+:- pragma foreign_proc("Java",
+ string.append_iio(S1::in, S2::in, S3::uo),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ S3 = S1.concat(S2);
+").
+
:- pragma foreign_proc("Erlang",
string.append_iio(S1::in, S2::in, S3::uo),
[will_not_call_mercury, promise_pure, thread_safe],
@@ -4053,6 +4147,14 @@ string.append_ooi_2(NextS1Len, S3Len, S1, S2, S3) :-
S2 = S3.Substring(S1Len);
").
+:- pragma foreign_proc("Java",
+ string.append_ooi_3(S1Len::in, _S3Len::in, S1::out, S2::out, S3::in),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ S1 = S3.substring(0, S1Len);
+ S2 = S3.substring(S1Len);
+").
+
:- pragma foreign_proc("Erlang",
string.append_ooi_3(S1Len::in, _S3Len::in, S1::out, S2::out, S3::in),
[will_not_call_mercury, promise_pure, thread_safe],
@@ -4077,21 +4179,28 @@ string.mercury_append(X, Y, Z) :-
/*-----------------------------------------------------------------------*/
-string.substring(Str::in, Start::in, Count::in, SubStr::uo) :-
- End = min(Start + Count, string.length(Str)),
- SubStr = string.from_char_list(strchars(Start, End, Str)).
+substring(Str, !.Start, !.Count, SubStr) :-
+ ( !.Count =< 0 ->
+ SubStr = ""
+ ;
+ % Be careful about integer overflow when Count = max_int.
+ Len = string.length(Str),
+ max(0, !Start),
+ min(Len, !Start),
+ min(Len - !.Start, !Count),
+ CharList = strchars(!.Start, !.Start + !.Count, Str),
+ SubStr = string.from_char_list(CharList)
+ ).
:- func strchars(int, int, string) = list(char).
-strchars(I, End, Str) =
- (
- ( I < 0
- ; End =< I
- )
- ->
- []
+strchars(I, End, Str) = Chars :-
+ ( I >= End ->
+ Chars = []
;
- [string.index_det(Str, I) | strchars(I + 1, End, Str)]
+ C = string.unsafe_index(Str, I),
+ Cs = strchars(I + 1, End, Str),
+ Chars = [C | Cs]
).
:- pragma foreign_proc("C",
@@ -4119,6 +4228,26 @@ strchars(I, End, Str) =
}
}").
+:- pragma foreign_proc("Java",
+ string.substring(Str::in, Start::in, Count::in, SubString::uo),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+ does_not_affect_liveness, may_not_duplicate, no_sharing],
+"
+ if (Start < 0) Start = 0;
+ if (Count <= 0) {
+ SubString = """";
+ } else {
+ int len = Str.length();
+ if (Start > len) {
+ Start = len;
+ }
+ if (Count > len - Start) {
+ Count = len - Start;
+ }
+ SubString = Str.substring(Start, Start + Count);
+ }
+").
+
:- pragma foreign_proc("Erlang",
string.substring(Str::in, Start0::in, Count::in, SubString::uo),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
@@ -4222,6 +4351,23 @@ strchars(I, End, Str) =
}
}").
+:- pragma foreign_proc("Java",
+ string.split(Str::in, Count::in, Left::uo, Right::uo),
+ [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",
string.split(Str::in, Count::in, Left::uo, Right::uo),
[will_not_call_mercury, promise_pure, thread_safe],
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 6271558..837bee0 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -33,6 +33,7 @@ ORDINARY_PROGS= \
construct_test \
construct_test_exist \
contains_char \
+ contains_char_2 \
contravariance_bug \
contravariance_poly \
curry \
@@ -215,11 +216,18 @@ ORDINARY_PROGS= \
stream_test \
string_alignment \
string_alignment_bug \
+ string_append_iii \
+ string_append_ioi \
+ string_append_ooi \
string_builder_test \
string_loop \
+ string_set_char \
string_split \
+ string_split_2 \
string_string \
string_strip \
+ string_substring \
+ string_sub_string_search \
string_suffix_bug \
string_various \
sv_nested_closures \
@@ -286,6 +294,7 @@ JAVA_PASS_PROGS= \
compare_spec \
constant_prop_2 \
contains_char \
+ contains_char_2 \
constraint \
curry \
cut_test \
diff --git a/tests/hard_coded/contains_char_2.exp
b/tests/hard_coded/contains_char_2.exp
new file mode 100644
index 0000000..4745bd8
--- /dev/null
+++ b/tests/hard_coded/contains_char_2.exp
@@ -0,0 +1 @@
+test succeeded
diff --git a/tests/hard_coded/contains_char_2.m
b/tests/hard_coded/contains_char_2.m
new file mode 100644
index 0000000..b250cdc
--- /dev/null
+++ b/tests/hard_coded/contains_char_2.m
@@ -0,0 +1,32 @@
+%-----------------------------------------------------------------------------%
+
+:- module contains_char_2.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ (
+ string__contains_char("cat", 'c'),
+ string__contains_char("cat", 'a'),
+ string__contains_char("cat", 't'),
+ not string__contains_char("cat", 'm')
+ ->
+ io.write_string("test succeeded\n", !IO)
+ ;
+ io.write_string("test failed\n", !IO)
+ ).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
diff --git a/tests/hard_coded/string_append_iii.exp
b/tests/hard_coded/string_append_iii.exp
new file mode 100644
index 0000000..4745bd8
--- /dev/null
+++ b/tests/hard_coded/string_append_iii.exp
@@ -0,0 +1 @@
+test succeeded
diff --git a/tests/hard_coded/string_append_iii.m
b/tests/hard_coded/string_append_iii.m
new file mode 100644
index 0000000..e38c69d
--- /dev/null
+++ b/tests/hard_coded/string_append_iii.m
@@ -0,0 +1,32 @@
+%-----------------------------------------------------------------------------%
+
+:- module string_append_iii.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ (
+ string.append("", "cat", "cat"),
+ string.append("c", "at", "cat"),
+ string.append("ca", "t", "cat"),
+ string.append("cat", "", "cat")
+ ->
+ io.write_string("test succeeded\n", !IO)
+ ;
+ io.write_string("test failed\n", !IO)
+ ).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
diff --git a/tests/hard_coded/string_append_ioi.exp
b/tests/hard_coded/string_append_ioi.exp
new file mode 100644
index 0000000..13c6a01
--- /dev/null
+++ b/tests/hard_coded/string_append_ioi.exp
@@ -0,0 +1 @@
+["cat", "at", "t", ""]
diff --git a/tests/hard_coded/string_append_ioi.m
b/tests/hard_coded/string_append_ioi.m
new file mode 100644
index 0000000..1109af4
--- /dev/null
+++ b/tests/hard_coded/string_append_ioi.m
@@ -0,0 +1,35 @@
+%-----------------------------------------------------------------------------%
+
+:- module string_append_ioi.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module list.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ (
+ string.append("", A, "cat"),
+ string.append("c", B, "cat"),
+ string.append("ca", C, "cat"),
+ string.append("cat", D, "cat"),
+ not string.append("cat", _, "dogcat")
+ ->
+ io.write([A, B, C, D], !IO),
+ io.nl(!IO)
+ ;
+ io.write_string("tested failed\n", !IO)
+ ).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
diff --git a/tests/hard_coded/string_append_ooi.exp
b/tests/hard_coded/string_append_ooi.exp
new file mode 100644
index 0000000..54d4d91
--- /dev/null
+++ b/tests/hard_coded/string_append_ooi.exp
@@ -0,0 +1 @@
+["" - "cat", "c" - "at", "ca" - "t", "cat" - ""]
diff --git a/tests/hard_coded/string_append_ooi.m
b/tests/hard_coded/string_append_ooi.m
new file mode 100644
index 0000000..98a3b44
--- /dev/null
+++ b/tests/hard_coded/string_append_ooi.m
@@ -0,0 +1,32 @@
+%-----------------------------------------------------------------------------%
+
+:- module string_append_ooi.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is cc_multi.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module list.
+:- import_module pair.
+:- import_module solutions.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ unsorted_solutions(
+ (pred(L - R::out) is multi :-
+ string.append(L, R, "cat")
+ ), UnsortedSolutions),
+ list.sort(UnsortedSolutions, Solutions),
+ io.write(Solutions, !IO),
+ io.nl(!IO).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
diff --git a/tests/hard_coded/string_set_char.exp
b/tests/hard_coded/string_set_char.exp
new file mode 100644
index 0000000..4745bd8
--- /dev/null
+++ b/tests/hard_coded/string_set_char.exp
@@ -0,0 +1 @@
+test succeeded
diff --git a/tests/hard_coded/string_set_char.m
b/tests/hard_coded/string_set_char.m
new file mode 100644
index 0000000..d2f27b9
--- /dev/null
+++ b/tests/hard_coded/string_set_char.m
@@ -0,0 +1,61 @@
+%-----------------------------------------------------------------------------%
+
+:- module string_set_char.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module require.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ ( string.set_char('x', -1, "", _) ->
+ error("test failed")
+ ;
+ true
+ ),
+ ( string.set_char('x', 0, "", _) ->
+ error("test failed")
+ ;
+ true
+ ),
+ ( string.set_char('x', 1, "", _) ->
+ error("test failed")
+ ;
+ true
+ ),
+
+ ( string.set_char('m', 0, "cat", "mat") ->
+ true
+ ;
+ error("test failed")
+ ),
+ ( string.set_char('u', 1, "cat", "cut") ->
+ true
+ ;
+ error("test failed")
+ ),
+ ( string.set_char('b', 2, "cat", "cab") ->
+ true
+ ;
+ error("test failed")
+ ),
+ ( string.set_char('x', 3, "cat", _) ->
+ error("test failed")
+ ;
+ true
+ ),
+
+ io.write_string("test succeeded\n", !IO).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
diff --git a/tests/hard_coded/string_split_2.exp
b/tests/hard_coded/string_split_2.exp
new file mode 100644
index 0000000..4745bd8
--- /dev/null
+++ b/tests/hard_coded/string_split_2.exp
@@ -0,0 +1 @@
+test succeeded
diff --git a/tests/hard_coded/string_split_2.m
b/tests/hard_coded/string_split_2.m
new file mode 100644
index 0000000..0aae852
--- /dev/null
+++ b/tests/hard_coded/string_split_2.m
@@ -0,0 +1,34 @@
+%-----------------------------------------------------------------------------%
+
+:- module string_split_2.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ (
+ string.split("cat", -1, "", "cat"),
+ string.split("cat", 0, "", "cat"),
+ string.split("cat", 1, "c", "at"),
+ string.split("cat", 2, "ca", "t"),
+ string.split("cat", 3, "cat", ""),
+ string.split("cat", 4, "cat", "")
+ ->
+ io.write_string("test succeeded\n", !IO)
+ ;
+ io.write_string("test failed\n", !IO)
+ ).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
diff --git a/tests/hard_coded/string_sub_string_search.exp
b/tests/hard_coded/string_sub_string_search.exp
new file mode 100644
index 0000000..4745bd8
--- /dev/null
+++ b/tests/hard_coded/string_sub_string_search.exp
@@ -0,0 +1 @@
+test succeeded
diff --git a/tests/hard_coded/string_sub_string_search.m
b/tests/hard_coded/string_sub_string_search.m
new file mode 100644
index 0000000..2124bc5
--- /dev/null
+++ b/tests/hard_coded/string_sub_string_search.m
@@ -0,0 +1,39 @@
+%-----------------------------------------------------------------------------%
+
+:- module string_sub_string_search.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ (
+ string.sub_string_search("", "", 0),
+ not string.sub_string_search("", "dog", _),
+ not string.sub_string_search("cat", "catdog", _),
+
+ string.sub_string_search("cat", "", 0),
+ string.sub_string_search("cat", "cat", 0),
+ string.sub_string_search("cat", "at", 1),
+ string.sub_string_search("cat", "t", 2),
+
+ string.sub_string_search_start("catcatcat", "cat", 1, 3),
+ not string.sub_string_search_start("catcatcat", "cat", 9, _)
+ ->
+ io.write_string("test succeeded\n", !IO)
+ ;
+ io.write_string("test failed\n", !IO)
+ ).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
diff --git a/tests/hard_coded/string_substring.exp
b/tests/hard_coded/string_substring.exp
new file mode 100644
index 0000000..4745bd8
--- /dev/null
+++ b/tests/hard_coded/string_substring.exp
@@ -0,0 +1 @@
+test succeeded
diff --git a/tests/hard_coded/string_substring.m
b/tests/hard_coded/string_substring.m
new file mode 100644
index 0000000..07e7bfe
--- /dev/null
+++ b/tests/hard_coded/string_substring.m
@@ -0,0 +1,44 @@
+%-----------------------------------------------------------------------------%
+
+:- module string_substring.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ (
+ string.substring("cat", -1, max_int, "cat"),
+ string.substring("cat", 0, max_int, "cat"),
+ string.substring("cat", 1, max_int, "at"),
+ string.substring("cat", 2, max_int, "t"),
+ string.substring("cat", 3, max_int, ""),
+ string.substring("cat", 4, max_int, ""),
+ string.substring("cat", 0, 0, ""),
+ string.substring("cat", 0, 1, "c"),
+ string.substring("cat", 0, 2, "ca"),
+ string.substring("cat", 0, 3, "cat"),
+ string.substring("cat", 1, -1, ""),
+ string.substring("cat", 1, 0, ""),
+ string.substring("cat", 1, 1, "a"),
+ string.substring("cat", 1, 2, "at"),
+ string.substring("cat", 1, 3, "at")
+ ->
+ io.write_string("test succeeded\n", !IO)
+ ;
+ io.write_string("test failed\n", !IO)
+ ).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list