ppujson.pp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. {
  2. Copyright (c) 2013 by Yury Sidorov and the FPC Development Team
  3. JSON output of a PPU File
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************}
  16. unit ppujson;
  17. {$mode objfpc}{$H+}
  18. interface
  19. uses
  20. SysUtils, Classes, ppuout;
  21. type
  22. { TPpuJsonOutput }
  23. TPpuJsonOutput = class(TPpuOutput)
  24. private
  25. FNeedDelim: array of boolean;
  26. function JsonStr(const s: string): string;
  27. procedure BeforeWriteElement;
  28. procedure WriteAttr(const AName, AValue: string);
  29. protected
  30. procedure WriteObjectStart(const AName: string; Def: TPpuDef); override;
  31. procedure WriteObjectEnd(const AName: string; Def: TPpuDef); override;
  32. procedure WriteArrayStart(const AName: string); override;
  33. procedure WriteArrayEnd(const AName: string); override;
  34. procedure WriteStr(const AName, AValue: string); override;
  35. procedure WriteInt(const AName: string; AValue: Int64; Signed: boolean); override;
  36. procedure WriteFloat(const AName: string; AValue: extended); override;
  37. procedure WriteBool(const AName: string; AValue: boolean); override;
  38. procedure WriteNull(const AName: string); override;
  39. public
  40. constructor Create(OutFileHandle: THandle); override;
  41. procedure IncI; override;
  42. procedure DecI; override;
  43. end;
  44. implementation
  45. { TPpuJsonOutput }
  46. function TPpuJsonOutput.JsonStr(const s: string): string;
  47. var
  48. ws: widestring;
  49. ps: PWideChar;
  50. pd: PAnsiChar;
  51. i, slen, dlen, dpos: integer;
  52. procedure _AddChar(c: ansichar);
  53. begin
  54. if dpos = dlen then begin
  55. dlen:=dlen*2;
  56. SetLength(Result, dlen);
  57. pd:=PAnsiChar(Result) + dpos;
  58. end;
  59. pd^:=c;
  60. Inc(pd);
  61. Inc(dpos);
  62. end;
  63. var
  64. c: widechar;
  65. ss: shortstring;
  66. begin
  67. ws:=UTF8Decode(s);
  68. ps:=PWideChar(ws);
  69. slen:=Length(ws);
  70. dlen:=slen + 2;
  71. SetLength(Result, dlen);
  72. pd:=PAnsiChar(Result);
  73. dpos:=0;
  74. _AddChar('"');
  75. while slen > 0 do begin
  76. c:=ps^;
  77. case c of
  78. '"', '\', '/':
  79. begin
  80. _AddChar('\');
  81. _AddChar(c);
  82. end;
  83. #8:
  84. begin
  85. _AddChar('\');
  86. _AddChar('b');
  87. end;
  88. #9:
  89. begin
  90. _AddChar('\');
  91. _AddChar('t');
  92. end;
  93. #10:
  94. begin
  95. _AddChar('\');
  96. _AddChar('n');
  97. end;
  98. #13:
  99. begin
  100. _AddChar('\');
  101. _AddChar('r');
  102. end;
  103. #12:
  104. begin
  105. _AddChar('\');
  106. _AddChar('f');
  107. end;
  108. else
  109. if (c < #32) or (c > #127) then begin
  110. _AddChar('\');
  111. _AddChar('u');
  112. ss:=hexStr(integer(c), 4);
  113. for i:=1 to 4 do
  114. _AddChar(ss[i]);
  115. end
  116. else
  117. _AddChar(c);
  118. end;
  119. Inc(ps);
  120. Dec(slen);
  121. end;
  122. _AddChar('"');
  123. SetLength(Result, dpos);
  124. end;
  125. procedure TPpuJsonOutput.BeforeWriteElement;
  126. begin
  127. if FNeedDelim[Indent] then
  128. WriteLn(',');
  129. FNeedDelim[Indent]:=True;
  130. end;
  131. procedure TPpuJsonOutput.WriteAttr(const AName, AValue: string);
  132. begin
  133. BeforeWriteElement;
  134. if AName <> '' then
  135. Write(Format('"%s": %s', [AName, AValue]))
  136. else
  137. Write(AValue);
  138. end;
  139. procedure TPpuJsonOutput.WriteStr(const AName, AValue: string);
  140. begin
  141. WriteAttr(AName, JsonStr(AValue));
  142. end;
  143. procedure TPpuJsonOutput.WriteInt(const AName: string; AValue: Int64; Signed: boolean);
  144. begin
  145. if Signed then
  146. WriteAttr(AName, IntToStr(AValue))
  147. else
  148. WriteAttr(AName, IntToStr(QWord(AValue)));
  149. end;
  150. procedure TPpuJsonOutput.WriteFloat(const AName: string; AValue: extended);
  151. var
  152. s: string;
  153. begin
  154. Str(AValue, s);
  155. WriteAttr(AName, s);
  156. end;
  157. procedure TPpuJsonOutput.WriteBool(const AName: string; AValue: boolean);
  158. begin
  159. if AValue then
  160. WriteAttr(AName, 'true')
  161. else
  162. WriteAttr(AName, 'false');
  163. end;
  164. procedure TPpuJsonOutput.WriteNull(const AName: string);
  165. begin
  166. WriteAttr(AName, 'null');
  167. end;
  168. procedure TPpuJsonOutput.WriteArrayStart(const AName: string);
  169. begin
  170. WriteAttr(AName, '[');
  171. WriteLn;
  172. inherited;
  173. end;
  174. procedure TPpuJsonOutput.WriteArrayEnd(const AName: string);
  175. begin
  176. inherited;
  177. Write(']');
  178. end;
  179. procedure TPpuJsonOutput.WriteObjectStart(const AName: string; Def: TPpuDef);
  180. begin
  181. WriteAttr(AName, '{');
  182. WriteLn;
  183. inherited;
  184. end;
  185. procedure TPpuJsonOutput.WriteObjectEnd(const AName: string; Def: TPpuDef);
  186. begin
  187. inherited;
  188. Write('}');
  189. end;
  190. constructor TPpuJsonOutput.Create(OutFileHandle: THandle);
  191. begin
  192. inherited Create(OutFileHandle);
  193. SetLength(FNeedDelim, 10);
  194. FNeedDelim[0]:=False;
  195. end;
  196. procedure TPpuJsonOutput.IncI;
  197. begin
  198. inherited IncI;
  199. if Length(FNeedDelim) >= Indent then
  200. SetLength(FNeedDelim, Indent + 1);
  201. FNeedDelim[Indent]:=False;
  202. end;
  203. procedure TPpuJsonOutput.DecI;
  204. begin
  205. if FNeedDelim[Indent] then
  206. WriteLn;
  207. inherited DecI;
  208. end;
  209. end.