1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
22 #include <tokenarray.hxx>
23 #include <refdata.hxx>
24 #include <sal/log.hxx>
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;
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
; }
59 T_RefC
, // Cell Reference
60 T_RefA
, // Area Reference
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
70 template<typename T
, int InitialCapacity
>
73 std::unique_ptr
<T
[]> ppP_Str
;
74 sal_uInt16 m_capacity
;
75 sal_uInt16 m_writemark
;
78 ppP_Str( new T
[InitialCapacity
] ),
79 m_capacity(InitialCapacity
),
83 bool Grow(sal_uInt16 nByMin
= 1)
85 sal_uInt16 nP_StrNew
= lcl_canGrow(m_capacity
, nByMin
);
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
);
99 /** Returns the new number of elements, or 0 if overflow. */
100 static sal_uInt16
lcl_canGrow( sal_uInt16 nOld
, sal_uInt16 nByMin
)
103 return nByMin
? nByMin
: 1;
104 if (nOld
== SAL_MAX_UINT16
)
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
)
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
122 T
& operator[](sal_uInt16 n
)
130 // !ATTENTION!: external Id-Basis is 1, internal 0!
131 // return Id = 0 -> Error
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
147 sal_uInt16 nP_IdCurrent
;
148 sal_uInt16 nP_IdLast
; // last set-start
154 EXTCONT( const DefTokenId e
, const OUString
& r
) :
155 eId( e
), aText( r
){}
157 TokenPoolPool
<std::unique_ptr
<EXTCONT
>, 32>
160 TokenPoolPool
<std::unique_ptr
<ScSingleRefData
>, 16>
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 */
173 ::std::vector
<RangeName
> maRangeNames
;
175 /** for storage of external names */
181 ::std::vector
<ExtName
> maExtNames
;
183 /** for storage of external cell references */
187 ScSingleRefData maRef
;
190 ::std::vector
<ExtCellRef
> maExtCellRefs
;
192 /** for storage of external area references */
196 ScComplexRefData maRef
;
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
205 sal_uInt16 nElementCurrent
;
207 static const sal_uInt16 nScTokenOff
;// Offset for SC-Token
209 sal_uInt16 m_nRek
; // recursion counter
212 bool GrowTripel( sal_uInt16 nByMin
);
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
222 bool CheckElementOrGrow();
223 bool GetElement( const sal_uInt16 nId
, ScTokenArray
* pScToken
);
224 bool GetElementRek( const sal_uInt16 nId
, ScTokenArray
* pScToken
);
227 TokenPool( svl::SharedStringPool
& rSPool
);
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
);
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;
261 // Stack for Token-Ids: reserve Id=0 for error; e.g. Get() returns 0 on error
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
271 inline TokenStack
& operator <<( const TokenId
& rNewId
);
272 inline void operator >>( TokenId
&rId
);
276 bool HasMoreTokens() const { return nPos
> 0; }
277 inline TokenId
Get();
280 inline TokenId
TokenStack::Get()
286 SAL_WARN("sc.filter", "*TokenStack::Get(): is empty, is empty, ...");
292 nRet
= pStack
[ nPos
];
298 inline TokenStack
&TokenStack::operator <<( const TokenId
& rNewId
)
302 pStack
[ nPos
] = rNewId
;
307 SAL_WARN("sc.filter", "*TokenStack::<<(): Stack overflow for " << static_cast<sal_uInt16
>(rNewId
));
313 inline void TokenStack::operator >>( TokenId
& rId
)
318 rId
= pStack
[ nPos
];
322 SAL_WARN("sc.filter", "*TokenStack::>>(): is empty, is empty, ...");
327 inline void TokenStack::Reset()
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
);
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
351 nId
= static_cast<sal_uInt16
>(ocErrNull
) + nScTokenOff
+ 1;
354 if( nP_IdCurrent
>= nP_Id
&& !GrowId())
357 pP_Id
[ nP_IdCurrent
] = nId
- 1;
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())
373 pP_Id
[ nP_IdCurrent
] = static_cast<sal_uInt16
>(eId
) + nScTokenOff
;
379 inline TokenPool
& TokenPool::operator <<( TokenStack
& rStack
)
381 if( nP_IdCurrent
>= nP_Id
&& !GrowId())
384 sal_uInt16 nId
= static_cast<sal_uInt16
>(rStack
.Get());
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;
396 inline void TokenPool::operator >>( TokenStack
& rStack
)
403 inline TokenId
TokenPool::Store()
410 inline std::unique_ptr
<ScTokenArray
> TokenPool::GetTokenArray( const ScDocument
& rDoc
, const TokenId
& rId
)
412 std::unique_ptr
<ScTokenArray
> pScToken( new ScTokenArray(rDoc
) );
415 {//...only if rId > 0!
419 GetElement( static_cast<sal_uInt16
>(rId
) - 1, pScToken
.get());
426 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */