summaryrefslogtreecommitdiff
path: root/tests/webtbs/tw36215.pp
blob: 56a2e8c44f71fb130c8b78eb0ab65c8b22f2f614 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
program IntArrayCode;
{$MODE OBJFPC}
{$R+}
{$OPTIMIZATION ON}

uses SysUtils;

type
  TIntegerArray = array of Integer;
  TSeparator = (tlSpace=0, tlComma=1, tlTab=2, tlAny, tlDetect);

var
  EmptyArray: TIntegerArray = nil;

function TryReadIntegerTabbedLine(Separator: TSeparator; s, Last: PAnsiChar; V: array of PInteger; out nFields: Integer; var SeparatorCount: TIntegerArray):PAnsiChar;
var
  P, B, Start: PAnsiChar;
  Value: Integer;
  IsString, Negative: Boolean;
begin
  nFields := 0;
  Result := nil;
  if s = nil then
    Exit; { No values read }
  P := s;
  while (nFields < Length(V)) and (V[nFields] <> nil) do begin
    while (P <> Last) and (P^ = ' ') do
      Inc(p);
    if (P = Last) or (P^ = #0) then
      Exit
    else if P^ in [#10,#13] then
      Break
    else if (P^ = #9) then begin
      if Separator in [tlComma, tlSpace] then
        Continue { Treat as white space }
      else if Separator = tlDetect then
        Inc(SeparatorCount[Ord(tlTab)]);
      Inc(P) { Empty field }
    end else if P^ = ',' then begin
      if Separator in [tlSpace, tlTab] then
        Break { Start of string field }
      else if Separator = tlDetect then
        Inc(SeparatorCount[Ord(tlComma)]);
      Inc(P) { Empty field }
    end else begin
      Start := P;
      IsString := False;
      Value := 0;
      Negative := P^ = '-';
      if P^ in ['+', '-'] then
        Inc(P);
      while not IsString and (P <> Last) and (P^ in ['0'..'9']) do begin
        if Value <= High(Integer) div 10 then
          Value := Value*10 + Ord(P^)-Ord('0')
        else
          IsString := True;
        Inc(P);
      end;
      while (P <> Last) and not (P^ in [#0, ' ', #9, ',', #10, #13]) do begin
        IsString := True;
        Inc(P);
      end;
      if not IsString then begin
        if Negative then
          Value := -Value;
        V[nFields]^ := Value;
      end;
      B := P;
      while (P <> Last) and ((P^ = ' ') or ((Separator in [tlSpace, tlComma]) and (P^ = #9))) do
        Inc(P);
      if (P <> Last) and not IsString then
        if P^ = #9 then begin
          if Separator = tlDetect then
            Inc(SeparatorCount[Ord(tlTab)]);
          Inc(P); { Non-empty field }
        end else if P^ = ',' then begin
          if Separator in [tlSpace, tlTab] then
            Break { Start of string field }
          else if Separator = tlDetect then
            Inc(SeparatorCount[Ord(tlComma)]);
          Inc(P); { Non-empty field }
        end else if (Separator = tlDetect) and (B <> P) then
          Inc(SeparatorCount[Ord(tlSpace)]);
      if IsString then begin
        P := Start;
        Break;
      end;
    end;
    Inc(nFields);
  end;
  if (P = Last) or (P^ = #0) then
    Result := nil
  else
    Result := P;
end;

function SkipLineEnding(var P: PAnsiChar):Boolean;
begin
  Result := True;
  case P^ of
    #10: if (P+1)^ = #13 then
           Inc(P,2)
         else
           Inc(P);
    #13: if (P+1)^ = #10 then
           Inc(P,2)
         else
           Inc(P);
  else
    Result := False;
  end;
end;

function ReadIntegerArray(S: AnsiString): TIntegerArray;
var
  P: PAnsiChar;
  V, nRows, nFields: Integer;
begin
  Result := nil;
  nRows := 0;
  P := PAnsiChar(S);
  while P^ <> #0 do begin
    P := TryReadIntegerTabbedLine(tlAny, P, nil, [@V], nFields, EmptyArray);
    if nFields > 0 then begin
      if nRows >= Length(Result) then
        if Length(Result) = 0 then { Length read from wrong placer? }
          SetLength(Result, 16)
        else
          SetLength(Result, Length(Result)*2);
      Result[nRows] := V;
      Inc(nRows);
    end;
    if P = nil then
      Break;
    while not (P^ in [#10, #13]) do
      Inc(P);
    SkipLineEnding(P);
  end;
  SetLength(Result, nRows);
end;

begin
  WriteLn(Length(ReadIntegerArray('-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10'-1'#10)));
end.