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 2724 : sal_Int32 ScDPItemData::Compare(const ScDPItemData& rA, const ScDPItemData& rB)
33 : {
34 2724 : if (rA.meType != rB.meType)
35 : {
36 : // group value, value and string in this order. Ensure that the empty
37 : // type comes last.
38 2 : return rA.meType < rB.meType ? -1 : 1;
39 : }
40 :
41 2722 : switch (rA.meType)
42 : {
43 : case GroupValue:
44 : {
45 150 : if (rA.maGroupValue.mnGroupType == rB.maGroupValue.mnGroupType)
46 : {
47 150 : if (rA.maGroupValue.mnValue == rB.maGroupValue.mnValue)
48 0 : return 0;
49 :
50 150 : 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 1834 : if (rA.mfValue == rB.mfValue)
59 174 : return 0;
60 :
61 1660 : return rA.mfValue < rB.mfValue ? -1 : 1;
62 : }
63 : case String:
64 : case Error:
65 678 : if (rA.mpString == rB.mpString)
66 : // strings may be interned.
67 198 : return 0;
68 :
69 480 : return ScGlobal::GetCollator()->compareString(rA.GetString(), rB.GetString());
70 : default:
71 : ;
72 : }
73 60 : return 0;
74 : }
75 :
76 3270 : ScDPItemData::ScDPItemData() :
77 3270 : mfValue(0.0), meType(Empty), mbStringInterned(false) {}
78 :
79 13074 : ScDPItemData::ScDPItemData(const ScDPItemData& r) :
80 13074 : meType(r.meType), mbStringInterned(r.mbStringInterned)
81 : {
82 13074 : switch (r.meType)
83 : {
84 : case String:
85 : case Error:
86 2308 : mpString = mbStringInterned ? r.mpString : new rtl::OUString(*r.mpString);
87 2308 : break;
88 : case Value:
89 : case RangeStart:
90 10362 : mfValue = r.mfValue;
91 10362 : break;
92 : case GroupValue:
93 196 : maGroupValue.mnGroupType = r.maGroupValue.mnGroupType;
94 196 : maGroupValue.mnValue = r.maGroupValue.mnValue;
95 196 : break;
96 : case Empty:
97 : default:
98 208 : mfValue = 0.0;
99 : }
100 13074 : }
101 :
102 27136 : void ScDPItemData::DisposeString()
103 : {
104 27136 : if (!mbStringInterned)
105 : {
106 22908 : if (meType == String || meType == Error)
107 432 : delete mpString;
108 : }
109 :
110 27136 : mbStringInterned = false;
111 27136 : }
112 :
113 16 : ScDPItemData::ScDPItemData(const rtl::OUString& rStr) :
114 16 : mpString(new rtl::OUString(rStr)), meType(String), mbStringInterned(false) {}
115 :
116 144 : ScDPItemData::ScDPItemData(sal_Int32 nGroupType, sal_Int32 nValue) :
117 144 : meType(GroupValue), mbStringInterned(false)
118 : {
119 144 : maGroupValue.mnGroupType = nGroupType;
120 144 : maGroupValue.mnValue = nValue;
121 144 : }
122 :
123 16504 : ScDPItemData::~ScDPItemData()
124 : {
125 16504 : DisposeString();
126 16504 : }
127 :
128 2628 : ScDPItemData::Type ScDPItemData::GetType() const
129 : {
130 2628 : return static_cast<Type>(meType);
131 : }
132 :
133 56 : void ScDPItemData::SetEmpty()
134 : {
135 56 : DisposeString();
136 56 : meType = Empty;
137 56 : }
138 :
139 166 : void ScDPItemData::SetString(const rtl::OUString& rS)
140 : {
141 166 : DisposeString();
142 166 : mpString = new rtl::OUString(rS);
143 166 : meType = String;
144 166 : }
145 :
146 324 : void ScDPItemData::SetString(const rtl::OUString* pS)
147 : {
148 324 : DisposeString();
149 324 : mpString = pS;
150 324 : meType = String;
151 324 : mbStringInterned = true;
152 324 : }
153 :
154 670 : void ScDPItemData::SetValue(double fVal)
155 : {
156 670 : DisposeString();
157 670 : mfValue = fVal;
158 670 : meType = Value;
159 670 : }
160 :
161 42 : void ScDPItemData::SetRangeStart(double fVal)
162 : {
163 42 : DisposeString();
164 42 : mfValue = fVal;
165 42 : meType = RangeStart;
166 42 : }
167 :
168 2 : void ScDPItemData::SetRangeFirst()
169 : {
170 2 : DisposeString();
171 2 : rtl::math::setInf(&mfValue, true);
172 2 : meType = RangeStart;
173 2 : }
174 :
175 2 : void ScDPItemData::SetRangeLast()
176 : {
177 2 : DisposeString();
178 2 : rtl::math::setInf(&mfValue, false);
179 2 : meType = RangeStart;
180 2 : }
181 :
182 0 : void ScDPItemData::SetErrorString(const rtl::OUString* pS)
183 : {
184 0 : SetString(pS);
185 0 : meType = Error;
186 0 : }
187 :
188 1186 : bool ScDPItemData::IsCaseInsEqual(const ScDPItemData& r) const
189 : {
190 1186 : if (meType != r.meType)
191 2 : return false;
192 :
193 1184 : switch (meType)
194 : {
195 : case Value:
196 : case RangeStart:
197 616 : 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 568 : if (mpString == r.mpString)
206 : // Fast equality check for interned strings.
207 158 : return true;
208 :
209 410 : return ScGlobal::GetpTransliteration()->isEqual(GetString(), r.GetString());
210 : }
211 :
212 2836 : bool ScDPItemData::operator== (const ScDPItemData& r) const
213 : {
214 2836 : if (meType != r.meType)
215 832 : return false;
216 :
217 2004 : switch (meType)
218 : {
219 : case Value:
220 : case RangeStart:
221 1532 : return rtl::math::approxEqual(mfValue, r.mfValue);
222 : case GroupValue:
223 : return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType &&
224 236 : maGroupValue.mnValue == r.maGroupValue.mnValue;
225 : default:
226 : ;
227 : }
228 :
229 : // need exact equality until we have a safe case insensitive string hash
230 236 : return GetString() == r.GetString();
231 : }
232 :
233 0 : bool ScDPItemData::operator!= (const ScDPItemData& r) const
234 : {
235 0 : return !operator== (r);
236 : }
237 :
238 2454 : bool ScDPItemData::operator< (const ScDPItemData& r) const
239 : {
240 2454 : return Compare(*this, r) == -1;
241 : }
242 :
243 9370 : ScDPItemData& ScDPItemData::operator= (const ScDPItemData& r)
244 : {
245 9370 : DisposeString();
246 9370 : meType = r.meType;
247 9370 : mbStringInterned = false;
248 9370 : switch (r.meType)
249 : {
250 : case String:
251 : case Error:
252 1846 : mpString = r.mbStringInterned ? r.mpString : new rtl::OUString(*r.mpString);
253 1846 : mbStringInterned = r.mbStringInterned;
254 1846 : break;
255 : case Value:
256 : case RangeStart:
257 7304 : mfValue = r.mfValue;
258 7304 : break;
259 : case GroupValue:
260 98 : maGroupValue.mnGroupType = r.maGroupValue.mnGroupType;
261 98 : maGroupValue.mnValue = r.maGroupValue.mnValue;
262 98 : break;
263 : case Empty:
264 : default:
265 122 : mfValue = 0.0;
266 : }
267 9370 : return *this;
268 : }
269 :
270 592 : sal_uInt8 ScDPItemData::GetCellType() const
271 : {
272 592 : switch (meType)
273 : {
274 : case Error:
275 0 : return SC_VALTYPE_ERROR;
276 : case Empty:
277 4 : return SC_VALTYPE_EMPTY;
278 : case Value:
279 588 : 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 1026 : bool ScDPItemData::IsEmpty() const
324 : {
325 1026 : return meType == Empty;
326 : }
327 :
328 3674 : bool ScDPItemData::IsValue() const
329 : {
330 3674 : return meType == Value;
331 : }
332 :
333 2684 : rtl::OUString ScDPItemData::GetString() const
334 : {
335 2684 : switch (meType)
336 : {
337 : case String:
338 : case Error:
339 2682 : 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 2 : return rtl::OUString();
351 : }
352 :
353 5080 : double ScDPItemData::GetValue() const
354 : {
355 5080 : if (meType == Value || meType == RangeStart)
356 5080 : return mfValue;
357 :
358 0 : return 0.0;
359 : }
360 :
361 334 : ScDPItemData::GroupValueAttr ScDPItemData::GetGroupValue() const
362 : {
363 334 : if (meType == GroupValue)
364 334 : 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 102 : }
376 :
377 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|