Skip to content

Commit

Permalink
Fix TryStrToFloat and FloatToStr
Browse files Browse the repository at this point in the history
Fix TryStrToFloat and FloatToStr when global variable DecimalSeparator <> '.', because TryStrToFloat and FloatToStr use global variable DecimalSeparator and JSON always expect dot (.) as decimal separator.
  • Loading branch information
goncons authored Oct 3, 2017
1 parent 1483a3f commit 98d1917
Showing 1 changed file with 66 additions and 10 deletions.
76 changes: 66 additions & 10 deletions src/Jsons.pas
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/****************************************************************************
{****************************************************************************
Copyright (c) 2014 Randolph
mail: rilyu@sina.com
@@ -20,7 +20,7 @@
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
****************************************************************************}

unit Jsons;

@@ -309,6 +309,62 @@ TJson = class(TJsonBase)

implementation

{**
* Fixed FloatToStr to convert DecimalSeparator to dot (.) decimal separator, FloatToStr returns
* DecimalSeparator as decimal separator, but JSON uses dot (.) as decimal separator.
*}
function FixedFloatToStr(const Value: Extended): string;
var
S: string;
begin
try
S := FloatToStr(Value);
if (DecimalSeparator <> '.') and (Pos(DecimalSeparator, S) <> 0) then
Result := StringReplace(S, DecimalSeparator, '.', [rfReplaceAll])
else
Result := S;
finally
SetLength(S, 0);
end;
end;

{**
* Fixed TryStrToFloat to convert dot (.) decimal separator to DecimalSeparator, TryStrToFloat expects
* decimal separator to be DecimalSeparator, but JSON uses dot (.) as decimal separator.
*}
function FixedTryStrToFloat(const S: string; out Value: Extended): Boolean;
var
FixedS: string;
begin
try
if (DecimalSeparator <> '.') and (Pos('.', S) <> 0) then
FixedS := StringReplace(S, '.', DecimalSeparator, [rfReplaceAll])
else
FixedS := S;
Result := TryStrToFloat(FixedS, Value);
finally
SetLength(FixedS, 0);
end;
end;
{**
* Fixed StrToFloat to convert dot (.) decimal separator to DecimalSeparator, StrToFloat expects
* decimal separator to be DecimalSeparator, but JSON uses dot (.) as decimal separator.
*}
function FixedStrToFloat(const S: string): Extended;
var
FixedS: string;
begin
try
if (DecimalSeparator <> '.') and (Pos('.', S) <> 0) then
FixedS := StringReplace(S, '.', DecimalSeparator, [rfReplaceAll])
else
FixedS := S;
Result := StrToFloat(FixedS);
finally
SetLength(FixedS, 0);
end;
end;

{ TJsonBase }

function TJsonBase.AnalyzeJsonValueType(const S: String): TJsonValueType;
@@ -325,9 +381,9 @@ function TJsonBase.AnalyzeJsonValueType(const S: String): TJsonValueType;
else if (S[1] = '"') and (S[Len] = '"') then Result := jvString
else if SameText(S, 'null') then Result := jvNull
else if SameText(S, 'true') or SameText(S, 'false') then Result := jvBoolean
else if TryStrToFloat(S, Number) then Result := jvNumber;
else if FixedTryStrToFloat(S, Number) then Result := jvNumber;
end
else if TryStrToFloat(S, Number) then Result := jvNumber;
else if FixedTryStrToFloat(S, Number) then Result := jvNumber;
end;

constructor TJsonBase.Create(AOwner: TJsonBase);
@@ -460,7 +516,7 @@ function TJsonBase.IsJsonNumber(const S: String): Boolean;
var
Number: Extended;
begin
Result := TryStrToFloat(S, Number);
Result := FixedTryStrToFloat(S, Number);
end;

function TJsonBase.IsJsonObject(const S: String): Boolean;
@@ -672,7 +728,7 @@ function TJsonValue.GetAsInteger: Integer;
Result := 0;
case FValueType of
jvNone, jvNull: Result := 0;
jvString: Result := Trunc(StrToFloat(FStringValue));
jvString: Result := Trunc(FixedStrToFloat(FStringValue));
jvNumber: Result := Trunc(FNumberValue);
jvBoolean: Result := Ord(FBooleanValue);
jvObject, jvArray: RaiseValueTypeError(jvNumber);
@@ -684,7 +740,7 @@ function TJsonValue.GetAsNumber: Extended;
Result := 0;
case FValueType of
jvNone, jvNull: Result := 0;
jvString: Result := StrToFloat(FStringValue);
jvString: Result := FixedStrToFloat(FStringValue);
jvNumber: Result := FNumberValue;
jvBoolean: Result := Ord(FBooleanValue);
jvObject, jvArray: RaiseValueTypeError(jvNumber);
@@ -710,7 +766,7 @@ function TJsonValue.GetAsString: String;
case FValueType of
jvNone, jvNull: Result := '';
jvString: Result := FStringValue;
jvNumber: Result := FloatToStr(FNumberValue);
jvNumber: Result := FixedFloatToStr(FNumberValue);
jvBoolean: Result := BooleanStr[FBooleanValue];
jvObject, jvArray: RaiseValueTypeError(jvString);
end;
@@ -734,7 +790,7 @@ procedure TJsonValue.Parse(JsonString: String);
jvNone: RaiseParseError(JsonString);
jvNull: ;
jvString: FStringValue := Decode(Copy(JsonString, 2, Length(JsonString) - 2));
jvNumber: FNumberValue := StrToFloat(JsonString);
jvNumber: FNumberValue := FixedStrToFloat(JsonString);
jvBoolean: FBooleanValue := SameText(JsonString, 'true');
jvObject:
begin
@@ -846,7 +902,7 @@ function TJsonValue.Stringify: String;
case FValueType of
jvNone, jvNull: Result := 'null';
jvString: Result := '"' + Encode(FStringValue) + '"';
jvNumber: Result := FloatToStr(FNumberValue);
jvNumber: Result := FixedFloatToStr(FNumberValue);
jvBoolean: Result := StrBoolean[FBooleanValue];
jvObject: Result := FObjectValue.Stringify;
jvArray: Result := FArrayValue.Stringify;

0 comments on commit 98d1917

Please sign in to comment.