office-gobmx/sc/inc/scmatrix.hxx
Rüdiger Timm 47b1cc26c2 CWS-TOOLING: integrate CWS mooxlsc
2008-12-12 09:32:19 +0100 dr  r265390 : #i10000# warning
2008-12-11 14:54:26 +0100 dr  r265301 : add strings from dr66 to meet ui freeze
2008-12-11 14:53:20 +0100 dr  r265300 : add strings from dr66 to meet ui freeze
2008-12-08 14:43:25 +0100 er  r264997 : DBG_... need semicolon
2008-12-04 19:16:50 +0100 er  r264872 : DBG_... needs semicolon
2008-12-04 11:09:27 +0100 er  r264824 : DBG_ERROR needs semicolon
2008-12-03 13:29:46 +0100 er  r264770 : CWS-TOOLING: rebase CWS mooxlsc to trunk@264325 (milestone: DEV300:m36)
2008-12-02 16:49:09 +0100 er  r264722 : disable code for named references #i4385# import as long as #i3740# isn't fully implemented
2008-12-02 16:45:04 +0100 er  r264721 : some compilers attempt to be too smart; persuade them it's really meant what was written
2008-12-02 16:04:56 +0100 er  r264715 : #i3740# no storage in ODF for external name references
2008-11-29 02:20:50 +0100 er  r264575 : some huge performance improvement when reading repeated empty rows for the external references cache from ODF, as they often occur in the sparse matrix
2008-11-29 01:14:55 +0100 er  r264574 : WriteExternalRefCaches: for table:number-columns-repeated write used columns instead of MAXCOLCOUNT
2008-11-28 18:30:04 +0100 er  r264570 : #i3740# write/read external name references as bracketed references, as proposed on the ODFF list
2008-11-27 20:36:54 +0100 er  r264521 : merge i95068 from cws calc46 for code correctness
2008-11-21 20:39:34 +0100 kohei  r264174 : fixed a crash when importing a BIFF8 document with per-sheet external names.
For now, we don't support per-sheet external names.  Let's throw in NoName
error until they are supported.
2008-11-21 18:47:27 +0100 kohei  r264168 : I forgot to process cached range references in the EXTERNNAME record, which 
prevented cached external names with range references from being imported 
correctly.
P.S. I swear I thought I had covered this....
2008-11-20 23:07:22 +0100 er  r264104 : #i4385# parse external defined names in MOOXML import
2008-11-14 23:18:54 +0100 er  r263700 : #i92797# parse external sheet references under aspects of MOOXML import and new ScExternalRefManager
2008-11-14 18:49:48 +0100 er  r263696 : remove infinity assertion, leftover from binary file format; coded double error may occur via filter import
2008-11-12 13:29:44 +0100 er  r263593 : make references to entire rows/columns, such as A:A or 3:3, actually work in MOOXML import
2008-11-03 12:35:11 +0100 er  r263282 : a struct is a struct is a ...
2008-10-31 00:30:59 +0100 er  r262843 : aTableRowCellAttrTokenMap needed
2008-10-31 00:26:07 +0100 er  r262842 : GetTableRowCellAttrTokenMap() is not unused
2008-10-31 00:13:53 +0100 er  r262841 : merge error
2008-10-31 00:05:39 +0100 er  r262840 : merge error
2008-10-30 23:17:48 +0100 er  r262839 : unresolved merge conflict!?!
2008-10-30 22:59:11 +0100 er  r262838 : merge error
2008-10-30 16:31:04 +0100 hr  r262833 : CWS-TOOLING: rebase CWS mooxlsc to trunk@262620 (milestone: DEV300:m34)
2008-10-16 21:57:51 +0200 er  r262272 : migrate CWS mooxlsc to SVN
2008-12-12 09:38:47 +00:00

331 lines
12 KiB
C++

/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: scmatrix.hxx,v $
* $Revision: 1.11.32.1 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#ifndef SC_MATRIX_HXX
#define SC_MATRIX_HXX
#include "global.hxx"
#include "intruref.hxx"
#include "errorcodes.hxx"
#include <tools/string.hxx>
class SvStream;
class ScInterpreter;
class SvNumberFormatter;
typedef BYTE ScMatValType;
const ScMatValType SC_MATVAL_VALUE = 0x00;
const ScMatValType SC_MATVAL_BOOLEAN = 0x01;
const ScMatValType SC_MATVAL_STRING = 0x02;
const ScMatValType SC_MATVAL_EMPTY = SC_MATVAL_STRING | 0x04; // STRING plus flag
const ScMatValType SC_MATVAL_EMPTYPATH = SC_MATVAL_EMPTY | 0x08; // EMPTY plus flag
union ScMatrixValue
{
double fVal;
String* pS;
/// Only valid if ScMatrix methods indicate so!
const String& GetString() const { return pS ? *pS : EMPTY_STRING; }
/// Only valid if ScMatrix methods indicate that this is no string!
USHORT GetError() const { return GetDoubleErrorValue( fVal); }
/// Only valid if ScMatrix methods indicate that this is a boolean
bool GetBoolean() const { return fVal != 0.; }
};
/** Matrix representation of double values and strings.
@ATTENTION: optimized for speed and double values.
Matrix elements are NOT initialized after construction!
All methods using an SCSIZE nIndex parameter and all Is... methods do NOT
check the range for validity! However, the Put... and Get... methods using
nCol/nRow parameters do check the range. <p>
GetString( SCSIZE nIndex ) does not check if there really is a string, do
this with IsString() first. GetString( SCSIZE nC, SCSIZE nR ) does check
it and returns and empty string if there is no string. Both GetDouble()
methods don't check for a string, do this with IsNumeric() or IsString()
or IsValue() first. <p>
The GetString( SvNumberFormatter&, ...) methods return the matrix element's
string if one is present, otherwise the numerical value is formatted as a
string, or in case of an error the error string is returned.
PutDouble() does not reset an eventual string! Use
PutDoubleAndResetString() if that is wanted. Also the FillDouble...()
methods don't reset strings. As a consequence memory leaks may occur if
used wrong.
*/
class ScMatrix
{
ScMatrixValue* pMat;
ScMatValType* mnValType;
ULONG mnNonValue; // how many strings and empties
ScInterpreter* pErrorInterpreter;
mutable ULONG nRefCnt; // reference count
SCSIZE nColCount;
SCSIZE nRowCount;
void ResetIsString();
void DeleteIsString();
void CreateMatrix( SCSIZE nC, SCSIZE nR);
// pStr may be NULL, bFlag MUST NOT be 0
void PutStringEntry( const String* pStr, BYTE bFlag, SCSIZE nIndex );
// only delete via Delete()
~ScMatrix();
// not implemented, prevent usage
ScMatrix( const ScMatrix& );
ScMatrix& operator=( const ScMatrix&);
void SetErrorAtInterpreter( USHORT nError) const;
public:
/// The maximum number of elements a matrix may have at runtime.
inline static size_t GetElementsMax()
{
// Roughly 125MB in total, divided by 8+1 per element => 14M elements.
const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
// With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
// Stuffed with a million rows would limit this to 14 columns.
return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
}
/// Value or boolean.
inline static bool IsValueType( ScMatValType nType )
{
return nType <= SC_MATVAL_BOOLEAN;
}
/// Boolean.
inline static bool IsBooleanType( ScMatValType nType )
{
return nType == SC_MATVAL_BOOLEAN;
}
/// String, empty or empty path, but not value nor boolean.
inline static bool IsStringType( ScMatValType nType )
{
return (nType & SC_MATVAL_STRING) != 0;
}
/// Empty, but not empty path or any other type.
inline static bool IsEmptyType( ScMatValType nType )
{
return (nType & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY;
}
/// Empty path, but not empty or any other type.
inline static bool IsEmptyPathType( ScMatValType nType )
{
return (nType & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH;
}
/** If nC*nR results in more than GetElementsMax() entries, a 1x1 matrix is
created instead and a double error value (errStackOverflow) is set.
Compare nC and nR with a GetDimensions() call to check. */
ScMatrix( SCSIZE nC, SCSIZE nR) : nRefCnt(0) { CreateMatrix( nC, nR); }
ScMatrix* Clone() const;
/// disable refcounting forever, may only be deleted via Delete() afterwards
inline void SetEternalRef() { nRefCnt = ULONG_MAX; }
inline bool IsEternalRef() const { return nRefCnt == ULONG_MAX; }
inline void IncRef() const
{
if ( !IsEternalRef() )
++nRefCnt;
}
inline void DecRef() const
{
if ( nRefCnt > 0 && !IsEternalRef() )
if ( --nRefCnt == 0 )
delete this;
}
inline void Delete()
{
if ( nRefCnt == 0 || IsEternalRef() )
delete this;
else
--nRefCnt;
}
void SetErrorInterpreter( ScInterpreter* p)
{ pErrorInterpreter = p; }
ScMatrix( SvStream& rStream);
void Store( SvStream& rStream) const;
void GetDimensions( SCSIZE& rC, SCSIZE& rR) const
{ rC = nColCount; rR = nRowCount; };
SCSIZE GetElementCount() const
{ return nColCount * nRowCount; }
inline bool ValidColRow( SCSIZE nC, SCSIZE nR) const
{ return nC < nColCount && nR < nRowCount; }
inline SCSIZE CalcOffset( SCSIZE nC, SCSIZE nR) const
{ return nC * nRowCount + nR; }
void PutDouble( double fVal, SCSIZE nC, SCSIZE nR);
void PutDouble( double fVal, SCSIZE nIndex)
{ pMat[nIndex].fVal = fVal; }
void PutString( const String& rStr, SCSIZE nC, SCSIZE nR);
void PutString( const String& rStr, SCSIZE nIndex);
void PutEmpty( SCSIZE nC, SCSIZE nR);
void PutEmpty( SCSIZE nIndex);
/// Jump FALSE without path
void PutEmptyPath( SCSIZE nC, SCSIZE nR);
void PutEmptyPath( SCSIZE nIndex);
void PutError( USHORT nErrorCode, SCSIZE nC, SCSIZE nR )
{ PutDouble( CreateDoubleError( nErrorCode ), nC, nR ); }
void PutError( USHORT nErrorCode, SCSIZE nIndex )
{ PutDouble( CreateDoubleError( nErrorCode ), nIndex ); }
void PutBoolean( bool bVal, SCSIZE nC, SCSIZE nR);
void PutBoolean( bool bVal, SCSIZE nIndex);
void FillDouble( double fVal,
SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
/** May be used before obtaining the double value of an element to avoid
passing its NAN around.
@ATTENTION: MUST NOT be used if the element is a string!
@returns 0 if no error, else one of err... constants */
USHORT GetError( SCSIZE nC, SCSIZE nR) const;
USHORT GetError( SCSIZE nIndex) const
{ return pMat[nIndex].GetError(); }
/** Use in ScInterpreter to obtain the error code, if any.
@returns 0 if no error or string element, else one of err... constants */
USHORT GetErrorIfNotString( SCSIZE nC, SCSIZE nR) const
{ return IsValue( nC, nR) ? GetError( nC, nR) : 0; }
USHORT GetErrorIfNotString( SCSIZE nIndex) const
{ return IsValue( nIndex) ? GetError( nIndex) : 0; }
/// @return 0.0 if empty
double GetDouble( SCSIZE nC, SCSIZE nR) const;
/// @return 0.0 if empty
double GetDouble( SCSIZE nIndex) const
{
if ( pErrorInterpreter )
{
USHORT nError = GetDoubleErrorValue( pMat[nIndex].fVal);
if ( nError )
SetErrorAtInterpreter( nError);
}
return pMat[nIndex].fVal;
}
const String& GetString( SCSIZE nC, SCSIZE nR) const;
const String& GetString( SCSIZE nIndex) const
{ return pMat[nIndex].GetString(); }
String GetString( SvNumberFormatter& rFormatter, SCSIZE nIndex) const;
String GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
/// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
/// an empty string!
const ScMatrixValue* Get( SCSIZE nC, SCSIZE nR, ScMatValType& nType) const;
/// @return <TRUE/> if string or empty
BOOL IsString( SCSIZE nIndex ) const
{ return mnValType && IsStringType( mnValType[nIndex]); }
/// @return <TRUE/> if string or empty
BOOL IsString( SCSIZE nC, SCSIZE nR ) const
{ return mnValType && IsStringType( mnValType[ nC * nRowCount + nR ]); }
BOOL IsEmpty( SCSIZE nIndex ) const
{ return mnValType && ((mnValType[nIndex] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
BOOL IsEmptyPath( SCSIZE nC, SCSIZE nR ) const
{ return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
BOOL IsEmptyPath( SCSIZE nIndex ) const
{ return mnValType && ((mnValType[nIndex] & SC_MATVAL_EMPTYPATH) == SC_MATVAL_EMPTYPATH); }
BOOL IsEmpty( SCSIZE nC, SCSIZE nR ) const
{ return mnValType && ((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
BOOL IsValue( SCSIZE nIndex ) const
{ return !mnValType || IsValueType( mnValType[nIndex]); }
BOOL IsValue( SCSIZE nC, SCSIZE nR ) const
{ return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]); }
BOOL IsValueOrEmpty( SCSIZE nIndex ) const
{ return !mnValType || IsValueType( mnValType[nIndex] ) ||
((mnValType[nIndex] & SC_MATVAL_EMPTY) == SC_MATVAL_EMPTY); }
BOOL IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const
{ return !mnValType || IsValueType( mnValType[ nC * nRowCount + nR ]) ||
((mnValType[ nC * nRowCount + nR ] & SC_MATVAL_EMPTY) ==
SC_MATVAL_EMPTY); }
BOOL IsBoolean( SCSIZE nIndex ) const
{ return mnValType && IsBooleanType( mnValType[nIndex]); }
BOOL IsBoolean( SCSIZE nC, SCSIZE nR ) const
{ return mnValType && IsBooleanType( mnValType[ nC * nRowCount + nR ]); }
/// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
BOOL IsNumeric() const
{ return 0 == mnNonValue; }
void MatTrans( ScMatrix& mRes) const;
void MatCopy ( ScMatrix& mRes) const;
// Convert ScInterpreter::CompareMat values (-1,0,1) to boolean values
void CompareEqual();
void CompareNotEqual();
void CompareLess();
void CompareGreater();
void CompareLessEqual();
void CompareGreaterEqual();
double And(); // logical AND of all matrix values, or NAN
double Or(); // logical OR of all matrix values, or NAN
// All other matrix functions MatMult, MInv, ... are in ScInterpreter
// to be numerically safe.
};
typedef ScSimpleIntrusiveReference< class ScMatrix > ScMatrixRef;
typedef ScSimpleIntrusiveReference< const class ScMatrix > ScConstMatrixRef;
// Old values as used up to SO52.
// The overall elements count had to be <= SC_MAX_MAT_DIM * SC_MAX_MAT_DIM.
// Don't use except maybe for file format compatibility.
// In any other case use ScMatrix::GetElementsMax() instead.
#ifdef WIN
#define SC_OLD_MAX_MAT_DIM 64
#else
#define SC_OLD_MAX_MAT_DIM 128
#endif
#define SC_OLD_MAX_MAT_ELEMENTS ((SC_OLD_MAX_MAT_DIM) * (SC_OLD_MAX_MAT_DIM))
#endif