1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #ifndef SC_TOKSTACK_HXX
25 #define SC_TOKSTACK_HXX
26
27 #include <string.h>
28 #include <tools/debug.hxx>
29 #include "compiler.hxx"
30 #include "tokenarray.hxx"
31
32 #include <vector>
33
34 typedef OpCode DefTokenId;
35 // in PRODUCT version: ambiguity between OpCode (being sal_uInt16) and UINT16
36 // Unfortunately a typedef is just a dumb alias and not a real type ...
37 //typedef sal_uInt16 TokenId;
38 struct TokenId
39 {
40 sal_uInt16 nId;
41
TokenIdTokenId42 TokenId() : nId( 0 ) {}
TokenIdTokenId43 TokenId( sal_uInt16 n ) : nId( n ) {}
TokenIdTokenId44 TokenId( const TokenId& r ) : nId( r.nId ) {}
operator =TokenId45 inline TokenId& operator =( const TokenId& r ) { nId = r.nId; return *this; }
operator =TokenId46 inline TokenId& operator =( sal_uInt16 n ) { nId = n; return *this; }
operator sal_uInt16&TokenId47 inline operator sal_uInt16&() { return nId; }
48 inline operator const sal_uInt16&() const { return nId; }
operator <TokenId49 inline sal_Bool operator <( sal_uInt16 n ) const { return nId < n; }
operator >TokenId50 inline sal_Bool operator >( sal_uInt16 n ) const { return nId > n; }
operator <=TokenId51 inline sal_Bool operator <=( sal_uInt16 n ) const { return nId <= n; }
operator >=TokenId52 inline sal_Bool operator >=( sal_uInt16 n ) const { return nId >= n; }
operator ==TokenId53 inline sal_Bool operator ==( sal_uInt16 n ) const { return nId == n; }
operator !=TokenId54 inline sal_Bool operator !=( sal_uInt16 n ) const { return nId != n; }
55 };
56
57
58 //------------------------------------------------------------------------
59 struct ScComplexRefData;
60 class TokenStack;
61 class ScToken;
62
63
64 enum E_TYPE
65 {
66 T_Id, // Id-Folge
67 T_Str, // String
68 T_D, // Double
69 T_Err, // Error code
70 T_RefC, // Cell Reference
71 T_RefA, // Area Reference
72 T_RN, // Range Name
73 T_Ext, // irgendwas Unbekanntes mit Funktionsnamen
74 T_Nlf, // token for natural language formula
75 T_Matrix, // token for inline arrays
76 T_ExtName, // token for external names
77 T_ExtRefC,
78 T_ExtRefA,
79 T_Error // fuer Abfrage im Fehlerfall
80 };
81
82
83
84
85 class TokenPool
86 {
87 // !ACHTUNG!: externe Id-Basis ist 1, interne 0!
88 // Ausgabe Id = 0 -> Fehlerfall
89 private:
90 String** ppP_Str; // Pool fuer Strings
91 sal_uInt16 nP_Str; // ...mit Groesse
92 sal_uInt16 nP_StrAkt; // ...und Schreibmarke
93
94 double* pP_Dbl; // Pool fuer Doubles
95 sal_uInt16 nP_Dbl;
96 sal_uInt16 nP_DblAkt;
97
98 sal_uInt16* pP_Err; // Pool for error codes
99 sal_uInt16 nP_Err;
100 sal_uInt16 nP_ErrAkt;
101
102 ScSingleRefData** ppP_RefTr; // Pool fuer Referenzen
103 sal_uInt16 nP_RefTr;
104 sal_uInt16 nP_RefTrAkt;
105
106 sal_uInt16* pP_Id; // Pool fuer Id-Folgen
107 sal_uInt16 nP_Id;
108 sal_uInt16 nP_IdAkt;
109 sal_uInt16 nP_IdLast; // letzter Folgen-Beginn
110
111 struct EXTCONT
112 {
113 DefTokenId eId;
114 String aText;
EXTCONTTokenPool::EXTCONT115 EXTCONT( const DefTokenId e, const String& r ) :
116 eId( e ), aText( r ){}
117 };
118 EXTCONT** ppP_Ext;
119 sal_uInt16 nP_Ext;
120 sal_uInt16 nP_ExtAkt;
121
122 struct NLFCONT
123 {
124 ScSingleRefData aRef;
NLFCONTTokenPool::NLFCONT125 NLFCONT( const ScSingleRefData& r ) : aRef( r ) {}
126 };
127 NLFCONT** ppP_Nlf;
128 sal_uInt16 nP_Nlf;
129 sal_uInt16 nP_NlfAkt;
130
131 ScMatrix** ppP_Matrix; // Pool fuer Matricies
132 sal_uInt16 nP_Matrix;
133 sal_uInt16 nP_MatrixAkt;
134
135 /** for storage of external names */
136 struct ExtName
137 {
138 sal_uInt16 mnFileId;
139 String maName;
140 };
141 ::std::vector<ExtName> maExtNames;
142
143 /** for storage of external cell references */
144 struct ExtCellRef
145 {
146 sal_uInt16 mnFileId;
147 String maTabName;
148 ScSingleRefData maRef;
149 };
150 ::std::vector<ExtCellRef> maExtCellRefs;
151
152 /** for storage of external area references */
153 struct ExtAreaRef
154 {
155 sal_uInt16 mnFileId;
156 String maTabName;
157 ScComplexRefData maRef;
158 };
159 ::std::vector<ExtAreaRef> maExtAreaRefs;
160
161 sal_uInt16* pElement; // Array mit Indizes fuer Elemente
162 E_TYPE* pType; // ...mit Typ-Info
163 sal_uInt16* pSize; // ...mit Laengenangabe (Anz. sal_uInt16)
164 sal_uInt16 nElement;
165 sal_uInt16 nElementAkt;
166
167 static const sal_uInt16 nScTokenOff;// Offset fuer SC-Token
168 #ifdef DBG_UTIL
169 sal_uInt16 nRek; // Rekursionszaehler
170 #endif
171 ScTokenArray* pScToken; // Tokenbastler
172
173 bool GrowString( void );
174 bool GrowDouble( void );
175 /* TODO: in case we had FormulaTokenArray::AddError() */
176 #if 0
177 bool GrowError( void );
178 #endif
179 bool GrowTripel( sal_uInt16 nByMin = 1 );
180 bool GrowId( void );
181 bool GrowElement( void );
182 bool GrowExt( void );
183 bool GrowNlf( void );
184 bool GrowMatrix( void );
185 bool GetElement( const sal_uInt16 nId );
186 bool GetElementRek( const sal_uInt16 nId );
187 public:
188 TokenPool( void );
189 ~TokenPool();
190 inline TokenPool& operator <<( const TokenId nId );
191 inline TokenPool& operator <<( const DefTokenId eId );
192 inline TokenPool& operator <<( TokenStack& rStack );
193 void operator >>( TokenId& rId );
194 inline void operator >>( TokenStack& rStack );
195 inline const TokenId Store( void );
196 const TokenId Store( const double& rDouble );
197 //UNUSED2008-05 const TokenId StoreError( sal_uInt16 nError );
198
199 // nur fuer Range-Names
200 const TokenId Store( const sal_uInt16 nIndex );
201 inline const TokenId Store( const sal_Int16 nWert );
202 const TokenId Store( const String& rString );
203 const TokenId Store( const ScSingleRefData& rTr );
204 const TokenId Store( const ScComplexRefData& rTr );
205
206 const TokenId Store( const DefTokenId eId, const String& rName );
207 // 4 externals (e.g. AddIns, Makros...)
208 const TokenId StoreNlf( const ScSingleRefData& rTr );
209 const TokenId StoreMatrix();
210 const TokenId StoreExtName( sal_uInt16 nFileId, const String& rName );
211 const TokenId StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef );
212 const TokenId StoreExtRef( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef );
213
214 inline const TokenId LastId( void ) const;
215 inline const ScTokenArray* operator []( const TokenId nId );
216 void Reset( void );
217 inline E_TYPE GetType( const TokenId& nId ) const;
218 sal_Bool IsSingleOp( const TokenId& nId, const DefTokenId eId ) const;
219 const String* GetExternal( const TokenId& nId ) const;
220 ScMatrix* GetMatrix( unsigned int n ) const;
221 };
222
223
224
225
226 class TokenStack
227 // Stack fuer Token-Ids: Id 0 sollte reserviert bleiben als
228 // fehlerhafte Id, da z.B. Get() im Fehlerfall 0 liefert
229 {
230 private:
231 TokenId* pStack; // Stack als Array
232 sal_uInt16 nPos; // Schreibmarke
233 sal_uInt16 nSize; // Erster Index ausserhalb des Stacks
234 public:
235 TokenStack( sal_uInt16 nNewSize = 1024 );
236 ~TokenStack();
237 inline TokenStack& operator <<( const TokenId nNewId );
238 inline void operator >>( TokenId &rId );
239
240 inline void Reset( void );
241
HasMoreTokens() const242 inline bool HasMoreTokens() const { return nPos > 0; }
243 inline const TokenId Get( void );
244 };
245
246
247
248
Get(void)249 inline const TokenId TokenStack::Get( void )
250 {
251 DBG_ASSERT( nPos > 0,
252 "*TokenStack::Get(): Leer ist leer, ist leer, ist leer, ist..." );
253
254 TokenId nRet;
255
256 if( nPos == 0 )
257 nRet = 0;
258 else
259 {
260 nPos--;
261 nRet = pStack[ nPos ];
262 }
263
264 return nRet;
265 }
266
267
operator <<(const TokenId nNewId)268 inline TokenStack &TokenStack::operator <<( const TokenId nNewId )
269 {// Element auf Stack
270 DBG_ASSERT( nPos < nSize, "*TokenStack::<<(): Stackueberlauf" );
271 if( nPos < nSize )
272 {
273 pStack[ nPos ] = nNewId;
274 nPos++;
275 }
276
277 return *this;
278 }
279
280
operator >>(TokenId & rId)281 inline void TokenStack::operator >>( TokenId& rId )
282 {// Element von Stack
283 DBG_ASSERT( nPos > 0,
284 "*TokenStack::>>(): Leer ist leer, ist leer, ist leer, ..." );
285 if( nPos > 0 )
286 {
287 nPos--;
288 rId = pStack[ nPos ];
289 }
290 }
291
292
Reset(void)293 inline void TokenStack::Reset( void )
294 {
295 nPos = 0;
296 }
297
298
299
300
operator <<(const TokenId nId)301 inline TokenPool& TokenPool::operator <<( const TokenId nId )
302 {
303 // POST: nId's werden hintereinander im Pool unter einer neuen Id
304 // abgelegt. Vorgang wird mit >> oder Store() abgeschlossen
305 // nId -> ( sal_uInt16 ) nId - 1;
306 DBG_ASSERT( ( sal_uInt16 ) nId < nScTokenOff,
307 "-TokenPool::operator <<: TokenId im DefToken-Bereich!" );
308
309 if( nP_IdAkt >= nP_Id )
310 if (!GrowId())
311 return *this;
312
313 pP_Id[ nP_IdAkt ] = ( ( sal_uInt16 ) nId ) - 1;
314 nP_IdAkt++;
315
316 return *this;
317 }
318
319
operator <<(const DefTokenId eId)320 inline TokenPool& TokenPool::operator <<( const DefTokenId eId )
321 {
322 DBG_ASSERT( ( sal_uInt32 ) eId + nScTokenOff < 0xFFFF,
323 "-TokenPool::operator<<: enmum zu gross!" );
324
325 if( nP_IdAkt >= nP_Id )
326 if (!GrowId())
327 return *this;
328
329 pP_Id[ nP_IdAkt ] = ( ( sal_uInt16 ) eId ) + nScTokenOff;
330 nP_IdAkt++;
331
332 return *this;
333 }
334
335
operator <<(TokenStack & rStack)336 inline TokenPool& TokenPool::operator <<( TokenStack& rStack )
337 {
338 if( nP_IdAkt >= nP_Id )
339 if (!GrowId())
340 return *this;
341
342 pP_Id[ nP_IdAkt ] = ( ( sal_uInt16 ) rStack.Get() ) - 1;
343 nP_IdAkt++;
344
345 return *this;
346 }
347
348
operator >>(TokenStack & rStack)349 inline void TokenPool::operator >>( TokenStack& rStack )
350 {
351 TokenId nId;
352 *this >> nId;
353 rStack << nId;
354 }
355
356
Store(void)357 inline const TokenId TokenPool::Store( void )
358 {
359 TokenId nId;
360 *this >> nId;
361 return nId;
362 }
363
364
Store(const sal_Int16 nWert)365 inline const TokenId TokenPool::Store( const sal_Int16 nWert )
366 {
367 return Store( ( double ) nWert );
368 }
369
370
LastId(void) const371 inline const TokenId TokenPool::LastId( void ) const
372 {
373 return ( TokenId ) nElementAkt; // stimmt, da Ausgabe mit Offset 1!
374 }
375
376
operator [](const TokenId nId)377 const inline ScTokenArray* TokenPool::operator []( const TokenId nId )
378 {
379 pScToken->Clear();
380
381 if( nId )
382 {//...nur wenn nId > 0!
383 #ifdef DBG_UTIL
384 nRek = 0;
385 #endif
386 GetElement( ( sal_uInt16 ) nId - 1 );
387 }
388
389 return pScToken;
390 }
391
392
GetType(const TokenId & rId) const393 inline E_TYPE TokenPool::GetType( const TokenId& rId ) const
394 {
395 E_TYPE nRet;
396
397 sal_uInt16 nId = (sal_uInt16) rId - 1;
398
399 if( nId < nElementAkt )
400 nRet = pType[ nId ] ;
401 else
402 nRet = T_Error;
403
404 return nRet;
405 }
406
407
408 #endif
409
410