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 : #include "dpitemdata.hxx"
21 :
22 : #include "document.hxx"
23 : #include "dpobject.hxx"
24 : #include "formulacell.hxx"
25 : #include "globstr.hrc"
26 : #include "dptabdat.hxx"
27 : #include "rtl/math.hxx"
28 :
29 : const sal_Int32 ScDPItemData::DateFirst = -1;
30 : const sal_Int32 ScDPItemData::DateLast = 10000;
31 :
32 0 : size_t ScDPItemData::Hash::operator() (const ScDPItemData& rVal) const
33 : {
34 0 : switch (rVal.GetType())
35 : {
36 : case GroupValue:
37 : case Value:
38 : case RangeStart:
39 0 : return (size_t)(rVal.mfValue);
40 : case String:
41 : case Error:
42 : {
43 0 : if (!rVal.mpString)
44 0 : return 0;
45 :
46 0 : if (rVal.mbStringInterned)
47 0 : return reinterpret_cast<size_t>(rVal.mpString);
48 :
49 : OUStringHash aStrHasher;
50 0 : return aStrHasher(*rVal.mpString);
51 : }
52 : default:
53 : ;
54 : }
55 :
56 0 : return 0;
57 : }
58 :
59 10147 : sal_Int32 ScDPItemData::Compare(const ScDPItemData& rA, const ScDPItemData& rB)
60 : {
61 10147 : if (rA.meType != rB.meType)
62 : {
63 : // group value, value and string in this order. Ensure that the empty
64 : // type comes last.
65 9 : return rA.meType < rB.meType ? -1 : 1;
66 : }
67 :
68 10138 : switch (rA.meType)
69 : {
70 : case GroupValue:
71 : {
72 134 : if (rA.maGroupValue.mnGroupType == rB.maGroupValue.mnGroupType)
73 : {
74 134 : if (rA.maGroupValue.mnValue == rB.maGroupValue.mnValue)
75 22 : return 0;
76 :
77 112 : return rA.maGroupValue.mnValue < rB.maGroupValue.mnValue ? -1 : 1;
78 : }
79 :
80 0 : return rA.maGroupValue.mnGroupType < rB.maGroupValue.mnGroupType ? -1 : 1;
81 : }
82 : case Value:
83 : case RangeStart:
84 : {
85 7847 : if (rA.mfValue == rB.mfValue)
86 1225 : return 0;
87 :
88 6622 : return rA.mfValue < rB.mfValue ? -1 : 1;
89 : }
90 : case String:
91 : case Error:
92 2111 : if (rA.mpString == rB.mpString)
93 : // strings may be interned.
94 578 : return 0;
95 :
96 1533 : return ScGlobal::GetCollator()->compareString(rA.GetString(), rB.GetString());
97 : default:
98 : ;
99 : }
100 46 : return 0;
101 : }
102 :
103 8409 : ScDPItemData::ScDPItemData() :
104 8409 : mfValue(0.0), meType(Empty), mbStringInterned(false) {}
105 :
106 25914 : ScDPItemData::ScDPItemData(const ScDPItemData& r) :
107 25914 : meType(r.meType), mbStringInterned(r.mbStringInterned)
108 : {
109 25914 : switch (r.meType)
110 : {
111 : case String:
112 : case Error:
113 2288 : mpString = mbStringInterned ? r.mpString : new OUString(*r.mpString);
114 2288 : break;
115 : case Value:
116 : case RangeStart:
117 22922 : mfValue = r.mfValue;
118 22922 : break;
119 : case GroupValue:
120 161 : maGroupValue.mnGroupType = r.maGroupValue.mnGroupType;
121 161 : maGroupValue.mnValue = r.maGroupValue.mnValue;
122 161 : break;
123 : case Empty:
124 : default:
125 543 : mfValue = 0.0;
126 : }
127 25914 : }
128 :
129 49126 : void ScDPItemData::DisposeString()
130 : {
131 49126 : if (!mbStringInterned)
132 : {
133 45231 : if (meType == String || meType == Error)
134 409 : delete mpString;
135 : }
136 :
137 49126 : mbStringInterned = false;
138 49126 : }
139 :
140 14 : ScDPItemData::ScDPItemData(const OUString& rStr) :
141 14 : mpString(new OUString(rStr)), meType(String), mbStringInterned(false) {}
142 :
143 72 : ScDPItemData::ScDPItemData(sal_Int32 nGroupType, sal_Int32 nValue) :
144 72 : meType(GroupValue), mbStringInterned(false)
145 : {
146 72 : maGroupValue.mnGroupType = nGroupType;
147 72 : maGroupValue.mnValue = nValue;
148 72 : }
149 :
150 34409 : ScDPItemData::~ScDPItemData()
151 : {
152 34409 : DisposeString();
153 34409 : }
154 :
155 2839 : ScDPItemData::Type ScDPItemData::GetType() const
156 : {
157 2839 : return static_cast<Type>(meType);
158 : }
159 :
160 56 : void ScDPItemData::SetEmpty()
161 : {
162 56 : DisposeString();
163 56 : meType = Empty;
164 56 : }
165 :
166 131 : void ScDPItemData::SetString(const OUString& rS)
167 : {
168 131 : DisposeString();
169 131 : mpString = new OUString(rS);
170 131 : meType = String;
171 131 : }
172 :
173 204 : void ScDPItemData::SetString(const OUString* pS)
174 : {
175 204 : DisposeString();
176 204 : mpString = pS;
177 204 : meType = String;
178 204 : mbStringInterned = true;
179 204 : }
180 :
181 666 : void ScDPItemData::SetValue(double fVal)
182 : {
183 666 : DisposeString();
184 666 : mfValue = fVal;
185 666 : meType = Value;
186 666 : }
187 :
188 21 : void ScDPItemData::SetRangeStart(double fVal)
189 : {
190 21 : DisposeString();
191 21 : mfValue = fVal;
192 21 : meType = RangeStart;
193 21 : }
194 :
195 1 : void ScDPItemData::SetRangeFirst()
196 : {
197 1 : DisposeString();
198 1 : rtl::math::setInf(&mfValue, true);
199 1 : meType = RangeStart;
200 1 : }
201 :
202 1 : void ScDPItemData::SetRangeLast()
203 : {
204 1 : DisposeString();
205 1 : rtl::math::setInf(&mfValue, false);
206 1 : meType = RangeStart;
207 1 : }
208 :
209 0 : void ScDPItemData::SetErrorString(const OUString* pS)
210 : {
211 0 : SetString(pS);
212 0 : meType = Error;
213 0 : }
214 :
215 953 : bool ScDPItemData::IsCaseInsEqual(const ScDPItemData& r) const
216 : {
217 953 : if (meType != r.meType)
218 1 : return false;
219 :
220 952 : switch (meType)
221 : {
222 : case Value:
223 : case RangeStart:
224 568 : return rtl::math::approxEqual(mfValue, r.mfValue);
225 : case GroupValue:
226 0 : return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType &&
227 0 : maGroupValue.mnValue == r.maGroupValue.mnValue;
228 : default:
229 : ;
230 : }
231 :
232 384 : if (mpString == r.mpString)
233 : // Fast equality check for interned strings.
234 96 : return true;
235 :
236 288 : return ScGlobal::GetpTransliteration()->isEqual(GetString(), r.GetString());
237 : }
238 :
239 4343 : bool ScDPItemData::operator== (const ScDPItemData& r) const
240 : {
241 4343 : if (meType != r.meType)
242 416 : return false;
243 :
244 3927 : switch (meType)
245 : {
246 : case Value:
247 : case RangeStart:
248 3646 : return rtl::math::approxEqual(mfValue, r.mfValue);
249 : case GroupValue:
250 236 : return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType &&
251 236 : maGroupValue.mnValue == r.maGroupValue.mnValue;
252 : default:
253 : ;
254 : }
255 :
256 : // need exact equality until we have a safe case insensitive string hash
257 163 : return GetString() == r.GetString();
258 : }
259 :
260 0 : bool ScDPItemData::operator!= (const ScDPItemData& r) const
261 : {
262 0 : return !operator== (r);
263 : }
264 :
265 9958 : bool ScDPItemData::operator< (const ScDPItemData& r) const
266 : {
267 9958 : return Compare(*this, r) == -1;
268 : }
269 :
270 13637 : ScDPItemData& ScDPItemData::operator= (const ScDPItemData& r)
271 : {
272 13637 : DisposeString();
273 13637 : meType = r.meType;
274 13637 : mbStringInterned = false;
275 13637 : switch (r.meType)
276 : {
277 : case String:
278 : case Error:
279 1667 : mpString = r.mbStringInterned ? r.mpString : new OUString(*r.mpString);
280 1667 : mbStringInterned = r.mbStringInterned;
281 1667 : break;
282 : case Value:
283 : case RangeStart:
284 11752 : mfValue = r.mfValue;
285 11752 : break;
286 : case GroupValue:
287 87 : maGroupValue.mnGroupType = r.maGroupValue.mnGroupType;
288 87 : maGroupValue.mnValue = r.maGroupValue.mnValue;
289 87 : break;
290 : case Empty:
291 : default:
292 131 : mfValue = 0.0;
293 : }
294 13637 : return *this;
295 : }
296 :
297 419 : ScDPValue::Type ScDPItemData::GetCellType() const
298 : {
299 419 : switch (meType)
300 : {
301 : case Error:
302 0 : return ScDPValue::Error;
303 : case Empty:
304 2 : return ScDPValue::Empty;
305 : case Value:
306 417 : return ScDPValue::Value;
307 : default:
308 : ;
309 : }
310 :
311 0 : return ScDPValue::String;
312 : }
313 :
314 : #if DEBUG_PIVOT_TABLE
315 :
316 : void ScDPItemData::Dump(const char* msg) const
317 : {
318 : printf("--- (%s)\n", msg);
319 : switch (meType)
320 : {
321 : case Empty:
322 : printf("empty\n");
323 : break;
324 : case Error:
325 : printf("error: %s\n",
326 : OUStringToOString(*mpString, RTL_TEXTENCODING_UTF8).getStr());
327 : break;
328 : case GroupValue:
329 : printf("group value: group type = %d value = %d\n",
330 : maGroupValue.mnGroupType, maGroupValue.mnValue);
331 : break;
332 : case String:
333 : printf("string: %s\n",
334 : OUStringToOString(*mpString, RTL_TEXTENCODING_UTF8).getStr());
335 : break;
336 : case Value:
337 : printf("value: %g\n", mfValue);
338 : break;
339 : case RangeStart:
340 : printf("range start: %g\n", mfValue);
341 : break;
342 : default:
343 : printf("unknown type\n");
344 : }
345 : printf("---\n");
346 : }
347 : #endif
348 :
349 918 : bool ScDPItemData::IsEmpty() const
350 : {
351 918 : return meType == Empty;
352 : }
353 :
354 8930 : bool ScDPItemData::IsValue() const
355 : {
356 8930 : return meType == Value;
357 : }
358 :
359 4353 : OUString ScDPItemData::GetString() const
360 : {
361 4353 : switch (meType)
362 : {
363 : case String:
364 : case Error:
365 4352 : return *mpString;
366 : case Value:
367 : case RangeStart:
368 0 : return OUString::valueOf(mfValue);
369 : case GroupValue:
370 0 : return OUString::valueOf(maGroupValue.mnValue);
371 : case Empty:
372 : default:
373 : ;
374 : }
375 :
376 1 : return OUString();
377 : }
378 :
379 10771 : double ScDPItemData::GetValue() const
380 : {
381 10771 : if (meType == Value || meType == RangeStart)
382 10771 : return mfValue;
383 :
384 0 : return 0.0;
385 : }
386 :
387 167 : ScDPItemData::GroupValueAttr ScDPItemData::GetGroupValue() const
388 : {
389 167 : if (meType == GroupValue)
390 167 : return maGroupValue;
391 :
392 : GroupValueAttr aGV;
393 0 : aGV.mnGroupType = -1;
394 0 : aGV.mnValue = -1;
395 0 : return aGV;
396 : }
397 :
398 0 : bool ScDPItemData::HasStringData() const
399 : {
400 0 : return meType == String || meType == Error;
401 93 : }
402 :
403 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|