Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const
- CR = #13;
- LF = #10;
- TAB = #9;
- SPACES = [' ', CR, LF, TAB];
- QUOTES = ['"', '''', '´', '`'];
- function EOF: Boolean;
- begin
- Result := P^ = #0;
- end;
- function NEOF: Boolean;
- begin
- Result := not EOF;
- end;
- function Skip(const CS: TSysCharSet = SPACES): Boolean; overload;
- begin
- while NEOF and CharInSet(P^, CS) do Inc(P);
- Result := NEOF;
- end;
- function Skip(const C: Char): Boolean; overload;
- begin
- while NEOF and (P^ = C) do Inc(P);
- Result := NEOF;
- end;
- function SkipTo(const CS: TSysCharSet): Boolean; overload;
- begin
- while NEOF and not CharInSet(P^, CS) do Inc(P);
- Result := NEOF;
- end;
- function SkipTo(const C: Char): Boolean; overload;
- begin
- while NEOF and (P^ <> C) do Inc(P);
- Result := NEOF;
- end;
- procedure SkipQuotes;
- var
- C: Char;
- Q: PChar;
- N: Integer;
- begin
- C := P^;
- Inc(P);
- while NEOF do
- begin
- if P^ = C then
- begin
- Q := P - 1;
- N := 0;
- while Q^ = '\' do
- begin
- Inc(N);
- Dec(Q);
- end;
- if not Odd(N) then Break;
- end;
- Inc(P);
- end;
- end;
- function Read(const CS: TSysCharSet): string; overload;
- var
- Q: PChar;
- begin
- Q := P;
- while NEOF and CharInSet(P^, CS) do Inc(P);
- SetString(Result, Q, P - Q);
- end;
- function Read(const C: Char): string; overload;
- var
- Q: PChar;
- begin
- Q := P;
- while NEOF and (P^ = C) do Inc(P);
- SetString(Result, Q, P - Q);
- end;
- function ReadTo(const CS: TSysCharSet = SPACES): string; overload;
- var
- Q: PChar;
- begin
- Q := P;
- while NEOF and not CharInSet(P^, CS) do Inc(P);
- SetString(Result, Q, P - Q);
- end;
- function ReadTo(const C: Char): string; overload;
- var
- Q: PChar;
- begin
- Q := P;
- while NEOF and (P^ <> C) do Inc(P);
- SetString(Result, Q, P - Q);
- end;
- function ReadToQ: string; overload;
- var
- Q: PChar;
- begin
- Q := P;
- SkipQuotes;
- SetString(Result, Q + 1, P - Q - 1);
- if NEOF then Inc(P);
- end;
- function ReadN(N: Integer): string;
- var
- Q: PChar;
- begin
- Q := P;
- while NEOF and (N > 0) do
- begin
- Inc(P);
- Dec(N);
- end;
- SetString(Result, Q, P - Q);
- end;
- function ReadQuoted(var S: string; const CS: TSysCharSet = SPACES;
- ASkipQuotes: Boolean = False): Boolean;
- var
- C: Char;
- begin
- C := P^;
- if CharInSet(C, QUOTES) then
- begin
- if ASkipQuotes then
- S := ReadToQ
- else
- begin
- Inc(P);
- if NEOF then
- begin
- S := ReadTo(C);
- if NEOF then Inc(P);
- end;
- end;
- end
- else
- S := ReadTo(CS);
- Result := NEOF;
- end;
- function IsNext(const S: string): Boolean;
- var
- Q: PChar;
- begin
- Q := P;
- Result := SameText(S, ReadN(Length(S))){ and NEOF};
- if not Result and (Q <> P) then P := Q;
- end;
- function SkipA(const A: Array of string): Boolean;
- var
- Q: PChar;
- B: Boolean;
- I: Integer;
- begin
- Q := P;
- B := True;
- for I := Low(A) to High(A) do
- begin
- if not B then Break;
- B := IsNext(A[I]);
- if B then
- begin
- B := NEOF;
- if B then Skip;
- end
- end;
- if not B and (Q <> P) then P := Q;
- Result := NEOF;
- end;
- procedure SkipComments;
- begin
- case P^ of
- '/':
- begin
- if ((P + 1)^ <> #0) and ((P + 1)^ = '*') then
- begin
- Inc(P, 2);
- while NEOF do
- begin
- if ((P + 1)^ <> #0) and (P^ = '*') and ((P + 1)^ = '/') then
- begin
- Inc(P);
- Break;
- end;
- Inc(P);
- end;
- end;
- end;
- '-':
- begin
- if ((P + 1)^ <> #0) and ((P + 1)^ = '-') then
- begin
- Inc(P, 2);
- while NEOF do
- begin
- if ((P + 1)^ <> #0) and (P^ = CR) and ((P + 1)^ = LF) then
- begin
- Inc(P);
- Break;
- end
- else if (P^ = LF) or (P^ = CR) then
- Break;
- Inc(P);
- end;
- end;
- end;
- '#':
- begin
- Inc(P);
- while NEOF do
- begin
- if ((P + 1)^ <> #0) and (P^ = CR) and ((P + 1)^ = LF) then
- begin
- Inc(P);
- Break;
- end
- else if (P^ = LF) or (P^ = CR) then
- Break;
- Inc(P);
- end;
- end;
- end;
- end;
- procedure RipTableColumnNames(const S: string);
- var
- T : string;
- TCN: TTableColumnNames;
- begin
- P := Pointer(S);
- if P <> nil then
- while NEOF do
- begin
- case P^ of
- '"', '''', '´', '`': SkipQuotes;
- '/', '-', '#' : SkipComments;
- 'c', 'C':
- begin
- if IsNext('CREATE') and
- Skip and
- SkipA(['OR', 'REPLACE']) and
- IsNext('TABLE') and
- Skip and
- SkipA(['IF', 'NOT', 'EXISTS']) and
- ReadQuoted(T, SPACES + ['(']) and
- Skip and
- (P^ = '(') then
- begin
- TCN.TableName := T;
- TCN.ColumnNames := TStringList.Create;
- Inc(P);
- while Skip and (P^ <> ';') do
- begin
- if P^ = ')' then Break;
- if ReadQuoted(T, SPACES + [')']) then
- begin
- if IsGoodColumnName(T) then TCN.ColumnNames.Add(T);
- if Skip then
- begin
- while NEOF and not CharInSet(P^, [',', ';']) do
- begin
- case P^ of
- '"', '''', '´', '`': SkipQuotes;
- '(':
- begin
- Inc(P);
- if not SkipTo(')') then Break;
- end;
- end;
- Inc(P);
- end;
- if NEOF and (P^ = ',') then Inc(P);
- end;
- end;
- end;
- TableColumnNames.Add(TCN);
- end;
- end;
- end;
- if NEOF then Inc(P);
- end;
- end;
- procedure RipTableRows(const S: string; const ATableName: string;
- ARipToFile: Boolean = False; AFileStream: TFileStream = nil;
- const ARowDelimiter: string = '');
- var
- IL : TList<Integer>;
- SL : TStringList;
- function GetColumnNameIndex(const AColumnName: string): Integer;
- var
- I: Integer;
- begin
- Result := -1;
- for I := 0 to Pred(SL.Count) do
- if SameText(SL[I], AColumnName) then
- begin
- Result := I;
- Break;
- end;
- end;
- function IsIndexAvailable: Boolean;
- var
- I: Integer;
- begin
- Result := False;
- for I := 0 to Pred(IL.Count) do
- if IL[I] > -1 then
- begin
- Result := True;
- Break;
- end;
- end;
- var
- T : string;
- I, N: Integer;
- begin
- IL := TList<Integer>.Create;
- SL := TStringList.Create;
- P := Pointer(S);
- if P <> nil then
- while NEOF do
- begin
- case P^ of
- '"', '''', '´', '`': SkipQuotes;
- '/', '-', '#' : SkipComments;
- 'i', 'I':
- begin
- if IsNext('INSERT') and
- Skip and
- SkipA(['IGNORE']) and
- SkipA(['OR', 'IGNORE']) and
- IsNext('INTO') and
- Skip and
- ReadQuoted(T, SPACES + ['(']) and
- Skip and
- SameText(T, ATableName) then
- begin
- IL.Clear;
- if P^ = '(' then
- begin
- SL.Clear;
- Inc(P);
- while Skip and
- (P^ <> ')') and
- (ReadQuoted(T, SPACES + [',', ')'])) and
- Skip do
- begin
- SL.Add(T);
- if Skip and (P^ = ',') then Inc(P);
- end;
- if Skip and (P^ = ')') then Inc(P);
- for I := 0 to Pred(ColumnNamesIndexes.Count) do
- IL.Add(GetColumnNameIndex(ColumnNamesIndexes[I].ColumnName));
- end;
- if Skip and IsNext('VALUES') then
- begin
- while Skip and (P^ <> ';') do
- begin
- if P^ = '(' then
- begin
- SL.Clear;
- Inc(P);
- while Skip and
- (P^ <> ')') and
- ReadQuoted(T, SPACES + [',', ')'], True) and
- Skip do
- begin
- SL.Add(T);
- if Skip and (P^ = ',') then Inc(P);
- end;
- if Skip and (P^ = ')') then Inc(P);
- if Skip and (P^ = ',') then Inc(P);
- N := SL.Count;
- if IL.Count > 0 then
- begin
- if IsIndexAvailable then
- begin
- if ARipToFile then
- begin
- T := '';
- for I := 0 to Pred(IL.Count) do
- if IL[I] = -1 then
- T := T + ARowDelimiter
- else if IL[I] < N then
- T := T + SL[IL[I]] + ARowDelimiter;
- T := T + sLineBreak;
- AFileStream.WriteBuffer(Pointer(AnsiString(T))^,
- Length(T));
- end
- else
- begin
- TableRows.Add(TStringList.Create);
- for I := 0 to Pred(IL.Count) do
- if IL[I] = -1 then
- TableRows[iTableRowCounter].Add('')
- else if IL[I] < N then
- TableRows[iTableRowCounter].Add(SL[IL[I]]);
- Inc(iTableRowCounter);
- end;
- end;
- end
- else
- begin
- if ARipToFile then
- begin
- T := '';
- for I := 0 to Pred(ColumnNamesIndexes.Count) do
- if ColumnNamesIndexes[I].ColumnIndex < N then
- T := T + SL[ColumnNamesIndexes[I].ColumnIndex] +
- ARowDelimiter;
- T := T + sLineBreak;
- AFileStream.WriteBuffer(Pointer(AnsiString(T))^,
- Length(T));
- end
- else
- begin
- TableRows.Add(TStringList.Create);
- for I := 0 to Pred(ColumnNamesIndexes.Count) do
- if ColumnNamesIndexes[I].ColumnIndex < N then
- TableRows[iTableRowCounter].Add(
- SL[ColumnNamesIndexes[I].ColumnIndex]);
- Inc(iTableRowCounter);
- end;
- end;
- end
- else
- Break;
- end;
- end;
- end;
- end;
- end;
- if NEOF then Inc(P);
- end;
- IL.Free;
- SL.Free;
- end;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement