Correctly handle empty cells for string arrays too.
Because we need to make a distinction between an empty cell and a string cell containing zero-length string, I decided to switch to using rtl_uString* array and use NULL values as empty cells. Change-Id: I5bedb593507f34782e41a8a900602d445e5b1f6f
This commit is contained in:
@@ -13,7 +13,7 @@ namespace formula {
|
|||||||
|
|
||||||
VectorRefArray::VectorRefArray() : mpNumericArray(NULL), mbNumeric(true) {}
|
VectorRefArray::VectorRefArray() : mpNumericArray(NULL), mbNumeric(true) {}
|
||||||
VectorRefArray::VectorRefArray( const double* pArray ) : mpNumericArray(pArray), mbNumeric(true) {}
|
VectorRefArray::VectorRefArray( const double* pArray ) : mpNumericArray(pArray), mbNumeric(true) {}
|
||||||
VectorRefArray::VectorRefArray( const OUString* pArray ) : mpStringArray(pArray), mbNumeric(false) {}
|
VectorRefArray::VectorRefArray( rtl_uString** pArray ) : mpStringArray(pArray), mbNumeric(false) {}
|
||||||
|
|
||||||
SingleVectorRefToken::SingleVectorRefToken( const double* pArray, size_t nLength ) :
|
SingleVectorRefToken::SingleVectorRefToken( const double* pArray, size_t nLength ) :
|
||||||
FormulaToken(svSingleVectorRef, ocPush), maArray(pArray), mnArrayLength(nLength) {}
|
FormulaToken(svSingleVectorRef, ocPush), maArray(pArray), mnArrayLength(nLength) {}
|
||||||
|
@@ -18,14 +18,14 @@ struct FORMULA_DLLPUBLIC VectorRefArray
|
|||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
const double* mpNumericArray;
|
const double* mpNumericArray;
|
||||||
const OUString* mpStringArray;
|
rtl_uString** mpStringArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool mbNumeric;
|
bool mbNumeric;
|
||||||
|
|
||||||
VectorRefArray();
|
VectorRefArray();
|
||||||
VectorRefArray( const double* pArray );
|
VectorRefArray( const double* pArray );
|
||||||
VectorRefArray( const OUString* pArray );
|
VectorRefArray( rtl_uString** pArray );
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
class ScDocument;
|
class ScDocument;
|
||||||
class ScTokenArray;
|
class ScTokenArray;
|
||||||
@@ -23,13 +24,17 @@ namespace sc {
|
|||||||
|
|
||||||
struct FormulaGroupContext : boost::noncopyable
|
struct FormulaGroupContext : boost::noncopyable
|
||||||
{
|
{
|
||||||
|
typedef boost::unordered_set<OUString, OUStringHash> StrHashType;
|
||||||
typedef std::vector<double> NumArrayType;
|
typedef std::vector<double> NumArrayType;
|
||||||
typedef std::vector<OUString> StrArrayType;
|
typedef std::vector<rtl_uString*> StrArrayType;
|
||||||
typedef boost::ptr_vector<NumArrayType> NumArrayStoreType;
|
typedef boost::ptr_vector<NumArrayType> NumArrayStoreType;
|
||||||
typedef boost::ptr_vector<StrArrayType> StrArrayStoreType;
|
typedef boost::ptr_vector<StrArrayType> StrArrayStoreType;
|
||||||
|
|
||||||
|
StrHashType maStrPool;
|
||||||
NumArrayStoreType maNumArrays;
|
NumArrayStoreType maNumArrays;
|
||||||
StrArrayStoreType maStrArrays;
|
StrArrayStoreType maStrArrays;
|
||||||
|
|
||||||
|
rtl_uString* intern( const OUString& rStr );
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2256,8 +2256,16 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext&
|
|||||||
if (nLenRequested <= nLen)
|
if (nLenRequested <= nLen)
|
||||||
{
|
{
|
||||||
// Requested length fits a single block.
|
// Requested length fits a single block.
|
||||||
|
rCxt.maStrArrays.push_back(new sc::FormulaGroupContext::StrArrayType);
|
||||||
|
sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back();
|
||||||
|
rArray.reserve(nLenRequested);
|
||||||
|
|
||||||
const OUString* p = &sc::string_block::at(*aPos.first->data, aPos.second);
|
const OUString* p = &sc::string_block::at(*aPos.first->data, aPos.second);
|
||||||
return formula::VectorRefArray(p);
|
const OUString* pEnd = p + nLenRequested;
|
||||||
|
for (; p != pEnd; ++p)
|
||||||
|
rArray.push_back(rCxt.intern(*p));
|
||||||
|
|
||||||
|
return formula::VectorRefArray(&rArray[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle cases where the requested length goes beyond the
|
// TODO: handle cases where the requested length goes beyond the
|
||||||
|
@@ -29,6 +29,23 @@
|
|||||||
|
|
||||||
namespace sc {
|
namespace sc {
|
||||||
|
|
||||||
|
rtl_uString* FormulaGroupContext::intern( const OUString& rStr )
|
||||||
|
{
|
||||||
|
StrHashType::iterator it = maStrPool.find(rStr);
|
||||||
|
if (it == maStrPool.end())
|
||||||
|
{
|
||||||
|
// Not yet in the pool.
|
||||||
|
std::pair<StrHashType::iterator, bool> r = maStrPool.insert(rStr.intern());
|
||||||
|
if (!r.second)
|
||||||
|
// Insertion failed.
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
it = r.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->pData;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,7 +80,49 @@ void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen )
|
|||||||
{
|
{
|
||||||
// Flush last non-NaN segment to the matrix.
|
// Flush last non-NaN segment to the matrix.
|
||||||
rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums);
|
rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums);
|
||||||
pHead = NULL;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen )
|
||||||
|
{
|
||||||
|
rtl_uString** p = pStrs;
|
||||||
|
rtl_uString** pEnd = p + nLen;
|
||||||
|
rtl_uString** pHead = NULL;
|
||||||
|
for (; p != pEnd; ++p)
|
||||||
|
{
|
||||||
|
if (*p)
|
||||||
|
{
|
||||||
|
if (!pHead)
|
||||||
|
// Store the first non-empty string position.
|
||||||
|
pHead = p;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pHead)
|
||||||
|
{
|
||||||
|
// Flush this non-empty segment to the matrix.
|
||||||
|
size_t nOffset = pHead - pStrs;
|
||||||
|
std::vector<OUString> aStrs;
|
||||||
|
aStrs.reserve(p - pHead);
|
||||||
|
for (; pHead != p; ++pHead)
|
||||||
|
aStrs.push_back(OUString(*pHead));
|
||||||
|
|
||||||
|
rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset);
|
||||||
|
pHead = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pHead)
|
||||||
|
{
|
||||||
|
// Flush last non-empty segment to the matrix.
|
||||||
|
size_t nOffset = pHead - pStrs;
|
||||||
|
std::vector<OUString> aStrs;
|
||||||
|
aStrs.reserve(p - pHead);
|
||||||
|
for (; pHead != p; ++pHead)
|
||||||
|
aStrs.push_back(OUString(*pHead));
|
||||||
|
|
||||||
|
rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +183,14 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
|
|||||||
aCode2.AddDouble(fVal);
|
aCode2.AddDouble(fVal);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
aCode2.AddString(static_cast<size_t>(i) < p2->GetArrayLength() ? rArray.mpStringArray[i] : OUString());
|
{
|
||||||
|
rtl_uString* pStr = NULL;
|
||||||
|
if (static_cast<size_t>(i) < p2->GetArrayLength())
|
||||||
|
pStr = rArray.mpStringArray[i];
|
||||||
|
|
||||||
|
if (pStr)
|
||||||
|
aCode2.AddString(OUString(pStr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case formula::svDoubleVectorRef:
|
case formula::svDoubleVectorRef:
|
||||||
@@ -138,6 +204,10 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
|
|||||||
nRowEnd += i;
|
nRowEnd += i;
|
||||||
size_t nRowSize = nRowEnd - nRowStart + 1;
|
size_t nRowSize = nRowEnd - nRowStart + 1;
|
||||||
ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize));
|
ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize));
|
||||||
|
if (p2->GetArrayLength() < nRowSize)
|
||||||
|
// Data array is shorter than the row size of the reference. Truncate it.
|
||||||
|
nRowSize = p2->GetArrayLength();
|
||||||
|
|
||||||
for (size_t nCol = 0; nCol < nColSize; ++nCol)
|
for (size_t nCol = 0; nCol < nColSize; ++nCol)
|
||||||
{
|
{
|
||||||
const formula::VectorRefArray& rArray = rArrays[nCol];
|
const formula::VectorRefArray& rArray = rArrays[nCol];
|
||||||
@@ -149,9 +219,9 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const OUString* pStrs = rArray.mpStringArray;
|
rtl_uString** pStrs = rArray.mpStringArray;
|
||||||
pStrs += nRowStart;
|
pStrs += nRowStart;
|
||||||
pMat->PutString(pStrs, nRowSize, nCol, 0);
|
fillMatrix(*pMat, nCol, pStrs, nRowSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user