// DEPRECATED
{$modeswitch advancedrecords}
unit djsonparser;

interface

uses
  dparser,
  dstrnum,
  dpool,
  djson;

const
  QM = #34;

type
TJsonValueHelper = record helper for TJsonValue
  function AsJson: String;
end;

TJsonObjectHelper = class helper for TJsonObject
  procedure Parse(var P: PAnsiChar; Pool: TPool = nil);
  procedure ParseFromString(const S: String; Pool: TPool = nil);
  function AsJson: String;
end;

TJsonArrayHelper = class helper for TJsonArray
  function AsJson: String;
end;

function JsonParseString(var P: PAnsiChar; Pool: TPool = nil): PWideChar;
function JsonParseObject(var P: PAnsiChar; Pool: TPool = nil): TJsonObject;

implementation

function TJsonValueHelper.AsJson: String;
begin
  case JsonType of
    JT_NULL: Result := 'null';
    JT_STRING: Result := QM + S + QM;
    JT_NUMBER: Result := IntToStr(I);
    JT_OBJECT: Result := O.AsJson;
    JT_ARRAY: Result := A.AsJson;
    JT_BOOLEAN: if B then Result := 'true' else Result := 'false';
  else
    Result := '<unknown>';
  end;
end;

procedure TJsonObjectHelper.Parse(var P: PAnsiChar; Pool: TPool = nil);
var
  Name: PWideChar;
  Value: TJsonValue;
begin
  if Pool = nil then
    Pool := DefaultPool;
  P := SkipSpaces(P);
  if P[0] <> '{' then
    Writeln('raise exception TJsonObjectHelper.Parse: must be {');
  Inc(P);
  while True do begin
    P := SkipSpaces(P);
    case Char(P[0]) of
      '}': begin Inc(P); Exit; end;
      QM :
        begin
          Name := JsonParseString(P, Pool);
          P := SkipSpaces(P);
          if CheckPrefixAndSkip(':', P, P) then begin
            P := SkipSpaces(P);
            if CheckPrefixAndSkip('null', P, P) then begin
              Add(Name);
            end else if CheckPrefixAndSkip('true', P, P) then begin
              Add(Name, True);
            end else if CheckPrefixAndSkip('false', P, P) then begin
              Add(Name, False);
            end;
            case P[0] of
              '{':
                begin
                  Value.JsonType := JT_OBJECT;
                  Value.O := JsonParseObject(P, Pool);
                  Add(Name, Value);
                end;
            end;
          end else
            Writeln('raise exception TJsonObjectHelper.Parse: must be :');
          P := SkipSpaces(P);
          if P[0] = ',' then
            Inc(P);
        end;
      #0: Writeln('raise execption TJsonObjectHelper.Parse: must be }');
    else
      Writeln('raise execption TJsonObjectHelper.Parse: incorrect pair}');
    end;
  end;
end;

procedure TJsonObjectHelper.ParseFromString(const S: String; Pool: TPool = nil);
var
  P: PAnsiChar;
begin
  P := PAnsiChar(S);
  Parse(P, Pool);
end;

function TJsonObjectHelper.AsJson: String;
var
  I: Integer;
begin
  Result := '{';
  for I := 0 to High(FPairs) do
    with FPairs[I] do begin
      Result := Result + ' ' + QM + Name + QM + ': ' + Value.AsJson;
      if I <> High(FPairs) then
          Result := Result + ',';
    end;
  Result := Result + ' }';
end;

function TJsonArrayHelper.AsJson: String;
var
  I: Integer;
begin
  Result := '[';
  for I := 0 to High(FPairs) do
    with FPairs[I] do begin
      Result := Result + ' ' + Value.AsJson;
      if I <> High(FPairs) then
          Result := Result + ',';
    end;
  Result := Result + ' ]';
end;

function JsonParseString(var P: PAnsiChar; Pool: TPool = nil): PWideChar;
var
  S: WideString;
begin
  if Pool = nil then
    Pool := DefaultPool;
  if P[0] <> QM then
    Writeln('raise exception JsonParseString: must be {');
  Inc(P); // skip QM
  while P[0] <> QM do begin
    if P[0] = '\' then begin
      Inc(P);
      case P[0] of
        '\': S := S + '\';
        '/': S := S + '/';
        'b': S := S + #08;
        't': S := S + #09;
        'n': S := S + #10;
        'f': S := S + #12;
        'r': S := S + #13;
        'u': Inc(P, 4); // TODO hexdecimal read
      else
        S := S + P[0];
      end;
    end else
      S := S + P[0];
    Inc(P);
  end;
  Result := Pool.Add(PWideChar(S));
  Inc(P);
end;

function JsonParseObject(var P: PAnsiChar; Pool: TPool = nil): TJsonObject;
begin
  Result := TJsonObject.Create;
  Result.Parse(P, Pool);
end;

end.
