Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / inc / tokstack.hxx
blob82a6a95522198bd3ae6d9df967c682837cafb46b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SC_SOURCE_FILTER_INC_TOKSTACK_HXX
21 #define INCLUDED_SC_SOURCE_FILTER_INC_TOKSTACK_HXX
23 #include <tokenarray.hxx>
24 #include <refdata.hxx>
25 #include <sal/log.hxx>
27 #include <memory>
28 #include <vector>
30 namespace svl {
32 class SharedStringPool;
36 typedef OpCode DefTokenId;
37 // in PRODUCT version: ambiguity between OpCode (being sal_uInt16) and UINT16
38 // Unfortunately a typedef is just a dumb alias and not a real type ...
39 //typedef sal_uInt16 TokenId;
40 struct TokenId
42 sal_uInt16 nId;
44 TokenId() : nId( 0 ) {}
45 TokenId( sal_uInt16 n ) : nId( n ) {}
46 TokenId( const TokenId& r ) : nId( r.nId ) {}
47 TokenId& operator =( const TokenId& r ) { nId = r.nId; return *this; }
48 TokenId& operator =( sal_uInt16 n ) { nId = n; return *this; }
49 operator const sal_uInt16&() const { return nId; }
52 class TokenStack;
54 enum E_TYPE
56 T_Id, // Id-Folge
57 T_Str, // String
58 T_D, // Double
59 T_Err, // Error code
60 T_RefC, // Cell Reference
61 T_RefA, // Area Reference
62 T_RN, // Range Name
63 T_Ext, // something unknown with function name
64 T_Nlf, // token for natural language formula
65 T_Matrix, // token for inline arrays
66 T_ExtName, // token for external names
67 T_ExtRefC,
68 T_ExtRefA
71 template<typename T, int InitialCapacity>
72 struct TokenPoolPool
74 std::unique_ptr<T[]> ppP_Str;
75 sal_uInt16 m_capacity;
76 sal_uInt16 m_writemark;
78 TokenPoolPool() :
79 ppP_Str( new T[InitialCapacity] ),
80 m_capacity(InitialCapacity),
81 m_writemark(0)
84 bool Grow(sal_uInt16 nByMin = 1)
86 sal_uInt16 nP_StrNew = lcl_canGrow(m_capacity, nByMin);
87 if (!nP_StrNew)
88 return false;
90 T* ppP_StrNew = new T[ nP_StrNew ];
92 for( sal_uInt16 i = 0 ; i < m_capacity ; i++ )
93 ppP_StrNew[ i ] = std::move(ppP_Str[ i ]);
95 m_capacity = nP_StrNew;
97 ppP_Str.reset( ppP_StrNew );
98 return true;
100 /** Returns the new number of elements, or 0 if overflow. */
101 static sal_uInt16 lcl_canGrow( sal_uInt16 nOld, sal_uInt16 nByMin )
103 if (!nOld)
104 return nByMin ? nByMin : 1;
105 if (nOld == SAL_MAX_UINT16)
106 return 0;
107 sal_uInt32 nNew = ::std::max( static_cast<sal_uInt32>(nOld) * 2,
108 static_cast<sal_uInt32>(nOld) + nByMin);
109 if (nNew > SAL_MAX_UINT16)
110 nNew = SAL_MAX_UINT16;
111 if (nNew - nByMin < nOld)
112 nNew = 0;
113 return static_cast<sal_uInt16>(nNew);
115 T* getIfInRange(sal_uInt16 n) const
117 return ( n < m_capacity ) ? &ppP_Str[ n ] : nullptr;
119 T const & operator[](sal_uInt16 n) const
121 return ppP_Str[ n ];
123 T & operator[](sal_uInt16 n)
125 return ppP_Str[ n ];
129 class TokenPool
131 // !ATTENTION!: external Id-Basis is 1, internal 0!
132 // return Id = 0 -> Error
133 private:
134 svl::SharedStringPool& mrStringPool;
136 TokenPoolPool<std::unique_ptr<OUString>, 4>
137 ppP_Str; // Pool for Strings
139 TokenPoolPool<double, 8> pP_Dbl; // Pool for Doubles
141 TokenPoolPool<sal_uInt16, 8>
142 pP_Err; // Pool for error codes
144 TokenPoolPool<std::unique_ptr<ScSingleRefData>, 32>
145 ppP_RefTr; // Pool for References
146 std::unique_ptr<sal_uInt16[]> pP_Id; // Pool for Id-sets
147 sal_uInt16 nP_Id;
148 sal_uInt16 nP_IdCurrent;
149 sal_uInt16 nP_IdLast; // last set-start
151 struct EXTCONT
153 DefTokenId eId;
154 OUString aText;
155 EXTCONT( const DefTokenId e, const OUString& r ) :
156 eId( e ), aText( r ){}
158 TokenPoolPool<std::unique_ptr<EXTCONT>, 32>
159 ppP_Ext;
161 TokenPoolPool<std::unique_ptr<ScSingleRefData>, 16>
162 ppP_Nlf;
164 std::unique_ptr<ScMatrix*[]> ppP_Matrix; // Pool for Matrices
165 sal_uInt16 nP_Matrix;
166 sal_uInt16 nP_MatrixCurrent;
168 /** for storage of named ranges */
169 struct RangeName
171 sal_uInt16 mnIndex;
172 sal_Int16 mnSheet;
174 ::std::vector<RangeName> maRangeNames;
176 /** for storage of external names */
177 struct ExtName
179 sal_uInt16 mnFileId;
180 OUString maName;
182 ::std::vector<ExtName> maExtNames;
184 /** for storage of external cell references */
185 struct ExtCellRef
187 sal_uInt16 mnFileId;
188 OUString maTabName;
189 ScSingleRefData maRef;
191 ::std::vector<ExtCellRef> maExtCellRefs;
193 /** for storage of external area references */
194 struct ExtAreaRef
196 sal_uInt16 mnFileId;
197 OUString maTabName;
198 ScComplexRefData maRef;
200 ::std::vector<ExtAreaRef> maExtAreaRefs;
202 std::unique_ptr<sal_uInt16[]> pElement; // Array with Indices for elements
203 std::unique_ptr<E_TYPE[]> pType; // ...with Type-Info
204 std::unique_ptr<sal_uInt16[]> pSize; // ...with size
205 sal_uInt16 nElement;
206 sal_uInt16 nElementCurrent;
208 static const sal_uInt16 nScTokenOff;// Offset for SC-Token
209 #ifdef DBG_UTIL
210 sal_uInt16 m_nRek; // recursion counter
211 #endif
213 bool GrowTripel( sal_uInt16 nByMin );
214 bool GrowId();
215 bool GrowElement();
216 bool GrowMatrix();
217 /** @return false means nElementCurrent range
218 below nScTokenOff would overflow or
219 further allocation is not possible, no
220 new ID available other than
221 nElementCurrent+1.
223 bool CheckElementOrGrow();
224 bool GetElement( const sal_uInt16 nId, ScTokenArray* pScToken );
225 bool GetElementRek( const sal_uInt16 nId, ScTokenArray* pScToken );
226 void ClearMatrix();
227 public:
228 TokenPool( svl::SharedStringPool& rSPool );
229 ~TokenPool();
230 inline TokenPool& operator <<( const TokenId& rId );
231 inline TokenPool& operator <<( const DefTokenId eId );
232 inline TokenPool& operator <<( TokenStack& rStack );
233 void operator >>( TokenId& rId );
234 inline void operator >>( TokenStack& rStack );
235 inline TokenId Store();
236 TokenId Store( const double& rDouble );
238 // only for Range-Names
239 TokenId Store( const sal_uInt16 nIndex );
241 TokenId Store( const OUString& rString );
242 TokenId Store( const ScSingleRefData& rTr );
243 TokenId Store( const ScComplexRefData& rTr );
245 TokenId Store( const DefTokenId eId, const OUString& rName );
246 // 4 externals (e.g. AddIns, Macros...)
247 TokenId StoreNlf( const ScSingleRefData& rTr );
248 TokenId StoreMatrix();
249 TokenId StoreName( sal_uInt16 nIndex, sal_Int16 nSheet );
250 TokenId StoreExtName( sal_uInt16 nFileId, const OUString& rName );
251 TokenId StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef );
252 TokenId StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef );
254 std::unique_ptr<ScTokenArray> GetTokenArray( const TokenId& rId );
255 void Reset();
256 bool IsSingleOp( const TokenId& rId, const DefTokenId eId ) const;
257 const OUString* GetExternal( const TokenId& rId ) const;
258 ScMatrix* GetMatrix( unsigned int n ) const;
261 class TokenStack
262 // Stack for Token-Ids: reserve Id=0 for error; e.g. Get() returns 0 on error
265 private:
266 std::unique_ptr<TokenId[]> pStack; // Stack as Array
267 sal_uInt16 nPos; // Write-mark
268 static const sal_uInt16 nSize = 1024; // first Index outside of stack
269 public:
270 TokenStack();
271 ~TokenStack();
272 inline TokenStack& operator <<( const TokenId& rNewId );
273 inline void operator >>( TokenId &rId );
275 inline void Reset();
277 bool HasMoreTokens() const { return nPos > 0; }
278 inline TokenId Get();
281 inline TokenId TokenStack::Get()
283 TokenId nRet;
285 if( nPos == 0 )
287 SAL_WARN("sc.filter", "*TokenStack::Get(): is empty, is empty, ...");
288 nRet = 0;
290 else
292 nPos--;
293 nRet = pStack[ nPos ];
296 return nRet;
299 inline TokenStack &TokenStack::operator <<( const TokenId& rNewId )
300 {// Element on Stack
301 if( nPos < nSize )
303 pStack[ nPos ] = rNewId;
304 nPos++;
306 else
308 SAL_WARN("sc.filter", "*TokenStack::<<(): Stack overflow for " << static_cast<sal_uInt16>(rNewId));
311 return *this;
314 inline void TokenStack::operator >>( TokenId& rId )
315 {// Element of Stack
316 if( nPos > 0 )
318 nPos--;
319 rId = pStack[ nPos ];
321 else
323 SAL_WARN("sc.filter", "*TokenStack::>>(): is empty, is empty, ...");
324 rId = 0;
328 inline void TokenStack::Reset()
330 nPos = 0;
333 inline TokenPool& TokenPool::operator <<( const TokenId& rId )
335 // POST: rId's are stored consecutively in Pool under a new Id;
336 // finalize with >> or Store()
337 // rId -> ( sal_uInt16 ) rId - 1;
338 sal_uInt16 nId = static_cast<sal_uInt16>(rId);
339 if (nId == 0)
341 // This would result in nId-1==0xffff, create error.
342 SAL_WARN("sc.filter", "-TokenPool::operator <<: TokenId 0");
343 nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
345 else if (nId >= nScTokenOff)
347 SAL_WARN("sc.filter", "-TokenPool::operator <<: TokenId in DefToken-Range! " << static_cast<sal_uInt16>(rId));
349 // Do not "invent" OpCode values by arbitrarily mapping into the Calc
350 // space. This badly smells like an overflow or binary garbage, so
351 // treat as error.
352 nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
355 if( nP_IdCurrent >= nP_Id && !GrowId())
356 return *this;
358 pP_Id[ nP_IdCurrent ] = nId - 1;
359 nP_IdCurrent++;
361 return *this;
364 inline TokenPool& TokenPool::operator <<( const DefTokenId eId )
366 if (static_cast<sal_uInt32>(eId) + nScTokenOff >= 0xFFFF)
368 SAL_WARN("sc.filter", "-TokenPool::operator<<: enum too large! " << static_cast<sal_uInt32>(eId));
371 if( nP_IdCurrent >= nP_Id && !GrowId())
372 return *this;
374 pP_Id[ nP_IdCurrent ] = static_cast<sal_uInt16>(eId) + nScTokenOff;
375 nP_IdCurrent++;
377 return *this;
380 inline TokenPool& TokenPool::operator <<( TokenStack& rStack )
382 if( nP_IdCurrent >= nP_Id && !GrowId())
383 return *this;
385 sal_uInt16 nId = static_cast<sal_uInt16>(rStack.Get());
386 if (nId == 0)
388 // Indicates error, so generate one. Empty stack, overflow, ...
389 nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
391 pP_Id[ nP_IdCurrent ] = nId - 1;
392 nP_IdCurrent++;
394 return *this;
397 inline void TokenPool::operator >>( TokenStack& rStack )
399 TokenId nId;
400 *this >> nId;
401 rStack << nId;
404 inline TokenId TokenPool::Store()
406 TokenId nId;
407 *this >> nId;
408 return nId;
411 inline std::unique_ptr<ScTokenArray> TokenPool::GetTokenArray( const TokenId& rId )
413 std::unique_ptr<ScTokenArray> pScToken( new ScTokenArray );
415 if( rId )
416 {//...only if rId > 0!
417 #ifdef DBG_UTIL
418 m_nRek = 0;
419 #endif
420 GetElement( static_cast<sal_uInt16>(rId) - 1, pScToken.get());
423 return pScToken;
427 #endif
429 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */