/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include const sal_Int32 ScDPItemData::DateFirst = -1; const sal_Int32 ScDPItemData::DateLast = 10000; sal_Int32 ScDPItemData::Compare(const ScDPItemData& rA, const ScDPItemData& rB) { if (rA.meType != rB.meType) { // group value, value and string in this order. Ensure that the empty // type comes last. return rA.meType < rB.meType ? -1 : 1; } switch (rA.meType) { case GroupValue: { if (rA.maGroupValue.mnGroupType == rB.maGroupValue.mnGroupType) { if (rA.maGroupValue.mnValue == rB.maGroupValue.mnValue) return 0; return rA.maGroupValue.mnValue < rB.maGroupValue.mnValue ? -1 : 1; } return rA.maGroupValue.mnGroupType < rB.maGroupValue.mnGroupType ? -1 : 1; } case Value: case RangeStart: { if (rA.mfValue == rB.mfValue) return 0; return rA.mfValue < rB.mfValue ? -1 : 1; } case String: case Error: if (rA.mpString == rB.mpString) // strings may be interned. return 0; return ScGlobal::GetCollator()->compareString(rA.GetString(), rB.GetString()); default: ; } return 0; } ScDPItemData::ScDPItemData() : mfValue(0.0), meType(Empty), mbStringInterned(false) {} ScDPItemData::ScDPItemData(const ScDPItemData& r) : meType(r.meType), mbStringInterned(r.mbStringInterned) { switch (r.meType) { case String: case Error: mpString = r.mpString; if (!mbStringInterned) rtl_uString_acquire(mpString); break; case Value: case RangeStart: mfValue = r.mfValue; break; case GroupValue: maGroupValue.mnGroupType = r.maGroupValue.mnGroupType; maGroupValue.mnValue = r.maGroupValue.mnValue; break; case Empty: default: mfValue = 0.0; } } void ScDPItemData::DisposeString() { if (!mbStringInterned) { if (meType == String || meType == Error) rtl_uString_release(mpString); } mbStringInterned = false; } ScDPItemData::ScDPItemData(const OUString& rStr) : mpString(rStr.pData), meType(String), mbStringInterned(false) { rtl_uString_acquire(mpString); } ScDPItemData::ScDPItemData(sal_Int32 nGroupType, sal_Int32 nValue) : meType(GroupValue), mbStringInterned(false) { maGroupValue.mnGroupType = nGroupType; maGroupValue.mnValue = nValue; } ScDPItemData::~ScDPItemData() { DisposeString(); } void ScDPItemData::SetEmpty() { DisposeString(); meType = Empty; } void ScDPItemData::SetString(const OUString& rS) { DisposeString(); mpString = rS.pData; rtl_uString_acquire(mpString); meType = String; } void ScDPItemData::SetStringInterned( rtl_uString* pS ) { DisposeString(); mpString = pS; meType = String; mbStringInterned = true; } void ScDPItemData::SetValue(double fVal) { DisposeString(); mfValue = fVal; meType = Value; } void ScDPItemData::SetRangeStart(double fVal) { DisposeString(); mfValue = fVal; meType = RangeStart; } void ScDPItemData::SetRangeFirst() { DisposeString(); rtl::math::setInf(&mfValue, true); meType = RangeStart; } void ScDPItemData::SetRangeLast() { DisposeString(); rtl::math::setInf(&mfValue, false); meType = RangeStart; } void ScDPItemData::SetErrorStringInterned( rtl_uString* pS ) { SetStringInterned(pS); meType = Error; } bool ScDPItemData::IsCaseInsEqual(const ScDPItemData& r) const { if (meType != r.meType) return false; switch (meType) { case Value: case RangeStart: return rtl::math::approxEqual(mfValue, r.mfValue); case GroupValue: return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType && maGroupValue.mnValue == r.maGroupValue.mnValue; default: ; } if (mpString == r.mpString) // Fast equality check for interned strings. return true; return ScGlobal::GetpTransliteration()->isEqual(GetString(), r.GetString()); } bool ScDPItemData::operator== (const ScDPItemData& r) const { if (meType != r.meType) return false; switch (meType) { case Value: case RangeStart: return rtl::math::approxEqual(mfValue, r.mfValue); case GroupValue: return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType && maGroupValue.mnValue == r.maGroupValue.mnValue; default: ; } // need exact equality until we have a safe case insensitive string hash return GetString() == r.GetString(); } bool ScDPItemData::operator< (const ScDPItemData& r) const { return Compare(*this, r) == -1; } ScDPItemData& ScDPItemData::operator= (const ScDPItemData& r) { DisposeString(); meType = r.meType; switch (r.meType) { case String: case Error: mbStringInterned = r.mbStringInterned; mpString = r.mpString; if (!mbStringInterned) rtl_uString_acquire(mpString); break; case Value: case RangeStart: mfValue = r.mfValue; break; case GroupValue: maGroupValue.mnGroupType = r.maGroupValue.mnGroupType; maGroupValue.mnValue = r.maGroupValue.mnValue; break; case Empty: default: mfValue = 0.0; } return *this; } ScDPValue::Type ScDPItemData::GetCellType() const { switch (meType) { case Error: return ScDPValue::Error; case Empty: return ScDPValue::Empty; case Value: return ScDPValue::Value; default: ; } return ScDPValue::String; } #if DEBUG_PIVOT_TABLE void ScDPItemData::Dump(const char* msg) const { printf("--- (%s)\n", msg); switch (meType) { case Empty: printf("empty\n"); break; case Error: printf("error: %s\n", OUStringToOString(OUString(mpString), RTL_TEXTENCODING_UTF8).getStr()); break; case GroupValue: printf("group value: group type = %d value = %d\n", maGroupValue.mnGroupType, maGroupValue.mnValue); break; case String: printf("string: %s\n", OUStringToOString(OUString(mpString), RTL_TEXTENCODING_UTF8).getStr()); break; case Value: printf("value: %g\n", mfValue); break; case RangeStart: printf("range start: %g\n", mfValue); break; default: printf("unknown type\n"); } printf("---\n"); } #endif bool ScDPItemData::IsEmpty() const { return meType == Empty; } bool ScDPItemData::IsValue() const { return meType == Value; } OUString ScDPItemData::GetString() const { switch (meType) { case String: case Error: return OUString(mpString); case Value: case RangeStart: return OUString::number(mfValue); case GroupValue: return OUString::number(maGroupValue.mnValue); case Empty: default: ; } return OUString(); } double ScDPItemData::GetValue() const { if (meType == Value || meType == RangeStart) return mfValue; return 0.0; } ScDPItemData::GroupValueAttr ScDPItemData::GetGroupValue() const { if (meType == GroupValue) return maGroupValue; GroupValueAttr aGV; aGV.mnGroupType = -1; aGV.mnValue = -1; return aGV; } bool ScDPItemData::HasStringData() const { return meType == String || meType == Error; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */