blob: e7dd5da725b93f1acb37492dd9905c39c6273168 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef SC_TOKSTACK_HXX
#define SC_TOKSTACK_HXX
#include <string.h>
#include <tools/debug.hxx>
#include "compiler.hxx"
#include "tokenarray.hxx"
#include <vector>
typedef OpCode DefTokenId;
// in PRODUCT version: ambiguity between OpCode (being sal_uInt16) and UINT16
// Unfortunately a typedef is just a dumb alias and not a real type ...
//typedef sal_uInt16 TokenId;
struct TokenId
{
sal_uInt16 nId;
TokenId() : nId( 0 ) {}
TokenId( sal_uInt16 n ) : nId( n ) {}
TokenId( const TokenId& r ) : nId( r.nId ) {}
inline TokenId& operator =( const TokenId& r ) { nId = r.nId; return *this; }
inline TokenId& operator =( sal_uInt16 n ) { nId = n; return *this; }
inline operator sal_uInt16&() { return nId; }
inline operator const sal_uInt16&() const { return nId; }
inline sal_Bool operator <( sal_uInt16 n ) const { return nId < n; }
inline sal_Bool operator >( sal_uInt16 n ) const { return nId > n; }
inline sal_Bool operator <=( sal_uInt16 n ) const { return nId <= n; }
inline sal_Bool operator >=( sal_uInt16 n ) const { return nId >= n; }
inline sal_Bool operator ==( sal_uInt16 n ) const { return nId == n; }
inline sal_Bool operator !=( sal_uInt16 n ) const { return nId != n; }
};
//------------------------------------------------------------------------
struct ScComplexRefData;
class TokenStack;
class ScToken;
enum E_TYPE
{
T_Id, // Id-Folge
T_Str, // String
T_D, // Double
T_Err, // Error code
T_RefC, // Cell Reference
T_RefA, // Area Reference
T_RN, // Range Name
T_Ext, // irgendwas Unbekanntes mit Funktionsnamen
T_Nlf, // token for natural language formula
T_Matrix, // token for inline arrays
T_ExtName, // token for external names
T_ExtRefC,
T_ExtRefA,
T_Error // fuer Abfrage im Fehlerfall
};
class TokenPool
{
// !ACHTUNG!: externe Id-Basis ist 1, interne 0!
// Ausgabe Id = 0 -> Fehlerfall
private:
String** ppP_Str; // Pool fuer Strings
sal_uInt16 nP_Str; // ...mit Groesse
sal_uInt16 nP_StrAkt; // ...und Schreibmarke
double* pP_Dbl; // Pool fuer Doubles
sal_uInt16 nP_Dbl;
sal_uInt16 nP_DblAkt;
sal_uInt16* pP_Err; // Pool for error codes
sal_uInt16 nP_Err;
sal_uInt16 nP_ErrAkt;
ScSingleRefData** ppP_RefTr; // Pool fuer Referenzen
sal_uInt16 nP_RefTr;
sal_uInt16 nP_RefTrAkt;
sal_uInt16* pP_Id; // Pool fuer Id-Folgen
sal_uInt16 nP_Id;
sal_uInt16 nP_IdAkt;
sal_uInt16 nP_IdLast; // letzter Folgen-Beginn
struct EXTCONT
{
DefTokenId eId;
String aText;
EXTCONT( const DefTokenId e, const String& r ) :
eId( e ), aText( r ){}
};
EXTCONT** ppP_Ext;
sal_uInt16 nP_Ext;
sal_uInt16 nP_ExtAkt;
struct NLFCONT
{
ScSingleRefData aRef;
NLFCONT( const ScSingleRefData& r ) : aRef( r ) {}
};
NLFCONT** ppP_Nlf;
sal_uInt16 nP_Nlf;
sal_uInt16 nP_NlfAkt;
ScMatrix** ppP_Matrix; // Pool fuer Matricies
sal_uInt16 nP_Matrix;
sal_uInt16 nP_MatrixAkt;
/** for storage of external names */
struct ExtName
{
sal_uInt16 mnFileId;
String maName;
};
::std::vector<ExtName> maExtNames;
/** for storage of external cell references */
struct ExtCellRef
{
sal_uInt16 mnFileId;
String maTabName;
ScSingleRefData maRef;
};
::std::vector<ExtCellRef> maExtCellRefs;
/** for storage of external area references */
struct ExtAreaRef
{
sal_uInt16 mnFileId;
String maTabName;
ScComplexRefData maRef;
};
::std::vector<ExtAreaRef> maExtAreaRefs;
sal_uInt16* pElement; // Array mit Indizes fuer Elemente
E_TYPE* pType; // ...mit Typ-Info
sal_uInt16* pSize; // ...mit Laengenangabe (Anz. sal_uInt16)
sal_uInt16 nElement;
sal_uInt16 nElementAkt;
static const sal_uInt16 nScTokenOff;// Offset fuer SC-Token
#ifdef DBG_UTIL
sal_uInt16 nRek; // Rekursionszaehler
#endif
ScTokenArray* pScToken; // Tokenbastler
bool GrowString( void );
bool GrowDouble( void );
/* TODO: in case we had FormulaTokenArray::AddError() */
#if 0
bool GrowError( void );
#endif
bool GrowTripel( sal_uInt16 nByMin = 1 );
bool GrowId( void );
bool GrowElement( void );
bool GrowExt( void );
bool GrowNlf( void );
bool GrowMatrix( void );
bool GetElement( const sal_uInt16 nId );
bool GetElementRek( const sal_uInt16 nId );
public:
TokenPool( void );
~TokenPool();
inline TokenPool& operator <<( const TokenId nId );
inline TokenPool& operator <<( const DefTokenId eId );
inline TokenPool& operator <<( TokenStack& rStack );
void operator >>( TokenId& rId );
inline void operator >>( TokenStack& rStack );
inline const TokenId Store( void );
const TokenId Store( const double& rDouble );
//UNUSED2008-05 const TokenId StoreError( sal_uInt16 nError );
// nur fuer Range-Names
const TokenId Store( const sal_uInt16 nIndex );
inline const TokenId Store( const sal_Int16 nWert );
const TokenId Store( const String& rString );
const TokenId Store( const ScSingleRefData& rTr );
const TokenId Store( const ScComplexRefData& rTr );
const TokenId Store( const DefTokenId eId, const String& rName );
// 4 externals (e.g. AddIns, Makros...)
const TokenId StoreNlf( const ScSingleRefData& rTr );
const TokenId StoreMatrix();
const TokenId StoreExtName( sal_uInt16 nFileId, const String& rName );
const TokenId StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef );
const TokenId StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef );
inline const TokenId LastId( void ) const;
inline const ScTokenArray* operator []( const TokenId nId );
void Reset( void );
inline E_TYPE GetType( const TokenId& nId ) const;
sal_Bool IsSingleOp( const TokenId& nId, const DefTokenId eId ) const;
const String* GetExternal( const TokenId& nId ) const;
ScMatrix* GetMatrix( unsigned int n ) const;
};
class TokenStack
// Stack fuer Token-Ids: Id 0 sollte reserviert bleiben als
// fehlerhafte Id, da z.B. Get() im Fehlerfall 0 liefert
{
private:
TokenId* pStack; // Stack als Array
sal_uInt16 nPos; // Schreibmarke
sal_uInt16 nSize; // Erster Index ausserhalb des Stacks
public:
TokenStack( sal_uInt16 nNewSize = 1024 );
~TokenStack();
inline TokenStack& operator <<( const TokenId nNewId );
inline void operator >>( TokenId &rId );
inline void Reset( void );
inline bool HasMoreTokens() const { return nPos > 0; }
inline const TokenId Get( void );
};
inline const TokenId TokenStack::Get( void )
{
DBG_ASSERT( nPos > 0,
"*TokenStack::Get(): Leer ist leer, ist leer, ist leer, ist..." );
TokenId nRet;
if( nPos == 0 )
nRet = 0;
else
{
nPos--;
nRet = pStack[ nPos ];
}
return nRet;
}
inline TokenStack &TokenStack::operator <<( const TokenId nNewId )
{// Element auf Stack
DBG_ASSERT( nPos < nSize, "*TokenStack::<<(): Stackueberlauf" );
if( nPos < nSize )
{
pStack[ nPos ] = nNewId;
nPos++;
}
return *this;
}
inline void TokenStack::operator >>( TokenId& rId )
{// Element von Stack
DBG_ASSERT( nPos > 0,
"*TokenStack::>>(): Leer ist leer, ist leer, ist leer, ..." );
if( nPos > 0 )
{
nPos--;
rId = pStack[ nPos ];
}
}
inline void TokenStack::Reset( void )
{
nPos = 0;
}
inline TokenPool& TokenPool::operator <<( const TokenId nId )
{
// POST: nId's werden hintereinander im Pool unter einer neuen Id
// abgelegt. Vorgang wird mit >> oder Store() abgeschlossen
// nId -> ( sal_uInt16 ) nId - 1;
DBG_ASSERT( ( sal_uInt16 ) nId < nScTokenOff,
"-TokenPool::operator <<: TokenId im DefToken-Bereich!" );
if( nP_IdAkt >= nP_Id )
if (!GrowId())
return *this;
pP_Id[ nP_IdAkt ] = ( ( sal_uInt16 ) nId ) - 1;
nP_IdAkt++;
return *this;
}
inline TokenPool& TokenPool::operator <<( const DefTokenId eId )
{
DBG_ASSERT( ( sal_uInt32 ) eId + nScTokenOff < 0xFFFF,
"-TokenPool::operator<<: enmum zu gross!" );
if( nP_IdAkt >= nP_Id )
if (!GrowId())
return *this;
pP_Id[ nP_IdAkt ] = ( ( sal_uInt16 ) eId ) + nScTokenOff;
nP_IdAkt++;
return *this;
}
inline TokenPool& TokenPool::operator <<( TokenStack& rStack )
{
if( nP_IdAkt >= nP_Id )
if (!GrowId())
return *this;
pP_Id[ nP_IdAkt ] = ( ( sal_uInt16 ) rStack.Get() ) - 1;
nP_IdAkt++;
return *this;
}
inline void TokenPool::operator >>( TokenStack& rStack )
{
TokenId nId;
*this >> nId;
rStack << nId;
}
inline const TokenId TokenPool::Store( void )
{
TokenId nId;
*this >> nId;
return nId;
}
inline const TokenId TokenPool::Store( const sal_Int16 nWert )
{
return Store( ( double ) nWert );
}
inline const TokenId TokenPool::LastId( void ) const
{
return ( TokenId ) nElementAkt; // stimmt, da Ausgabe mit Offset 1!
}
const inline ScTokenArray* TokenPool::operator []( const TokenId nId )
{
pScToken->Clear();
if( nId )
{//...nur wenn nId > 0!
#ifdef DBG_UTIL
nRek = 0;
#endif
GetElement( ( sal_uInt16 ) nId - 1 );
}
return pScToken;
}
inline E_TYPE TokenPool::GetType( const TokenId& rId ) const
{
E_TYPE nRet;
sal_uInt16 nId = (sal_uInt16) rId - 1;
if( nId < nElementAkt )
nRet = pType[ nId ] ;
else
nRet = T_Error;
return nRet;
}
#endif