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 20208 : sal_Int32 ScDPItemData::Compare(const ScDPItemData& rA, const ScDPItemData& rB)
60 : {
61 20208 : if (rA.meType != rB.meType)
62 : {
63 : // group value, value and string in this order. Ensure that the empty
64 : // type comes last.
65 2 : return rA.meType < rB.meType ? -1 : 1;
66 : }
67 :
68 20206 : switch (rA.meType)
69 : {
70 : case GroupValue:
71 : {
72 150 : if (rA.maGroupValue.mnGroupType == rB.maGroupValue.mnGroupType)
73 : {
74 150 : if (rA.maGroupValue.mnValue == rB.maGroupValue.mnValue)
75 0 : return 0;
76 :
77 150 : 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 12004 : if (rA.mfValue == rB.mfValue)
86 4960 : return 0;
87 :
88 7044 : return rA.mfValue < rB.mfValue ? -1 : 1;
89 : }
90 : case String:
91 : case Error:
92 7960 : if (rA.mpString == rB.mpString)
93 : // strings may be interned.
94 3574 : return 0;
95 :
96 4386 : return ScGlobal::GetCollator()->compareString(rA.GetString(), rB.GetString());
97 : default:
98 : ;
99 : }
100 92 : return 0;
101 : }
102 :
103 16486 : ScDPItemData::ScDPItemData() :
104 16486 : mfValue(0.0), meType(Empty), mbStringInterned(false) {}
105 :
106 73124 : ScDPItemData::ScDPItemData(const ScDPItemData& r) :
107 73124 : meType(r.meType), mbStringInterned(r.mbStringInterned)
108 : {
109 73124 : switch (r.meType)
110 : {
111 : case String:
112 : case Error:
113 14496 : mpString = mbStringInterned ? r.mpString : new OUString(*r.mpString);
114 14496 : break;
115 : case Value:
116 : case RangeStart:
117 54354 : mfValue = r.mfValue;
118 54354 : break;
119 : case GroupValue:
120 3920 : maGroupValue.mnGroupType = r.maGroupValue.mnGroupType;
121 3920 : maGroupValue.mnValue = r.maGroupValue.mnValue;
122 3920 : break;
123 : case Empty:
124 : default:
125 354 : mfValue = 0.0;
126 : }
127 73124 : }
128 :
129 164106 : void ScDPItemData::DisposeString()
130 : {
131 164106 : if (!mbStringInterned)
132 : {
133 124558 : if (meType == String || meType == Error)
134 758 : delete mpString;
135 : }
136 :
137 164106 : mbStringInterned = false;
138 164106 : }
139 :
140 28 : ScDPItemData::ScDPItemData(const OUString& rStr) :
141 28 : mpString(new OUString(rStr)), meType(String), mbStringInterned(false) {}
142 :
143 1700 : ScDPItemData::ScDPItemData(sal_Int32 nGroupType, sal_Int32 nValue) :
144 1700 : meType(GroupValue), mbStringInterned(false)
145 : {
146 1700 : maGroupValue.mnGroupType = nGroupType;
147 1700 : maGroupValue.mnValue = nValue;
148 1700 : }
149 :
150 91338 : ScDPItemData::~ScDPItemData()
151 : {
152 91338 : DisposeString();
153 91338 : }
154 :
155 112 : void ScDPItemData::SetEmpty()
156 : {
157 112 : DisposeString();
158 112 : meType = Empty;
159 112 : }
160 :
161 288 : void ScDPItemData::SetString(const OUString& rS)
162 : {
163 288 : DisposeString();
164 288 : mpString = new OUString(rS);
165 288 : meType = String;
166 288 : }
167 :
168 1738 : void ScDPItemData::SetString(const OUString* pS)
169 : {
170 1738 : DisposeString();
171 1738 : mpString = pS;
172 1738 : meType = String;
173 1738 : mbStringInterned = true;
174 1738 : }
175 :
176 2908 : void ScDPItemData::SetValue(double fVal)
177 : {
178 2908 : DisposeString();
179 2908 : mfValue = fVal;
180 2908 : meType = Value;
181 2908 : }
182 :
183 48 : void ScDPItemData::SetRangeStart(double fVal)
184 : {
185 48 : DisposeString();
186 48 : mfValue = fVal;
187 48 : meType = RangeStart;
188 48 : }
189 :
190 4 : void ScDPItemData::SetRangeFirst()
191 : {
192 4 : DisposeString();
193 4 : rtl::math::setInf(&mfValue, true);
194 4 : meType = RangeStart;
195 4 : }
196 :
197 4 : void ScDPItemData::SetRangeLast()
198 : {
199 4 : DisposeString();
200 4 : rtl::math::setInf(&mfValue, false);
201 4 : meType = RangeStart;
202 4 : }
203 :
204 0 : void ScDPItemData::SetErrorString(const OUString* pS)
205 : {
206 0 : SetString(pS);
207 0 : meType = Error;
208 0 : }
209 :
210 4722 : bool ScDPItemData::IsCaseInsEqual(const ScDPItemData& r) const
211 : {
212 4722 : if (meType != r.meType)
213 2 : return false;
214 :
215 4720 : switch (meType)
216 : {
217 : case Value:
218 : case RangeStart:
219 2676 : return rtl::math::approxEqual(mfValue, r.mfValue);
220 : case GroupValue:
221 0 : return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType &&
222 0 : maGroupValue.mnValue == r.maGroupValue.mnValue;
223 : default:
224 : ;
225 : }
226 :
227 2044 : if (mpString == r.mpString)
228 : // Fast equality check for interned strings.
229 1320 : return true;
230 :
231 724 : return ScGlobal::GetpTransliteration()->isEqual(GetString(), r.GetString());
232 : }
233 :
234 8738 : bool ScDPItemData::operator== (const ScDPItemData& r) const
235 : {
236 8738 : if (meType != r.meType)
237 832 : return false;
238 :
239 7906 : switch (meType)
240 : {
241 : case Value:
242 : case RangeStart:
243 7292 : return rtl::math::approxEqual(mfValue, r.mfValue);
244 : case GroupValue:
245 472 : return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType &&
246 472 : maGroupValue.mnValue == r.maGroupValue.mnValue;
247 : default:
248 : ;
249 : }
250 :
251 : // need exact equality until we have a safe case insensitive string hash
252 378 : return GetString() == r.GetString();
253 : }
254 :
255 0 : bool ScDPItemData::operator!= (const ScDPItemData& r) const
256 : {
257 0 : return !operator== (r);
258 : }
259 :
260 19830 : bool ScDPItemData::operator< (const ScDPItemData& r) const
261 : {
262 19830 : return Compare(*this, r) == -1;
263 : }
264 :
265 67666 : ScDPItemData& ScDPItemData::operator= (const ScDPItemData& r)
266 : {
267 67666 : DisposeString();
268 67666 : meType = r.meType;
269 67666 : mbStringInterned = false;
270 67666 : switch (r.meType)
271 : {
272 : case String:
273 : case Error:
274 23756 : mpString = r.mbStringInterned ? r.mpString : new OUString(*r.mpString);
275 23756 : mbStringInterned = r.mbStringInterned;
276 23756 : break;
277 : case Value:
278 : case RangeStart:
279 43478 : mfValue = r.mfValue;
280 43478 : break;
281 : case GroupValue:
282 136 : maGroupValue.mnGroupType = r.maGroupValue.mnGroupType;
283 136 : maGroupValue.mnValue = r.maGroupValue.mnValue;
284 136 : break;
285 : case Empty:
286 : default:
287 296 : mfValue = 0.0;
288 : }
289 67666 : return *this;
290 : }
291 :
292 956 : ScDPValue::Type ScDPItemData::GetCellType() const
293 : {
294 956 : switch (meType)
295 : {
296 : case Error:
297 0 : return ScDPValue::Error;
298 : case Empty:
299 4 : return ScDPValue::Empty;
300 : case Value:
301 952 : return ScDPValue::Value;
302 : default:
303 : ;
304 : }
305 :
306 0 : return ScDPValue::String;
307 : }
308 :
309 : #if DEBUG_PIVOT_TABLE
310 :
311 : void ScDPItemData::Dump(const char* msg) const
312 : {
313 : printf("--- (%s)\n", msg);
314 : switch (meType)
315 : {
316 : case Empty:
317 : printf("empty\n");
318 : break;
319 : case Error:
320 : printf("error: %s\n",
321 : OUStringToOString(*mpString, RTL_TEXTENCODING_UTF8).getStr());
322 : break;
323 : case GroupValue:
324 : printf("group value: group type = %d value = %d\n",
325 : maGroupValue.mnGroupType, maGroupValue.mnValue);
326 : break;
327 : case String:
328 : printf("string: %s\n",
329 : OUStringToOString(*mpString, RTL_TEXTENCODING_UTF8).getStr());
330 : break;
331 : case Value:
332 : printf("value: %g\n", mfValue);
333 : break;
334 : case RangeStart:
335 : printf("range start: %g\n", mfValue);
336 : break;
337 : default:
338 : printf("unknown type\n");
339 : }
340 : printf("---\n");
341 : }
342 : #endif
343 :
344 4760 : bool ScDPItemData::IsEmpty() const
345 : {
346 4760 : return meType == Empty;
347 : }
348 :
349 17978 : bool ScDPItemData::IsValue() const
350 : {
351 17978 : return meType == Value;
352 : }
353 :
354 13032 : OUString ScDPItemData::GetString() const
355 : {
356 13032 : switch (meType)
357 : {
358 : case String:
359 : case Error:
360 12920 : return *mpString;
361 : case Value:
362 : case RangeStart:
363 0 : return OUString::number(mfValue);
364 : case GroupValue:
365 0 : return OUString::number(maGroupValue.mnValue);
366 : case Empty:
367 : default:
368 : ;
369 : }
370 :
371 112 : return OUString();
372 : }
373 :
374 24750 : double ScDPItemData::GetValue() const
375 : {
376 24750 : if (meType == Value || meType == RangeStart)
377 24750 : return mfValue;
378 :
379 0 : return 0.0;
380 : }
381 :
382 1916 : ScDPItemData::GroupValueAttr ScDPItemData::GetGroupValue() const
383 : {
384 1916 : if (meType == GroupValue)
385 1916 : return maGroupValue;
386 :
387 : GroupValueAttr aGV;
388 0 : aGV.mnGroupType = -1;
389 0 : aGV.mnValue = -1;
390 0 : return aGV;
391 : }
392 :
393 0 : bool ScDPItemData::HasStringData() const
394 : {
395 0 : return meType == String || meType == Error;
396 228 : }
397 :
398 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|