2
0
Эх сурвалжийг харах

* XPath: number-to-string conversion is now compliant to the specs (no scientific notation, decimal separator is a hardcoded period, correct output values for INF/NAN) + tests.

git-svn-id: trunk@13389 -
sergei 16 жил өмнө
parent
commit
a9d9841eee

+ 71 - 2
packages/fcl-xml/src/xpath.pp

@@ -1486,9 +1486,78 @@ begin
 end;
 
 function TXPathNumberVariable.AsText: DOMString;
+var
+  frec: TFloatRec;
+  i, nd, reqlen: Integer;
+  P: DOMPChar;
 begin
-// TODO: Decimal separator!!!
-  Result := FloatToStr(FValue);
+  FloatToDecimal(frec, FValue, fvExtended, 17, 9999);
+
+  // TODO: remove workaround after #14143 is fixed
+  if {frec.Exponent = -32768} frec.Digits[0] = 'N' then
+  begin
+    Result := 'NaN';          // do not localize
+    Exit;
+  end
+  else if {frec.Exponent = 32767} (frec.Digits[0] = 'I') or ((frec.Digits[0] = '+') and (frec.Digits[1] = 'I')) then
+  begin
+    if frec.Negative then
+      Result := '-Infinity'   // do not localize
+    else
+      Result := 'Infinity';   // do not localize
+    Exit;  
+  end
+  else if frec.Digits[0] = #0 then
+  begin
+    Result := '0';
+    Exit;
+  end
+  else
+  begin
+    nd := StrLen(@frec.Digits[0]);
+    reqlen := nd + ord(frec.Negative);  // maybe minus sign
+    if frec.Exponent > nd then
+      Inc(reqlen, frec.Exponent - nd)   // add this much zeroes at the right
+    else if frec.Exponent < nd then
+    begin
+      Inc(reqlen);                      // decimal point
+      if frec.Exponent <= 0 then
+        Inc(reqlen, 1 - frec.Exponent); // zeroes at the left + one more for the int part
+    end;
+    SetLength(Result, reqlen);
+    P := DOMPChar(Result);
+    if frec.Negative then
+    begin
+      P^ := '-';
+      Inc(P);
+    end;
+    if frec.Exponent <= 0 then          // value less than 1, put zeroes at left
+    begin
+      for i := 0 to 1-frec.Exponent do
+        P[i] := '0';
+      P[1] := '.';
+      for i := 0 to nd-1 do
+        P[i+2-frec.Exponent] := WideChar(ord(frec.Digits[i]));
+    end
+    else if frec.Exponent > nd then    // large integer, put zeroes at right
+    begin
+      for i := 0 to nd-1 do
+        P[i] := WideChar(ord(frec.Digits[i]));
+      for i := nd to reqlen-1-ord(frec.Negative) do
+        P[i] := '0';
+    end
+    else  // 0 < exponent <= digits, insert decimal point into middle
+    begin
+      for i := 0 to frec.Exponent-1 do
+        P[i] := WideChar(ord(frec.Digits[i]));
+      if frec.Exponent < nd then
+      begin
+        P[frec.Exponent] := '.';
+        for i := frec.Exponent to nd-1 do
+          P[i+1] := WideChar(ord(frec.Digits[i]));
+      end;
+    end;
+  end;
 end;
 
 

+ 16 - 2
packages/fcl-xml/tests/xpathts.pp

@@ -542,7 +542,8 @@ const
   '<b ns1:attrib2="test"/>'#10+
   '</doc>';
 
-  StringTests: array[0..75] of TTestRec = (             // numbers refer to xalan/string/stringXX
+  StringTests: array[0..84] of TTestRec = (             // numbers refer to xalan/string/stringXX
+    (expr: 'string(0)';       rt: rtString; s: '0'),
     (expr: 'string(5)';       rt: rtString; s: '5'),    // #38/39
     (expr: 'string(0.5)';     rt: rtString; s: '0.5'),
     (expr: 'string(-0.5)';    rt: rtString; s: '-0.5'),
@@ -634,7 +635,20 @@ const
 
     (data: str30; expr: 'local-name(baz2:b)'; rt: rtString; s: 'b'), // namespace07
     (data: str30; expr: 'local-name(baz2:b/@baz1:attrib2)'; rt: rtString; s: 'attrib2'), // namespace09
-    (data: str30; expr: 'local-name()'; rt: rtString; s: 'doc')      // namespace26
+    (data: str30; expr: 'local-name()'; rt: rtString; s: 'doc'),      // namespace26
+    
+    // tests for number->string conversions at boundary conditions
+    (expr: 'string(123456789012345678)';     rt: rtString; s: '123456789012345680'),    // #132.1
+    (expr: 'string(-123456789012345678)';    rt: rtString; s: '-123456789012345680'),   // #132.2
+    (expr: 'string(.10123456789234567893)';  rt: rtString; s: '0.10123456789234568'),   // #133.1
+    (expr: 'string(-.10123456789234567893)'; rt: rtString; s: '-0.10123456789234568'),  // #133.2
+    
+    (expr: 'string(9.87654321012345)'; rt: rtString; s: '9.87654321012345'),  // #134.1
+    (expr: 'string(98765432101234.5)'; rt: rtString; s: '98765432101234.5'),  // #134.2
+    (expr: 'string(.0000000000000000000000000000000000000000123456789)'; rt: rtString;  // #135.1
+      s: '0.0000000000000000000000000000000000000000123456789'),
+    (expr: 'string(-.0000000000000000000000000000000000000000123456789)'; rt: rtString; // #135.2
+      s: '-0.0000000000000000000000000000000000000000123456789')
   );
   
   ax114='<doc>'+