Реализация записывателей и конвертера:
Код:
MODULE some;
IMPORT
YSonConverters, YSonModels, YSonParser, YSonGenerator, O3baseFiles, StringsUtf;
TYPE
O3FileConv = POINTER TO RECORD (YSonConverters.Converter) END;
O3FileReader = POINTER TO RECORD (YSonParser.Reader)
base: O3baseFiles.File;
rd: O3baseFiles.Reader;
END;
O3FileWriter = POINTER TO RECORD (YSonGenerator.Writer)
wr: O3baseFiles.Writer;
END;
VAR
conv: O3FileConv;
PROCEDURE ReadUtf8Char(rd: O3baseFiles.Reader; OUT res: INTEGER): CHAR;
VAR c: ARRAY 3 OF BYTE; ch: CHAR; len: INTEGER;
BEGIN
ASSERT(rd#NIL, 20);
res:=0; ch:=0X;
rd.Read(c[0]);
len:=StringsUtf.ProposeUtf8Len(c[0]);
IF (len>1) & ((rd.Pos()+len)<=rd.File().Len()) THEN
rd.ReadBlock(c, 1, len-1, res);
IF res=len-1 THEN
StringsUtf.Utf8ToChar(c, ch);
ELSE res:=-1 END;
ELSE ch:=CHR(c[0]) END;
RETURN ch;
END ReadUtf8Char;
PROCEDURE (r: O3FileReader) Read (OUT ch: CHAR): BOOLEAN;
VAR res: INTEGER;
BEGIN
ASSERT(r.Base()#NIL, 20);
res:=-1;
IF ~r.rd.end THEN ch:=ReadUtf8Char(r.rd, res) END;
RETURN (res>=0)
END Read;
PROCEDURE (r: O3FileReader) SetPos (x: INTEGER);
BEGIN
IF x<r.base.Len() THEN r.rd.PosSet(x) END;
END SetPos;
PROCEDURE (r: O3FileReader) Pos (): INTEGER;
BEGIN
RETURN r.rd.Pos()
END Pos;
PROCEDURE (r: O3FileReader) ConnectTo (source: ANYPTR);
BEGIN
ASSERT(source#NIL, 20);
WITH source: O3baseFiles.File DO
r.base:=source; r.rd:=r.base.RdNew();
ASSERT(r.rd#NIL, 60)
ELSE HALT(100) END;
END ConnectTo;
PROCEDURE (r: O3FileReader) Base (): ANYPTR;
BEGIN
RETURN r.base
END Base;
PROCEDURE (r: O3FileReader) Eot(): BOOLEAN;
BEGIN
RETURN r.rd.end;
END Eot;
PROCEDURE (w: O3FileWriter) Utf8Char (ch: CHAR), NEW;
VAR i, len : INTEGER; x: ARRAY 3 OF BYTE;
BEGIN (* UTF-8 format *)
len:=0;
StringsUtf.Utf8FromChar(ch, x, len);
FOR i:=0 TO len-1 DO w.wr.Write(x[i]) END;
END Utf8Char;
PROCEDURE (w: O3FileWriter) Char* (c: CHAR);
BEGIN
w.Utf8Char(c);
END Char;
PROCEDURE (w: O3FileWriter) Whitespace (s: ARRAY OF CHAR), EMPTY;
PROCEDURE (c: O3FileConv) Supported(op: INTEGER; x: ANYPTR): BOOLEAN;
BEGIN
RETURN (x#NIL) & (x IS O3baseFiles.File)
END Supported;
PROCEDURE (c: O3FileConv) Load (source: ANYPTR; OUT res: INTEGER): YSonModels.Value;
VAR p: YSonParser.Parser; rd: O3FileReader; x: ANYPTR; rs: YSonModels.Value;
BEGIN
ASSERT(source#NIL, 20);
WITH source: O3baseFiles.File DO
NEW(rd); rd.ConnectTo(source);
p:=YSonParser.dir.New(rd);
x:=p.Parse(res);
IF x#NIL THEN
WITH x: YSonModels.Value DO rs:=x
ELSE HALT(100) END
END;
ELSE HALT(100) END;
RETURN rs;
END Load;
PROCEDURE (c: O3FileConv) Store (v: YSonModels.Value; target: ANYPTR; OUT res: INTEGER);
VAR g: YSonGenerator.Generator; wr: O3FileWriter;
BEGIN
res:=-1;
NEW(wr);
IF target # NIL THEN
WITH target: O3baseFiles.File DO wr.SetBase(target); wr.wr:=target.WrNew() ELSE END;
END;
g:=YSonGenerator.dir.New(wr);
g.ConnectTo(v);
g.Generate;
END Store;
PROCEDURE NewWriter (target: O3baseFiles.File): YSonGenerator.Writer;
VAR wr: O3FileWriter;
BEGIN
NEW(wr);
IF target # NIL THEN
wr.SetBase(target); wr.wr:=target.WrNew();
END;
RETURN wr;
END NewWriter;
PROCEDURE Install;
BEGIN
NEW(conv);
YSonConverters.Install(conv);
END Install;
BEGIN
Install
CLOSE
IF conv#NIL THEN YSonConverters.Remove(conv); conv:=NIL END;
END some
В реализацию O3-сервлета прилетает запрос O3stdWebServer.ServletMsg.rq, у которого есть поле body: O3baseFiles.File. Реализовав для такого источника байтов Reader/Writer, а поверх них конвертер мы получим возможность разобрать json с помощью конвертера, а так же записать громадный json в ответном сообщении O3-сервлета.
Конвертер может быть полезен тем, кто принимает маленькие json, их удобно превращать в модель из YSonModels и разбирать на месте, они же маленькие