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