LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sc / source / filter / inc / tokstack.hxx
blob03301d510e2f01f397ef401a9341447997fb6313
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 #pragma once
22 #include <tokenarray.hxx>
23 #include <refdata.hxx>
24 #include <sal/log.hxx>
26 #include <memory>
27 #include <vector>
29 namespace svl {
31 class SharedStringPool;
35 typedef OpCode DefTokenId;
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
41 sal_uInt16 nId;
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; }
51 class TokenStack;
53 enum E_TYPE
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
66 T_ExtRefC,
67 T_ExtRefA
70 template<typename T, int InitialCapacity>
71 struct TokenPoolPool
73 std::unique_ptr<T[]> ppP_Str;
74 sal_uInt16 m_capacity;
75 sal_uInt16 m_writemark;
77 TokenPoolPool() :
78 ppP_Str( new T[InitialCapacity] ),
79 m_capacity(InitialCapacity),
80 m_writemark(0)
83 bool Grow(sal_uInt16 nByMin = 1)
85 sal_uInt16 nP_StrNew = lcl_canGrow(m_capacity, nByMin);
86 if (!nP_StrNew)
87 return false;
89 T* ppP_StrNew = new T[ nP_StrNew ];
91 for( sal_uInt16 i = 0 ; i < m_capacity ; i++ )
92 ppP_StrNew[ i ] = std::move(ppP_Str[ i ]);
94 m_capacity = nP_StrNew;
96 ppP_Str.reset( ppP_StrNew );
97 return true;
99 /** Returns the new number of elements, or 0 if overflow. */
100 static sal_uInt16 lcl_canGrow( sal_uInt16 nOld, sal_uInt16 nByMin )
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);
114 T* getIfInRange(sal_uInt16 n) const
116 return ( n < m_capacity ) ? &ppP_Str[ n ] : nullptr;
118 T const & operator[](sal_uInt16 n) const
120 return ppP_Str[ n ];
122 T & operator[](sal_uInt16 n)
124 return ppP_Str[ n ];
128 class TokenPool
130 // !ATTENTION!: external Id-Basis is 1, internal 0!
131 // return Id = 0 -> Error
132 private:
133 svl::SharedStringPool& mrStringPool;
135 TokenPoolPool<std::unique_ptr<OUString>, 4>
136 ppP_Str; // Pool for Strings
138 TokenPoolPool<double, 8> pP_Dbl; // Pool for Doubles
140 TokenPoolPool<sal_uInt16, 8>
141 pP_Err; // Pool for error codes
143 TokenPoolPool<std::unique_ptr<ScSingleRefData>, 32>
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
150 struct EXTCONT
152 DefTokenId eId;
153 OUString aText;
154 EXTCONT( const DefTokenId e, const OUString& r ) :
155 eId( e ), aText( r ){}
157 TokenPoolPool<std::unique_ptr<EXTCONT>, 32>
158 ppP_Ext;
160 TokenPoolPool<std::unique_ptr<ScSingleRefData>, 16>
161 ppP_Nlf;
163 std::unique_ptr<ScMatrix*[]> ppP_Matrix; // Pool for Matrices
164 sal_uInt16 nP_Matrix;
165 sal_uInt16 nP_MatrixCurrent;
167 /** for storage of named ranges */
168 struct RangeName
170 sal_uInt16 mnIndex;
171 sal_Int16 mnSheet;
173 ::std::vector<RangeName> maRangeNames;
175 /** for storage of external names */
176 struct ExtName
178 sal_uInt16 mnFileId;
179 OUString maName;
181 ::std::vector<ExtName> maExtNames;
183 /** for storage of external cell references */
184 struct ExtCellRef
186 OUString maTabName;
187 ScSingleRefData maRef;
188 sal_uInt16 mnFileId;
190 ::std::vector<ExtCellRef> maExtCellRefs;
192 /** for storage of external area references */
193 struct ExtAreaRef
195 OUString maTabName;
196 ScComplexRefData maRef;
197 sal_uInt16 mnFileId;
199 ::std::vector<ExtAreaRef> maExtAreaRefs;
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;
207 static const sal_uInt16 nScTokenOff;// Offset for SC-Token
208 #ifdef DBG_UTIL
209 sal_uInt16 m_nRek; // recursion counter
210 #endif
212 bool GrowTripel( sal_uInt16 nByMin );
213 bool GrowId();
214 bool GrowElement();
215 bool GrowMatrix();
216 /** @return false means nElementCurrent range
217 below nScTokenOff would overflow or
218 further allocation is not possible, no
219 new ID available other than
220 nElementCurrent+1.
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 );
237 // only for Range-Names
238 TokenId Store( const sal_uInt16 nIndex );
240 TokenId Store( const OUString& rString );
241 TokenId Store( const ScSingleRefData& rTr );
242 TokenId Store( const ScComplexRefData& rTr );
244 TokenId Store( const DefTokenId eId, const OUString& rName );
245 // 4 externals (e.g. AddIns, Macros...)
246 TokenId StoreNlf( const ScSingleRefData& rTr );
247 TokenId StoreMatrix();
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 );
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;
260 class TokenStack
261 // Stack for Token-Ids: reserve Id=0 for error; e.g. Get() returns 0 on error
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 );
274 inline void Reset();
276 bool HasMoreTokens() const { return nPos > 0; }
277 inline TokenId Get();
280 inline TokenId TokenStack::Get()
282 TokenId nRet;
284 if( nPos == 0 )
286 SAL_WARN("sc.filter", "*TokenStack::Get(): is empty, is empty, ...");
287 nRet = 0;
289 else
291 nPos--;
292 nRet = pStack[ nPos ];
295 return nRet;
298 inline TokenStack &TokenStack::operator <<( const TokenId& rNewId )
299 {// Element on Stack
300 if( nPos < nSize )
302 pStack[ nPos ] = rNewId;
303 nPos++;
305 else
307 SAL_WARN("sc.filter", "*TokenStack::<<(): Stack overflow for " << static_cast<sal_uInt16>(rNewId));
310 return *this;
313 inline void TokenStack::operator >>( TokenId& rId )
314 {// Element of Stack
315 if( nPos > 0 )
317 nPos--;
318 rId = pStack[ nPos ];
320 else
322 SAL_WARN("sc.filter", "*TokenStack::>>(): is empty, is empty, ...");
323 rId = 0;
327 inline void TokenStack::Reset()
329 nPos = 0;
332 inline TokenPool& TokenPool::operator <<( const TokenId& rId )
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)
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;
344 else if (nId >= nScTokenOff)
346 SAL_WARN("sc.filter", "-TokenPool::operator <<: TokenId in DefToken-Range! " << static_cast<sal_uInt16>(rId));
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;
354 if( nP_IdCurrent >= nP_Id && !GrowId())
355 return *this;
357 pP_Id[ nP_IdCurrent ] = nId - 1;
358 nP_IdCurrent++;
360 return *this;
363 inline TokenPool& TokenPool::operator <<( const DefTokenId eId )
365 if (static_cast<sal_uInt32>(eId) + nScTokenOff >= 0xFFFF)
367 SAL_WARN("sc.filter", "-TokenPool::operator<<: enum too large! " << static_cast<sal_uInt32>(eId));
370 if( nP_IdCurrent >= nP_Id && !GrowId())
371 return *this;
373 pP_Id[ nP_IdCurrent ] = static_cast<sal_uInt16>(eId) + nScTokenOff;
374 nP_IdCurrent++;
376 return *this;
379 inline TokenPool& TokenPool::operator <<( TokenStack& rStack )
381 if( nP_IdCurrent >= nP_Id && !GrowId())
382 return *this;
384 sal_uInt16 nId = static_cast<sal_uInt16>(rStack.Get());
385 if (nId == 0)
387 // Indicates error, so generate one. Empty stack, overflow, ...
388 nId = static_cast<sal_uInt16>(ocErrNull) + nScTokenOff + 1;
390 pP_Id[ nP_IdCurrent ] = nId - 1;
391 nP_IdCurrent++;
393 return *this;
396 inline void TokenPool::operator >>( TokenStack& rStack )
398 TokenId nId;
399 *this >> nId;
400 rStack << nId;
403 inline TokenId TokenPool::Store()
405 TokenId nId;
406 *this >> nId;
407 return nId;
410 inline std::unique_ptr<ScTokenArray> TokenPool::GetTokenArray( const ScDocument& rDoc, const TokenId& rId )
412 std::unique_ptr<ScTokenArray> pScToken( new ScTokenArray(rDoc) );
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());
422 return pScToken;
426 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */