summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/inc/tokstack.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/inc/tokstack.hxx')
-rw-r--r--sc/source/filter/inc/tokstack.hxx426
1 files changed, 426 insertions, 0 deletions
diff --git a/sc/source/filter/inc/tokstack.hxx b/sc/source/filter/inc/tokstack.hxx
new file mode 100644
index 000000000..03301d510
--- /dev/null
+++ b/sc/source/filter/inc/tokstack.hxx
@@ -0,0 +1,426 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <tokenarray.hxx>
+#include <refdata.hxx>
+#include <sal/log.hxx>
+
+#include <memory>
+#include <vector>
+
+namespace svl {
+
+class SharedStringPool;
+
+}
+
+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 ) {}
+ TokenId& operator =( const TokenId& r ) { nId = r.nId; return *this; }
+ TokenId& operator =( sal_uInt16 n ) { nId = n; return *this; }
+ operator const sal_uInt16&() const { return nId; }
+};
+
+class TokenStack;
+
+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, // something unknown with function name
+ T_Nlf, // token for natural language formula
+ T_Matrix, // token for inline arrays
+ T_ExtName, // token for external names
+ T_ExtRefC,
+ T_ExtRefA
+};
+
+template<typename T, int InitialCapacity>
+struct TokenPoolPool
+{
+ std::unique_ptr<T[]> ppP_Str;
+ sal_uInt16 m_capacity;
+ sal_uInt16 m_writemark;
+
+ TokenPoolPool() :
+ ppP_Str( new T[InitialCapacity] ),
+ m_capacity(InitialCapacity),
+ m_writemark(0)
+ {
+ }
+ bool Grow(sal_uInt16 nByMin = 1)
+ {
+ sal_uInt16 nP_StrNew = lcl_canGrow(m_capacity, nByMin);
+ if (!nP_StrNew)
+ return false;
+
+ T* ppP_StrNew = new T[ nP_StrNew ];
+
+ for( sal_uInt16 i = 0 ; i < m_capacity ; i++ )
+ ppP_StrNew[ i ] = std::move(ppP_Str[ i ]);
+
+ m_capacity = nP_StrNew;
+
+ ppP_Str.reset( ppP_StrNew );
+ return true;
+ }
+ /** Returns the new number of elements, or 0 if overflow. */
+ static sal_uInt16 lcl_canGrow( sal_uInt16 nOld, sal_uInt16 nByMin )
+ {
+ if (!nOld)
+ return nByMin ? nByMin : 1;
+ if (nOld == SAL_MAX_UINT16)
+ return 0;
+ sal_uInt32 nNew = ::std::max( static_cast<sal_uInt32>(nOld) * 2,
+ static_cast<sal_uInt32>(nOld) + nByMin);
+ if (nNew > SAL_MAX_UINT16)
+ nNew = SAL_MAX_UINT16;
+ if (nNew - nByMin < nOld)
+ nNew = 0;
+ return static_cast<sal_uInt16>(nNew);
+ }
+ T* getIfInRange(sal_uInt16 n) const
+ {
+ return ( n < m_capacity ) ? &ppP_Str[ n ] : nullptr;
+ }
+ T const & operator[](sal_uInt16 n) const
+ {
+ return ppP_Str[ n ];
+ }
+ T & operator[](sal_uInt16 n)
+ {
+ return ppP_Str[ n ];
+ }
+};
+
+class TokenPool
+{
+ // !ATTENTION!: external Id-Basis is 1, internal 0!
+ // return Id = 0 -> Error
+private:
+ svl::SharedStringPool& mrStringPool;
+
+ TokenPoolPool<std::unique_ptr<OUString>, 4>
+ ppP_Str; // Pool for Strings
+
+ TokenPoolPool<double, 8> pP_Dbl; // Pool for Doubles
+
+ TokenPoolPool<sal_uInt16, 8>
+ pP_Err; // Pool for error codes
+
+ TokenPoolPool<std::unique_ptr<ScSingleRefData>, 32>
+ ppP_RefTr; // Pool for References
+ std::unique_ptr<sal_uInt16[]> pP_Id; // Pool for Id-sets
+ sal_uInt16 nP_Id;
+ sal_uInt16 nP_IdCurrent;
+ sal_uInt16 nP_IdLast; // last set-start
+
+ struct EXTCONT
+ {
+ DefTokenId eId;
+ OUString aText;
+ EXTCONT( const DefTokenId e, const OUString& r ) :
+ eId( e ), aText( r ){}
+ };
+ TokenPoolPool<std::unique_ptr<EXTCONT>, 32>
+ ppP_Ext;
+
+ TokenPoolPool<std::unique_ptr<ScSingleRefData>, 16>
+ ppP_Nlf;
+
+ std::unique_ptr<ScMatrix*[]> ppP_Matrix; // Pool for Matrices
+ sal_uInt16 nP_Matrix;
+ sal_uInt16 nP_MatrixCurrent;
+
+ /** for storage of named ranges */
+ struct RangeName
+ {
+ sal_uInt16 mnIndex;
+ sal_Int16 mnSheet;
+ };
+ ::std::vector<RangeName> maRangeNames;
+
+ /** for storage of external names */
+ struct ExtName
+ {
+ sal_uInt16 mnFileId;
+ OUString maName;
+ };
+ ::std::vector<ExtName> maExtNames;
+
+ /** for storage of external cell references */
+ struct ExtCellRef
+ {
+ OUString maTabName;
+ ScSingleRefData maRef;
+ sal_uInt16 mnFileId;
+ };
+ ::std::vector<ExtCellRef> maExtCellRefs;
+
+ /** for storage of external area references */
+ struct ExtAreaRef
+ {
+ OUString maTabName;
+ ScComplexRefData maRef;
+ sal_uInt16 mnFileId;
+ };
+ ::std::vector<ExtAreaRef> maExtAreaRefs;
+
+ std::unique_ptr<sal_uInt16[]> pElement; // Array with Indices for elements
+ std::unique_ptr<E_TYPE[]> pType; // ...with Type-Info
+ std::unique_ptr<sal_uInt16[]> pSize; // ...with size
+ sal_uInt16 nElement;
+ sal_uInt16 nElementCurrent;
+
+ static const sal_uInt16 nScTokenOff;// Offset for SC-Token
+#ifdef DBG_UTIL
+ sal_uInt16 m_nRek; // recursion counter
+#endif
+
+ bool GrowTripel( sal_uInt16 nByMin );
+ bool GrowId();
+ bool GrowElement();
+ bool GrowMatrix();
+ /** @return false means nElementCurrent range
+ below nScTokenOff would overflow or
+ further allocation is not possible, no
+ new ID available other than
+ nElementCurrent+1.
+ */
+ bool CheckElementOrGrow();
+ bool GetElement( const sal_uInt16 nId, ScTokenArray* pScToken );
+ bool GetElementRek( const sal_uInt16 nId, ScTokenArray* pScToken );
+ void ClearMatrix();
+public:
+ TokenPool( svl::SharedStringPool& rSPool );
+ ~TokenPool();
+ inline TokenPool& operator <<( const TokenId& rId );
+ inline TokenPool& operator <<( const DefTokenId eId );
+ inline TokenPool& operator <<( TokenStack& rStack );
+ void operator >>( TokenId& rId );
+ inline void operator >>( TokenStack& rStack );
+ inline TokenId Store();
+ TokenId Store( const double& rDouble );
+
+ // only for Range-Names
+ TokenId Store( const sal_uInt16 nIndex );
+
+ TokenId Store( const OUString& rString );
+ TokenId Store( const ScSingleRefData& rTr );
+ TokenId Store( const ScComplexRefData& rTr );
+
+ TokenId Store( const DefTokenId eId, const OUString& rName );
+ // 4 externals (e.g. AddIns, Macros...)
+ TokenId StoreNlf( const ScSingleRefData& rTr );
+ TokenId StoreMatrix();
+ TokenId StoreName( sal_uInt16 nIndex, sal_Int16 nSheet );
+ TokenId StoreExtName( sal_uInt16 nFileId, const OUString& rName );
+ TokenId StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef );
+ TokenId StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef );
+
+ std::unique_ptr<ScTokenArray> GetTokenArray( const ScDocument& rDoc, const TokenId& rId );
+ void Reset();
+ bool IsSingleOp( const TokenId& rId, const DefTokenId eId ) const;
+ const OUString* GetExternal( const TokenId& rId ) const;
+ ScMatrix* GetMatrix( unsigned int n ) const;
+};
+
+class TokenStack
+ // Stack for Token-Ids: reserve Id=0 for error; e.g. Get() returns 0 on error
+
+{
+ private:
+ std::unique_ptr<TokenId[]> pStack; // Stack as Array
+ sal_uInt16 nPos; // Write-mark
+ static const sal_uInt16 nSize = 1024; // first Index outside of stack
+ public:
+ TokenStack();
+ ~TokenStack();
+ inline TokenStack& operator <<( const TokenId& rNewId );
+ inline void operator >>( TokenId &rId );
+
+ inline void Reset();
+
+ bool HasMoreTokens() const { return nPos > 0; }
+ inline TokenId Get();
+};
+
+inline TokenId TokenStack::Get()
+{
+ TokenId nRet;
+
+ if( nPos == 0 )
+ {
+ SAL_WARN("sc.filter", "*TokenStack::Get(): is empty, is empty, ...");
+ nRet = 0;
+ }
+ else
+ {
+ nPos--;
+ nRet = pStack[ nPos ];
+ }
+
+ return nRet;
+}
+
+inline TokenStack &TokenStack::operator <<( const TokenId& rNewId )
+{// Element on Stack
+ if( nPos < nSize )
+ {
+ pStack[ nPos ] = rNewId;
+ nPos++;
+ }
+ else
+ {
+ SAL_WARN("sc.filter", "*TokenStack::<<(): Stack overflow for " << static_cast<sal_uInt16>(rNewId));
+ }
+
+ return *this;
+}
+
+inline void TokenStack::operator >>( TokenId& rId )
+{// Element of Stack
+ if( nPos > 0 )
+ {
+ nPos--;
+ rId = pStack[ nPos ];
+ }
+ else
+ {
+ SAL_WARN("sc.filter", "*TokenStack::>>(): is empty, is empty, ...");
+ rId = 0;
+ }
+}
+
+inline void TokenStack::Reset()
+{
+ nPos = 0;
+}
+
+inline TokenPool& TokenPool::operator <<( const TokenId& rId )
+{
+ // POST: rId's are stored consecutively in Pool under a new Id;
+ // finalize with >> or Store()
+ // rId -> ( sal_uInt16 ) rId - 1;
+ sal_uInt16 nId = static_cast<sal_uInt16>(rId);
+ if (nId == 0)
+ {
+ // This would result in nId-1==0xffff, create error.
+ SAL_WARN("sc.filter", "-TokenPool::operator <<: TokenId 0");
+ nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
+ }
+ else if (nId >= nScTokenOff)
+ {
+ SAL_WARN("sc.filter", "-TokenPool::operator <<: TokenId in DefToken-Range! " << static_cast<sal_uInt16>(rId));
+
+ // Do not "invent" OpCode values by arbitrarily mapping into the Calc
+ // space. This badly smells like an overflow or binary garbage, so
+ // treat as error.
+ nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
+ }
+
+ if( nP_IdCurrent >= nP_Id && !GrowId())
+ return *this;
+
+ pP_Id[ nP_IdCurrent ] = nId - 1;
+ nP_IdCurrent++;
+
+ return *this;
+}
+
+inline TokenPool& TokenPool::operator <<( const DefTokenId eId )
+{
+ if (static_cast<sal_uInt32>(eId) + nScTokenOff >= 0xFFFF)
+ {
+ SAL_WARN("sc.filter", "-TokenPool::operator<<: enum too large! " << static_cast<sal_uInt32>(eId));
+ }
+
+ if( nP_IdCurrent >= nP_Id && !GrowId())
+ return *this;
+
+ pP_Id[ nP_IdCurrent ] = static_cast<sal_uInt16>(eId) + nScTokenOff;
+ nP_IdCurrent++;
+
+ return *this;
+}
+
+inline TokenPool& TokenPool::operator <<( TokenStack& rStack )
+{
+ if( nP_IdCurrent >= nP_Id && !GrowId())
+ return *this;
+
+ sal_uInt16 nId = static_cast<sal_uInt16>(rStack.Get());
+ if (nId == 0)
+ {
+ // Indicates error, so generate one. Empty stack, overflow, ...
+ nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
+ }
+ pP_Id[ nP_IdCurrent ] = nId - 1;
+ nP_IdCurrent++;
+
+ return *this;
+}
+
+inline void TokenPool::operator >>( TokenStack& rStack )
+{
+ TokenId nId;
+ *this >> nId;
+ rStack << nId;
+}
+
+inline TokenId TokenPool::Store()
+{
+ TokenId nId;
+ *this >> nId;
+ return nId;
+}
+
+inline std::unique_ptr<ScTokenArray> TokenPool::GetTokenArray( const ScDocument& rDoc, const TokenId& rId )
+{
+ std::unique_ptr<ScTokenArray> pScToken( new ScTokenArray(rDoc) );
+
+ if( rId )
+ {//...only if rId > 0!
+#ifdef DBG_UTIL
+ m_nRek = 0;
+#endif
+ GetElement( static_cast<sal_uInt16>(rId) - 1, pScToken.get());
+ }
+
+ return pScToken;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */