{ This file is part of the Free Component Library JSON Data structures Copyright (c) 2007 by Michael Van Canneyt michael@freepascal.org See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} //modifed by Red_prig {$mode objfpc} {$h+} unit Ufpjson; interface uses {$ifdef fpc} variants, {$endif} {$ifdef pas2js} JS, RTLConsts, Types, {$endif} SysUtils, classes; type TJSONtype = (jtUnknown, jtNumber, jtString, jtBoolean, jtNull, jtArray, jtObject); TJSONInstanceType = ( jitUnknown, jitNumberInteger, {$ifdef fpc} jitNumberInt64, jitNumberQWord, {$endif} jitNumberFloat, jitString, jitBoolean, jitNull, jitArray, jitObject); TJSONFloat = Double; TJSONStringType = {$ifdef fpc}UTF8String{$else}string{$endif}; TJSONUnicodeStringType = Unicodestring; {$ifdef fpc} TJSONCharType = AnsiChar; PJSONCharType = ^TJSONCharType; TJSONVariant = variant; TFPJSStream = TMemoryStream; {$else} TJSONCharType = char; TJSONVariant = jsvalue; TFPJSStream = TJSArray; {$endif} TFormatOption = (foSingleLineArray, // Array without CR/LF : all on one line foSingleLineObject, // Object without CR/LF : all on one line foDoNotQuoteMembers, // Do not quote object member names. foUseTabchar, // Use tab characters instead of spaces. foSkipWhiteSpace, // Do not use whitespace at all foSkipWhiteSpaceOnlyLeading // When foSkipWhiteSpace is active, skip whitespace for object members only before : ); TFormatOptions = set of TFormatOption; Const DefaultIndentSize = 2; DefaultFormat = []; AsJSONFormat = [foSingleLineArray,foSingleLineObject]; // These options make FormatJSON behave as AsJSON AsCompressedJSON = [foSingleLineArray,foSingleLineObject,foskipWhiteSpace]; // These options make FormatJSON behave as AsJSON with TJSONData.CompressedJSON=True AsCompactJSON = [foSingleLineArray,foSingleLineObject,foskipWhiteSpace,foDoNotQuoteMembers]; // These options make FormatJSON behave as AsJSON with TJSONData.CompressedJSON=True and TJSONObject.UnquotedMemberNames=True ValueJSONTypes = [jtNumber, jtString, jtBoolean, jtNull]; ActualValueJSONTypes = ValueJSONTypes - [jtNull]; StructuredJSONTypes = [jtArray,jtObject]; Type TJSONNumberType = ( ntFloat, ntInteger {$ifdef fpc} ,ntInt64 ,ntQWord {$endif} ); type TAddStr=object FStr:PChar; FLen:SizeInt; Procedure AddStr(Const S:RawByteString); Procedure AddChar(C:AnsiChar); Procedure Reset; inline; Procedure Free; inline; function GetStr:RawByteString; inline; end; TUtf8AddStr=object(TAddStr) FSP:SizeUInt; Procedure AddChar(C:AnsiChar); inline; Procedure AddWideChar(C:WideChar); Procedure Reset; inline; end; Function StringToJSONString(const S : TJSONStringType;Strict:Boolean=False):TJSONStringType; inline; procedure _StringToJSONString(Var FAddStr:TAddStr;const S:TJSONStringType;Strict:Boolean=False); inline; procedure __StringToJSONString(Var FAddStr:TAddStr;P:PJSONCharType;Len:SizeInt;Strict:Boolean=False); Function JSONStringToString(const S :TJSONStringType):TJSONStringType; inline; procedure _JSONStringToString(Var FAddStr:TUtf8AddStr;const S:TJSONStringType); inline; procedure __JSONStringToString(Var FAddStr:TUtf8AddStr;P:PJSONCharType;Len:SizeInt); Function JSONTypeName(JSONType:TJSONType):String; implementation Uses typinfo; Procedure TAddStr.AddStr(Const S:RawByteString); Var i:SizeInt; begin if Length(S)>0 then For i:=1 to Length(S) do AddChar(S[i]); end; Procedure TAddStr.AddChar(C:AnsiChar); Var i,MemLen:SizeInt; begin if (FStr=nil) then begin MemLen:=0 end else begin MemLen:=MemSize(FStr); end; i:=FLen; FLen:=FLen+1; if (MemLen0 then begin case lw of $dc00..$dfff: {High Surrogates 2} begin { $d7c0 is ($d800 - ($10000 shr 10)) } lw:=(longword(FSP-$d7c0) shl 10) + (lw xor $dc00); inherited AddChar(AnsiChar($f0 or (lw shr 18))); inherited AddChar(AnsiChar($80 or ((lw shr 12) and $3f))); inherited AddChar(AnsiChar($80 or ((lw shr 6) and $3f))); inherited AddChar(AnsiChar($80 or (lw and $3f))); end; end; FSP:=0; end else begin case lw of 0..$7f: begin inherited AddChar(AnsiChar(lw)); end; $80..$7ff: begin inherited AddChar(AnsiChar($c0 or (lw shr 6))); inherited AddChar(AnsiChar($80 or (lw and $3f))); end; $800..$d7ff,$e000..$ffff: begin inherited AddChar(AnsiChar($e0 or (lw shr 12))); inherited AddChar(AnsiChar($80 or ((lw shr 6) and $3f))); inherited AddChar(AnsiChar($80 or (lw and $3f))); end; $d800..$dbff: {High Surrogates 1} begin FSP:=lw; end; end; end; end; Procedure TUtf8AddStr.Reset; inline; begin inherited; FSP:=0; end; function StringToJSONString(const S:TJSONStringType;Strict:Boolean=False):TJSONStringType; inline; Var FAddStr:TAddStr; begin FAddStr:=Default(TAddStr); _StringToJSONString(FAddStr,S,Strict); Result:=FAddStr.GetStr; FAddStr.Free; end; procedure _StringToJSONString(Var FAddStr:TAddStr;const S:TJSONStringType;Strict:Boolean=False); inline; begin __StringToJSONString(FAddStr,PJSONCharType(S),Length(S),Strict); end; procedure __StringToJSONString(Var FAddStr:TAddStr;P:PJSONCharType;Len:SizeInt;Strict:Boolean=False); Var I:SizeInt; C,T:AnsiChar; begin I:=0; if Strict then T:='/' else T:=#0; While (I