Pārlūkot izejas kodu

* fpc_Val_SInt_ShortStr: bug fixes and improvements by Bart B

florian 3 gadi atpakaļ
vecāks
revīzija
f39a6a7755
1 mainītis faili ar 30 papildinājumiem un 37 dzēšanām
  1. 30 37
      rtl/inc/sstrings.inc

+ 30 - 37
rtl/inc/sstrings.inc

@@ -1154,33 +1154,41 @@ end;
 
 Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
 var
-  temp, prev, maxPrevValue, maxNewValue: ValUInt;
+  temp, prev, maxPrevValue: ValUInt;
   base,u : byte;
-  negative, RolledOver: boolean;
-  SignedLower, SignedUpper: Int64;
-  UnsignedUpper: UInt64;
-  RolledOverAt: integer;
-  RollOverPoint: ValUInt;
+  negative: boolean;
+  UnsignedUpperLimit: ValUInt;
 const
-  ValueArray : array['0'..'f'] of byte = (0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,10,11,12,13,14,15,
-                                          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  ValueArray : array['0'..'f'] of byte = (0,1,2,3,4,5,6,7,8,9,$FF,$FF,$FF,$FF,$FF,$FF,$FF,10,11,12,13,14,15,
+                                          $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,
                                           10,11,12,13,14,15);
 begin
   fpc_Val_SInt_ShortStr := 0;
   Temp:=0;
   Code:=InitVal(s,negative,base);
-  case DestSize of
-    1: begin SignedLower:=Low(ShortInt); SignedUpper:=(High(ShortInt)); UnSignedUpper:=High(Byte) end;
-    2: begin SignedLower:=Low(SmallInt); SignedUpper:=(High(SmallInt)); UnSignedUpper:=High(Word) end;
-    4: begin SignedLower:=Low(LongInt);  SignedUpper:=(High(LongInt));  UnSignedUpper:=High(DWord) end;
-    8: begin SignedLower:=Low(Int64);    SignedUpper:=(High(Int64));    UnSignedUpper:=High(QWord) end;
-  end;
 
-  RolledOver:=False;
-  if negative then
-    RollOverPoint:=-SignedLower
+  if (base=10) or negative then
+    begin //always limit to either Low(DestType) or High(DestType)
+      case DestSize of
+        1: UnsignedUpperLimit := ValUInt(High(ShortInt))+Ord(negative);
+        2: UnsignedUpperLimit := ValUInt(High(SmallInt))+Ord(negative);
+        4: UnsignedUpperLimit := ValUInt(High(LongInt))+Ord(negative);
+        {$ifdef CPU64}
+        8: UnsignedUpperLimit := ValUInt(High(Int64))+Ord(negative);
+        {$endif CPU64}
+      end;
+    end
   else
-    RollOverPoint:=SignedUpper;
+    begin //not decimal and not negative
+      case DestSize of
+        1: UnsignedUpperLimit := High(Byte);
+        2: UnsignedUpperLimit := High(Word);
+        4: UnsignedUpperLimit := High(DWord);
+        {$ifdef CPU64}
+        8: UnsignedUpperLimit := High(UInt64);
+        {$endif CPU64}
+      end;
+    end;
 
   if Code>length(s) then
    exit;
@@ -1190,11 +1198,8 @@ begin
         Code:=0;
       exit;
     end;
+
   maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
-  if (base = 10) then
-    maxNewValue := MaxSIntValue + ord(negative)
-  else
-    maxNewValue := MaxUIntValue;
 
   while Code<=Length(s) do
    begin
@@ -1208,19 +1213,14 @@ begin
 
      Prev := Temp;
      Temp := Temp*ValUInt(base);
+
      If (u >= base) or
-        (ValUInt(maxNewValue-u) < Temp) or
-        (prev > maxPrevValue) or
-        ((Temp+u)>UnsignedUpper) Then
+        (prev > maxPrevValue)
+        or ((Temp)>(UnsignedUpperLimit-u)) Then
        Begin
          fpc_Val_SInt_ShortStr := 0;
          Exit
        End;
-     if (not RolledOver) and ((Temp+u)>RollOverPoint) then
-       begin
-         RolledOver := True;
-         RolledOverAt := Code;
-       end;
      Temp:=Temp+u;
      inc(code);
    end;
@@ -1230,13 +1230,6 @@ begin
   If Negative Then
     fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
 
-  if RolledOver and ((base=10) or ((base<>10) and (negative))) {and (not negative)} then
-    begin
-      fpc_Val_SInt_ShortStr:=0;
-      Code := RolledOverAt;
-      exit;
-    end;
-
   If Not(Negative) and (base <> 10) Then
    {sign extend the result to allow proper range checking}
     Case DestSize of