Bläddra i källkod

[cs] String compare fix (#7562)

* add test for issue #6717

* [cs] use string.CompareOrdinal() instead of string.Compare()...

Compare() reports different results compared to all other targets, as it is culture-sensitive.

CompareOrdinal() should be faster (compares unicode value) and does what all other targets do.

* [cs] add CompareOrdinal() extern
Giuseppe Di Mauro 6 år sedan
förälder
incheckning
2621c73a2e
3 ändrade filer med 26 tillägg och 1 borttagningar
  1. 1 1
      src/generators/gencs.ml
  2. 2 0
      std/cs/_std/String.hx
  3. 23 0
      tests/unit/src/unit/issues/Issue6717.hx

+ 1 - 1
src/generators/gencs.ml

@@ -3075,7 +3075,7 @@ let generate con =
 						{ e with eexpr = TBinop(op, e1, mk_cast t2 e2) }
 					| _ ->
 							let handler = if is_string e1.etype then begin
-									{ e1 with eexpr = TCall(mk_static_field_access_infer string_cl "Compare" e1.epos [], [ e1; e2 ]); etype = gen.gcon.basic.tint }
+									{ e1 with eexpr = TCall(mk_static_field_access_infer string_cl "CompareOrdinal" e1.epos [], [ e1; e2 ]); etype = gen.gcon.basic.tint }
 								end else begin
 									let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
 									{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }

+ 2 - 0
std/cs/_std/String.hx

@@ -26,6 +26,8 @@ import cs.StdTypes;
 	@:overload private static function Compare(s1:String, s2:String):Int;
 	@:overload private static function Compare(s1:String, s2:String, kind:cs.system.StringComparison):Int;
 
+	private static function CompareOrdinal(s1:String, s2:String):Int;
+
 	var length(default,null) : Int;
 
 	function new(string:String) : Void;

+ 23 - 0
tests/unit/src/unit/issues/Issue6717.hx

@@ -0,0 +1,23 @@
+package unit.issues;
+
+class Issue6717 extends unit.Test {
+	function test() {
+		var space = " ";  // ASCII 0x20
+		var hyphen = "-"; // ASCII 0x2D
+
+		t(space.charAt(0) < hyphen.charAt(0));
+
+		// example strings from https://docs.microsoft.com/en-us/dotnet/api/system.globalization.compareoptions
+		var unsorted = ["cant", "bill's", "coop", "cannot", "billet", "can't", "con", "bills", "co-op"];
+		var expected = ["bill's", "billet", "bills", "can't", "cannot", "cant", "co-op", "con", "coop"];
+
+		var actual = unsorted.copy();
+		actual.sort(strcmp);
+
+		aeq(expected, actual);
+	}
+
+	static function strcmp(a:String, b:String):Int {
+		return a < b ? -1 : a > b ? 1 : 0;
+	}
+}