{$MODE FPC}
{$MODESWITCH DEFAULTPARAMETERS}
{$MODESWITCH Out}
{$MODESWITCH RESULT}
unit dparser_old;

interface

uses
  strings,
  dexception,
  dtypes;

function StringDeletePre(S: TString; Count: Integer): TString;
function StringDeletePost(S: TString; Start: Integer): TString;
function ParseBinary(S, B: TString; Var L, R: TString): Boolean;

function IsSpace(C: TChar): Boolean; inline;
function IsNewLine(C: AnsiChar): Boolean; inline;
function SkipSpaces(P: PAnsiChar): PAnsiChar;
function CheckPrefixAndSkip(Prefix, P: PAnsiChar; var Dest: PAnsiChar): Boolean;
function SkipToCloseBrace(P: PAnsiChar; O: Char = '('; C: Char = ')'): PAnsiChar;

function Split(Source, SourceEnd: PAnsiChar; Delim: AnsiChar): PAnsiChar;

// NextChar
//
// Returns: True:  Cursor points to next char
//          False: Eof, that is Cursor >= SourceEnd;
function NextChar(var Cursor: PAnsiChar;
                  SourceEnd: PAnsiChar): Boolean; inline;
// NextLine
//
//      Skips current line
//
// Returns: True:  Cursor points to first char in new line
//          False:    (1) Eof, that is Cursor >= SourceEnd
//                 or (2) Cursor did not point to new line char
//          EndOfLine: end of previous line
function NextLine(Cursor: PAnsiChar;
                  SourceEnd: PAnsiChar;
                  out EndOfLine: PAnsiChar;
                  out NewLine: PAnsiChar): Boolean;

// NextNonSpace
//
//      Skips all space (32) and TAB (9) characters
//      Does NOT skip new line characters
//
// Returns: True:  Cursor point to non-space characters
//          False: SourceEnd reached, that is Cursor >= SourceEnd
function NextNonSpace(Cursor: PAnsiChar;
                      SourceEnd: PAnsiChar;
                      out NewCursor: PAnsiChar): Boolean;

procedure SkipWord(Cursor: PAnsiChar;
                   SourceEnd: PAnsiChar;
                   out NewCursor: PAnsiChar);

implementation

function StringDeletePre(S: TString; Count: Integer): TString;
begin
  Result := S;
    if Count = 0 then
      Exit;
  Delete(Result, 1, Count);
end;

function StringDeletePost(S: TString; Start: Integer): TString;
begin
  Result := S;
  if Start = 0 then
    Exit;
  Delete(Result, Start, Length(Result) - Start + 1);
end;

function ParseBinary(S, B: TString; Var L, R: TString): Boolean;
begin
  Result := Pos(B, S) <> 0;
  L := StringDeletePost(S, Pos(B, S));
  R := StringDeletePre(S, Pos(B, S) + Length(B) - 1);
end;

function IsSpace(C: TChar): Boolean;
begin
  Result := Byte(Ord(C) - 1) <= 32;
end;

function IsNewLine(C: AnsiChar): Boolean;
begin
  Result := C in [#9, #32];
end;

function SkipSpaces(P: PAnsiChar): PAnsiChar;
begin
  while (Ord(P[0]) <= 32) and (Ord(P[0]) <> 0) do
    Inc(P);
  Result := P;
end;

function CheckPrefixAndSkip(Prefix, P: PAnsiChar; var Dest: PAnsiChar): Boolean;
var
  L: Integer;
begin
  L := StrLen(Prefix);
  Result := CompareByte(Prefix^, P^, L) = 0;
  if Result then
    Dest := @P[L];
end;

function SkipToCloseBrace(P: PAnsiChar; O: Char = '('; C: Char = ')'): PAnsiChar;
var
  Score: Integer;
begin
  Score := 1;
  while Score > 0 do begin
    if P[0] = #0 then
      RaiseException('SkipToCloseBrace');
    if P[0] = O then
      Inc(Score);
    if P[0] = C then
      Dec(Score);
    Inc(P);
  end;
  Result := P;
end;

function Split(Source, SourceEnd: PAnsiChar; Delim: AnsiChar): PAnsiChar;
begin
  while Source < SourceEnd do begin
    if Source^ = Delim then
      Exit(Source);
    Inc(Source);
  end;
  Exit(nil);
end;

function NextChar(var Cursor: PAnsiChar;
                  SourceEnd: PAnsiChar): Boolean;
begin
  Inc(Cursor);
  Result := Cursor >= SourceEnd;
end;

function NextLine(Cursor: PAnsiChar;
                  SourceEnd: PAnsiChar;
                  out EndOfLine: PAnsiChar;
                  out NewLine: PAnsiChar): Boolean;
begin
  while Cursor < SourceEnd do begin
    if Cursor^ = #10 then begin
      EndOfLine := Cursor;
      Inc(Cursor);
      Exit(Cursor < SourceEnd);
    end else if Cursor = #13 then begin
      EndOfLine := Cursor;
      Inc(Cursor);
      if Cursor >= SourceEnd then begin
        NewLine := Cursor;
        Exit(False);
      end;
      if Cursor^ = #10 then begin
        Inc(Cursor);
        NewLine := Cursor;
        Exit(Cursor < SourceEnd);
      end else begin
        NewLine := Cursor;
        Exit(True);
      end;
    end else
      Inc(Cursor);
  end;
  Exit(False);
end;

function NextNonSpace(Cursor: PAnsiChar;
                      SourceEnd: PAnsiChar;
                      out NewCursor: PAnsiChar): Boolean;
begin
  while Cursor < SourceEnd do begin
    if not (Cursor^ in [#32, #9]) then begin
      NewCursor := Cursor;
      Exit(True);
    end;
    Inc(Cursor);
  end;
  NewCursor := Cursor;
  Exit(False);
end;

procedure SkipWord(Cursor: PAnsiChar;
                   SourceEnd: PAnsiChar;
                   out NewCursor: PAnsiChar);
begin
  while Cursor < SourceEnd do begin
    if Cursor^ <= #32 then begin
      NewCursor := Cursor;
      Exit;
    end;
    Inc(Cursor);
  end;
  NewCursor := Cursor;
end;

end.

