LibreOffice Module sc (master)  1
tokstack.hxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #ifndef INCLUDED_SC_SOURCE_FILTER_INC_TOKSTACK_HXX
21 #define INCLUDED_SC_SOURCE_FILTER_INC_TOKSTACK_HXX
22 
23 #include <tokenarray.hxx>
24 #include <refdata.hxx>
25 #include <sal/log.hxx>
26 
27 #include <memory>
28 #include <vector>
29 
30 namespace svl {
31 
32 class SharedStringPool;
33 
34 }
35 
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
41 {
42  sal_uInt16 nId;
43 
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; }
50 };
51 
52 class TokenStack;
53 
54 enum E_TYPE
55 {
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
69 };
70 
71 template<typename T, int InitialCapacity>
73 {
74  std::unique_ptr<T[]> ppP_Str;
75  sal_uInt16 m_capacity;
76  sal_uInt16 m_writemark;
77 
79  ppP_Str( new T[InitialCapacity] ),
80  m_capacity(InitialCapacity),
81  m_writemark(0)
82  {
83  }
84  bool Grow(sal_uInt16 nByMin = 1)
85  {
86  sal_uInt16 nP_StrNew = lcl_canGrow(m_capacity, nByMin);
87  if (!nP_StrNew)
88  return false;
89 
90  T* ppP_StrNew = new T[ nP_StrNew ];
91 
92  for( sal_uInt16 i = 0 ; i < m_capacity ; i++ )
93  ppP_StrNew[ i ] = std::move(ppP_Str[ i ]);
94 
95  m_capacity = nP_StrNew;
96 
97  ppP_Str.reset( ppP_StrNew );
98  return true;
99  }
101  static sal_uInt16 lcl_canGrow( sal_uInt16 nOld, sal_uInt16 nByMin )
102  {
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);
114  }
115  T* getIfInRange(sal_uInt16 n) const
116  {
117  return ( n < m_capacity ) ? &ppP_Str[ n ] : nullptr;
118  }
119  T const & operator[](sal_uInt16 n) const
120  {
121  return ppP_Str[ n ];
122  }
123  T & operator[](sal_uInt16 n)
124  {
125  return ppP_Str[ n ];
126  }
127 };
128 
130 {
131  // !ATTENTION!: external Id-Basis is 1, internal 0!
132  // return Id = 0 -> Error
133 private:
135 
137  ppP_Str; // Pool for Strings
138 
139  TokenPoolPool<double, 8> pP_Dbl; // Pool for Doubles
140 
142  pP_Err; // Pool for error codes
143 
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
150 
151  struct EXTCONT
152  {
154  OUString aText;
155  EXTCONT( const DefTokenId e, const OUString& r ) :
156  eId( e ), aText( r ){}
157  };
160 
163 
164  std::unique_ptr<ScMatrix*[]> ppP_Matrix; // Pool for Matrices
165  sal_uInt16 nP_Matrix;
166  sal_uInt16 nP_MatrixCurrent;
167 
169  struct RangeName
170  {
171  sal_uInt16 mnIndex;
172  sal_Int16 mnSheet;
173  };
174  ::std::vector<RangeName> maRangeNames;
175 
177  struct ExtName
178  {
179  sal_uInt16 mnFileId;
180  OUString maName;
181  };
182  ::std::vector<ExtName> maExtNames;
183 
185  struct ExtCellRef
186  {
187  sal_uInt16 mnFileId;
188  OUString maTabName;
190  };
191  ::std::vector<ExtCellRef> maExtCellRefs;
192 
194  struct ExtAreaRef
195  {
196  sal_uInt16 mnFileId;
197  OUString maTabName;
199  };
200  ::std::vector<ExtAreaRef> maExtAreaRefs;
201 
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;
207 
208  static const sal_uInt16 nScTokenOff;// Offset for SC-Token
209 #ifdef DBG_UTIL
210  sal_uInt16 m_nRek; // recursion counter
211 #endif
212 
213  bool GrowTripel( sal_uInt16 nByMin );
214  bool GrowId();
215  bool GrowElement();
216  bool GrowMatrix();
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 );
237 
238  // only for Range-Names
239  TokenId Store( const sal_uInt16 nIndex );
240 
241  TokenId Store( const OUString& rString );
242  TokenId Store( const ScSingleRefData& rTr );
243  TokenId Store( const ScComplexRefData& rTr );
244 
245  TokenId Store( const DefTokenId eId, const OUString& rName );
246  // 4 externals (e.g. AddIns, Macros...)
247  TokenId StoreNlf( const ScSingleRefData& rTr );
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 );
253 
254  std::unique_ptr<ScTokenArray> GetTokenArray( const ScDocument* pDoc, 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;
259 };
260 
262  // Stack for Token-Ids: reserve Id=0 for error; e.g. Get() returns 0 on error
263 
264 {
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 );
274 
275  inline void Reset();
276 
277  bool HasMoreTokens() const { return nPos > 0; }
278  inline TokenId Get();
279 };
280 
282 {
283  TokenId nRet;
284 
285  if( nPos == 0 )
286  {
287  SAL_WARN("sc.filter", "*TokenStack::Get(): is empty, is empty, ...");
288  nRet = 0;
289  }
290  else
291  {
292  nPos--;
293  nRet = pStack[ nPos ];
294  }
295 
296  return nRet;
297 }
298 
300 {// Element on Stack
301  if( nPos < nSize )
302  {
303  pStack[ nPos ] = rNewId;
304  nPos++;
305  }
306  else
307  {
308  SAL_WARN("sc.filter", "*TokenStack::<<(): Stack overflow for " << static_cast<sal_uInt16>(rNewId));
309  }
310 
311  return *this;
312 }
313 
314 inline void TokenStack::operator >>( TokenId& rId )
315 {// Element of Stack
316  if( nPos > 0 )
317  {
318  nPos--;
319  rId = pStack[ nPos ];
320  }
321  else
322  {
323  SAL_WARN("sc.filter", "*TokenStack::>>(): is empty, is empty, ...");
324  rId = 0;
325  }
326 }
327 
328 inline void TokenStack::Reset()
329 {
330  nPos = 0;
331 }
332 
334 {
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)
340  {
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;
344  }
345  else if (nId >= nScTokenOff)
346  {
347  SAL_WARN("sc.filter", "-TokenPool::operator <<: TokenId in DefToken-Range! " << static_cast<sal_uInt16>(rId));
348 
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;
353  }
354 
355  if( nP_IdCurrent >= nP_Id && !GrowId())
356  return *this;
357 
358  pP_Id[ nP_IdCurrent ] = nId - 1;
359  nP_IdCurrent++;
360 
361  return *this;
362 }
363 
365 {
366  if (static_cast<sal_uInt32>(eId) + nScTokenOff >= 0xFFFF)
367  {
368  SAL_WARN("sc.filter", "-TokenPool::operator<<: enum too large! " << static_cast<sal_uInt32>(eId));
369  }
370 
371  if( nP_IdCurrent >= nP_Id && !GrowId())
372  return *this;
373 
374  pP_Id[ nP_IdCurrent ] = static_cast<sal_uInt16>(eId) + nScTokenOff;
375  nP_IdCurrent++;
376 
377  return *this;
378 }
379 
381 {
382  if( nP_IdCurrent >= nP_Id && !GrowId())
383  return *this;
384 
385  sal_uInt16 nId = static_cast<sal_uInt16>(rStack.Get());
386  if (nId == 0)
387  {
388  // Indicates error, so generate one. Empty stack, overflow, ...
389  nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
390  }
391  pP_Id[ nP_IdCurrent ] = nId - 1;
392  nP_IdCurrent++;
393 
394  return *this;
395 }
396 
397 inline void TokenPool::operator >>( TokenStack& rStack )
398 {
399  TokenId nId;
400  *this >> nId;
401  rStack << nId;
402 }
403 
405 {
406  TokenId nId;
407  *this >> nId;
408  return nId;
409 }
410 
411 inline std::unique_ptr<ScTokenArray> TokenPool::GetTokenArray( const ScDocument *pDoc, const TokenId& rId )
412 {
413  std::unique_ptr<ScTokenArray> pScToken( new ScTokenArray(pDoc) );
414 
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());
421  }
422 
423  return pScToken;
424 }
425 
426 
427 #endif
428 
429 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 nP_Id
Definition: tokstack.hxx:147
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:113
TokenPoolPool< std::unique_ptr< OUString >, 4 > ppP_Str
Definition: tokstack.hxx:137
svl::SharedStringPool & mrStringPool
Definition: tokstack.hxx:134
ScComplexRefData maRef
Definition: tokstack.hxx:198
std::unique_ptr< T[]> ppP_Str
Definition: tokstack.hxx:74
E_TYPE
Definition: tokstack.hxx:54
std::unique_ptr< sal_uInt16[]> pElement
Definition: tokstack.hxx:202
std::unique_ptr< sal_uInt16[]> pP_Id
Definition: tokstack.hxx:146
OpCode DefTokenId
Definition: tokstack.hxx:36
bool GetElementRek(const sal_uInt16 nId, ScTokenArray *pScToken)
Definition: tokstack.cxx:332
TokenId & operator=(const TokenId &r)
Definition: tokstack.hxx:47
bool GrowTripel(sal_uInt16 nByMin)
Single reference (one address) into the sheet.
Definition: refdata.hxx:30
TokenPoolPool< std::unique_ptr< EXTCONT >, 32 > ppP_Ext
Definition: tokstack.hxx:159
sal_uInt16 m_capacity
Definition: tokstack.hxx:75
std::unique_ptr< ScMatrix *[]> ppP_Matrix
Definition: tokstack.hxx:164
sal_uInt16 nP_MatrixCurrent
Definition: tokstack.hxx:166
TokenId StoreExtName(sal_uInt16 nFileId, const OUString &rName)
Definition: tokstack.cxx:619
TokenPoolPool< std::unique_ptr< ScSingleRefData >, 16 > ppP_Nlf
Definition: tokstack.hxx:162
sal_Int16 nId
std::unique_ptr< E_TYPE[]> pType
Definition: tokstack.hxx:203
sal_uInt16 m_writemark
Definition: tokstack.hxx:76
for storage of external area references
Definition: tokstack.hxx:194
const OUString * GetExternal(const TokenId &rId) const
Definition: tokstack.cxx:713
bool GrowId()
Definition: tokstack.cxx:88
bool GetElement(const sal_uInt16 nId, ScTokenArray *pScToken)
Definition: tokstack.cxx:170
TokenPool(svl::SharedStringPool &rSPool)
Definition: tokstack.cxx:46
TokenId Store()
Definition: tokstack.hxx:404
#define SAL_MAX_UINT16
TokenId Get()
Definition: tokstack.hxx:281
OpCode
void ClearMatrix()
Definition: tokstack.cxx:740
bool HasMoreTokens() const
Definition: tokstack.hxx:277
TokenId StoreNlf(const ScSingleRefData &rTr)
Definition: tokstack.cxx:554
sal_uInt16 nElementCurrent
Definition: tokstack.hxx:206
::std::vector< RangeName > maRangeNames
Definition: tokstack.hxx:174
sal_uInt16 nP_IdCurrent
Definition: tokstack.hxx:148
void Reset()
Definition: tokstack.hxx:328
for storage of named ranges
Definition: tokstack.hxx:169
DefTokenId eId
Definition: tokstack.hxx:153
T & operator[](sal_uInt16 n)
Definition: tokstack.hxx:123
int i
static const sal_uInt16 nSize
Definition: tokstack.hxx:268
TokenId(const TokenId &r)
Definition: tokstack.hxx:46
static const sal_uInt16 nScTokenOff
Definition: tokstack.hxx:208
sal_uInt16 nP_IdLast
Definition: tokstack.hxx:149
std::unique_ptr< TokenId[]> pStack
Definition: tokstack.hxx:266
Definition: tokstack.hxx:58
EXTCONT(const DefTokenId e, const OUString &r)
Definition: tokstack.hxx:155
bool IsSingleOp(const TokenId &rId, const DefTokenId eId) const
Definition: tokstack.cxx:687
sal_uInt16 mnIndex
Definition: tokstack.hxx:171
static sal_uInt16 lcl_canGrow(sal_uInt16 nOld, sal_uInt16 nByMin)
Returns the new number of elements, or 0 if overflow.
Definition: tokstack.hxx:101
void operator>>(TokenId &rId)
Definition: tokstack.hxx:314
ocErrNull
ScMatrix * GetMatrix(unsigned int n) const
Definition: tokstack.cxx:731
TokenId StoreMatrix()
Definition: tokstack.cxx:579
bool GrowElement()
Definition: tokstack.cxx:122
TokenId StoreName(sal_uInt16 nIndex, sal_Int16 nSheet)
Definition: tokstack.cxx:601
T * getIfInRange(sal_uInt16 n) const
Definition: tokstack.hxx:115
for storage of external cell references
Definition: tokstack.hxx:185
sal_uInt16 nElement
Definition: tokstack.hxx:205
::std::vector< ExtCellRef > maExtCellRefs
Definition: tokstack.hxx:191
bool GrowMatrix()
Definition: tokstack.cxx:151
sal_uInt16 m_nRek
Definition: tokstack.hxx:210
TokenId()
Definition: tokstack.hxx:44
TokenId(sal_uInt16 n)
Definition: tokstack.hxx:45
TokenPoolPool< sal_uInt16, 8 > pP_Err
Definition: tokstack.hxx:142
bool Grow(sal_uInt16 nByMin=1)
Definition: tokstack.hxx:84
::std::vector< ExtAreaRef > maExtAreaRefs
Definition: tokstack.hxx:200
T const & operator[](sal_uInt16 n) const
Definition: tokstack.hxx:119
std::unique_ptr< sal_uInt16[]> pSize
Definition: tokstack.hxx:204
These need to be in global namespace just like their respective types are.
TokenId StoreExtRef(sal_uInt16 nFileId, const OUString &rTabName, const ScSingleRefData &rRef)
Definition: tokstack.cxx:637
Complex reference (a range) into the sheet.
Definition: refdata.hxx:123
::std::vector< ExtName > maExtNames
Definition: tokstack.hxx:182
sal_uInt16 nP_Matrix
Definition: tokstack.hxx:165
for storage of external names
Definition: tokstack.hxx:177
std::unique_ptr< ScTokenArray > GetTokenArray(const ScDocument *pDoc, const TokenId &rId)
Definition: tokstack.hxx:411
#define SAL_WARN(area, stream)
bool CheckElementOrGrow()
Definition: tokstack.cxx:107
sal_uInt16 mnFileId
Definition: tokstack.hxx:179
void Reset()
Definition: tokstack.cxx:675
sal_uInt16 nId
Definition: tokstack.hxx:42
sal_uInt16 nPos
Definition: tokstack.hxx:267
TokenStack & operator<<(const TokenId &rNewId)
Definition: tokstack.hxx:299
~TokenPool()
Definition: tokstack.cxx:67
TokenPoolPool< std::unique_ptr< ScSingleRefData >, 32 > ppP_RefTr
Definition: tokstack.hxx:145
void operator>>(TokenId &rId)
Definition: tokstack.cxx:403
TokenPool & operator<<(const TokenId &rId)
Definition: tokstack.hxx:333
ScSingleRefData maRef
Definition: tokstack.hxx:189
TokenPoolPool< double, 8 > pP_Dbl
Definition: tokstack.hxx:139