Kaydet (Commit) ecc884e9 authored tarafından Kohei Yoshida's avatar Kohei Yoshida

Use orcus csv parser to streamd data which has much less overhead.

Also, use DocumentStreamAccess to modify ScDocument's content.

Change-Id: I516260cff1f2315267afcff05e36e620798a1aed
üst df63ec60
...@@ -2621,6 +2621,10 @@ endef ...@@ -2621,6 +2621,10 @@ endef
define gb_LinkTarget__use_orcus-parser define gb_LinkTarget__use_orcus-parser
$(call gb_LinkTarget_use_external_project,$(1),liborcus) $(call gb_LinkTarget_use_external_project,$(1),liborcus)
$(call gb_LinkTarget_set_include,$(1),\
-I$(call gb_UnpackedTarball_get_dir,liborcus/include) \
$$(INCLUDE) \
)
$(call gb_LinkTarget_add_libs,$(1),\ $(call gb_LinkTarget_add_libs,$(1),\
$(call gb_UnpackedTarball_get_dir,liborcus)/src/parser/.libs/liborcus-parser-0.6$(gb_StaticLibrary_PLAINEXT) \ $(call gb_UnpackedTarball_get_dir,liborcus)/src/parser/.libs/liborcus-parser-0.6$(gb_StaticLibrary_PLAINEXT) \
) )
......
...@@ -45,6 +45,12 @@ $(eval $(call gb_Library_use_externals,sc,\ ...@@ -45,6 +45,12 @@ $(eval $(call gb_Library_use_externals,sc,\
mdds_headers \ mdds_headers \
)) ))
ifeq ($(SYSTEM_LIBORCUS),YES)
$(eval $(call gb_Library_use_externals,sc,orcus))
else
$(eval $(call gb_Library_use_externals,sc,orcus-parser))
endif
ifeq ($(ENABLE_TELEPATHY),TRUE) ifeq ($(ENABLE_TELEPATHY),TRUE)
$(eval $(call gb_Library_use_libraries,sc,tubes)) $(eval $(call gb_Library_use_libraries,sc,tubes))
......
...@@ -18,11 +18,15 @@ $(eval $(call gb_Library_set_include,scqahelper,\ ...@@ -18,11 +18,15 @@ $(eval $(call gb_Library_set_include,scqahelper,\
$(eval $(call gb_Library_use_externals,scqahelper, \ $(eval $(call gb_Library_use_externals,scqahelper, \
boost_headers \ boost_headers \
mdds_headers \ mdds_headers \
orcus \
orcus-parser \
cppunit \ cppunit \
)) ))
ifeq ($(SYSTEM_LIBORCUS),YES)
$(eval $(call gb_Library_use_externals,scqahelper,orcus))
else
$(eval $(call gb_Library_use_externals,scqahelper,orcus-parser))
endif
$(eval $(call gb_Library_add_defs,scqahelper,\ $(eval $(call gb_Library_add_defs,scqahelper,\
-DSCQAHELPER_DLLIMPLEMENTATION \ -DSCQAHELPER_DLLIMPLEMENTATION \
)) ))
......
...@@ -10,7 +10,11 @@ ...@@ -10,7 +10,11 @@
#ifndef SC_DOCUMENTSTREAMACCESS_HXX #ifndef SC_DOCUMENTSTREAMACCESS_HXX
#define SC_DOCUMENTSTREAMACCESS_HXX #define SC_DOCUMENTSTREAMACCESS_HXX
#include <rtl/ustring.hxx>
class ScDocument; class ScDocument;
class ScAddress;
class ScRange;
namespace sc { namespace sc {
...@@ -28,6 +32,26 @@ class DocumentStreamAccess ...@@ -28,6 +32,26 @@ class DocumentStreamAccess
public: public:
DocumentStreamAccess( ScDocument& rDoc ); DocumentStreamAccess( ScDocument& rDoc );
void setStringCell( const ScAddress& rPos, const OUString& rStr );
/**
* Clear its internal state, and more importantly all the block position
* hints currently held.
*/
void reset();
/**
* Pop the top row inside specified range, shift all the other rows up by
* one, then set the bottom row empty.
*/
void shiftRangeUp( const ScRange& rRange );
/**
* Top the bottom row inside specified range, shift all the other rows
* above downward by one by inserting an empty row at the top.
*/
void shiftRangeDown( const ScRange& rRange );
}; };
} }
......
...@@ -145,6 +145,8 @@ public: ...@@ -145,6 +145,8 @@ public:
ColumnBlockPositionSet(ScDocument& rDoc); ColumnBlockPositionSet(ScDocument& rDoc);
ColumnBlockPosition* getBlockPosition(SCTAB nTab, SCCOL nCol); ColumnBlockPosition* getBlockPosition(SCTAB nTab, SCCOL nCol);
void clear();
}; };
ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset ); ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset );
......
...@@ -9,19 +9,114 @@ ...@@ -9,19 +9,114 @@
#include "documentstreamaccess.hxx" #include "documentstreamaccess.hxx"
#include "document.hxx" #include "document.hxx"
#include "table.hxx"
#include "column.hxx"
#include "mtvelements.hxx"
#include "svl/sharedstringpool.hxx"
namespace sc { namespace sc {
struct DocumentStreamAccessImpl struct DocumentStreamAccessImpl
{ {
ScDocument& mrDoc; ScDocument& mrDoc;
ColumnBlockPositionSet maBlockPosSet;
DocumentStreamAccessImpl( ScDocument& rDoc ) : mrDoc(rDoc) {} DocumentStreamAccessImpl( ScDocument& rDoc ) :
mrDoc(rDoc),
maBlockPosSet(rDoc)
{}
}; };
DocumentStreamAccess::DocumentStreamAccess( ScDocument& rDoc ) : DocumentStreamAccess::DocumentStreamAccess( ScDocument& rDoc ) :
mpImpl(new DocumentStreamAccessImpl(rDoc)) {} mpImpl(new DocumentStreamAccessImpl(rDoc)) {}
void DocumentStreamAccess::setStringCell( const ScAddress& rPos, const OUString& rStr )
{
ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
if (!pTab)
return;
ColumnBlockPosition* pBlockPos =
mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
if (!pBlockPos)
return;
svl::SharedString aSS = mpImpl->mrDoc.GetSharedStringPool().intern(rStr);
if (!aSS.getData())
return;
// Set the string.
CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aSS);
// Be sure to set the corresponding text attribute to the default value.
CellTextAttrStoreType& rAttrs = pTab->aCol[rPos.Col()].maCellTextAttrs;
pBlockPos->miCellTextAttrPos = rAttrs.set(pBlockPos->miCellTextAttrPos, rPos.Row(), CellTextAttr());
}
void DocumentStreamAccess::reset()
{
mpImpl->maBlockPosSet.clear();
}
void DocumentStreamAccess::shiftRangeUp( const ScRange& rRange )
{
ScTable* pTab = mpImpl->mrDoc.FetchTable(rRange.aStart.Tab());
if (!pTab)
return;
SCROW nTopRow = rRange.aStart.Row();
SCROW nLastRow = rRange.aEnd.Row();
for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
{
ColumnBlockPosition* pBlockPos =
mpImpl->maBlockPosSet.getBlockPosition(rRange.aStart.Tab(), nCol);
if (!pBlockPos)
return;
CellStoreType& rCells = pTab->aCol[nCol].maCells;
rCells.erase(nTopRow, nTopRow); // Erase the top, and shift the rest up.
pBlockPos->miCellPos = rCells.insert_empty(nLastRow, 1);
// Do the same for the text attribute storage.
CellTextAttrStoreType& rAttrs = pTab->aCol[nCol].maCellTextAttrs;
rAttrs.erase(nTopRow, nTopRow);
pBlockPos->miCellTextAttrPos = rAttrs.insert_empty(nLastRow, 1);
}
}
void DocumentStreamAccess::shiftRangeDown( const ScRange& rRange )
{
ScTable* pTab = mpImpl->mrDoc.FetchTable(rRange.aStart.Tab());
if (!pTab)
return;
SCROW nTopRow = rRange.aStart.Row();
SCROW nLastRow = rRange.aEnd.Row();
for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
{
ColumnBlockPosition* pBlockPos =
mpImpl->maBlockPosSet.getBlockPosition(rRange.aStart.Tab(), nCol);
if (!pBlockPos)
return;
CellStoreType& rCells = pTab->aCol[nCol].maCells;
rCells.erase(nLastRow, nLastRow); // Erase the bottom.
pBlockPos->miCellPos = rCells.insert_empty(nTopRow, 1); // insert at the top and shift everything down.
// Do the same for the text attribute storage.
CellTextAttrStoreType& rAttrs = pTab->aCol[nCol].maCellTextAttrs;
rAttrs.erase(nLastRow, nLastRow);
pBlockPos->miCellTextAttrPos = rAttrs.insert_empty(nTopRow, 1);
}
}
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -67,6 +67,12 @@ ColumnBlockPosition* ColumnBlockPositionSet::getBlockPosition(SCTAB nTab, SCCOL ...@@ -67,6 +67,12 @@ ColumnBlockPosition* ColumnBlockPositionSet::getBlockPosition(SCTAB nTab, SCCOL
return &it->second; return &it->second;
} }
void ColumnBlockPositionSet::clear()
{
osl::MutexGuard aGuard(&maMtxTables);
maTables.clear();
}
ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset ) ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
{ {
switch (itPos->type) switch (itPos->type)
......
...@@ -28,6 +28,15 @@ ...@@ -28,6 +28,15 @@
#include <tabvwsh.hxx> #include <tabvwsh.hxx>
#include <viewdata.hxx> #include <viewdata.hxx>
#include <config_orcus.h>
#if ENABLE_ORCUS
#if defined WNT
#define __ORCUS_STATIC_LIB
#endif
#include <orcus/csv_parser.hpp>
#endif
#include <queue> #include <queue>
namespace sc { namespace sc {
...@@ -316,6 +325,7 @@ void DataStream::StartImport() ...@@ -316,6 +325,7 @@ void DataStream::StartImport()
{ {
if (mbRunning) if (mbRunning)
return; return;
if (!mxReaderThread.is()) if (!mxReaderThread.is())
{ {
SvStream *pStream = 0; SvStream *pStream = 0;
...@@ -327,6 +337,7 @@ void DataStream::StartImport() ...@@ -327,6 +337,7 @@ void DataStream::StartImport()
mxReaderThread->launch(); mxReaderThread->launch();
} }
mbRunning = true; mbRunning = true;
maDocAccess.reset();
mxThread->maStart.set(); mxThread->maStart.set();
} }
...@@ -334,6 +345,7 @@ void DataStream::StopImport() ...@@ -334,6 +345,7 @@ void DataStream::StopImport()
{ {
if (!mbRunning) if (!mbRunning)
return; return;
mbRunning = false; mbRunning = false;
Repaint(); Repaint();
} }
...@@ -362,23 +374,32 @@ void DataStream::MoveData() ...@@ -362,23 +374,32 @@ void DataStream::MoveData()
switch (meMove) switch (meMove)
{ {
case RANGE_DOWN: case RANGE_DOWN:
{
if (mnCurRow == mpEndRange->aStart.Row()) if (mnCurRow == mpEndRange->aStart.Row())
meMove = MOVE_UP; meMove = MOVE_UP;
break; }
break;
case MOVE_UP: case MOVE_UP:
{
// Remove the top row and shift the remaining rows upward. Then // Remove the top row and shift the remaining rows upward. Then
// insert a new row at the end row position. // insert a new row at the end row position.
mpDoc->DeleteRow(maStartRange); ScRange aRange = maStartRange;
mpDoc->InsertRow(*mpEndRange); aRange.aEnd = mpEndRange->aEnd;
break; maDocAccess.shiftRangeUp(aRange);
}
break;
case MOVE_DOWN: case MOVE_DOWN:
{
// Remove the end row and shift the remaining rows downward by // Remove the end row and shift the remaining rows downward by
// inserting a new row at the top row. // inserting a new row at the top row.
mpDoc->DeleteRow(*mpEndRange); ScRange aRange = maStartRange;
mpDoc->InsertRow(maStartRange); aRange.aEnd = mpEndRange->aEnd;
break; maDocAccess.shiftRangeDown(aRange);
}
break;
case NO_MOVE: case NO_MOVE:
break; default:
;
} }
} }
...@@ -388,77 +409,61 @@ IMPL_LINK_NOARG(DataStream, RefreshHdl) ...@@ -388,77 +409,61 @@ IMPL_LINK_NOARG(DataStream, RefreshHdl)
return 0; return 0;
} }
// lcl_ScanString and Text2Doc is simplified version #if ENABLE_ORCUS
// of code from sc/source/ui/docshell/impex.cxx
const sal_Unicode* lcl_ScanString( const sal_Unicode* p, OUString& rString, sal_Unicode cStr) namespace {
/**
* This handler handles a single line CSV input.
*/
class CSVHandler
{ {
const sal_Unicode* p0 = p; DocumentStreamAccess& mrDoc;
for( ;; ) ScAddress maPos;
SCROW mnRow;
SCCOL mnCol;
SCCOL mnEndCol;
SCTAB mnTab;
public:
CSVHandler( DocumentStreamAccess& rDoc, const ScAddress& rPos, SCCOL nEndCol ) :
mrDoc(rDoc), maPos(rPos), mnEndCol(nEndCol) {}
void begin_parse() {}
void end_parse() {}
void begin_row() {}
void end_row() {}
void cell(const char* p, size_t n)
{ {
if (!*p) if (maPos.Col() <= mnEndCol)
break;
if (*p == cStr)
{ {
if (*++p != cStr) mrDoc.setStringCell(maPos, OUString(p, n, RTL_TEXTENCODING_UTF8));
break;
p++;
} }
else maPos.IncCol();
p++;
} }
if (p0 < p) };
if (rString.getLength() + (p - p0) <= STRING_MAXLEN)
rString += OUString( p0, sal::static_int_cast<sal_Int32>( p - p0 ) );
return p;
} }
void DataStream::Text2Doc() void DataStream::Text2Doc()
{ {
sal_Unicode cSep(','); OString aLine = ConsumeLine();
sal_Unicode cStr('"'); orcus::csv_parser_config aConfig;
SCCOL nStartCol = maStartRange.aStart.Col(); aConfig.delimiters.push_back(',');
SCCOL nEndCol = maStartRange.aEnd.Col(); aConfig.text_qualifier = '"';
OUString aCell; CSVHandler aHdl(maDocAccess, ScAddress(maStartRange.aStart.Col(), mnCurRow, maStartRange.aStart.Tab()), maStartRange.aEnd.Col());
ScDocumentImport aDocImport(*mpDoc); orcus::csv_parser<CSVHandler> parser(aLine.getStr(), aLine.getLength(), aHdl, aConfig);
parser.parse();
SCCOL nCol = nStartCol;
OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
const sal_Unicode* p = sLine.getStr();
while (*p)
{
aCell = "";
const sal_Unicode* q = p;
while (*p && *p != cSep)
{
// Always look for a pairing quote and ignore separator in between.
while (*p && *p == cStr)
q = p = lcl_ScanString(p, aCell, cStr);
// All until next separator or quote.
while (*p && *p != cSep && *p != cStr)
++p;
if (aCell.getLength() + (p - q) <= STRING_MAXLEN)
aCell += OUString( q, sal::static_int_cast<sal_Int32>( p - q ) );
q = p;
}
if (*p)
++p;
if (nCol <= nEndCol)
{
ScAddress aAddress(nCol, mnCurRow, maStartRange.aStart.Tab());
if (aCell == "0" || ( aCell.indexOf(':') == -1 && aCell.toDouble() ))
aDocImport.setNumericCell(aAddress, aCell.toDouble());
else
aDocImport.setStringCell(aAddress, aCell);
}
++nCol;
}
++mnRepaintCounter; ++mnRepaintCounter;
}
aDocImport.finalize(); #else
ScRange aBCRange(nStartCol, mnCurRow, maStartRange.aStart.Tab(), nEndCol, mnCurRow, maStartRange.aStart.Tab()); void DataStream::Text2Doc() {}
maBroadcastRanges.Join(aBCRange);
} #endif
bool DataStream::ImportData() bool DataStream::ImportData()
{ {
...@@ -474,6 +479,7 @@ bool DataStream::ImportData() ...@@ -474,6 +479,7 @@ bool DataStream::ImportData()
} }
else else
{ {
#if 0 // TODO : temporarily disable this code.
ScDocumentImport aDocImport(*mpDoc); ScDocumentImport aDocImport(*mpDoc);
// read more lines at once but not too much // read more lines at once but not too much
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
...@@ -496,8 +502,9 @@ bool DataStream::ImportData() ...@@ -496,8 +502,9 @@ bool DataStream::ImportData()
maBroadcastRanges.Join(aAddress); maBroadcastRanges.Join(aAddress);
} }
aDocImport.finalize(); aDocImport.finalize();
#endif
} }
mpDocShell->SetDocumentModified();
if (meMove == NO_MOVE) if (meMove == NO_MOVE)
return mbRunning; return mbRunning;
......
...@@ -78,8 +78,8 @@ private: ...@@ -78,8 +78,8 @@ private:
void Broadcast(); void Broadcast();
private: private:
ScDocShell *mpDocShell; ScDocShell* mpDocShell;
ScDocument *mpDoc; ScDocument* mpDoc;
DocumentStreamAccess maDocAccess; DocumentStreamAccess maDocAccess;
OUString msURL; OUString msURL;
OUString msMove; OUString msMove;
...@@ -88,7 +88,7 @@ private: ...@@ -88,7 +88,7 @@ private:
MoveEnum meMove; MoveEnum meMove;
bool mbRunning; bool mbRunning;
bool mbValuesInLine; bool mbValuesInLine;
LinesList *mpLines; LinesList* mpLines;
size_t mnLinesCount; size_t mnLinesCount;
size_t mnRepaintCounter; size_t mnRepaintCounter;
SCROW mnCurRow; SCROW mnCurRow;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment