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 #pragma once
21 
22 #include <tokenarray.hxx>
23 #include <refdata.hxx>
24 #include <sal/log.hxx>
25 
26 #include <memory>
27 #include <vector>
28 
29 namespace svl {
30 
31 class SharedStringPool;
32 
33 }
34 
36 // in PRODUCT version: ambiguity between OpCode (being sal_uInt16) and UINT16
37 // Unfortunately a typedef is just a dumb alias and not a real type ...
38 //typedef sal_uInt16 TokenId;
39 struct TokenId
40 {
41  sal_uInt16 nId;
42 
43  TokenId() : nId( 0 ) {}
44  TokenId( sal_uInt16 n ) : nId( n ) {}
45  TokenId( const TokenId& r ) : nId( r.nId ) {}
46  TokenId& operator =( const TokenId& r ) { nId = r.nId; return *this; }
47  TokenId& operator =( sal_uInt16 n ) { nId = n; return *this; }
48  operator const sal_uInt16&() const { return nId; }
49 };
50 
51 class TokenStack;
52 
53 enum E_TYPE
54 {
55  T_Id, // Id-Folge
56  T_Str, // String
57  T_D, // Double
58  T_Err, // Error code
59  T_RefC, // Cell Reference
60  T_RefA, // Area Reference
61  T_RN, // Range Name
62  T_Ext, // something unknown with function name
63  T_Nlf, // token for natural language formula
64  T_Matrix, // token for inline arrays
65  T_ExtName, // token for external names
68 };
69 
70 template<typename T, int InitialCapacity>
72 {
73  std::unique_ptr<T[]> ppP_Str;
74  sal_uInt16 m_capacity;
75  sal_uInt16 m_writemark;
76 
78  ppP_Str( new T[InitialCapacity] ),
79  m_capacity(InitialCapacity),
80  m_writemark(0)
81  {
82  }
83  bool Grow(sal_uInt16 nByMin = 1)
84  {
85  sal_uInt16 nP_StrNew = lcl_canGrow(m_capacity, nByMin);
86  if (!nP_StrNew)
87  return false;
88 
89  T* ppP_StrNew = new T[ nP_StrNew ];
90 
91  for( sal_uInt16 i = 0 ; i < m_capacity ; i++ )
92  ppP_StrNew[ i ] = std::move(ppP_Str[ i ]);
93 
94  m_capacity = nP_StrNew;
95 
96  ppP_Str.reset( ppP_StrNew );
97  return true;
98  }
100  static sal_uInt16 lcl_canGrow( sal_uInt16 nOld, sal_uInt16 nByMin )
101  {
102  if (!nOld)
103  return nByMin ? nByMin : 1;
104  if (nOld == SAL_MAX_UINT16)
105  return 0;
106  sal_uInt32 nNew = ::std::max( static_cast<sal_uInt32>(nOld) * 2,
107  static_cast<sal_uInt32>(nOld) + nByMin);
108  if (nNew > SAL_MAX_UINT16)
109  nNew = SAL_MAX_UINT16;
110  if (nNew - nByMin < nOld)
111  nNew = 0;
112  return static_cast<sal_uInt16>(nNew);
113  }
114  T* getIfInRange(sal_uInt16 n) const
115  {
116  return ( n < m_capacity ) ? &ppP_Str[ n ] : nullptr;
117  }
118  T const & operator[](sal_uInt16 n) const
119  {
120  return ppP_Str[ n ];
121  }
122  T & operator[](sal_uInt16 n)
123  {
124  return ppP_Str[ n ];
125  }
126 };
127 
129 {
130  // !ATTENTION!: external Id-Basis is 1, internal 0!
131  // return Id = 0 -> Error
132 private:
134 
136  ppP_Str; // Pool for Strings
137 
138  TokenPoolPool<double, 8> pP_Dbl; // Pool for Doubles
139 
141  pP_Err; // Pool for error codes
142 
144  ppP_RefTr; // Pool for References
145  std::unique_ptr<sal_uInt16[]> pP_Id; // Pool for Id-sets
146  sal_uInt16 nP_Id;
147  sal_uInt16 nP_IdCurrent;
148  sal_uInt16 nP_IdLast; // last set-start
149 
150  struct EXTCONT
151  {
153  OUString aText;
154  EXTCONT( const DefTokenId e, const OUString& r ) :
155  eId( e ), aText( r ){}
156  };
159 
162 
163  std::unique_ptr<ScMatrix*[]> ppP_Matrix; // Pool for Matrices
164  sal_uInt16 nP_Matrix;
165  sal_uInt16 nP_MatrixCurrent;
166 
168  struct RangeName
169  {
170  sal_uInt16 mnIndex;
171  sal_Int16 mnSheet;
172  };
173  ::std::vector<RangeName> maRangeNames;
174 
176  struct ExtName
177  {
178  sal_uInt16 mnFileId;
179  OUString maName;
180  };
181  ::std::vector<ExtName> maExtNames;
182 
184  struct ExtCellRef
185  {
186  sal_uInt16 mnFileId;
187  OUString maTabName;
189  };
190  ::std::vector<ExtCellRef> maExtCellRefs;
191 
193  struct ExtAreaRef
194  {
195  sal_uInt16 mnFileId;
196  OUString maTabName;
198  };
199  ::std::vector<ExtAreaRef> maExtAreaRefs;
200 
201  std::unique_ptr<sal_uInt16[]> pElement; // Array with Indices for elements
202  std::unique_ptr<E_TYPE[]> pType; // ...with Type-Info
203  std::unique_ptr<sal_uInt16[]> pSize; // ...with size
204  sal_uInt16 nElement;
205  sal_uInt16 nElementCurrent;
206 
207  static const sal_uInt16 nScTokenOff;// Offset for SC-Token
208 #ifdef DBG_UTIL
209  sal_uInt16 m_nRek; // recursion counter
210 #endif
211 
212  bool GrowTripel( sal_uInt16 nByMin );
213  bool GrowId();
214  bool GrowElement();
215  bool GrowMatrix();
222  bool CheckElementOrGrow();
223  bool GetElement( const sal_uInt16 nId, ScTokenArray* pScToken );
224  bool GetElementRek( const sal_uInt16 nId, ScTokenArray* pScToken );
225  void ClearMatrix();
226 public:
227  TokenPool( svl::SharedStringPool& rSPool );
228  ~TokenPool();
229  inline TokenPool& operator <<( const TokenId& rId );
230  inline TokenPool& operator <<( const DefTokenId eId );
231  inline TokenPool& operator <<( TokenStack& rStack );
232  void operator >>( TokenId& rId );
233  inline void operator >>( TokenStack& rStack );
234  inline TokenId Store();
235  TokenId Store( const double& rDouble );
236 
237  // only for Range-Names
238  TokenId Store( const sal_uInt16 nIndex );
239 
240  TokenId Store( const OUString& rString );
241  TokenId Store( const ScSingleRefData& rTr );
242  TokenId Store( const ScComplexRefData& rTr );
243 
244  TokenId Store( const DefTokenId eId, const OUString& rName );
245  // 4 externals (e.g. AddIns, Macros...)
246  TokenId StoreNlf( const ScSingleRefData& rTr );
248  TokenId StoreName( sal_uInt16 nIndex, sal_Int16 nSheet );
249  TokenId StoreExtName( sal_uInt16 nFileId, const OUString& rName );
250  TokenId StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef );
251  TokenId StoreExtRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef );
252 
253  std::unique_ptr<ScTokenArray> GetTokenArray( const ScDocument& rDoc, const TokenId& rId );
254  void Reset();
255  bool IsSingleOp( const TokenId& rId, const DefTokenId eId ) const;
256  const OUString* GetExternal( const TokenId& rId ) const;
257  ScMatrix* GetMatrix( unsigned int n ) const;
258 };
259 
261  // Stack for Token-Ids: reserve Id=0 for error; e.g. Get() returns 0 on error
262 
263 {
264  private:
265  std::unique_ptr<TokenId[]> pStack; // Stack as Array
266  sal_uInt16 nPos; // Write-mark
267  static const sal_uInt16 nSize = 1024; // first Index outside of stack
268  public:
269  TokenStack();
270  ~TokenStack();
271  inline TokenStack& operator <<( const TokenId& rNewId );
272  inline void operator >>( TokenId &rId );
273 
274  inline void Reset();
275 
276  bool HasMoreTokens() const { return nPos > 0; }
277  inline TokenId Get();
278 };
279 
281 {
282  TokenId nRet;
283 
284  if( nPos == 0 )
285  {
286  SAL_WARN("sc.filter", "*TokenStack::Get(): is empty, is empty, ...");
287  nRet = 0;
288  }
289  else
290  {
291  nPos--;
292  nRet = pStack[ nPos ];
293  }
294 
295  return nRet;
296 }
297 
299 {// Element on Stack
300  if( nPos < nSize )
301  {
302  pStack[ nPos ] = rNewId;
303  nPos++;
304  }
305  else
306  {
307  SAL_WARN("sc.filter", "*TokenStack::<<(): Stack overflow for " << static_cast<sal_uInt16>(rNewId));
308  }
309 
310  return *this;
311 }
312 
313 inline void TokenStack::operator >>( TokenId& rId )
314 {// Element of Stack
315  if( nPos > 0 )
316  {
317  nPos--;
318  rId = pStack[ nPos ];
319  }
320  else
321  {
322  SAL_WARN("sc.filter", "*TokenStack::>>(): is empty, is empty, ...");
323  rId = 0;
324  }
325 }
326 
327 inline void TokenStack::Reset()
328 {
329  nPos = 0;
330 }
331 
333 {
334  // POST: rId's are stored consecutively in Pool under a new Id;
335  // finalize with >> or Store()
336  // rId -> ( sal_uInt16 ) rId - 1;
337  sal_uInt16 nId = static_cast<sal_uInt16>(rId);
338  if (nId == 0)
339  {
340  // This would result in nId-1==0xffff, create error.
341  SAL_WARN("sc.filter", "-TokenPool::operator <<: TokenId 0");
342  nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
343  }
344  else if (nId >= nScTokenOff)
345  {
346  SAL_WARN("sc.filter", "-TokenPool::operator <<: TokenId in DefToken-Range! " << static_cast<sal_uInt16>(rId));
347 
348  // Do not "invent" OpCode values by arbitrarily mapping into the Calc
349  // space. This badly smells like an overflow or binary garbage, so
350  // treat as error.
351  nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
352  }
353 
354  if( nP_IdCurrent >= nP_Id && !GrowId())
355  return *this;
356 
357  pP_Id[ nP_IdCurrent ] = nId - 1;
358  nP_IdCurrent++;
359 
360  return *this;
361 }
362 
364 {
365  if (static_cast<sal_uInt32>(eId) + nScTokenOff >= 0xFFFF)
366  {
367  SAL_WARN("sc.filter", "-TokenPool::operator<<: enum too large! " << static_cast<sal_uInt32>(eId));
368  }
369 
370  if( nP_IdCurrent >= nP_Id && !GrowId())
371  return *this;
372 
373  pP_Id[ nP_IdCurrent ] = static_cast<sal_uInt16>(eId) + nScTokenOff;
374  nP_IdCurrent++;
375 
376  return *this;
377 }
378 
380 {
381  if( nP_IdCurrent >= nP_Id && !GrowId())
382  return *this;
383 
384  sal_uInt16 nId = static_cast<sal_uInt16>(rStack.Get());
385  if (nId == 0)
386  {
387  // Indicates error, so generate one. Empty stack, overflow, ...
388  nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
389  }
390  pP_Id[ nP_IdCurrent ] = nId - 1;
391  nP_IdCurrent++;
392 
393  return *this;
394 }
395 
396 inline void TokenPool::operator >>( TokenStack& rStack )
397 {
398  TokenId nId;
399  *this >> nId;
400  rStack << nId;
401 }
402 
404 {
405  TokenId nId;
406  *this >> nId;
407  return nId;
408 }
409 
410 inline std::unique_ptr<ScTokenArray> TokenPool::GetTokenArray( const ScDocument& rDoc, const TokenId& rId )
411 {
412  std::unique_ptr<ScTokenArray> pScToken( new ScTokenArray(rDoc) );
413 
414  if( rId )
415  {//...only if rId > 0!
416 #ifdef DBG_UTIL
417  m_nRek = 0;
418 #endif
419  GetElement( static_cast<sal_uInt16>(rId) - 1, pScToken.get());
420  }
421 
422  return pScToken;
423 }
424 
425 
426 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 nP_Id
Definition: tokstack.hxx:146
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:112
TokenPoolPool< std::unique_ptr< OUString >, 4 > ppP_Str
Definition: tokstack.hxx:136
svl::SharedStringPool & mrStringPool
Definition: tokstack.hxx:133
ScComplexRefData maRef
Definition: tokstack.hxx:197
std::unique_ptr< T[]> ppP_Str
Definition: tokstack.hxx:73
E_TYPE
Definition: tokstack.hxx:53
std::unique_ptr< sal_uInt16[]> pElement
Definition: tokstack.hxx:201
std::unique_ptr< sal_uInt16[]> pP_Id
Definition: tokstack.hxx:145
OpCode DefTokenId
Definition: tokstack.hxx:35
bool GetElementRek(const sal_uInt16 nId, ScTokenArray *pScToken)
Definition: tokstack.cxx:332
TokenId & operator=(const TokenId &r)
Definition: tokstack.hxx:46
bool GrowTripel(sal_uInt16 nByMin)
Single reference (one address) into the sheet.
Definition: refdata.hxx:29
TokenPoolPool< std::unique_ptr< EXTCONT >, 32 > ppP_Ext
Definition: tokstack.hxx:158
sal_uInt16 m_capacity
Definition: tokstack.hxx:74
std::unique_ptr< ScMatrix *[]> ppP_Matrix
Definition: tokstack.hxx:163
sal_uInt16 nP_MatrixCurrent
Definition: tokstack.hxx:165
TokenId StoreExtName(sal_uInt16 nFileId, const OUString &rName)
Definition: tokstack.cxx:619
TokenPoolPool< std::unique_ptr< ScSingleRefData >, 16 > ppP_Nlf
Definition: tokstack.hxx:161
sal_Int16 nId
std::unique_ptr< E_TYPE[]> pType
Definition: tokstack.hxx:202
sal_uInt16 m_writemark
Definition: tokstack.hxx:75
for storage of external area references
Definition: tokstack.hxx:193
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:403
#define SAL_MAX_UINT16
TokenId Get()
Definition: tokstack.hxx:280
OpCode
void ClearMatrix()
Definition: tokstack.cxx:740
bool HasMoreTokens() const
Definition: tokstack.hxx:276
TokenId StoreNlf(const ScSingleRefData &rTr)
Definition: tokstack.cxx:554
sal_uInt16 nElementCurrent
Definition: tokstack.hxx:205
::std::vector< RangeName > maRangeNames
Definition: tokstack.hxx:173
sal_uInt16 nP_IdCurrent
Definition: tokstack.hxx:147
void Reset()
Definition: tokstack.hxx:327
for storage of named ranges
Definition: tokstack.hxx:168
DefTokenId eId
Definition: tokstack.hxx:152
T & operator[](sal_uInt16 n)
Definition: tokstack.hxx:122
int i
static const sal_uInt16 nSize
Definition: tokstack.hxx:267
TokenId(const TokenId &r)
Definition: tokstack.hxx:45
static const sal_uInt16 nScTokenOff
Definition: tokstack.hxx:207
sal_uInt16 nP_IdLast
Definition: tokstack.hxx:148
std::unique_ptr< TokenId[]> pStack
Definition: tokstack.hxx:265
Definition: tokstack.hxx:57
EXTCONT(const DefTokenId e, const OUString &r)
Definition: tokstack.hxx:154
bool IsSingleOp(const TokenId &rId, const DefTokenId eId) const
Definition: tokstack.cxx:687
sal_uInt16 mnIndex
Definition: tokstack.hxx:170
static sal_uInt16 lcl_canGrow(sal_uInt16 nOld, sal_uInt16 nByMin)
Returns the new number of elements, or 0 if overflow.
Definition: tokstack.hxx:100
void operator>>(TokenId &rId)
Definition: tokstack.hxx:313
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:114
for storage of external cell references
Definition: tokstack.hxx:184
std::unique_ptr< ScTokenArray > GetTokenArray(const ScDocument &rDoc, const TokenId &rId)
Definition: tokstack.hxx:410
sal_uInt16 nElement
Definition: tokstack.hxx:204
::std::vector< ExtCellRef > maExtCellRefs
Definition: tokstack.hxx:190
bool GrowMatrix()
Definition: tokstack.cxx:151
sal_uInt16 m_nRek
Definition: tokstack.hxx:209
TokenId()
Definition: tokstack.hxx:43
TokenId(sal_uInt16 n)
Definition: tokstack.hxx:44
TokenPoolPool< sal_uInt16, 8 > pP_Err
Definition: tokstack.hxx:141
bool Grow(sal_uInt16 nByMin=1)
Definition: tokstack.hxx:83
::std::vector< ExtAreaRef > maExtAreaRefs
Definition: tokstack.hxx:199
T const & operator[](sal_uInt16 n) const
Definition: tokstack.hxx:118
std::unique_ptr< sal_uInt16[]> pSize
Definition: tokstack.hxx:203
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:122
::std::vector< ExtName > maExtNames
Definition: tokstack.hxx:181
sal_uInt16 nP_Matrix
Definition: tokstack.hxx:164
for storage of external names
Definition: tokstack.hxx:176
#define SAL_WARN(area, stream)
bool CheckElementOrGrow()
Definition: tokstack.cxx:107
sal_uInt16 mnFileId
Definition: tokstack.hxx:178
void Reset()
Definition: tokstack.cxx:675
sal_uInt16 nId
Definition: tokstack.hxx:41
sal_uInt16 nPos
Definition: tokstack.hxx:266
TokenStack & operator<<(const TokenId &rNewId)
Definition: tokstack.hxx:298
~TokenPool()
Definition: tokstack.cxx:67
TokenPoolPool< std::unique_ptr< ScSingleRefData >, 32 > ppP_RefTr
Definition: tokstack.hxx:144
void operator>>(TokenId &rId)
Definition: tokstack.cxx:403
TokenPool & operator<<(const TokenId &rId)
Definition: tokstack.hxx:332
ScSingleRefData maRef
Definition: tokstack.hxx:188
TokenPoolPool< double, 8 > pP_Dbl
Definition: tokstack.hxx:138