Branch data Line data Source code
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 : :
21 : : #include <math.h>
22 : : #include <tools/stream.hxx>
23 : :
24 : : #include <basic/sbx.hxx>
25 : : #include "sbxconv.hxx"
26 : : #include "runtime.hxx"
27 : :
28 [ - + ][ - + ]: 150455 : TYPEINIT1(SbxValue,SbxBase)
29 : :
30 : : ///////////////////////////// constructors //////////////////////////////
31 : :
32 [ # # ][ # # ]: 4470 : SbxValue::SbxValue() : SbxBase()
[ + - ][ + - ]
33 : : {
34 : 4470 : aData.eType = SbxEMPTY;
35 : 4470 : }
36 : :
37 [ # # ][ # # ]: 31517 : SbxValue::SbxValue( SbxDataType t, void* p ) : SbxBase()
[ + - ][ + - ]
38 : : {
39 : 31517 : int n = t & 0x0FFF;
40 [ # # ][ - + ]: 31517 : if( p )
41 : 0 : n |= SbxBYREF;
42 [ # # ][ + + ]: 31517 : if( n == SbxVARIANT )
43 : 623 : n = SbxEMPTY;
44 : : else
45 : 30894 : SetFlag( SBX_FIXED );
46 [ # # ][ - + ]: 31517 : if( p )
47 [ # # # # : 0 : switch( t & 0x0FFF )
# # # # #
# # # # #
# ][ # # #
# # # # #
# # # # #
# # ]
48 : : {
49 : 0 : case SbxINTEGER: n |= SbxBYREF; aData.pInteger = (sal_Int16*) p; break;
50 : 0 : case SbxSALUINT64: n |= SbxBYREF; aData.puInt64 = (sal_uInt64*) p; break;
51 : : case SbxSALINT64:
52 : 0 : case SbxCURRENCY: n |= SbxBYREF; aData.pnInt64 = (sal_Int64*) p; break;
53 : 0 : case SbxLONG: n |= SbxBYREF; aData.pLong = (sal_Int32*) p; break;
54 : 0 : case SbxSINGLE: n |= SbxBYREF; aData.pSingle = (float*) p; break;
55 : : case SbxDATE:
56 : 0 : case SbxDOUBLE: n |= SbxBYREF; aData.pDouble = (double*) p; break;
57 : 0 : case SbxSTRING: n |= SbxBYREF; aData.pOUString = (::rtl::OUString*) p; break;
58 : : case SbxERROR:
59 : : case SbxUSHORT:
60 : 0 : case SbxBOOL: n |= SbxBYREF; aData.pUShort = (sal_uInt16*) p; break;
61 : 0 : case SbxULONG: n |= SbxBYREF; aData.pULong = (sal_uInt32*) p; break;
62 : 0 : case SbxCHAR: n |= SbxBYREF; aData.pChar = (sal_Unicode*) p; break;
63 : 0 : case SbxBYTE: n |= SbxBYREF; aData.pByte = (sal_uInt8*) p; break;
64 : 0 : case SbxINT: n |= SbxBYREF; aData.pInt = (int*) p; break;
65 : : case SbxOBJECT:
66 : 0 : aData.pObj = (SbxBase*) p;
67 [ # # ][ # # ]: 0 : if( p )
68 : 0 : aData.pObj->AddRef();
69 : 0 : break;
70 : : case SbxDECIMAL:
71 : 0 : aData.pDecimal = (SbxDecimal*) p;
72 [ # # ][ # # ]: 0 : if( p )
73 : 0 : aData.pDecimal->addRef();
74 : 0 : break;
75 : : default:
76 : : DBG_ASSERT( !this, "Angabe eines Pointers unzulaessig" );
77 : 0 : n = SbxNULL;
78 : : }
79 : : else
80 : 31517 : memset( &aData, 0, sizeof( SbxValues ) );
81 : 31517 : aData.eType = SbxDataType( n );
82 : 31517 : }
83 : :
84 : 6123 : SbxValue::SbxValue( const SbxValue& r )
85 [ # # ][ # # ]: 6123 : : SvRefBase( r ), SbxBase( r )
[ + - ][ + - ]
86 : : {
87 [ # # ][ - + ]: 6123 : if( !r.CanRead() )
88 : : {
89 [ # # ][ # # ]: 0 : SetError( SbxERR_PROP_WRITEONLY );
90 [ # # ][ # # ]: 0 : if( !IsFixed() )
[ # # ][ # # ]
91 : 0 : aData.eType = SbxNULL;
92 : : }
93 : : else
94 : : {
95 [ # # ][ + - ]: 6123 : ((SbxValue*) &r)->Broadcast( SBX_HINT_DATAWANTED );
96 : 6123 : aData = r.aData;
97 : : // Copy pointer, increment references
98 [ # # # # ]: 6123 : switch( aData.eType )
[ + + - + ]
99 : : {
100 : : case SbxSTRING:
101 [ # # ][ + + ]: 1444 : if( aData.pOUString )
102 [ # # ][ + - ]: 984 : aData.pOUString = new ::rtl::OUString( *aData.pOUString );
103 : 1444 : break;
104 : : case SbxOBJECT:
105 [ # # ][ + + ]: 470 : if( aData.pObj )
106 : 428 : aData.pObj->AddRef();
107 : 470 : break;
108 : : case SbxDECIMAL:
109 [ # # ][ # # ]: 0 : if( aData.pDecimal )
110 : 0 : aData.pDecimal->addRef();
111 : 0 : break;
112 : 4209 : default: break;
113 : : }
114 : : }
115 : 6123 : }
116 : :
117 : 3367 : SbxValue& SbxValue::operator=( const SbxValue& r )
118 : : {
119 [ + - ]: 3367 : if( &r != this )
120 : : {
121 [ - + ]: 3367 : if( !CanWrite() )
122 : 0 : SetError( SbxERR_PROP_READONLY );
123 : : else
124 : : {
125 : : // string -> byte array
126 [ + - ][ + + ]: 3389 : if( IsFixed() && (aData.eType == SbxOBJECT)
[ + + ][ + + ]
[ - + ][ # # ]
[ - + ]
127 [ + - ]: 22 : && aData.pObj && ( aData.pObj->GetType() == (SbxARRAY | SbxBYTE) )
128 : : && (r.aData.eType == SbxSTRING) )
129 : : {
130 [ # # ][ # # ]: 0 : ::rtl::OUString aStr = r.GetString();
131 [ # # ]: 0 : SbxArray* pArr = StringToByteArray(aStr);
132 [ # # ]: 0 : PutObject(pArr);
133 : 0 : return *this;
134 : : }
135 : : // byte array -> string
136 [ + - ][ + + ]: 3569 : if( r.IsFixed() && (r.aData.eType == SbxOBJECT)
[ + + ][ + - ]
[ - + ][ # # ]
[ - + ]
137 [ + - ]: 202 : && r.aData.pObj && ( r.aData.pObj->GetType() == (SbxARRAY | SbxBYTE) )
138 : : && (aData.eType == SbxSTRING) )
139 : : {
140 [ # # ]: 0 : SbxBase* pObj = r.GetObject();
141 [ # # ][ # # ]: 0 : SbxArray* pArr = PTR_CAST(SbxArray, pObj);
[ # # ][ # # ]
142 [ # # ]: 0 : if( pArr )
143 : : {
144 [ # # ]: 0 : ::rtl::OUString aStr = ByteArrayToString( pArr );
145 [ # # ]: 0 : PutString(aStr);
146 : 0 : return *this;
147 : : }
148 : : }
149 : : // Readout the content of the variables
150 : 3367 : SbxValues aNew;
151 [ + + ][ + - ]: 3367 : if( IsFixed() )
152 : : // firm: then the type had to match
153 : 2928 : aNew.eType = aData.eType;
154 [ + - ][ + + ]: 439 : else if( r.IsFixed() )
155 : : // Source firm: take over the type
156 : 51 : aNew.eType = SbxDataType( r.aData.eType & 0x0FFF );
157 : : else
158 : : // both variant: then it is equal
159 : 388 : aNew.eType = SbxVARIANT;
160 [ + - ][ + - ]: 3367 : if( r.Get( aNew ) )
161 [ + - ]: 3367 : Put( aNew );
162 : : }
163 : : }
164 : 3367 : return *this;
165 : : }
166 : :
167 [ # # ][ # # ]: 40947 : SbxValue::~SbxValue()
[ + - ][ + - ]
168 : : {
169 [ # # ][ + - ]: 40947 : Broadcast( SBX_HINT_DYING );
170 : 40947 : SetFlag( SBX_WRITE );
171 [ # # + - ]: 40947 : SbxValue::Clear();
172 [ # # ][ # # ]: 40947 : }
[ # # ][ - + ]
[ - + ][ # # ]
173 : :
174 : 44283 : void SbxValue::Clear()
175 : : {
176 [ + + + + : 44283 : switch( aData.eType )
- + ]
177 : : {
178 : : case SbxNULL:
179 : : case SbxEMPTY:
180 : : case SbxVOID:
181 : 5875 : break;
182 : : case SbxSTRING:
183 [ + + ]: 13050 : delete aData.pOUString; aData.pOUString = NULL;
184 : 13050 : break;
185 : : case SbxOBJECT:
186 [ + + ]: 18168 : if( aData.pObj )
187 : : {
188 [ + + ]: 8826 : if( aData.pObj != this )
189 : : {
190 : : HACK(nicht bei Parent-Prop - sonst CyclicRef)
191 [ + - ][ + + ]: 1474 : SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
192 : : sal_Bool bParentProp = pThisVar && 5345 ==
193 [ + + ][ - + ]: 1474 : ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) );
194 [ + - ]: 1474 : if ( !bParentProp )
195 : 1474 : aData.pObj->ReleaseRef();
196 : : }
197 : 8826 : aData.pObj = NULL;
198 : : }
199 : 18168 : break;
200 : : case SbxDECIMAL:
201 [ + - ]: 182 : if( aData.eType == SbxDECIMAL )
202 : 182 : releaseDecimalPtr( aData.pDecimal );
203 : 182 : break;
204 : : case SbxDATAOBJECT:
205 : 0 : aData.pData = NULL; break;
206 : : default:
207 : : {
208 : 7008 : SbxValues aEmpty;
209 : 7008 : memset( &aEmpty, 0, sizeof( SbxValues ) );
210 [ + - ]: 7008 : aEmpty.eType = GetType();
211 [ + - ]: 7008 : Put( aEmpty );
212 : : }
213 : : }
214 : 44283 : }
215 : :
216 : : // Dummy
217 : :
218 : 49201 : void SbxValue::Broadcast( sal_uIntPtr )
219 : 49201 : {}
220 : :
221 : : //////////////////////////// Readout data //////////////////////////////
222 : :
223 : : // Detect the "right" variables. If it is an object, will be addressed either
224 : : // the object itself or its default property.
225 : : // If the variable contain a variable or an object, this will be
226 : : // addressed.
227 : :
228 : 21895 : SbxValue* SbxValue::TheRealValue() const
229 : : {
230 : 21895 : return TheRealValue( sal_True );
231 : : }
232 : :
233 : : // #55226 ship additional information
234 : : bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal ); // sbunoobj.cxx
235 : :
236 : 42955 : SbxValue* SbxValue::TheRealValue( sal_Bool bObjInObjError ) const
237 : : {
238 : 42955 : SbxValue* p = (SbxValue*) this;
239 : 0 : for( ;; )
240 : : {
241 : 42955 : SbxDataType t = SbxDataType( p->aData.eType & 0x0FFF );
242 [ + + ]: 42955 : if( t == SbxOBJECT )
243 : : {
244 : : // The block contains an object or a variable
245 [ + - ][ + - ]: 2 : SbxObject* pObj = PTR_CAST(SbxObject,p->aData.pObj);
246 [ + - ]: 2 : if( pObj )
247 : : {
248 : : // Has the object a default property?
249 : 2 : SbxVariable* pDflt = pObj->GetDfltProperty();
250 : :
251 : : // If this is an object and contains itself,
252 : : // we cannot access on it
253 : : // The old condition to set an error
254 : : // is not correct, because e.g. a regular variant variable with an object
255 : : // could be affected thereof, if another value should be assigned.
256 : : // Therefore with flag.
257 [ - + ][ # # ]: 2 : if( bObjInObjError && !pDflt &&
[ # # ][ + - ]
258 : : ((SbxValue*) pObj)->aData.eType == SbxOBJECT &&
259 : : ((SbxValue*) pObj)->aData.pObj == pObj )
260 : : {
261 : : #ifdef DISABLE_SCRIPTING // No sbunoobj
262 : : const bool bSuccess = false;
263 : : #else
264 : 0 : bool bSuccess = handleToStringForCOMObjects( pObj, p );
265 : : #endif
266 [ # # ]: 0 : if( !bSuccess )
267 : : {
268 : 0 : SetError( SbxERR_BAD_PROP_VALUE );
269 : 0 : p = NULL;
270 : 0 : }
271 : : }
272 [ + - ]: 2 : else if( pDflt )
273 : 2 : p = pDflt;
274 : 2 : break;
275 : : }
276 : : // Did we have an array?
277 [ # # ][ # # ]: 0 : SbxArray* pArray = PTR_CAST(SbxArray,p->aData.pObj);
278 [ # # ]: 0 : if( pArray )
279 : : {
280 : : // When indicated get the parameter
281 : 0 : SbxArray* pPar = NULL;
282 [ # # ][ # # ]: 0 : SbxVariable* pVar = PTR_CAST(SbxVariable,p);
283 [ # # ]: 0 : if( pVar )
284 : 0 : pPar = pVar->GetParameters();
285 [ # # ]: 0 : if( pPar )
286 : : {
287 : : // Did we have a dimensioned array?
288 [ # # ][ # # ]: 0 : SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,p->aData.pObj);
289 [ # # ]: 0 : if( pDimArray )
290 : 0 : p = pDimArray->Get( pPar );
291 : : else
292 : 0 : p = pArray->Get( pPar->Get( 1 )->GetInteger() );
293 : 0 : break;
294 : : }
295 : : }
296 : : // Elsewise guess a SbxValue
297 [ # # ][ # # ]: 0 : SbxValue* pVal = PTR_CAST(SbxValue,p->aData.pObj);
298 [ # # ]: 0 : if( pVal )
299 : 0 : p = pVal;
300 : : else
301 : 0 : break;
302 : : }
303 : : else
304 : 42953 : break;
305 : : }
306 : 42955 : return p;
307 : : }
308 : :
309 : 38525 : sal_Bool SbxValue::Get( SbxValues& rRes ) const
310 : : {
311 : 38525 : sal_Bool bRes = sal_False;
312 : 38525 : SbxError eOld = GetError();
313 [ - + ]: 38525 : if( eOld != SbxERR_OK )
314 : 0 : ResetError();
315 [ - + ]: 38525 : if( !CanRead() )
316 : : {
317 : 0 : SetError( SbxERR_PROP_WRITEONLY );
318 : 0 : rRes.pObj = NULL;
319 : : }
320 : : else
321 : : {
322 : : // If there was asked for an object or a VARIANT, don't search
323 : : // the real values
324 : 38525 : SbxValue* p = (SbxValue*) this;
325 [ + + ][ + + ]: 38525 : if( rRes.eType != SbxOBJECT && rRes.eType != SbxVARIANT )
326 : 21895 : p = TheRealValue();
327 [ + - ]: 38525 : if( p )
328 : : {
329 : 38525 : p->Broadcast( SBX_HINT_DATAWANTED );
330 [ + + + + : 38525 : switch( rRes.eType )
- - - + -
- - + - +
- - + - -
- + - ]
331 : : {
332 : : case SbxEMPTY:
333 : : case SbxVOID:
334 : 24 : case SbxNULL: break;
335 : 404 : case SbxVARIANT: rRes = p->aData; break;
336 : 1446 : case SbxINTEGER: rRes.nInteger = ImpGetInteger( &p->aData ); break;
337 : 5930 : case SbxLONG: rRes.nLong = ImpGetLong( &p->aData ); break;
338 : 0 : case SbxSALINT64: rRes.nInt64 = ImpGetInt64( &p->aData ); break;
339 : 0 : case SbxSALUINT64: rRes.uInt64 = ImpGetUInt64( &p->aData ); break;
340 : 0 : case SbxSINGLE: rRes.nSingle = ImpGetSingle( &p->aData ); break;
341 : 8433 : case SbxDOUBLE: rRes.nDouble = ImpGetDouble( &p->aData ); break;
342 : 0 : case SbxCURRENCY:rRes.nInt64 = ImpGetCurrency( &p->aData ); break;
343 : 0 : case SbxDECIMAL: rRes.pDecimal = ImpGetDecimal( &p->aData ); break;
344 : 0 : case SbxDATE: rRes.nDouble = ImpGetDate( &p->aData ); break;
345 : : case SbxBOOL:
346 : : rRes.nUShort = sal::static_int_cast< sal_uInt16 >(
347 : 1816 : ImpGetBool( &p->aData ) );
348 : 1816 : break;
349 : 0 : case SbxCHAR: rRes.nChar = ImpGetChar( &p->aData ); break;
350 : 10 : case SbxBYTE: rRes.nByte = ImpGetByte( &p->aData ); break;
351 : 0 : case SbxUSHORT: rRes.nUShort = ImpGetUShort( &p->aData ); break;
352 : 0 : case SbxULONG: rRes.nULong = ImpGetULong( &p->aData ); break;
353 : : case SbxLPSTR:
354 : 4236 : case SbxSTRING: p->aPic = ImpGetString( &p->aData );
355 : 4236 : rRes.pOUString = &p->aPic; break;
356 : 0 : case SbxCoreSTRING: p->aPic = ImpGetCoreString( &p->aData );
357 : 0 : rRes.pOUString = &p->aPic; break;
358 : : case SbxINT:
359 : : #if SAL_TYPES_SIZEOFINT == 2
360 : : rRes.nInt = (int) ImpGetInteger( &p->aData );
361 : : #else
362 : 0 : rRes.nInt = (int) ImpGetLong( &p->aData );
363 : : #endif
364 : 0 : break;
365 : : case SbxUINT:
366 : : #if SAL_TYPES_SIZEOFINT == 2
367 : : rRes.nUInt = (int) ImpGetUShort( &p->aData );
368 : : #else
369 : 0 : rRes.nUInt = (int) ImpGetULong( &p->aData );
370 : : #endif
371 : 0 : break;
372 : : case SbxOBJECT:
373 [ + - ]: 16226 : if( p->aData.eType == SbxOBJECT )
374 : 16226 : rRes.pObj = p->aData.pObj;
375 : : else
376 : : {
377 : 0 : SetError( SbxERR_NO_OBJECT );
378 : 0 : rRes.pObj = NULL;
379 : : }
380 : 16226 : break;
381 : : default:
382 [ # # ]: 0 : if( p->aData.eType == rRes.eType )
383 : 0 : rRes = p->aData;
384 : : else
385 : : {
386 : 0 : SetError( SbxERR_CONVERSION );
387 : 38525 : rRes.pObj = NULL;
388 : : }
389 : : }
390 : : }
391 : : else
392 : : {
393 : : // Object contained itself
394 : 0 : SbxDataType eTemp = rRes.eType;
395 : 0 : memset( &rRes, 0, sizeof( SbxValues ) );
396 : 0 : rRes.eType = eTemp;
397 : : }
398 : : }
399 [ + - ]: 38525 : if( !IsError() )
400 : : {
401 : 38525 : bRes = sal_True;
402 [ - + ]: 38525 : if( eOld != SbxERR_OK )
403 : 0 : SetError( eOld );
404 : : }
405 : 38525 : return bRes;
406 : : }
407 : :
408 : 552 : const XubString& SbxValue::GetString() const
409 : : {
410 : 552 : SbxValues aRes;
411 : 552 : aRes.eType = SbxSTRING;
412 [ + - ][ + - ]: 552 : if( Get( aRes ) )
413 [ + - ]: 552 : ((SbxValue*) this)->aToolString = *aRes.pOUString;
414 : : else
415 [ # # ]: 0 : ((SbxValue*) this)->aToolString.Erase();
416 : :
417 : 552 : return aToolString;
418 : : }
419 : :
420 : 0 : const XubString& SbxValue::GetCoreString() const
421 : : {
422 : 0 : SbxValues aRes;
423 : 0 : aRes.eType = SbxCoreSTRING;
424 [ # # ][ # # ]: 0 : if( Get( aRes ) )
425 [ # # ]: 0 : ((SbxValue*) this)->aToolString = *aRes.pOUString;
426 : : else
427 [ # # ]: 0 : ((SbxValue*) this)->aToolString.Erase();
428 : :
429 : 0 : return aToolString;
430 : : }
431 : :
432 : 434 : ::rtl::OUString SbxValue::GetOUString() const
433 : : {
434 : 434 : ::rtl::OUString aResult;
435 : 434 : SbxValues aRes;
436 : 434 : aRes.eType = SbxSTRING;
437 [ + - ][ + - ]: 434 : if( Get( aRes ) )
438 : 434 : aResult = *aRes.pOUString;
439 : :
440 : 434 : return aResult;
441 : : }
442 : :
443 : 1438 : sal_Bool SbxValue::GetBool() const
444 : : {
445 : 1438 : SbxValues aRes;
446 : 1438 : aRes.eType = SbxBOOL;
447 [ + - ]: 1438 : Get( aRes );
448 : 1438 : return sal_Bool( aRes.nUShort != 0 );
449 : : }
450 : :
451 : : #define GET( g, e, t, m ) \
452 : : t SbxValue::g() const { SbxValues aRes(e); Get( aRes ); return aRes.m; }
453 : :
454 [ + - ]: 10 : GET( GetByte, SbxBYTE, sal_uInt8, nByte )
455 [ # # ]: 0 : GET( GetChar, SbxCHAR, xub_Unicode, nChar )
456 [ # # ]: 0 : GET( GetCurrency, SbxCURRENCY, sal_Int64, nInt64 )
457 [ # # ]: 0 : GET( GetDate, SbxDATE, double, nDouble )
458 [ + - ]: 601 : GET( GetDouble, SbxDOUBLE, double, nDouble )
459 [ + - ]: 371 : GET( GetInteger, SbxINTEGER, sal_Int16, nInteger )
460 [ + - ]: 1862 : GET( GetLong, SbxLONG, sal_Int32, nLong )
461 [ + - ]: 16020 : GET( GetObject, SbxOBJECT, SbxBase*, pObj )
462 [ # # ]: 0 : GET( GetSingle, SbxSINGLE, float, nSingle )
463 [ # # ]: 0 : GET( GetULong, SbxULONG, sal_uInt32, nULong )
464 [ # # ]: 0 : GET( GetUShort, SbxUSHORT, sal_uInt16, nUShort )
465 [ # # ]: 0 : GET( GetInt64, SbxSALINT64, sal_Int64, nInt64 )
466 [ # # ]: 0 : GET( GetUInt64, SbxSALUINT64, sal_uInt64, uInt64 )
467 [ # # ]: 0 : GET( GetDecimal, SbxDECIMAL, SbxDecimal*, pDecimal )
468 : :
469 : :
470 : : //////////////////////////// Write data /////////////////////////////
471 : :
472 : 22114 : sal_Bool SbxValue::Put( const SbxValues& rVal )
473 : : {
474 : 22114 : sal_Bool bRes = sal_False;
475 : 22114 : SbxError eOld = GetError();
476 [ - + ]: 22114 : if( eOld != SbxERR_OK )
477 : 0 : ResetError();
478 [ - + ]: 22114 : if( !CanWrite() )
479 : 0 : SetError( SbxERR_PROP_READONLY );
480 [ - + ]: 22114 : else if( rVal.eType & 0xF000 )
481 : 0 : SetError( SbxERR_NOTIMP );
482 : : else
483 : : {
484 : : // If there was asked for an object, don't search
485 : : // the real values
486 : 22114 : SbxValue* p = this;
487 [ + + ]: 22114 : if( rVal.eType != SbxOBJECT )
488 : 21060 : p = TheRealValue( sal_False ); // Don't allow an error here
489 [ + - ]: 22114 : if( p )
490 : : {
491 [ - + ]: 22114 : if( !p->CanWrite() )
492 : 0 : SetError( SbxERR_PROP_READONLY );
493 [ + + ][ + - ]: 22114 : else if( p->IsFixed() || p->SetType( (SbxDataType) ( rVal.eType & 0x0FFF ) ) )
[ + - ]
494 [ + + + - : 22114 : switch( rVal.eType & 0x0FFF )
- - + - -
+ + - - -
- + - - +
- ]
495 : : {
496 : : case SbxEMPTY:
497 : : case SbxVOID:
498 : 374 : case SbxNULL: break;
499 : 7031 : case SbxINTEGER: ImpPutInteger( &p->aData, rVal.nInteger ); break;
500 : 4896 : case SbxLONG: ImpPutLong( &p->aData, rVal.nLong ); break;
501 : 0 : case SbxSALINT64: ImpPutInt64( &p->aData, rVal.nInt64 ); break;
502 : 0 : case SbxSALUINT64: ImpPutUInt64( &p->aData, rVal.uInt64 ); break;
503 : 0 : case SbxSINGLE: ImpPutSingle( &p->aData, rVal.nSingle ); break;
504 : 932 : case SbxDOUBLE: ImpPutDouble( &p->aData, rVal.nDouble ); break;
505 : 0 : case SbxCURRENCY: ImpPutCurrency( &p->aData, rVal.nInt64 ); break;
506 : 0 : case SbxDECIMAL: ImpPutDecimal( &p->aData, rVal.pDecimal ); break;
507 : 3 : case SbxDATE: ImpPutDate( &p->aData, rVal.nDouble ); break;
508 : 2029 : case SbxBOOL: ImpPutBool( &p->aData, rVal.nInteger ); break;
509 : 0 : case SbxCHAR: ImpPutChar( &p->aData, rVal.nChar ); break;
510 : 0 : case SbxBYTE: ImpPutByte( &p->aData, rVal.nByte ); break;
511 : 0 : case SbxUSHORT: ImpPutUShort( &p->aData, rVal.nUShort ); break;
512 : 0 : case SbxULONG: ImpPutULong( &p->aData, rVal.nULong ); break;
513 : : case SbxLPSTR:
514 : 5795 : case SbxSTRING: ImpPutString( &p->aData, rVal.pOUString ); break;
515 : : case SbxINT:
516 : : #if SAL_TYPES_SIZEOFINT == 2
517 : : ImpPutInteger( &p->aData, (sal_Int16) rVal.nInt );
518 : : #else
519 : 0 : ImpPutLong( &p->aData, (sal_Int32) rVal.nInt );
520 : : #endif
521 : 0 : break;
522 : : case SbxUINT:
523 : : #if SAL_TYPES_SIZEOFINT == 2
524 : : ImpPutUShort( &p->aData, (sal_uInt16) rVal.nUInt );
525 : : #else
526 : 0 : ImpPutULong( &p->aData, (sal_uInt32) rVal.nUInt );
527 : : #endif
528 : 0 : break;
529 : : case SbxOBJECT:
530 [ + + ][ + - ]: 1054 : if( !p->IsFixed() || p->aData.eType == SbxOBJECT )
[ + - ]
531 : : {
532 : : // is already inside
533 [ + - ][ + + ]: 1054 : if( p->aData.eType == SbxOBJECT && p->aData.pObj == rVal.pObj )
534 : 6 : break;
535 : :
536 : : // Delete only the value part!
537 : 1048 : p->SbxValue::Clear();
538 : :
539 : : // real allocation
540 : 1048 : p->aData.pObj = rVal.pObj;
541 : :
542 : : // if necessary cont in Ref-Count
543 [ + - ][ + + ]: 1048 : if( p->aData.pObj && p->aData.pObj != p )
544 : : {
545 : : if ( p != this )
546 : : {
547 : : OSL_FAIL( "TheRealValue" );
548 : : }
549 : : HACK(nicht bei Parent-Prop - sonst CyclicRef)
550 [ + - ][ + - ]: 1046 : SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
551 : : sal_Bool bParentProp = pThisVar && 5345 ==
552 [ + - ][ - + ]: 1046 : ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) );
553 [ + - ]: 1046 : if ( !bParentProp )
554 : 1046 : p->aData.pObj->AddRef();
555 : : }
556 : : }
557 : : else
558 : 0 : SetError( SbxERR_CONVERSION );
559 : 1048 : break;
560 : : default:
561 [ # # ]: 0 : if( p->aData.eType == rVal.eType )
562 : 0 : p->aData = rVal;
563 : : else
564 : : {
565 : 0 : SetError( SbxERR_CONVERSION );
566 [ # # ]: 0 : if( !p->IsFixed() )
567 : 22114 : p->aData.eType = SbxNULL;
568 : : }
569 : : }
570 [ + - ]: 22114 : if( !IsError() )
571 : : {
572 : 22114 : p->SetModified( sal_True );
573 : 22114 : p->Broadcast( SBX_HINT_DATACHANGED );
574 [ - + ]: 22114 : if( eOld != SbxERR_OK )
575 : 0 : SetError( eOld );
576 : 22114 : bRes = sal_True;
577 : : }
578 : : }
579 : : }
580 : 22114 : return bRes;
581 : : }
582 : :
583 : : // From 1996-03-28:
584 : : // Method to execute a pretreatment of the strings at special types.
585 : : // In particular necessary for BASIC-IDE, so that
586 : : // the output in the Watch-Window can be writen back with PutStringExt,
587 : : // if Float were declared with ',' as the decimal seperator or BOOl
588 : : // explicit with "TRUE" or "FALSE".
589 : : // Implementation in ImpConvStringExt (SBXSCAN.CXX)
590 : 0 : sal_Bool SbxValue::PutStringExt( const ::rtl::OUString& r )
591 : : {
592 : : // Copy; if it is Unicode convert it immediately
593 : 0 : ::rtl::OUString aStr( r );
594 : :
595 : : // Identify the own type (not as in Put() with TheRealValue(),
596 : : // Objects are not handled anyway)
597 : 0 : SbxDataType eTargetType = SbxDataType( aData.eType & 0x0FFF );
598 : :
599 : : // tinker a Source-Value
600 : 0 : SbxValues aRes;
601 : 0 : aRes.eType = SbxSTRING;
602 : :
603 : : // Only if really something was converted, take the copy,
604 : : // elsewise take the original (Unicode remain)
605 : : sal_Bool bRet;
606 [ # # ][ # # ]: 0 : if( ImpConvStringExt( aStr, eTargetType ) )
607 : 0 : aRes.pOUString = (::rtl::OUString*)&aStr;
608 : : else
609 : 0 : aRes.pOUString = (::rtl::OUString*)&r;
610 : :
611 : : // #34939: Set a Fixed-Flag at Strings. which contain a number, and
612 : : // if this has a Num-Type, so that the type will not be changed
613 : 0 : sal_uInt16 nFlags_ = GetFlags();
614 [ # # ][ # # ]: 0 : if( ( eTargetType >= SbxINTEGER && eTargetType <= SbxCURRENCY ) ||
[ # # ][ # # ]
[ # # ]
615 : : ( eTargetType >= SbxCHAR && eTargetType <= SbxUINT ) ||
616 : : eTargetType == SbxBOOL )
617 : : {
618 [ # # ]: 0 : SbxValue aVal;
619 [ # # ]: 0 : aVal.Put( aRes );
620 [ # # ][ # # ]: 0 : if( aVal.IsNumeric() )
621 [ # # ]: 0 : SetFlag( SBX_FIXED );
622 : : }
623 : :
624 [ # # ]: 0 : Put( aRes );
625 [ # # ]: 0 : bRet = sal_Bool( !IsError() );
626 : :
627 : : // If it throwed an error with FIXED, set it back
628 : : // (UI-Action should not cast an error, but only fail)
629 [ # # ]: 0 : if( !bRet )
630 [ # # ]: 0 : ResetError();
631 : :
632 : 0 : SetFlags( nFlags_ );
633 : 0 : return bRet;
634 : : }
635 : :
636 : 466 : sal_Bool SbxValue::PutBool( sal_Bool b )
637 : : {
638 : 466 : SbxValues aRes;
639 : 466 : aRes.eType = SbxBOOL;
640 [ + + ]: 466 : aRes.nUShort = sal::static_int_cast< sal_uInt16 >(b ? SbxTRUE : SbxFALSE);
641 [ + - ]: 466 : Put( aRes );
642 [ + - ]: 466 : return sal_Bool( !IsError() );
643 : : }
644 : :
645 : 96 : sal_Bool SbxValue::PutEmpty()
646 : : {
647 : 96 : sal_Bool bRet = SetType( SbxEMPTY );
648 : 96 : SetModified( sal_True );
649 : 96 : return bRet;
650 : : }
651 : :
652 : 0 : sal_Bool SbxValue::PutNull()
653 : : {
654 : 0 : sal_Bool bRet = SetType( SbxNULL );
655 [ # # ]: 0 : if( bRet )
656 : 0 : SetModified( sal_True );
657 : 0 : return bRet;
658 : : }
659 : :
660 : :
661 : : // Special decimal methods
662 : 0 : sal_Bool SbxValue::PutDecimal( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
663 : : {
664 : 0 : SbxValue::Clear();
665 [ # # ]: 0 : aData.pDecimal = new SbxDecimal( rAutomationDec );
666 : 0 : aData.pDecimal->addRef();
667 : 0 : aData.eType = SbxDECIMAL;
668 : 0 : return sal_True;
669 : : }
670 : :
671 : 0 : sal_Bool SbxValue::fillAutomationDecimal
672 : : ( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
673 : : {
674 : 0 : SbxDecimal* pDecimal = GetDecimal();
675 [ # # ]: 0 : if( pDecimal != NULL )
676 : : {
677 : 0 : pDecimal->fillAutomationDecimal( rAutomationDec );
678 : 0 : return sal_True;
679 : : }
680 : 0 : return sal_False;
681 : : }
682 : :
683 : :
684 : 2677 : sal_Bool SbxValue::PutString( const ::rtl::OUString& r )
685 : : {
686 : 2677 : SbxValues aRes;
687 : 2677 : aRes.eType = SbxSTRING;
688 : 2677 : aRes.pOUString = (::rtl::OUString*) &r;
689 [ + - ]: 2677 : Put( aRes );
690 [ + - ]: 2677 : return sal_Bool( !IsError() );
691 : : }
692 : :
693 : :
694 : : #define PUT( p, e, t, m ) \
695 : : sal_Bool SbxValue::p( t n ) \
696 : : { SbxValues aRes(e); aRes.m = n; Put( aRes ); return sal_Bool( !IsError() ); }
697 : :
698 [ # # ][ # # ]: 0 : PUT( PutByte, SbxBYTE, sal_uInt8, nByte )
699 [ # # ][ # # ]: 0 : PUT( PutChar, SbxCHAR, sal_Unicode, nChar )
700 [ # # ][ # # ]: 0 : PUT( PutCurrency, SbxCURRENCY, const sal_Int64&, nInt64 )
701 [ # # ][ # # ]: 0 : PUT( PutDate, SbxDATE, double, nDouble )
702 [ + - ][ + - ]: 50 : PUT( PutDouble, SbxDOUBLE, double, nDouble )
703 [ # # ][ # # ]: 0 : PUT( PutErr, SbxERROR, sal_uInt16, nUShort )
704 [ + - ][ + - ]: 2382 : PUT( PutInteger, SbxINTEGER, sal_Int16, nInteger )
705 [ + - ][ + - ]: 370 : PUT( PutLong, SbxLONG, sal_Int32, nLong )
706 [ + - ][ + - ]: 800 : PUT( PutObject, SbxOBJECT, SbxBase*, pObj )
707 [ # # ][ # # ]: 0 : PUT( PutSingle, SbxSINGLE, float, nSingle )
708 [ # # ][ # # ]: 0 : PUT( PutULong, SbxULONG, sal_uInt32, nULong )
709 [ # # ][ # # ]: 0 : PUT( PutUShort, SbxUSHORT, sal_uInt16, nUShort )
710 [ # # ][ # # ]: 0 : PUT( PutInt64, SbxSALINT64, sal_Int64, nInt64 )
711 [ # # ][ # # ]: 0 : PUT( PutUInt64, SbxSALUINT64, sal_uInt64, uInt64 )
712 [ # # ][ # # ]: 0 : PUT( PutDecimal, SbxDECIMAL, SbxDecimal*, pDecimal )
713 : :
714 : : ////////////////////////// Setting of the data type ///////////////////////////
715 : :
716 : 51066 : sal_Bool SbxValue::IsFixed() const
717 : : {
718 : 51066 : return ( (GetFlags() & SBX_FIXED) | (aData.eType & SbxBYREF) ) != 0;
719 : : }
720 : :
721 : : // A variable is numeric, if it is EMPTY or realy numeric
722 : : // or if it contains a complete convertible String
723 : :
724 : : // #41692, implement it for RTL and Basic-Core seperably
725 : 0 : sal_Bool SbxValue::IsNumeric() const
726 : : {
727 : 0 : return ImpIsNumeric( /*bOnlyIntntl*/sal_False );
728 : : }
729 : :
730 : 0 : sal_Bool SbxValue::IsNumericRTL() const
731 : : {
732 : 0 : return ImpIsNumeric( /*bOnlyIntntl*/sal_True );
733 : : }
734 : :
735 : 0 : sal_Bool SbxValue::ImpIsNumeric( sal_Bool bOnlyIntntl ) const
736 : : {
737 : :
738 [ # # ]: 0 : if( !CanRead() )
739 : : {
740 : 0 : SetError( SbxERR_PROP_WRITEONLY ); return sal_False;
741 : : }
742 : : // Test downcast!!!
743 [ # # ]: 0 : if( this->ISA(SbxVariable) )
744 : 0 : ((SbxVariable*)this)->Broadcast( SBX_HINT_DATAWANTED );
745 : 0 : SbxDataType t = GetType();
746 [ # # ]: 0 : if( t == SbxSTRING )
747 : : {
748 [ # # ]: 0 : if( aData.pOUString )
749 : : {
750 : 0 : ::rtl::OUString s( *aData.pOUString );
751 : : double n;
752 : : SbxDataType t2;
753 : 0 : sal_uInt16 nLen = 0;
754 [ # # ][ # # ]: 0 : if( ImpScan( s, n, t2, &nLen, /*bAllowIntntl*/sal_False, bOnlyIntntl ) == SbxERR_OK )
755 [ # # ]: 0 : return sal_Bool( nLen == s.getLength() );
756 : : }
757 : 0 : return sal_False;
758 : : }
759 : : else
760 : : return sal_Bool( t == SbxEMPTY
761 : : || ( t >= SbxINTEGER && t <= SbxCURRENCY )
762 [ # # ][ # # ]: 0 : || ( t >= SbxCHAR && t <= SbxUINT ) );
[ # # ][ # # ]
[ # # ]
763 : : }
764 : :
765 : 0 : SbxClassType SbxValue::GetClass() const
766 : : {
767 : 0 : return SbxCLASS_VALUE;
768 : : }
769 : :
770 : 19670 : SbxDataType SbxValue::GetType() const
771 : : {
772 : 19670 : return SbxDataType( aData.eType & 0x0FFF );
773 : : }
774 : :
775 : 0 : SbxDataType SbxValue::GetFullType() const
776 : : {
777 : 0 : return aData.eType;
778 : : }
779 : :
780 : 16630 : sal_Bool SbxValue::SetType( SbxDataType t )
781 : : {
782 : : DBG_ASSERT( !( t & 0xF000 ), "Setzen von BYREF|ARRAY verboten!" );
783 [ + + ][ - + ]: 16630 : if( ( t == SbxEMPTY && aData.eType == SbxVOID )
[ + + ][ + + ]
784 : : || ( aData.eType == SbxEMPTY && t == SbxVOID ) )
785 : 240 : return sal_True;
786 [ + + ]: 16390 : if( ( t & 0x0FFF ) == SbxVARIANT )
787 : : {
788 : : // Trial to set the data type to Variant
789 : 81 : ResetFlag( SBX_FIXED );
790 [ - + ]: 81 : if( IsFixed() )
791 : : {
792 : 0 : SetError( SbxERR_CONVERSION ); return sal_False;
793 : : }
794 : 81 : t = SbxEMPTY;
795 : : }
796 [ + + ]: 16390 : if( ( t & 0x0FFF ) != ( aData.eType & 0x0FFF ) )
797 : : {
798 [ + - ][ - + ]: 7778 : if( !CanWrite() || IsFixed() )
[ - + ]
799 : : {
800 : 0 : SetError( SbxERR_CONVERSION ); return sal_False;
801 : : }
802 : : else
803 : : {
804 : : // De-allocate potential objects
805 [ + - + ]: 7778 : switch( aData.eType )
806 : : {
807 : : case SbxSTRING:
808 [ + + ]: 24 : delete aData.pOUString;
809 : 24 : break;
810 : : case SbxOBJECT:
811 [ # # ][ # # ]: 0 : if( aData.pObj && aData.pObj != this )
812 : : {
813 : : HACK(nicht bei Parent-Prop - sonst CyclicRef)
814 [ # # ][ # # ]: 0 : SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
815 : : sal_uInt16 nSlotId = pThisVar
816 : 0 : ? ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) )
817 [ # # ]: 0 : : 0;
818 : : DBG_ASSERT( nSlotId != 5345 || pThisVar->GetName().EqualsAscii("Parent"),
819 : : "SID_PARENTOBJECT heisst nicht 'Parent'" );
820 : 0 : sal_Bool bParentProp = 5345 == nSlotId;
821 [ # # ]: 0 : if ( !bParentProp )
822 : 0 : aData.pObj->ReleaseRef();
823 : : }
824 : 0 : break;
825 : 7754 : default: break;
826 : : }
827 : : // This works always, because the Float representations are 0 as well.
828 : 7778 : memset( &aData, 0, sizeof( SbxValues ) );
829 : 7778 : aData.eType = t;
830 : : }
831 : : }
832 : 16630 : return sal_True;
833 : : }
834 : :
835 : 4 : sal_Bool SbxValue::Convert( SbxDataType eTo )
836 : : {
837 : 4 : eTo = SbxDataType( eTo & 0x0FFF );
838 [ + - ]: 4 : if( ( aData.eType & 0x0FFF ) == eTo )
839 : 4 : return sal_True;
840 [ # # ]: 0 : if( !CanWrite() )
841 : 0 : return sal_False;
842 [ # # ]: 0 : if( eTo == SbxVARIANT )
843 : : {
844 : : // Trial to set the data type to Variant
845 : 0 : ResetFlag( SBX_FIXED );
846 [ # # ][ # # ]: 0 : if( IsFixed() )
847 : : {
848 [ # # ]: 0 : SetError( SbxERR_CONVERSION ); return sal_False;
849 : : }
850 : : else
851 : 0 : return sal_True;
852 : : }
853 : : // Converting from zero doesn't work. Once zero, always zero!
854 [ # # ]: 0 : if( aData.eType == SbxNULL )
855 : : {
856 [ # # ]: 0 : SetError( SbxERR_CONVERSION ); return sal_False;
857 : : }
858 : :
859 : : // Conversion of the data:
860 : 0 : SbxValues aNew;
861 : 0 : aNew.eType = eTo;
862 [ # # ][ # # ]: 0 : if( Get( aNew ) )
863 : : {
864 : : // The data type could be converted. It ends here with fixed elements,
865 : : // because the data had not to be taken over
866 [ # # ][ # # ]: 0 : if( !IsFixed() )
867 : : {
868 [ # # ]: 0 : SetType( eTo );
869 [ # # ]: 0 : Put( aNew );
870 [ # # ]: 0 : SetModified( sal_True );
871 : : }
872 [ # # ]: 0 : Broadcast( SBX_HINT_CONVERTED );
873 : 0 : return sal_True;
874 : : }
875 : : else
876 : 4 : return sal_False;
877 : : }
878 : : ////////////////////////////////// Calculating /////////////////////////////////
879 : :
880 : 3351 : sal_Bool SbxValue::Compute( SbxOperator eOp, const SbxValue& rOp )
881 : : {
882 : : #ifdef DISABLE_SCRIPTING
883 : : bool bVBAInterop = false;
884 : : #else
885 : 3351 : bool bVBAInterop = SbiRuntime::isVBAEnabled();
886 : : #endif
887 : 3351 : SbxDataType eThisType = GetType();
888 : 3351 : SbxDataType eOpType = rOp.GetType();
889 : 3351 : SbxError eOld = GetError();
890 [ - + ]: 3351 : if( eOld != SbxERR_OK )
891 : 0 : ResetError();
892 [ - + ]: 3351 : if( !CanWrite() )
893 : 0 : SetError( SbxERR_PROP_READONLY );
894 [ - + ]: 3351 : else if( !rOp.CanRead() )
895 : 0 : SetError( SbxERR_PROP_WRITEONLY );
896 : : // Special rule 1: If one operand is zero, the result is zero
897 [ + - ][ - + ]: 3351 : else if( eThisType == SbxNULL || eOpType == SbxNULL )
898 : 0 : SetType( SbxNULL );
899 : : // Special rule 2: If the operand is Empty, the result is the 2. operand
900 [ - + ][ # # ]: 3351 : else if( eThisType == SbxEMPTY
901 : 0 : && !bVBAInterop
902 : : )
903 : 0 : *this = rOp;
904 : : // 1996-2-13: Don't test already before Get upon SbxEMPTY
905 : : else
906 : : {
907 : 3351 : SbxValues aL, aR;
908 : 3351 : bool bDecimal = false;
909 [ + + ][ + + ]: 3351 : if( bVBAInterop && ( ( eThisType == SbxSTRING && eOpType != SbxSTRING && eOpType != SbxEMPTY ) ||
[ - + ][ + + ]
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ]
910 : : ( eThisType != SbxSTRING && eThisType != SbxEMPTY && eOpType == SbxSTRING ) ) &&
911 : : ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS ) )
912 : : {
913 : : goto Lbl_OpIsDouble;
914 : : }
915 [ + + ][ + - ]: 3351 : else if( eThisType == SbxSTRING || eOp == SbxCAT || ( bVBAInterop && ( eOpType == SbxSTRING ) && ( eOp == SbxPLUS ) ) )
[ + + ][ - + ]
[ # # ]
916 : : {
917 [ + + ][ + - ]: 1424 : if( eOp == SbxCAT || eOp == SbxPLUS )
918 : : {
919 : : // From 1999-11-5, keep OUString in mind
920 : 712 : aL.eType = aR.eType = SbxSTRING;
921 [ + - ]: 712 : rOp.Get( aR );
922 : : // From 1999-12-8, #70399: Here call GetType() again, Get() can change the type!
923 [ + - ][ + - ]: 712 : if( rOp.GetType() == SbxEMPTY )
924 : : goto Lbl_OpIsEmpty;
925 [ + - ]: 712 : Get( aL );
926 : :
927 : : // #30576: To begin with test, if the conversion worked
928 [ + - ][ + - ]: 712 : if( aL.pOUString != NULL && aR.pOUString != NULL )
929 : : {
930 : 712 : *aL.pOUString += *aR.pOUString;
931 : : }
932 : : // Not even Left OK?
933 [ # # ]: 0 : else if( aL.pOUString == NULL )
934 : : {
935 [ # # ]: 0 : aL.pOUString = new ::rtl::OUString();
936 : : }
937 [ + - ]: 712 : Put( aL );
938 : : }
939 : : else
940 [ # # ]: 0 : SetError( SbxERR_CONVERSION );
941 : : }
942 [ - + ][ # # ]: 2639 : else if( eOpType == SbxSTRING && rOp.IsFixed() )
[ # # ][ - + ]
943 : : { // Numeric: there is no String allowed on the right side
944 [ # # ]: 0 : SetError( SbxERR_CONVERSION );
945 : : // falls all the way out
946 : : }
947 [ + + ][ - + ]: 2639 : else if( ( eOp >= SbxIDIV && eOp <= SbxNOT ) || eOp == SbxMOD )
[ - + ]
948 : : {
949 [ + - ][ + + ]: 2032 : if( GetType() == eOpType )
950 : : {
951 [ + - ][ + - ]: 6084 : if( GetType() == SbxSALUINT64 || GetType() == SbxSALINT64
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
952 [ + - ][ + - ]: 4056 : || GetType() == SbxCURRENCY || GetType() == SbxULONG )
953 [ # # ]: 0 : aL.eType = aR.eType = GetType();
954 [ - + ][ # # ]: 2028 : else if ( bVBAInterop && eOpType == SbxBOOL )
955 : 0 : aL.eType = aR.eType = SbxBOOL;
956 : : else
957 : 2028 : aL.eType = aR.eType = SbxLONG;
958 : : }
959 : : else
960 : 4 : aL.eType = aR.eType = SbxLONG;
961 : :
962 [ + - ][ + - ]: 4064 : if( rOp.Get( aR ) ) // re-do Get after type assigns above
963 : : {
964 [ + - ][ - + ]: 2032 : if( rOp.GetType() == SbxEMPTY )
965 : : {
966 [ # # ][ # # ]: 0 : if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNOT ) ) )
[ # # ]
967 : : goto Lbl_OpIsEmpty;
968 : : }
969 [ + - ][ + - ]: 2032 : if( Get( aL ) ) switch( eOp )
[ - - + +
- - - +
- ]
970 : : {
971 : : case SbxIDIV:
972 [ # # ]: 0 : if( aL.eType == SbxCURRENCY )
973 [ # # ][ # # ]: 0 : if( !aR.nInt64 ) SetError( SbxERR_ZERODIV );
974 : : else {
975 : 0 : aL.nInt64 /= aR.nInt64;
976 : 0 : aL.nInt64 *= CURRENCY_FACTOR;
977 : : }
978 [ # # ]: 0 : else if( aL.eType == SbxSALUINT64 )
979 [ # # ][ # # ]: 0 : if( !aR.uInt64 ) SetError( SbxERR_ZERODIV );
980 : 0 : else aL.uInt64 /= aR.uInt64;
981 [ # # ]: 0 : else if( aL.eType == SbxSALINT64 )
982 [ # # ][ # # ]: 0 : if( !aR.nInt64 ) SetError( SbxERR_ZERODIV );
983 : 0 : else aL.nInt64 /= aR.nInt64;
984 [ # # ]: 0 : else if( aL.eType == SbxLONG )
985 [ # # ][ # # ]: 0 : if( !aR.nLong ) SetError( SbxERR_ZERODIV );
986 : 0 : else aL.nLong /= aR.nLong;
987 : : else
988 [ # # ][ # # ]: 0 : if( !aR.nULong ) SetError( SbxERR_ZERODIV );
989 : 0 : else aL.nULong /= aR.nULong;
990 : 0 : break;
991 : : case SbxMOD:
992 [ # # ][ # # ]: 0 : if( aL.eType == SbxCURRENCY || aL.eType == SbxSALINT64 )
993 [ # # ][ # # ]: 0 : if( !aR.nInt64 ) SetError( SbxERR_ZERODIV );
994 : 0 : else aL.nInt64 %= aR.nInt64;
995 [ # # ]: 0 : else if( aL.eType == SbxSALUINT64 )
996 [ # # ][ # # ]: 0 : if( !aR.uInt64 ) SetError( SbxERR_ZERODIV );
997 : 0 : else aL.uInt64 %= aR.uInt64;
998 [ # # ]: 0 : else if( aL.eType == SbxLONG )
999 [ # # ][ # # ]: 0 : if( !aR.nLong ) SetError( SbxERR_ZERODIV );
1000 : 0 : else aL.nLong %= aR.nLong;
1001 : : else
1002 [ # # ][ # # ]: 0 : if( !aR.nULong ) SetError( SbxERR_ZERODIV );
1003 : 0 : else aL.nULong %= aR.nULong;
1004 : 0 : break;
1005 : : case SbxAND:
1006 [ - + ][ # # ]: 136 : if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1007 : 0 : aL.nInt64 &= aR.nInt64;
1008 : : else
1009 : 136 : aL.nLong &= aR.nLong;
1010 : 136 : break;
1011 : : case SbxOR:
1012 [ - + ][ # # ]: 1788 : if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1013 : 0 : aL.nInt64 |= aR.nInt64;
1014 : : else
1015 : 1788 : aL.nLong |= aR.nLong;
1016 : 1788 : break;
1017 : : case SbxXOR:
1018 [ # # ][ # # ]: 0 : if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1019 : 0 : aL.nInt64 ^= aR.nInt64;
1020 : : else
1021 : 0 : aL.nLong ^= aR.nLong;
1022 : 0 : break;
1023 : : case SbxEQV:
1024 [ # # ][ # # ]: 0 : if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1025 : 0 : aL.nInt64 = (aL.nInt64 & aR.nInt64) | (~aL.nInt64 & ~aR.nInt64);
1026 : : else
1027 : 0 : aL.nLong = (aL.nLong & aR.nLong) | (~aL.nLong & ~aR.nLong);
1028 : 0 : break;
1029 : : case SbxIMP:
1030 [ # # ][ # # ]: 0 : if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1031 : 0 : aL.nInt64 = ~aL.nInt64 | aR.nInt64;
1032 : : else
1033 : 0 : aL.nLong = ~aL.nLong | aR.nLong;
1034 : 0 : break;
1035 : : case SbxNOT:
1036 [ - + ][ # # ]: 108 : if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1037 : : {
1038 [ # # ]: 0 : if ( aL.eType != SbxBOOL )
1039 : 0 : aL.nInt64 = ~aL.nInt64;
1040 : : else
1041 : 0 : aL.nLong = ~aL.nLong;
1042 : : }
1043 : : else
1044 : 108 : aL.nLong = ~aL.nLong;
1045 : 108 : break;
1046 : 2032 : default: break;
1047 : : }
1048 : : }
1049 : : }
1050 [ + - ][ + - ]: 607 : else if( ( GetType() == SbxDECIMAL || rOp.GetType() == SbxDECIMAL )
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ - + ]
1051 : : && ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS || eOp == SbxNEG ) )
1052 : : {
1053 : 0 : aL.eType = aR.eType = SbxDECIMAL;
1054 : 0 : bDecimal = true;
1055 [ # # ][ # # ]: 0 : if( rOp.Get( aR ) )
1056 : : {
1057 [ # # ][ # # ]: 0 : if( rOp.GetType() == SbxEMPTY )
1058 : : {
1059 [ # # ]: 0 : releaseDecimalPtr( aL.pDecimal );
1060 : : goto Lbl_OpIsEmpty;
1061 : : }
1062 [ # # ][ # # ]: 0 : if( Get( aL ) )
1063 : : {
1064 [ # # ][ # # ]: 0 : if( aL.pDecimal && aR.pDecimal )
1065 : : {
1066 : 0 : bool bOk = true;
1067 [ # # # # : 0 : switch( eOp )
# # ]
1068 : : {
1069 : : case SbxMUL:
1070 [ # # ]: 0 : bOk = ( *(aL.pDecimal) *= *(aR.pDecimal) );
1071 : 0 : break;
1072 : : case SbxDIV:
1073 [ # # ][ # # ]: 0 : if( aR.pDecimal->isZero() )
1074 [ # # ]: 0 : SetError( SbxERR_ZERODIV );
1075 : : else
1076 [ # # ]: 0 : bOk = ( *(aL.pDecimal) /= *(aR.pDecimal) );
1077 : 0 : break;
1078 : : case SbxPLUS:
1079 [ # # ]: 0 : bOk = ( *(aL.pDecimal) += *(aR.pDecimal) );
1080 : 0 : break;
1081 : : case SbxMINUS:
1082 [ # # ]: 0 : bOk = ( *(aL.pDecimal) -= *(aR.pDecimal) );
1083 : 0 : break;
1084 : : case SbxNEG:
1085 [ # # ]: 0 : bOk = ( aL.pDecimal->neg() );
1086 : 0 : break;
1087 : : default:
1088 [ # # ]: 0 : SetError( SbxERR_NOTIMP );
1089 : : }
1090 [ # # ]: 0 : if( !bOk )
1091 [ # # ]: 0 : SetError( SbxERR_OVERFLOW );
1092 : : }
1093 : : else
1094 : : {
1095 [ # # ]: 0 : SetError( SbxERR_CONVERSION );
1096 : : }
1097 : : }
1098 : : }
1099 : : }
1100 [ + - ][ + - ]: 607 : else if( GetType() == SbxCURRENCY || rOp.GetType() == SbxCURRENCY )
[ + - ][ - + ]
[ - + ]
1101 : : {
1102 : 0 : aL.eType = SbxCURRENCY;
1103 : 0 : aR.eType = SbxCURRENCY;
1104 : :
1105 [ # # ][ # # ]: 0 : if( rOp.Get( aR ) )
1106 : : {
1107 [ # # ][ # # ]: 0 : if( rOp.GetType() == SbxEMPTY )
1108 : : goto Lbl_OpIsEmpty;
1109 : :
1110 [ # # ][ # # ]: 0 : if( Get( aL ) ) switch( eOp )
[ # # # #
# # ]
1111 : : {
1112 : : double dTest;
1113 : : case SbxMUL:
1114 : : // first overflow check: see if product will fit - test real value of product (hence 2 curr factors)
1115 : 0 : dTest = (double)aL.nInt64 * (double)aR.nInt64 / (double)CURRENCY_FACTOR_SQUARE;
1116 [ # # ][ # # ]: 0 : if( dTest < SbxMINCURR || SbxMAXCURR < dTest)
1117 : : {
1118 : 0 : aL.nInt64 = SAL_MAX_INT64;
1119 [ # # ]: 0 : if( dTest < SbxMINCURR ) aL.nInt64 = SAL_MIN_INT64;
1120 [ # # ]: 0 : SetError( SbxERR_OVERFLOW );
1121 : 0 : break;
1122 : : }
1123 : : // second overflow check: see if unscaled product overflows - if so use doubles
1124 : 0 : dTest = (double)aL.nInt64 * (double)aR.nInt64;
1125 [ # # ][ # # ]: 0 : if( dTest < SAL_MIN_INT64 || SAL_MAX_INT64 < dTest)
1126 : : {
1127 : 0 : aL.nInt64 = (sal_Int64)( dTest / (double)CURRENCY_FACTOR );
1128 : 0 : break;
1129 : : }
1130 : : // precise calc: multiply then scale back (move decimal pt)
1131 : 0 : aL.nInt64 *= aR.nInt64;
1132 : 0 : aL.nInt64 /= CURRENCY_FACTOR;
1133 : 0 : break;
1134 : :
1135 : : case SbxDIV:
1136 [ # # ]: 0 : if( !aR.nInt64 )
1137 : : {
1138 [ # # ]: 0 : SetError( SbxERR_ZERODIV );
1139 : 0 : break;
1140 : : }
1141 : : // first overflow check: see if quotient will fit - calc real value of quotient (curr factors cancel)
1142 : 0 : dTest = (double)aL.nInt64 / (double)aR.nInt64;
1143 [ # # ][ # # ]: 0 : if( dTest < SbxMINCURR || SbxMAXCURR < dTest)
1144 : : {
1145 [ # # ]: 0 : SetError( SbxERR_OVERFLOW );
1146 : 0 : break;
1147 : : }
1148 : : // second overflow check: see if scaled dividend overflows - if so use doubles
1149 : 0 : dTest = (double)aL.nInt64 * (double)CURRENCY_FACTOR;
1150 [ # # ][ # # ]: 0 : if( dTest < SAL_MIN_INT64 || SAL_MAX_INT64 < dTest)
1151 : : {
1152 : 0 : aL.nInt64 = (sal_Int64)(dTest / (double)aR.nInt64);
1153 : 0 : break;
1154 : : }
1155 : : // precise calc: scale (move decimal pt) then divide
1156 : 0 : aL.nInt64 *= CURRENCY_FACTOR;
1157 : 0 : aL.nInt64 /= aR.nInt64;
1158 : 0 : break;
1159 : :
1160 : : case SbxPLUS:
1161 : 0 : dTest = ( (double)aL.nInt64 + (double)aR.nInt64 ) / (double)CURRENCY_FACTOR;
1162 [ # # ][ # # ]: 0 : if( dTest < SbxMINCURR || SbxMAXCURR < dTest)
1163 : : {
1164 [ # # ]: 0 : SetError( SbxERR_OVERFLOW );
1165 : 0 : break;
1166 : : }
1167 : 0 : aL.nInt64 += aR.nInt64;
1168 : 0 : break;
1169 : :
1170 : : case SbxMINUS:
1171 : 0 : dTest = ( (double)aL.nInt64 - (double)aR.nInt64 ) / (double)CURRENCY_FACTOR;
1172 [ # # ][ # # ]: 0 : if( dTest < SbxMINCURR || SbxMAXCURR < dTest)
1173 : : {
1174 [ # # ]: 0 : SetError( SbxERR_OVERFLOW );
1175 : 0 : break;
1176 : : }
1177 : 0 : aL.nInt64 -= aR.nInt64;
1178 : 0 : break;
1179 : : case SbxNEG:
1180 : 0 : aL.nInt64 = -aL.nInt64;
1181 : 0 : break;
1182 : : default:
1183 [ # # ]: 0 : SetError( SbxERR_NOTIMP );
1184 : : }
1185 : : }
1186 : : }
1187 : : else
1188 : : Lbl_OpIsDouble:
1189 : : { // other types and operators including Date, Double and Single
1190 : 607 : aL.eType = aR.eType = SbxDOUBLE;
1191 [ + - ][ + - ]: 607 : if( rOp.Get( aR ) )
1192 : : {
1193 [ + - ][ - + ]: 607 : if( rOp.GetType() == SbxEMPTY )
1194 : : {
1195 [ # # ][ # # ]: 0 : if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNEG ) ) )
[ # # ]
1196 : : goto Lbl_OpIsEmpty;
1197 : : }
1198 [ + - ][ + - ]: 607 : if( Get( aL ) )
1199 : : {
1200 [ - - - + : 607 : switch( eOp )
+ - - ]
1201 : : {
1202 : : case SbxEXP:
1203 : 0 : aL.nDouble = pow( aL.nDouble, aR.nDouble );
1204 : 0 : break;
1205 : : case SbxMUL:
1206 : 0 : aL.nDouble *= aR.nDouble; break;
1207 : : case SbxDIV:
1208 [ # # ][ # # ]: 0 : if( !aR.nDouble ) SetError( SbxERR_ZERODIV );
1209 : 0 : else aL.nDouble /= aR.nDouble; break;
1210 : : case SbxPLUS:
1211 : 603 : aL.nDouble += aR.nDouble; break;
1212 : : case SbxMINUS:
1213 : 4 : aL.nDouble -= aR.nDouble; break;
1214 : : case SbxNEG:
1215 : 0 : aL.nDouble = -aL.nDouble; break;
1216 : : default:
1217 [ # # ]: 0 : SetError( SbxERR_NOTIMP );
1218 : : }
1219 : : // Date with "+" or "-" needs special handling that
1220 : : // forces the Date type. If the operation is '+' the
1221 : : // result is always a Date, if '-' the result is only
1222 : : // a Date if one of lhs or rhs ( but not both ) is already
1223 : : // a Date
1224 [ + - ][ + - ]: 607 : if( ( GetType() == SbxDATE || rOp.GetType() == SbxDATE ) )
[ + - ][ - + ]
[ - + ]
1225 : : {
1226 [ # # ][ # # ]: 0 : if( eOp == SbxPLUS || ( ( eOp == SbxMINUS ) && ( GetType() != rOp.GetType() ) ) )
[ # # ][ # # ]
[ # # ][ # # ]
1227 : 0 : aL.eType = SbxDATE;
1228 : : }
1229 : :
1230 : : }
1231 : : }
1232 : :
1233 : : }
1234 [ + - ][ + - ]: 3351 : if( !IsError() )
1235 [ + - ]: 3351 : Put( aL );
1236 [ - + ]: 3351 : if( bDecimal )
1237 : : {
1238 [ # # ]: 0 : releaseDecimalPtr( aL.pDecimal );
1239 [ # # ]: 3351 : releaseDecimalPtr( aR.pDecimal );
1240 : : }
1241 : : }
1242 : : Lbl_OpIsEmpty:
1243 : :
1244 : 3351 : sal_Bool bRes = sal_Bool( !IsError() );
1245 [ - + ][ + - ]: 3351 : if( bRes && eOld != SbxERR_OK )
1246 : 0 : SetError( eOld );
1247 : 3351 : return bRes;
1248 : : }
1249 : :
1250 : : // The comparison routine deliver TRUE or FALSE.
1251 : :
1252 : 3576 : sal_Bool SbxValue::Compare( SbxOperator eOp, const SbxValue& rOp ) const
1253 : : {
1254 : : #ifdef DISABLE_SCRIPTING
1255 : : bool bVBAInterop = false;
1256 : : #else
1257 : 3576 : bool bVBAInterop = SbiRuntime::isVBAEnabled();
1258 : : #endif
1259 : :
1260 : 3576 : sal_Bool bRes = sal_False;
1261 : 3576 : SbxError eOld = GetError();
1262 [ - + ]: 3576 : if( eOld != SbxERR_OK )
1263 : 0 : ResetError();
1264 [ + - ][ - + ]: 3576 : if( !CanRead() || !rOp.CanRead() )
[ - + ]
1265 : 0 : SetError( SbxERR_PROP_WRITEONLY );
1266 [ - + ][ # # ]: 3576 : else if( GetType() == SbxNULL && rOp.GetType() == SbxNULL && !bVBAInterop )
[ # # ][ - + ]
1267 : : {
1268 : 0 : bRes = sal_True;
1269 : : }
1270 [ - + ][ # # ]: 3576 : else if( GetType() == SbxEMPTY && rOp.GetType() == SbxEMPTY )
[ - + ]
1271 [ # # ][ # # ]: 0 : bRes = !bVBAInterop ? sal_True : ( eOp == SbxEQ ? sal_True : sal_False );
1272 : : // Special rule 1: If an operand is zero, the result is FALSE
1273 [ + - ][ - + ]: 3576 : else if( GetType() == SbxNULL || rOp.GetType() == SbxNULL )
[ - + ]
1274 : 0 : bRes = sal_False;
1275 : : // Special rule 2: If both are variant and one is numeric
1276 : : // and the other is a String, num is < str
1277 [ + + ][ + - : 3948 : else if( !IsFixed() && !rOp.IsFixed()
+ + - + #
# ][ # # ]
[ - + ]
1278 : 372 : && ( rOp.GetType() == SbxSTRING && GetType() != SbxSTRING && IsNumeric() ) && !bVBAInterop
1279 : : )
1280 [ # # ][ # # ]: 0 : bRes = sal_Bool( eOp == SbxLT || eOp == SbxLE || eOp == SbxNE );
[ # # ]
1281 [ + + ][ + - : 3948 : else if( !IsFixed() && !rOp.IsFixed()
+ + - + #
# ][ # # ]
[ - + ]
1282 : 372 : && ( GetType() == SbxSTRING && rOp.GetType() != SbxSTRING && rOp.IsNumeric() )
1283 : 0 : && !bVBAInterop
1284 : : )
1285 [ # # ][ # # ]: 0 : bRes = sal_Bool( eOp == SbxGT || eOp == SbxGE || eOp == SbxNE );
[ # # ]
1286 : : else
1287 : : {
1288 : 3576 : SbxValues aL, aR;
1289 : : // If one of the operands is a String,
1290 : : // a String comparing take place
1291 [ + + ][ + - ]: 3576 : if( GetType() == SbxSTRING || rOp.GetType() == SbxSTRING )
[ - + ][ + + ]
[ + - ]
1292 : : {
1293 : 268 : aL.eType = aR.eType = SbxSTRING;
1294 [ + - ][ + - ]: 268 : if( Get( aL ) && rOp.Get( aR ) ) switch( eOp )
[ + - ][ + - ]
[ + - ][ + +
- - - -
- ]
1295 : : {
1296 : : case SbxEQ:
1297 : 36 : bRes = sal_Bool( *aL.pOUString == *aR.pOUString ); break;
1298 : : case SbxNE:
1299 : 232 : bRes = sal_Bool( *aL.pOUString != *aR.pOUString ); break;
1300 : : case SbxLT:
1301 : 0 : bRes = sal_Bool( *aL.pOUString < *aR.pOUString ); break;
1302 : : case SbxGT:
1303 : 0 : bRes = sal_Bool( *aL.pOUString > *aR.pOUString ); break;
1304 : : case SbxLE:
1305 : 0 : bRes = sal_Bool( *aL.pOUString <= *aR.pOUString ); break;
1306 : : case SbxGE:
1307 : 0 : bRes = sal_Bool( *aL.pOUString >= *aR.pOUString ); break;
1308 : : default:
1309 [ # # ]: 268 : SetError( SbxERR_NOTIMP );
1310 : : }
1311 : : }
1312 : : // From 1995-12-19: If SbxSINGLE participate, then convert to SINGLE,
1313 : : // elsewise it shows a numeric error
1314 [ + - ][ + - ]: 3308 : else if( GetType() == SbxSINGLE || rOp.GetType() == SbxSINGLE )
[ + - ][ - + ]
[ - + ]
1315 : : {
1316 : 0 : aL.eType = aR.eType = SbxSINGLE;
1317 [ # # ][ # # ]: 0 : if( Get( aL ) && rOp.Get( aR ) )
[ # # ][ # # ]
[ # # ]
1318 [ # # # # : 0 : switch( eOp )
# # # ]
1319 : : {
1320 : : case SbxEQ:
1321 : 0 : bRes = sal_Bool( aL.nSingle == aR.nSingle ); break;
1322 : : case SbxNE:
1323 : 0 : bRes = sal_Bool( aL.nSingle != aR.nSingle ); break;
1324 : : case SbxLT:
1325 : 0 : bRes = sal_Bool( aL.nSingle < aR.nSingle ); break;
1326 : : case SbxGT:
1327 : 0 : bRes = sal_Bool( aL.nSingle > aR.nSingle ); break;
1328 : : case SbxLE:
1329 : 0 : bRes = sal_Bool( aL.nSingle <= aR.nSingle ); break;
1330 : : case SbxGE:
1331 : 0 : bRes = sal_Bool( aL.nSingle >= aR.nSingle ); break;
1332 : : default:
1333 [ # # ]: 0 : SetError( SbxERR_NOTIMP );
1334 : : }
1335 : : }
1336 [ + - ][ - + ]: 3308 : else if( GetType() == SbxDECIMAL && rOp.GetType() == SbxDECIMAL )
[ # # ][ # # ]
[ - + ]
1337 : : {
1338 : 0 : aL.eType = aR.eType = SbxDECIMAL;
1339 [ # # ]: 0 : Get( aL );
1340 [ # # ]: 0 : rOp.Get( aR );
1341 [ # # ][ # # ]: 0 : if( aL.pDecimal && aR.pDecimal )
1342 : : {
1343 [ # # ]: 0 : SbxDecimal::CmpResult eRes = compare( *aL.pDecimal, *aR.pDecimal );
1344 [ # # # # : 0 : switch( eOp )
# # # ]
1345 : : {
1346 : : case SbxEQ:
1347 : 0 : bRes = sal_Bool( eRes == SbxDecimal::EQ ); break;
1348 : : case SbxNE:
1349 : 0 : bRes = sal_Bool( eRes != SbxDecimal::EQ ); break;
1350 : : case SbxLT:
1351 : 0 : bRes = sal_Bool( eRes == SbxDecimal::LT ); break;
1352 : : case SbxGT:
1353 : 0 : bRes = sal_Bool( eRes == SbxDecimal::GT ); break;
1354 : : case SbxLE:
1355 : 0 : bRes = sal_Bool( eRes != SbxDecimal::GT ); break;
1356 : : case SbxGE:
1357 : 0 : bRes = sal_Bool( eRes != SbxDecimal::LT ); break;
1358 : : default:
1359 [ # # ]: 0 : SetError( SbxERR_NOTIMP );
1360 : 0 : }
1361 : : }
1362 : : else
1363 : : {
1364 [ # # ]: 0 : SetError( SbxERR_CONVERSION );
1365 : : }
1366 [ # # ]: 0 : releaseDecimalPtr( aL.pDecimal );
1367 [ # # ]: 0 : releaseDecimalPtr( aR.pDecimal );
1368 : : }
1369 : : // Everything else comparing on a SbxDOUBLE-Basis
1370 : : else
1371 : : {
1372 : 3308 : aL.eType = aR.eType = SbxDOUBLE;
1373 [ + - ]: 3308 : bool bGetL = Get( aL );
1374 [ + - ]: 3308 : bool bGetR = rOp.Get( aR );
1375 [ + - ][ + - ]: 3308 : if( bGetL && bGetR )
1376 [ + + - + : 6616 : switch( eOp )
- - - ]
1377 : : {
1378 : : case SbxEQ:
1379 : 2682 : bRes = sal_Bool( aL.nDouble == aR.nDouble ); break;
1380 : : case SbxNE:
1381 : 142 : bRes = sal_Bool( aL.nDouble != aR.nDouble ); break;
1382 : : case SbxLT:
1383 : 0 : bRes = sal_Bool( aL.nDouble < aR.nDouble ); break;
1384 : : case SbxGT:
1385 : 484 : bRes = sal_Bool( aL.nDouble > aR.nDouble ); break;
1386 : : case SbxLE:
1387 : 0 : bRes = sal_Bool( aL.nDouble <= aR.nDouble ); break;
1388 : : case SbxGE:
1389 : 0 : bRes = sal_Bool( aL.nDouble >= aR.nDouble ); break;
1390 : : default:
1391 [ # # ]: 0 : SetError( SbxERR_NOTIMP );
1392 : : }
1393 : : // at least one value was got
1394 : : // if this is VBA then a conversion error for one
1395 : : // side will yield a false result of an equality test
1396 [ # # ][ # # ]: 0 : else if ( bGetR || bGetL )
1397 : : {
1398 [ # # ][ # # ]: 0 : if ( bVBAInterop && eOp == SbxEQ && GetError() == SbxERR_CONVERSION )
[ # # ][ # # ]
[ # # ]
1399 : : {
1400 [ # # ]: 0 : ResetError();
1401 : 3576 : bRes = sal_False;
1402 : : }
1403 : : }
1404 : : }
1405 : : }
1406 [ - + ]: 3576 : if( eOld != SbxERR_OK )
1407 : 0 : SetError( eOld );
1408 : 3576 : return bRes;
1409 : : }
1410 : :
1411 : : ///////////////////////////// Reading/Writing ////////////////////////////
1412 : :
1413 : 0 : sal_Bool SbxValue::LoadData( SvStream& r, sal_uInt16 )
1414 : : {
1415 : : // #TODO see if these types are really dumped to any stream
1416 : : // more than likely this is functionality used in the binfilter alone
1417 [ # # ]: 0 : SbxValue::Clear();
1418 : : sal_uInt16 nType;
1419 [ # # ]: 0 : r >> nType;
1420 : 0 : aData.eType = SbxDataType( nType );
1421 [ # # # # : 0 : switch( nType )
# # # # #
# # # # #
# # # #
# ]
1422 : : {
1423 : : case SbxBOOL:
1424 : : case SbxINTEGER:
1425 [ # # ]: 0 : r >> aData.nInteger; break;
1426 : : case SbxLONG:
1427 [ # # ]: 0 : r >> aData.nLong; break;
1428 : : case SbxSINGLE:
1429 : : {
1430 : : // Floats as ASCII
1431 : : XubString aVal = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(r,
1432 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_ASCII_US);
1433 : : double d;
1434 : : SbxDataType t;
1435 [ # # ][ # # ]: 0 : if( ImpScan( aVal, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE )
[ # # ][ # # ]
[ # # # # ]
[ # # ]
1436 : : {
1437 : 0 : aData.nSingle = 0.0F;
1438 : 0 : return sal_False;
1439 : : }
1440 : 0 : aData.nSingle = (float) d;
1441 [ # # ][ # # ]: 0 : break;
1442 : : }
1443 : : case SbxDATE:
1444 : : case SbxDOUBLE:
1445 : : {
1446 : : // Floats as ASCII
1447 : : XubString aVal = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(r,
1448 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_ASCII_US);
1449 : : SbxDataType t;
1450 [ # # ][ # # ]: 0 : if( ImpScan( aVal, aData.nDouble, t, NULL ) != SbxERR_OK )
[ # # ]
1451 : : {
1452 : 0 : aData.nDouble = 0.0;
1453 : 0 : return sal_False;
1454 : : }
1455 [ # # ][ # # ]: 0 : break;
1456 : : }
1457 : : //#fdo39428 SvStream no longer supports operator>>(long&)
1458 : : //SvStream now has operator>>(sal_Int64&)
1459 : : case SbxSALINT64:
1460 [ # # ]: 0 : r >> aData.nInt64;
1461 : 0 : break;
1462 : : case SbxSALUINT64:
1463 [ # # ]: 0 : r >> aData.uInt64;
1464 : 0 : break;
1465 : : case SbxCURRENCY:
1466 : : {
1467 : 0 : sal_uInt32 tmpHi = 0;
1468 : 0 : sal_uInt32 tmpLo = 0;
1469 [ # # ][ # # ]: 0 : r >> tmpHi >> tmpLo;
1470 : 0 : aData.nInt64 = ((sal_Int64)tmpHi << 32);
1471 : 0 : aData.nInt64 |= (sal_Int64)tmpLo;
1472 : : break;
1473 : : }
1474 : : case SbxSTRING:
1475 : : {
1476 : : rtl::OUString aVal = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(r,
1477 [ # # ]: 0 : RTL_TEXTENCODING_ASCII_US);
1478 [ # # ]: 0 : if( aVal.getLength() )
1479 [ # # ]: 0 : aData.pOUString = new ::rtl::OUString( aVal );
1480 : : else
1481 : 0 : aData.pOUString = NULL; // JSM 1995-09-22
1482 : 0 : break;
1483 : : }
1484 : : case SbxERROR:
1485 : : case SbxUSHORT:
1486 [ # # ]: 0 : r >> aData.nUShort; break;
1487 : : case SbxOBJECT:
1488 : : {
1489 : : sal_uInt8 nMode;
1490 [ # # ]: 0 : r >> nMode;
1491 [ # # # # ]: 0 : switch( nMode )
1492 : : {
1493 : : case 0:
1494 : 0 : aData.pObj = NULL;
1495 : 0 : break;
1496 : : case 1:
1497 [ # # ]: 0 : aData.pObj = SbxBase::Load( r );
1498 : 0 : return sal_Bool( aData.pObj != NULL );
1499 : : case 2:
1500 : 0 : aData.pObj = this;
1501 : 0 : break;
1502 : : }
1503 : : break;
1504 : : }
1505 : : case SbxCHAR:
1506 : : {
1507 : : char c;
1508 [ # # ]: 0 : r >> c;
1509 : 0 : aData.nChar = c;
1510 : : break;
1511 : : }
1512 : : case SbxBYTE:
1513 [ # # ]: 0 : r >> aData.nByte; break;
1514 : : case SbxULONG:
1515 [ # # ]: 0 : r >> aData.nULong; break;
1516 : : case SbxINT:
1517 : : {
1518 : : sal_uInt8 n;
1519 [ # # ]: 0 : r >> n;
1520 : : // Match the Int on this system?
1521 [ # # ]: 0 : if( n > SAL_TYPES_SIZEOFINT )
1522 [ # # ]: 0 : r >> aData.nLong, aData.eType = SbxLONG;
1523 : : else {
1524 : : sal_Int32 nInt;
1525 [ # # ]: 0 : r >> nInt;
1526 : 0 : aData.nInt = nInt;
1527 : : }
1528 : : break;
1529 : : }
1530 : : case SbxUINT:
1531 : : {
1532 : : sal_uInt8 n;
1533 [ # # ]: 0 : r >> n;
1534 : : // Match the UInt on this system?
1535 [ # # ]: 0 : if( n > SAL_TYPES_SIZEOFINT )
1536 [ # # ]: 0 : r >> aData.nULong, aData.eType = SbxULONG;
1537 : : else {
1538 : : sal_uInt32 nUInt;
1539 [ # # ]: 0 : r >> nUInt;
1540 : 0 : aData.nUInt = nUInt;
1541 : : }
1542 : : break;
1543 : : }
1544 : : case SbxEMPTY:
1545 : : case SbxNULL:
1546 : : case SbxVOID:
1547 : 0 : break;
1548 : : case SbxDATAOBJECT:
1549 [ # # ]: 0 : r >> aData.nLong;
1550 : 0 : break;
1551 : : // #78919 For backwards compatibility
1552 : : case SbxWSTRING:
1553 : : case SbxWCHAR:
1554 : 0 : break;
1555 : : default:
1556 : 0 : memset (&aData,0,sizeof(aData));
1557 : 0 : ResetFlag(SBX_FIXED);
1558 : 0 : aData.eType = SbxNULL;
1559 : : DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
1560 : 0 : return sal_False;
1561 : : }
1562 : 0 : return sal_True;
1563 : : }
1564 : :
1565 : 0 : sal_Bool SbxValue::StoreData( SvStream& r ) const
1566 : : {
1567 : 0 : sal_uInt16 nType = sal::static_int_cast< sal_uInt16 >(aData.eType);
1568 : 0 : r << nType;
1569 [ # # # # : 0 : switch( nType & 0x0FFF )
# # # # #
# # # # #
# # # # ]
1570 : : {
1571 : : case SbxBOOL:
1572 : : case SbxINTEGER:
1573 : 0 : r << aData.nInteger; break;
1574 : : case SbxLONG:
1575 : 0 : r << aData.nLong; break;
1576 : : case SbxDATE:
1577 : : // #49935: Save as double, elsewise an error during the read in
1578 : 0 : ((SbxValue*)this)->aData.eType = (SbxDataType)( ( nType & 0xF000 ) | SbxDOUBLE );
1579 [ # # ]: 0 : write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(r, GetCoreString(), RTL_TEXTENCODING_ASCII_US);
1580 : 0 : ((SbxValue*)this)->aData.eType = (SbxDataType)nType;
1581 : 0 : break;
1582 : : case SbxSINGLE:
1583 : : case SbxDOUBLE:
1584 [ # # ]: 0 : write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(r, GetCoreString(), RTL_TEXTENCODING_ASCII_US);
1585 : 0 : break;
1586 : : case SbxSALUINT64:
1587 : : case SbxSALINT64:
1588 : : // see comment in SbxValue::StoreData
1589 : 0 : r << aData.uInt64;
1590 : 0 : break;
1591 : : case SbxCURRENCY:
1592 : : {
1593 : 0 : sal_Int32 tmpHi = ( (aData.nInt64 >> 32) & 0xFFFFFFFF );
1594 : 0 : sal_Int32 tmpLo = ( sal_Int32 )aData.nInt64;
1595 : 0 : r << tmpHi << tmpLo;
1596 : 0 : break;
1597 : : }
1598 : : case SbxSTRING:
1599 [ # # ]: 0 : if( aData.pOUString )
1600 : : {
1601 : 0 : write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(r, *aData.pOUString, RTL_TEXTENCODING_ASCII_US);
1602 : : }
1603 : : else
1604 : : {
1605 [ # # ]: 0 : write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(r, rtl::OUString(), RTL_TEXTENCODING_ASCII_US);
1606 : : }
1607 : 0 : break;
1608 : : case SbxERROR:
1609 : : case SbxUSHORT:
1610 : 0 : r << aData.nUShort; break;
1611 : : case SbxOBJECT:
1612 : : // to save itself as Objectptr does not work!
1613 [ # # ]: 0 : if( aData.pObj )
1614 : : {
1615 [ # # ][ # # ]: 0 : if( PTR_CAST(SbxValue,aData.pObj) != this )
[ # # ]
1616 : : {
1617 : 0 : r << (sal_uInt8) 1;
1618 : 0 : return aData.pObj->Store( r );
1619 : : }
1620 : : else
1621 : 0 : r << (sal_uInt8) 2;
1622 : : }
1623 : : else
1624 : 0 : r << (sal_uInt8) 0;
1625 : 0 : break;
1626 : : case SbxCHAR:
1627 : : {
1628 : 0 : char c = sal::static_int_cast< char >(aData.nChar);
1629 : 0 : r << c;
1630 : 0 : break;
1631 : : }
1632 : : case SbxBYTE:
1633 : 0 : r << aData.nByte; break;
1634 : : case SbxULONG:
1635 : 0 : r << aData.nULong; break;
1636 : : case SbxINT:
1637 : : {
1638 : 0 : sal_uInt8 n = SAL_TYPES_SIZEOFINT;
1639 : 0 : r << n << (sal_Int32)aData.nInt;
1640 : 0 : break;
1641 : : }
1642 : : case SbxUINT:
1643 : : {
1644 : 0 : sal_uInt8 n = SAL_TYPES_SIZEOFINT;
1645 : 0 : r << n << (sal_uInt32)aData.nUInt;
1646 : 0 : break;
1647 : : }
1648 : : case SbxEMPTY:
1649 : : case SbxNULL:
1650 : : case SbxVOID:
1651 : 0 : break;
1652 : : case SbxDATAOBJECT:
1653 : 0 : r << aData.nLong;
1654 : 0 : break;
1655 : : // #78919 For backwards compatibility
1656 : : case SbxWSTRING:
1657 : : case SbxWCHAR:
1658 : 0 : break;
1659 : : default:
1660 : : DBG_ASSERT( !this, "Speichern eines nicht unterstuetzten Datentyps" );
1661 : 0 : return sal_False;
1662 : : }
1663 : 0 : return sal_True;
1664 : : }
1665 : :
1666 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|