Browse Source

* Fix bug ID #30469 (allow quoting to start inside values)

git-svn-id: trunk@34509 -
michael 9 years ago
parent
commit
7fec0f92af

+ 1 - 0
.gitattributes

@@ -2075,6 +2075,7 @@ packages/fcl-base/src/wince/fileinfo.pp svneol=native#text/plain
 packages/fcl-base/src/wtex.pp svneol=native#text/plain
 packages/fcl-base/src/wtex.pp svneol=native#text/plain
 packages/fcl-base/tests/fclbase-unittests.lpi svneol=native#text/plain
 packages/fcl-base/tests/fclbase-unittests.lpi svneol=native#text/plain
 packages/fcl-base/tests/fclbase-unittests.pp svneol=native#text/plain
 packages/fcl-base/tests/fclbase-unittests.pp svneol=native#text/plain
+packages/fcl-base/tests/tccsvreadwrite.pp svneol=native#text/plain
 packages/fcl-base/tests/tchashlist.pp svneol=native#text/plain
 packages/fcl-base/tests/tchashlist.pp svneol=native#text/plain
 packages/fcl-base/tests/tcinifile.pp svneol=native#text/plain
 packages/fcl-base/tests/tcinifile.pp svneol=native#text/plain
 packages/fcl-base/tests/tcmaskutils.pp svneol=native#text/plain
 packages/fcl-base/tests/tcmaskutils.pp svneol=native#text/plain

+ 5 - 3
packages/fcl-base/src/csvreadwrite.pp

@@ -396,15 +396,17 @@ end;
 
 
 procedure TCSVParser.ParseValue;
 procedure TCSVParser.ParseValue;
 begin
 begin
-  while not ((FCurrentChar = FDelimiter) or EndOfLine or EndOfFile) do
+  while not ((FCurrentChar = FDelimiter) or EndOfLine or EndOfFile or (FCurrentChar = FQuoteChar)) do
   begin
   begin
-    AppendStr(FWhitespaceBuffer, FCurrentChar);
+    AppendStr(FCellBuffer, FCurrentChar);
     NextChar;
     NextChar;
   end;
   end;
+  if FCurrentChar = FQuoteChar then
+    ParseQuotedValue;
   // merge whitespace buffer
   // merge whitespace buffer
   if FIgnoreOuterWhitespace then
   if FIgnoreOuterWhitespace then
     RemoveTrailingChars(FWhitespaceBuffer, WhitespaceChars);
     RemoveTrailingChars(FWhitespaceBuffer, WhitespaceChars);
-  AppendStr(FCellBuffer, FWhitespaceBuffer);
+  AppendStr(FWhitespaceBuffer,FCellBuffer);
   FWhitespaceBuffer := '';
   FWhitespaceBuffer := '';
 end;
 end;
 
 

+ 6 - 2
packages/fcl-base/tests/fclbase-unittests.lpi

@@ -30,10 +30,10 @@
     <RunParams>
     <RunParams>
       <local>
       <local>
         <FormatVersion Value="1"/>
         <FormatVersion Value="1"/>
-        <CommandLineParams Value="--suite=TTestExpressionScanner.TestNumber"/>
+        <CommandLineParams Value="--suite=TTestCSVReadWrite.TestInlineQuotedLine"/>
       </local>
       </local>
     </RunParams>
     </RunParams>
-    <Units Count="5">
+    <Units Count="6">
       <Unit0>
       <Unit0>
         <Filename Value="fclbase-unittests.pp"/>
         <Filename Value="fclbase-unittests.pp"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -55,6 +55,10 @@
         <Filename Value="tcinifile.pp"/>
         <Filename Value="tcinifile.pp"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit4>
       </Unit4>
+      <Unit5>
+        <Filename Value="tccsvreadwrite.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit5>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>

+ 1 - 1
packages/fcl-base/tests/fclbase-unittests.pp

@@ -4,7 +4,7 @@ program fclbase_unittests;
 
 
 uses
 uses
   Classes, consoletestrunner, tests_fptemplate, tchashlist,
   Classes, consoletestrunner, tests_fptemplate, tchashlist,
