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>
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;
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
; }
60 T_RefC
, // Cell Reference
61 T_RefA
, // Area Reference
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
71 template<typename T
, int InitialCapacity
>
74 std::unique_ptr
<T
[]> ppP_Str
;
75 sal_uInt16 m_capacity
;
76 sal_uInt16 m_writemark
;
79 ppP_Str( new T
[InitialCapacity
] ),
80 m_capacity(InitialCapacity
),
84 bool Grow(sal_uInt16 nByMin
= 1)
86 sal_uInt16 nP_StrNew
= lcl_canGrow(m_capacity
, nByMin
);
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
);
100 /** Returns the new number of elements, or 0 if overflow. */
101 static sal_uInt16
lcl_canGrow( sal_uInt16 nOld
, sal_uInt16 nByMin
)
104 return nByMin
? nByMin
: 1;
105 if (nOld
== SAL_MAX_UINT16
)
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
)
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
123 T
& operator[](sal_uInt16 n
)
131 // !ATTENTION!: external Id-Basis is 1, internal 0!
132 // return Id = 0 -> Error
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
148 sal_uInt16 nP_IdCurrent
;
149 sal_uInt16 nP_IdLast
; // last set-start
155 EXTCONT( const DefTokenId e
, OUString a
) :
156 eId( e
), aText(std::move( a
)){}
158 TokenPoolPool
<std::unique_ptr
<EXTCONT
>, 32>
161 TokenPoolPool
<std::unique_ptr
<ScSingleRefData
>, 16>
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 */
174 ::std::vector
<RangeName
> maRangeNames
;
176 /** for storage of external names */
182 ::std::vector
<ExtName
> maExtNames
;
184 /** for storage of external cell references */
188 ScSingleRefData maRef
;
191 ::std::vector
<ExtCellRef
> maExtCellRefs
;
193 /** for storage of external area references */
197 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
206 sal_uInt16 nElementCurrent
;
208 static const sal_uInt16 nScTokenOff
;// Offset for SC-Token
210 sal_uInt16 m_nRek
; // recursion counter
213 bool GrowTripel( sal_uInt16 nByMin
);
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
223 bool CheckElementOrGrow();
224 bool GetElement( const sal_uInt16 nId
, ScTokenArray
* pScToken
);
225 bool GetElementRek( const sal_uInt16 nId
, ScTokenArray
* pScToken
);
228 TokenPool( svl::SharedStringPool
& rSPool
);
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 ScDocument
& rDoc
, const TokenId
& rId
);
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;
262 // Stack for Token-Ids: reserve Id=0 for error; e.g. Get() returns 0 on error
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
272 inline TokenStack
& operator <<( const TokenId
& rNewId
);
273 inline void operator >>( TokenId
&rId
);
277 bool HasMoreTokens() const { return nPos
> 0; }
278 inline TokenId
Get();
281 inline TokenId
TokenStack::Get()
287 SAL_WARN("sc.filter", "*TokenStack::Get(): is empty, is empty, ...");
293 nRet
= pStack
[ nPos
];
299 inline TokenStack
&TokenStack::operator <<( const TokenId
& rNewId
)
303 pStack
[ nPos
] = rNewId
;
308 SAL_WARN("sc.filter", "*TokenStack::<<(): Stack overflow for " << static_cast<sal_uInt16
>(rNewId
));
314 inline void TokenStack::operator >>( TokenId
& rId
)
319 rId
= pStack
[ nPos
];
323 SAL_WARN("sc.filter", "*TokenStack::>>(): is empty, is empty, ...");
328 inline void TokenStack::Reset()
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
);
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
352 nId
= static_cast<sal_uInt16
>(ocErrNull
) + nScTokenOff
+ 1;
355 if( nP_IdCurrent
>= nP_Id
&& !GrowId())
358 pP_Id
[ nP_IdCurrent
] = nId
- 1;
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())
374 pP_Id
[ nP_IdCurrent
] = static_cast<sal_uInt16
>(eId
) + nScTokenOff
;
380 inline TokenPool
& TokenPool::operator <<( TokenStack
& rStack
)
382 if( nP_IdCurrent
>= nP_Id
&& !GrowId())
385 sal_uInt16 nId
= static_cast<sal_uInt16
>(rStack
.Get());
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;
397 inline void TokenPool::operator >>( TokenStack
& rStack
)
404 inline TokenId
TokenPool::Store()
411 inline std::unique_ptr
<ScTokenArray
> TokenPool::GetTokenArray( const ScDocument
& rDoc
, const TokenId
& rId
)
413 std::unique_ptr
<ScTokenArray
> pScToken( new ScTokenArray(rDoc
) );
416 {//...only if rId > 0!
420 GetElement( static_cast<sal_uInt16
>(rId
) - 1, pScToken
.get());
427 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */