This is an automated email from the ASF dual-hosted git repository.
damjan pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/openoffice.git
The following commit(s) were added to refs/heads/trunk by this push:
new 7b2bc0e6bb Allow reading lines longer than 64 KiB in SvStream, and
reading CSV rows and cells longer than 64 KiB in OpenOffice Base. (They are now
limited to ~2 GiB).
7b2bc0e6bb is described below
commit 7b2bc0e6bba2fbc38d078306fe10d875115d6c86
Author: Damjan Jovanovic <[email protected]>
AuthorDate: Mon Jul 22 08:06:52 2024 +0200
Allow reading lines longer than 64 KiB in SvStream, and reading CSV rows and
cells longer than 64 KiB in OpenOffice Base. (They are now limited to
~2 GiB).
- New member functions were added to the main/tools SvStream class to work
with 32 bit ::rtl::OUString and ::rtl::OStringBuilder when reading lines.
- The helper class QuotedString had to be upgraded from using the 16 bit
String to the 32 bit ::rtl::OUString.
- The CSV database driver was patched to use ::rtl::OUString and 32 bit
indexes in various places.
- Luckily, little other work was needed, as the ORowSetValue class already
uses 32 bit ::rtl::OUString, and was previously converting 16 bit String
to 32 bit ::rtl::OUString internally anyway.
Also simplified some of the line parsing logic, and translated some
German comments to English.
Patch by: me
---
.../source/drivers/file/quotedstring.cxx | 48 +++---
main/connectivity/source/drivers/flat/ETable.cxx | 192 ++++++++++-----------
main/connectivity/source/inc/file/quotedstring.hxx | 18 +-
main/connectivity/source/inc/flat/ETable.hxx | 2 +-
main/tools/inc/tools/stream.hxx | 4 +
main/tools/source/stream/stream.cxx | 83 +++++++++
6 files changed, 210 insertions(+), 137 deletions(-)
diff --git a/main/connectivity/source/drivers/file/quotedstring.cxx
b/main/connectivity/source/drivers/file/quotedstring.cxx
index 4ea452613b..366036b6f7 100644
--- a/main/connectivity/source/drivers/file/quotedstring.cxx
+++ b/main/connectivity/source/drivers/file/quotedstring.cxx
@@ -25,6 +25,7 @@
#include "precompiled_connectivity.hxx"
#include "file/quotedstring.hxx"
#include <rtl/logfile.hxx>
+#include <rtl/ustrbuf.hxx>
namespace connectivity
{
@@ -32,21 +33,21 @@ namespace connectivity
//= QuotedTokenizedString
//==================================================================
//------------------------------------------------------------------
- xub_StrLen QuotedTokenizedString::GetTokenCount( sal_Unicode cTok,
sal_Unicode cStrDel ) const
+ sal_Int32 QuotedTokenizedString::GetTokenCount( sal_Unicode cTok,
sal_Unicode cStrDel ) const
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "[email protected]",
"QuotedTokenizedString::GetTokenCount" );
- const xub_StrLen nLen = m_sString.Len();
+ const sal_Int32 nLen = m_sString.getLength();
if ( !nLen )
return 0;
- xub_StrLen nTokCount = 1;
+ sal_Int32 nTokCount = 1;
sal_Bool bStart = sal_True; // Stehen wir auf dem ersten
Zeichen im Token?
sal_Bool bInString = sal_False; // Befinden wir uns INNERHALB
eines (cStrDel delimited) String?
// Suche bis Stringende nach dem ersten nicht uebereinstimmenden
Zeichen
- for( xub_StrLen i = 0; i < nLen; ++i )
+ for( sal_Int32 i = 0; i < nLen; ++i )
{
- const sal_Unicode cChar = m_sString.GetChar(i);
+ const sal_Unicode cChar = m_sString[ i ];
if (bStart)
{
bStart = sal_False;
@@ -63,7 +64,7 @@ namespace connectivity
// Wenn jetzt das String-Delimiter-Zeichen auftritt
...
if ( cChar == cStrDel )
{
- if ((i+1 < nLen) && (m_sString.GetChar(i+1)
== cStrDel))
+ if ((i+1 < nLen) && (m_sString[ i+1 ] ==
cStrDel))
{
// Verdoppeltes
String-Delimiter-Zeichen:
++i; // kein String-Ende,
naechstes Zeichen ueberlesen.
@@ -91,49 +92,47 @@ namespace connectivity
}
//------------------------------------------------------------------
- void QuotedTokenizedString::GetTokenSpecial( String& _rStr,xub_StrLen&
nStartPos, sal_Unicode cTok, sal_Unicode cStrDel ) const
+ void QuotedTokenizedString::GetTokenSpecial( ::rtl::OUString*
_rStr,sal_Int32& nStartPos, sal_Unicode cTok, sal_Unicode cStrDel ) const
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "[email protected]",
"QuotedTokenizedString::GetTokenCount" );
- _rStr.Erase();
- const xub_StrLen nLen = m_sString.Len();
+ *_rStr = ::rtl::OUString();
+ const sal_Int32 nLen = m_sString.getLength();
if ( nLen )
{
- sal_Bool bInString = (nStartPos < nLen) &&
(m_sString.GetChar(nStartPos) == cStrDel); // Befinden wir uns INNERHALB
eines (cStrDel delimited) String?
+ sal_Bool bInString = (nStartPos < nLen) && (m_sString[
nStartPos ] == cStrDel); // Are we inside a (cStrDel delimited) String?
- // Erstes Zeichen ein String-Delimiter?
+ // Is the first character a string delimiter?
if (bInString )
- ++nStartPos; // dieses
Zeichen ueberlesen!
+ ++nStartPos; // ignore this
character!
if ( nStartPos >= nLen )
return;
- sal_Unicode* pData = _rStr.AllocBuffer( nLen - nStartPos + 1 );
- const sal_Unicode* pStart = pData;
- // Suche bis Stringende nach dem ersten nicht
uebereinstimmenden Zeichen
- for( xub_StrLen i = nStartPos; i < nLen; ++i )
+ ::rtl::OUStringBuffer buffer( nLen - nStartPos);
+ // Search until the end of string for the first
non-matching character
+ for( sal_Int32 i = nStartPos; i < nLen; ++i )
{
- const sal_Unicode cChar = m_sString.GetChar(i);
+ const sal_Unicode cChar = m_sString[ i ];
if (bInString)
{
// Wenn jetzt das String-Delimiter-Zeichen
auftritt ...
if ( cChar == cStrDel )
{
- if ((i+1 < nLen) &&
(m_sString.GetChar(i+1) == cStrDel))
+ if ((i+1 < nLen) && (m_sString[ i+1
] == cStrDel))
{
// Verdoppeltes
String-Delimiter-Zeichen:
// kein String-Ende,
naechstes Zeichen ueberlesen.
++i;
- *pData++ =
m_sString.GetChar(i); // Zeichen gehoert zum Resultat-String
+ buffer.append( m_sString[ i
] ); // Zeichen gehoert zum Resultat-String
}
else
{
// String-Ende
bInString = sal_False;
- *pData = 0;
}
}
else
{
- *pData++ = cChar; // Zeichen
gehoert zum Resultat-String
+ buffer.append( cChar ); //
Zeichen gehoert zum Resultat-String
}
}
@@ -149,12 +148,11 @@ namespace connectivity
}
else
{
- *pData++ = cChar; // Zeichen
gehoert zum Resultat-String
+ buffer.append( cChar ); //
Zeichen gehoert zum Resultat-String
}
}
- } // for( xub_StrLen i = nStartPos; i < nLen; ++i )
- *pData = 0;
- _rStr.ReleaseBufferAccess(xub_StrLen(pData - pStart));
+ } // for( sal_Int32 i = nStartPos; i < nLen; ++i )
+ *_rStr = buffer.makeStringAndClear();
}
}
}
diff --git a/main/connectivity/source/drivers/flat/ETable.cxx
b/main/connectivity/source/drivers/flat/ETable.cxx
index 0f0e576b3d..23dbb3a9fb 100644
--- a/main/connectivity/source/drivers/flat/ETable.cxx
+++ b/main/connectivity/source/drivers/flat/ETable.cxx
@@ -97,7 +97,7 @@ void OFlatTable::fillColumns(const
::com::sun::star::lang::Locale& _aLocale)
aHeaderLine = aFirstLine;
}
// column count
- const xub_StrLen nFieldCount =
aHeaderLine.GetTokenCount(m_cFieldDelimiter,m_cStringDelimiter);
+ const sal_Int32 nFieldCount =
aHeaderLine.GetTokenCount(m_cFieldDelimiter,m_cStringDelimiter);
if(!m_aColumns.isValid())
m_aColumns = new OSQLColumns();
@@ -118,7 +118,7 @@ void OFlatTable::fillColumns(const
::com::sun::star::lang::Locale& _aLocale)
// read description
const sal_Unicode cDecimalDelimiter =
pConnection->getDecimalDelimiter();
const sal_Unicode cThousandDelimiter =
pConnection->getThousandDelimiter();
- String aColumnName;
+ ::rtl::OUString aColumnName;
::rtl::OUString aTypeName;
::comphelper::UStringMixEqual aCase(bCase);
::std::vector<String> aColumnNames,m_aTypeNames;
@@ -127,26 +127,26 @@ void OFlatTable::fillColumns(const
::com::sun::star::lang::Locale& _aLocale)
sal_Int32 nRowCount = 0;
do
{
- xub_StrLen nStartPosHeaderLine = 0; // use for eficient way to get
the tokens
- xub_StrLen nStartPosFirstLine = 0; // use for eficient way to get
the tokens
- xub_StrLen nStartPosFirstLine2 = 0;
- for (xub_StrLen i = 0; i < nFieldCount; i++)
+ sal_Int32 nStartPosHeaderLine = 0; // use for eficient way to get
the tokens
+ sal_Int32 nStartPosFirstLine = 0; // use for eficient way to get
the tokens
+ sal_Int32 nStartPosFirstLine2 = 0;
+ for (sal_Int32 i = 0; i < nFieldCount; i++)
{
if ( nRowCount == 0)
{
if ( bHasHeaderLine )
{
-
aHeaderLine.GetTokenSpecial(aColumnName,nStartPosHeaderLine,m_cFieldDelimiter,m_cStringDelimiter);
- if ( !aColumnName.Len() )
+
aHeaderLine.GetTokenSpecial(&aColumnName,nStartPosHeaderLine,m_cFieldDelimiter,m_cStringDelimiter);
+ if ( aColumnName.isEmpty() )
{
- aColumnName = 'C';
+ aColumnName =
::rtl::OUString::createFromAscii( "C" );
aColumnName +=
String::CreateFromInt32(i+1);
}
}
else
{
// no column name so ...
- aColumnName = 'C';
+ aColumnName = ::rtl::OUString::createFromAscii(
"C" );
aColumnName += String::CreateFromInt32(i+1);
}
aColumnNames.push_back(aColumnName);
@@ -157,7 +157,7 @@ void OFlatTable::fillColumns(const
::com::sun::star::lang::Locale& _aLocale)
}
while(nRowCount < nMaxRowsToScan && readLine(aFirstLine,nCurPos) &&
!m_pFileStream->IsEof());
- for (xub_StrLen i = 0; i < nFieldCount; i++)
+ for (sal_Int32 i = 0; i < nFieldCount; i++)
{
// check if the columname already exists
String aAlias(aColumnNames[i]);
@@ -183,7 +183,7 @@ void OFlatTable::fillColumns(const
::com::sun::star::lang::Locale& _aLocale)
}
m_pFileStream->Seek(m_nStartRowFilePos);
}
-void OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString&
aFirstLine,xub_StrLen& nStartPosFirstLine,xub_StrLen& nStartPosFirstLine2
+void OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString&
aFirstLine,sal_Int32& nStartPosFirstLine,sal_Int32& nStartPosFirstLine2
,sal_Int32& io_nType,sal_Int32&
io_nPrecisions,sal_Int32& io_nScales,String& o_sTypeName
,const sal_Unicode
cDecimalDelimiter,const sal_Unicode cThousandDelimiter,const CharClass&
aCharClass)
{
@@ -195,26 +195,26 @@ void
OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString& aFirstLine,x
if ( bNumeric )
{
// first without fielddelimiter
- String aField;
-
aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine,m_cFieldDelimiter,'\0');
- if (aField.Len() == 0 ||
- (m_cStringDelimiter && m_cStringDelimiter ==
aField.GetChar(0)))
+ ::rtl::OUString aField;
+
aFirstLine.GetTokenSpecial(&aField,nStartPosFirstLine,m_cFieldDelimiter,'\0');
+ if ( aField.isEmpty() ||
+ (m_cStringDelimiter && m_cStringDelimiter == aField[0]))
{
bNumeric = sal_False;
if ( m_cStringDelimiter != '\0' )
-
aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
+
aFirstLine.GetTokenSpecial(&aField,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
else
nStartPosFirstLine2 = nStartPosFirstLine;
}
else
{
- String aField2;
+ ::rtl::OUString aField2;
if ( m_cStringDelimiter != '\0' )
-
aFirstLine.GetTokenSpecial(aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
+
aFirstLine.GetTokenSpecial(&aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
else
aField2 = aField;
- if (aField2.Len() == 0)
+ if ( aField2.isEmpty() )
{
bNumeric = sal_False;
}
@@ -224,9 +224,9 @@ void
OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString& aFirstLine,x
xub_StrLen nDot = 0;
xub_StrLen nDecimalDelCount = 0;
xub_StrLen nSpaceCount = 0;
- for (xub_StrLen j = 0; j < aField2.Len(); j++)
+ for (sal_Int32 j = 0; j < aField2.getLength();
j++)
{
- const sal_Unicode c =
aField2.GetChar(j);
+ const sal_Unicode c = aField2[j];
if ( j == nSpaceCount && m_cFieldDelimiter != 32 && c
== 32 )
{
++nSpaceCount;
@@ -256,10 +256,11 @@ void
OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString& aFirstLine,x
if (bNumeric && cThousandDelimiter)
{
// Ist der Trenner richtig angegeben?
- const String aValue =
aField2.GetToken(0,cDecimalDelimiter);
- for (sal_Int32 j = aValue.Len() - 4; j
>= 0; j -= 4)
+ sal_Int32 tokenIdx = 0;
+ const ::rtl::OUString aValue =
aField2.getToken(0,cDecimalDelimiter,tokenIdx);
+ for (sal_Int32 j = aValue.getLength() -
4; j >= 0; j -= 4)
{
- const sal_Unicode c =
aValue.GetChar(static_cast<sal_uInt16>(j));
+ const sal_Unicode c = aValue[j];
// nur Ziffern und Dezimalpunkt
und Tausender-Trennzeichen?
if (c == cThousandDelimiter &&
j)
continue;
@@ -287,20 +288,20 @@ void
OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString& aFirstLine,x
}
else if ( io_nType == DataType::DATE || io_nType ==
DataType::TIMESTAMP || io_nType == DataType::TIME)
{
- String aField;
-
aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine,m_cFieldDelimiter,'\0');
- if (aField.Len() == 0 ||
- (m_cStringDelimiter && m_cStringDelimiter ==
aField.GetChar(0)))
+ ::rtl::OUString aField;
+
aFirstLine.GetTokenSpecial(&aField,nStartPosFirstLine,m_cFieldDelimiter,'\0');
+ if ( aField.isEmpty() ||
+ (m_cStringDelimiter && m_cStringDelimiter == aField[0]))
{
}
else
{
- String aField2;
+ ::rtl::OUString aField2;
if ( m_cStringDelimiter != '\0' )
-
aFirstLine.GetTokenSpecial(aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
+
aFirstLine.GetTokenSpecial(&aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
else
aField2 = aField;
- if (aField2.Len() )
+ if ( !aField2.isEmpty() )
{
try
{
@@ -378,21 +379,21 @@ void
OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString& aFirstLine,x
}
else
{
- String aField;
-
aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine,m_cFieldDelimiter,'\0');
- if (aField.Len() == 0 ||
- (m_cStringDelimiter && m_cStringDelimiter ==
aField.GetChar(0)))
+ ::rtl::OUString aField;
+
aFirstLine.GetTokenSpecial(&aField,nStartPosFirstLine,m_cFieldDelimiter,'\0');
+ if ( aField.isEmpty() ||
+ (m_cStringDelimiter && m_cStringDelimiter == aField[0]))
{
if ( m_cStringDelimiter != '\0' )
-
aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
+
aFirstLine.GetTokenSpecial(&aField,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
else
nStartPosFirstLine2 = nStartPosFirstLine;
}
else
{
- String aField2;
+ ::rtl::OUString aField2;
if ( m_cStringDelimiter != '\0' )
-
aFirstLine.GetTokenSpecial(aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
+
aFirstLine.GetTokenSpecial(&aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
}
}
}
@@ -490,7 +491,7 @@ String OFlatTable::getEntry()
// name and extension have to coincide
if ( m_pConnection->matchesExtension( sExt ) )
{
- if ( sExt.getLength() )
+ if ( !sExt.isEmpty() )
sName =
sName.replaceAt(sName.getLength()-(sExt.getLength()+1),sExt.getLength()+1,::rtl::OUString());
if ( sName == m_Name )
{
@@ -616,17 +617,17 @@ sal_Bool OFlatTable::fetchRow(OValueRefRow& _rRow,const
OSQLColumns & _rCols,sal
const sal_Unicode cDecimalDelimiter = pConnection->getDecimalDelimiter();
const sal_Unicode cThousandDelimiter =
pConnection->getThousandDelimiter();
// Felder:
- xub_StrLen nStartPos = 0;
- String aStr;
+ sal_Int32 nStartPos = 0;
+ ::rtl::OUString aStr;
OSQLColumns::Vector::const_iterator aIter = _rCols.get().begin();
OSQLColumns::Vector::const_iterator aEnd = _rCols.get().end();
const OValueRefVector::Vector::size_type nCount = _rRow->get().size();
for (OValueRefVector::Vector::size_type i = 1; aIter != aEnd && i <
nCount;
++aIter, i++)
{
-
m_aCurrentLine.GetTokenSpecial(aStr,nStartPos,m_cFieldDelimiter,m_cStringDelimiter);
+
m_aCurrentLine.GetTokenSpecial(&aStr,nStartPos,m_cFieldDelimiter,m_cStringDelimiter);
- if (aStr.Len() == 0)
+ if (aStr.isEmpty())
(_rRow->get())[i]->setNull();
else
{
@@ -680,7 +681,7 @@ sal_Bool OFlatTable::fetchRow(OValueRefRow& _rRow,const
OSQLColumns & _rCols,sal
String aStrConverted;
if ( DataType::INTEGER != nType )
{
- sal_Unicode* pData =
aStrConverted.AllocBuffer(aStr.Len());
+ sal_Unicode* pData =
aStrConverted.AllocBuffer(aStr.getLength());
const sal_Unicode* pStart = pData;
OSL_ENSURE(cDecimalDelimiter &&
nType != DataType::INTEGER ||
@@ -688,9 +689,9 @@ sal_Bool OFlatTable::fetchRow(OValueRefRow& _rRow,const
OSQLColumns & _rCols,sal
"FalscherTyp");
// In Standard-Notation
(DezimalPUNKT ohne Tausender-Komma) umwandeln:
- for (xub_StrLen j = 0; j <
aStr.Len(); ++j)
+ for (sal_Int32 j = 0; j <
aStr.getLength(); ++j)
{
- const sal_Unicode cChar = aStr.GetChar(j);
+ const sal_Unicode cChar = aStr[j];
if (cDecimalDelimiter &&
cChar == cDecimalDelimiter)
*pData++ = '.';
//aStrConverted.Append( '.' );
@@ -703,7 +704,7 @@ sal_Bool OFlatTable::fetchRow(OValueRefRow& _rRow,const
OSQLColumns & _rCols,sal
else
*pData++ = cChar;
//aStrConverted.Append(cChar);
- } // for (xub_StrLen j = 0; j <
aStr.Len(); ++j)
+ } // for (sal_Int32 j = 0; j <
aStr.Len(); ++j)
aStrConverted.ReleaseBufferAccess(xub_StrLen(pData -
pStart));
} // if ( DataType::INTEGER != nType )
else
@@ -898,77 +899,64 @@ sal_Bool OFlatTable::readLine(sal_Int32& _rnCurrentPos)
return readLine(m_aCurrentLine, _rnCurrentPos);
}
//
-----------------------------------------------------------------------------
-sal_Bool OFlatTable::readLine(QuotedTokenizedString& line, sal_Int32&
_rnCurrentPos)
+sal_Bool OFlatTable::readLine(QuotedTokenizedString& lineOut, sal_Int32&
_rnCurrentPos)
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "[email protected]",
"OFlatTable::readLine" );
const rtl_TextEncoding nEncoding = m_pConnection->getTextEncoding();
- m_pFileStream->ReadByteStringLine(line,nEncoding);
- if (m_pFileStream->IsEof())
- return sal_False;
-
- QuotedTokenizedString sLine = line; // check if the string continues on
next line
- xub_StrLen nLastOffset = 0;
- bool isQuoted = false;
+ ::rtl::OUStringBuffer lineBuffer( 4096 );
+ ::rtl::OUString separator = ::rtl::OUString();
+ static ::rtl::OUString lf = ::rtl::OUString::createFromAscii( "\n" );
bool isFieldStarting = true;
- while (sLine.Len() < STRING_MAXLEN)
+ bool inQuotedField = false;
+ sal_Bool result = sal_True;
+ do
{
- bool wasQuote = false;
- const sal_Unicode *p;
- p = sLine.GetString().GetBuffer();
- p += nLastOffset;
+ ::rtl::OUString line;
+ m_pFileStream->ReadByteStringLine(line,nEncoding);
+ if (m_pFileStream->IsEof())
+ {
+ result = sal_False;
+ break;
+ }
- while (*p)
+ bool wasPreviousQuote = false;
+ for ( sal_Int32 i = 0; i < line.getLength(); i++ )
{
- if (isQuoted)
+ sal_Unicode ch = line[i];
+ if ( ch == m_cStringDelimiter )
{
- if (*p == m_cStringDelimiter)
- wasQuote = !wasQuote;
+ if ( isFieldStarting )
+ {
+ isFieldStarting = false;
+ inQuotedField = true;
+ }
else
{
- if (wasQuote)
- {
- wasQuote = false;
- isQuoted = false;
- if (*p == m_cFieldDelimiter)
- isFieldStarting = true;
- }
+ wasPreviousQuote = !wasPreviousQuote;
}
}
- else
+ else if ( ch == m_cFieldDelimiter )
{
- if (isFieldStarting)
- {
- isFieldStarting = false;
- if (*p == m_cStringDelimiter)
- isQuoted = true;
- else if (*p == m_cFieldDelimiter)
- isFieldStarting = true;
- }
- else if (*p == m_cFieldDelimiter)
+ if ( !inQuotedField )
isFieldStarting = true;
}
- ++p;
- }
-
- if (wasQuote)
- isQuoted = false;
-
- if (isQuoted)
- {
- nLastOffset = sLine.Len();
- m_pFileStream->ReadByteStringLine(sLine,nEncoding);
- if ( !m_pFileStream->IsEof() )
+ else
{
- line.GetString().Append('\n');
- line.GetString() += sLine.GetString();
- sLine = line;
+ if ( wasPreviousQuote )
+ inQuotedField = false;
+ wasPreviousQuote = false;
}
- else
- break;
}
- else
- break;
- }
+ if ( wasPreviousQuote )
+ inQuotedField = false;
+
+ lineBuffer.append( separator );
+ separator = lf;
+ lineBuffer.append( line );
+
+ } while ( inQuotedField );
+
+ lineOut = lineBuffer.makeStringAndClear();
_rnCurrentPos = m_pFileStream->Tell();
- return sal_True;
+ return result;
}
diff --git a/main/connectivity/source/inc/file/quotedstring.hxx
b/main/connectivity/source/inc/file/quotedstring.hxx
index e5e8321d54..1bdd61e318 100644
--- a/main/connectivity/source/inc/file/quotedstring.hxx
+++ b/main/connectivity/source/inc/file/quotedstring.hxx
@@ -30,21 +30,21 @@
namespace connectivity
{
//==================================================================
- // Ableitung von String mit ueberladenen GetToken/GetTokenCount-Methoden
- // Speziell fuer FLAT FILE-Format: Strings koennen gequotet sein
+ // Derivation of string with overloaded GetToken/GetTokenCount methods
+ // Especially for FLAT FILE format: Strings can be quoted
//==================================================================
class OOO_DLLPUBLIC_FILE QuotedTokenizedString
{
- String m_sString;
+ ::rtl::OUString m_sString;
public:
QuotedTokenizedString() {}
- QuotedTokenizedString(const String& _sString) : m_sString(_sString){}
+ QuotedTokenizedString(const ::rtl::OUString& _sString) :
m_sString(_sString){}
- xub_StrLen GetTokenCount( sal_Unicode cTok , sal_Unicode
cStrDel ) const;
- void GetTokenSpecial( String& _rStr,xub_StrLen&
nStartPos, sal_Unicode cTok = ';', sal_Unicode cStrDel = '\0' ) const;
- inline String& GetString() { return m_sString; }
- inline xub_StrLen Len() const { return m_sString.Len(); }
- inline operator String&() { return m_sString; }
+ sal_Int32 GetTokenCount( sal_Unicode cTok , sal_Unicode cStrDel )
const;
+ void GetTokenSpecial( ::rtl::OUString* _rStr, sal_Int32&
nStartPos, sal_Unicode cTok = ';', sal_Unicode cStrDel = '\0' ) const;
+ inline ::rtl::OUString& GetString() { return m_sString; }
+ inline sal_Int32 Len() const { return m_sString.getLength(); }
+ inline operator ::rtl::OUString&() { return m_sString; }
};
}
diff --git a/main/connectivity/source/inc/flat/ETable.hxx
b/main/connectivity/source/inc/flat/ETable.hxx
index c946fb4c83..0e97d7abcf 100644
--- a/main/connectivity/source/inc/flat/ETable.hxx
+++ b/main/connectivity/source/inc/flat/ETable.hxx
@@ -65,7 +65,7 @@ namespace connectivity
sal_Bool CreateFile(const INetURLObject& aFile,
sal_Bool& bCreateMemo);
sal_Bool readLine(sal_Int32& _rnCurrentPos);
sal_Bool readLine(QuotedTokenizedString& line, sal_Int32&
_rnCurrentPos);
- void impl_fillColumnInfo_nothrow(QuotedTokenizedString&
aFirstLine,xub_StrLen& nStartPosFirstLine,xub_StrLen& nStartPosFirstLine2
+ void impl_fillColumnInfo_nothrow(QuotedTokenizedString&
aFirstLine,sal_Int32& nStartPosFirstLine,sal_Int32& nStartPosFirstLine2
,sal_Int32& io_nType,sal_Int32&
io_nPrecisions,sal_Int32& io_nScales,String& o_sTypeName
,const sal_Unicode
cDecimalDelimiter,const sal_Unicode cThousandDelimiter,const CharClass&
aCharClass);
public:
diff --git a/main/tools/inc/tools/stream.hxx b/main/tools/inc/tools/stream.hxx
index 51a44306d9..6f91567c43 100644
--- a/main/tools/inc/tools/stream.hxx
+++ b/main/tools/inc/tools/stream.hxx
@@ -31,6 +31,8 @@
#endif
#include <tools/ref.hxx>
#include <tools/rtti.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustring.hxx>
class FileCopier;
class StreamData;
@@ -443,10 +445,12 @@ public:
sal_Bool ReadCString( String& rStr, rtl_TextEncoding
eToEncode );
sal_Bool ReadCString( String& rStr ) { return
ReadCString( rStr, GetStreamCharSet()); }
+ sal_Bool ReadLine( ::rtl::OStringBuffer& rStr );
sal_Bool ReadLine( ByteString& rStr );
sal_Bool WriteLine( const ByteString& rStr );
sal_Bool WriteLines( const ByteString& rStr );
+ sal_Bool ReadByteStringLine( ::rtl::OUString& rStr,
rtl_TextEncoding eSrcCharSet );
sal_Bool ReadByteStringLine( String& rStr,
rtl_TextEncoding eSrcCharSet );
sal_Bool ReadByteStringLine( String& rStr ) { return
ReadByteStringLine( rStr, GetStreamCharSet()); }
sal_Bool WriteByteStringLine( const String& rStr,
rtl_TextEncoding eDestCharSet );
diff --git a/main/tools/source/stream/stream.cxx
b/main/tools/source/stream/stream.cxx
index 9805757e36..1b4d919770 100644
--- a/main/tools/source/stream/stream.cxx
+++ b/main/tools/source/stream/stream.cxx
@@ -676,6 +676,16 @@ void SvStream::ResetError()
|*
*************************************************************************/
+sal_Bool SvStream::ReadByteStringLine( ::rtl::OUString& rStr, rtl_TextEncoding
eSrcCharSet )
+{
+ sal_Bool bRet;
+ ::rtl::OStringBuffer stringBuffer;
+
+ bRet = ReadLine( stringBuffer );
+ rStr = ::rtl::OStringToOUString( stringBuffer.makeStringAndClear(),
eSrcCharSet );
+ return bRet;
+}
+
sal_Bool SvStream::ReadByteStringLine( String& rStr, rtl_TextEncoding
eSrcCharSet )
{
sal_Bool bRet;
@@ -686,6 +696,79 @@ sal_Bool SvStream::ReadByteStringLine( String& rStr,
rtl_TextEncoding eSrcCharSe
return bRet;
}
+sal_Bool SvStream::ReadLine( ::rtl::OStringBuffer& rStr )
+{
+ sal_Char buf[256+1];
+ sal_Bool bEnd = sal_False;
+ sal_Size nOldFilePos = Tell();
+ sal_Char c = 0;
+ sal_Size nTotalLen = 0;
+
+ rStr.setLength( 0 );
+ while( !bEnd && !GetError() ) // !!! do not test for EOF,
+ // !!! because we read in blocks
+ {
+ sal_uInt16 nLen = (sal_uInt16)Read( buf, sizeof(buf)-1 );
+ if ( !nLen )
+ {
+ if ( rStr.getLength() == 0 )
+ {
+ // the very first block read failed -> abort
+ bIsEof = sal_True;
+ return sal_False;
+ }
+ else
+ break;
+ }
+
+ sal_uInt16 j, n;
+ for( j = n = 0; j < nLen ; ++j )
+ {
+ c = buf[j];
+ if ( c == '\n' || c == '\r' )
+ {
+ bEnd = sal_True;
+ break;
+ }
+ // erAck 26.02.01: Old behavior was no special treatment of '\0'
+ // character here, but a following rStr+=c did ignore it. Is this
+ // really intended? Or should a '\0' better terminate a line?
+ // The nOldFilePos stuff wasn't correct then anyways.
+ if ( c )
+ {
+ if ( n < j )
+ buf[n] = c;
+ ++n;
+ }
+ }
+ if ( n )
+ rStr.append( buf, n );
+ nTotalLen += j;
+ }
+
+ if ( !bEnd && !GetError() && rStr.getLength() )
+ bEnd = sal_True;
+
+ nOldFilePos += nTotalLen;
+ if( Tell() > nOldFilePos )
+ nOldFilePos++;
+ Seek( nOldFilePos ); // seek because of the above BlockRead!
+
+ if ( bEnd && (c=='\r' || c=='\n') ) // Special treatment of DOS files
+ {
+ char cTemp;
+ sal_Size nLen = Read((char*)&cTemp , sizeof(cTemp) );
+ if ( nLen ) {
+ if( cTemp == c || (cTemp != '\n' && cTemp != '\r') )
+ Seek( nOldFilePos );
+ }
+ }
+
+ if ( bEnd )
+ bIsEof = sal_False;
+ return bEnd;
+}
+
sal_Bool SvStream::ReadLine( ByteString& rStr )
{
sal_Char buf[256+1];