-  testexprpars, tcmaskutils, tcinifile;
+  testexprpars, tcmaskutils, tcinifile, tccsvreadwrite;
 
 
 var
 var
   Application: TTestRunner;
   Application: TTestRunner;

+ 118 - 0
packages/fcl-base/tests/tccsvreadwrite.pp

@@ -0,0 +1,118 @@
+unit tccsvreadwrite;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry, csvreadwrite;
+
+type
+
+  { TTestCSVReadWrite }
+
+  TTestCSVReadWrite= class(TTestCase)
+  private
+    FData: TStrings;
+    FParser: TCSVParser;
+    procedure AssertLine(ARow: Integer; AValues: array of string);
+    procedure HaveNext(ARow, ACol: integer; AValue: String);
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+    Property Parser : TCSVParser Read FParser;
+    Property Data : TStrings Read FData;
+  published
+    procedure TestEmpty;
+    Procedure TestNormalLine;
+    Procedure TestQuotedLine;
+    Procedure TestInlineQuotedLine;
+    Procedure TestQuotedNewLine;
+    Procedure Test2Lines;
+    Procedure TestEscapedQuotes;
+  end;
+
+implementation
+
+procedure TTestCSVReadWrite.TestEmpty;
+begin
+  AssertNotNull('Have parser',Parser);
+end;
+
+procedure TTestCSVReadWrite.HaveNext(ARow,ACol: integer; AValue : String);
+
+Var
+  CN : String;
+
+begin
+  CN:=Format('Cell(row: %d, col: %d)',[ARow,ACol]);
+  AssertTrue('Have '+CN,Parser.ParseNextCell);
+  AssertEquals(CN+': Row matches',ARow,Parser.CurrentRow);
+  AssertEquals(CN+': Col matched',ACol,Parser.CurrentCol);
+  AssertEquals(CN+': Value',AValue,Parser.CurrentCellText);
+end;
+
+procedure TTestCSVReadWrite.AssertLine(ARow: Integer; AValues: array of string);
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to Length(AValues)-1 do
+    HaveNext(ARow,I,AValues[i]);
+end;
+
+procedure TTestCSVReadWrite.TestNormalLine;
+begin
+  FParser.SetSource('this,is,a,normal,line');
+  AssertLine(0,['this','is','a','normal','line']);
+end;
+
+procedure TTestCSVReadWrite.TestQuotedLine;
+begin
+   FParser.SetSource('"this","is","a","quoted","line"');
+   AssertLine(0,['this','is','a','quoted','line']);
+end;
+
+procedure TTestCSVReadWrite.TestInlineQuotedLine;
+begin
+  FParser.SetSource('"this","line",has,mixed" quoting"');
+  AssertLine(0,['this','line','has','mixed quoting']);
+end;
+
+procedure TTestCSVReadWrite.TestQuotedNewLine;
+begin
+  FParser.SetSource('"this","line",has,"an embedded'+lineEnding+'newline"');
+  AssertLine(0,['this','line','has','an embedded'+lineending+'newline']);
+end;
+
+procedure TTestCSVReadWrite.Test2Lines;
+begin
+  FParser.SetSource('"this","line",has,an embedded'+lineEnding+'newline');
+  AssertLine(0,['this','line','has','an embedded']);
+  AssertLine(1,['newline']);
+end;
+
+procedure TTestCSVReadWrite.TestEscapedQuotes;
+begin
+  FParser.SetSource('"this","line",has,"an embedded "" quote"');
+  AssertLine(0,['this','line','has','an embedded " quote']);
+end;
+
+procedure TTestCSVReadWrite.SetUp;
+begin
+  FParser:=TCSVParser.Create;
+  FData:=Tstrings.Create;
+end;
+
+procedure TTestCSVReadWrite.TearDown;
+begin
+  FreeAndNil(FData);
+  FreeAndNil(Fparser);
+end;
+
+initialization
+
+  RegisterTest(TTestCSVReadWrite);
+end.
+