sc: make ScAddress constexpr and clean-up

- remove the inlines which are implicit anyway
- make compile type tests of the class
- move inline methods into body

Change-Id: If2656c1b750a300bc0ed589bc7ea6aec27b3237a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190255
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Tested-by: Tomaž Vajngerl <quikee@gmail.com>
This commit is contained in:
Tomaž Vajngerl
2025-08-27 16:52:01 +02:00
committed by Tomaž Vajngerl
parent 827648dabe
commit 4ad007de60
4 changed files with 233 additions and 114 deletions
+35
View File
@@ -0,0 +1,35 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#*************************************************************************
#
# 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/.
#
#*************************************************************************
$(eval $(call gb_CppunitTest_CppunitTest,sc_basic_types_test))
$(eval $(call gb_CppunitTest_add_exception_objects,sc_basic_types_test,\
sc/qa/unit/ScAddressTest \
))
$(eval $(call gb_CppunitTest_use_external,sc_basic_types_test,boost_headers))
$(eval $(call gb_CppunitTest_set_include,sc_basic_types_test,\
-I$(SRCDIR)/sc/source/ui/inc \
-I$(SRCDIR)/sc/source/core/inc \
-I$(SRCDIR)/sc/inc \
$$(INCLUDE) \
))
$(eval $(call gb_CppunitTest_use_libraries,sc_basic_types_test,\
sal \
))
# Needed for include/test/cppunitasserthelper.hxx
$(eval $(call gb_CppunitTest_use_sdk_api,sc_basic_types_test))
# vim: set noet sw=4 ts=4:
+1
View File
@@ -61,6 +61,7 @@ $(eval $(call gb_Module_add_check_targets,sc,\
CppunitTest_sc_filters_test \
CppunitTest_sc_mark_test \
CppunitTest_sc_core \
CppunitTest_sc_basic_types_test \
CppunitTest_sc_dataprovider \
CppunitTest_sc_cache_test \
CppunitTest_sc_parallelism \
+119 -114
View File
@@ -248,77 +248,107 @@ public:
{}
};
ScAddress() :
constexpr ScAddress() :
nRow(0), nCol(0), nTab(0)
{}
ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP ) :
constexpr ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP ) :
nRow(nRowP), nCol(nColP), nTab(nTabP)
{}
/** coverity[uninit_member] - Yes, it is what it seems to be: Uninitialized.
May be used for performance reasons if it is initialized by other means. */
ScAddress( Uninitialized )
constexpr ScAddress( Uninitialized )
{}
ScAddress( InitializeInvalid ) :
constexpr ScAddress( InitializeInvalid ) :
nRow(-1), nCol(-1), nTab(-1)
{}
ScAddress( const ScAddress& rAddress ) :
constexpr ScAddress( const ScAddress& rAddress ) :
nRow(rAddress.nRow), nCol(rAddress.nCol), nTab(rAddress.nTab)
{}
inline ScAddress& operator=( const ScAddress& rAddress );
inline void Set( SCCOL nCol, SCROW nRow, SCTAB nTab );
constexpr ScAddress& operator=(const ScAddress& rAddress)
{
nCol = rAddress.nCol;
nRow = rAddress.nRow;
nTab = rAddress.nTab;
return *this;
}
SCROW Row() const
constexpr void Set(SCCOL nColP, SCROW nRowP, SCTAB nTabP)
{
nCol = nColP;
nRow = nRowP;
nTab = nTabP;
}
constexpr SCROW Row() const
{
return nRow;
}
SCCOL Col() const
constexpr SCCOL Col() const
{
return nCol;
}
SCTAB Tab() const
constexpr SCTAB Tab() const
{
return nTab;
}
void SetRow( SCROW nRowP )
constexpr void SetRow( SCROW nRowP )
{
nRow = nRowP;
}
void SetCol( SCCOL nColP )
constexpr void SetCol( SCCOL nColP )
{
nCol = nColP;
}
void SetTab( SCTAB nTabP )
constexpr void SetTab( SCTAB nTabP )
{
nTab = nTabP;
}
void SetInvalid()
constexpr void SetInvalid()
{
nRow = -1;
nCol = -1;
nTab = -1;
}
bool IsValid() const
constexpr bool IsValid() const
{
return (nRow >= 0) && (nCol >= 0) && (nTab >= 0);
}
inline void PutInOrder( ScAddress& rAddress );
constexpr void PutInOrder(ScAddress& rAddress)
{
::PutInOrder(nCol, rAddress.nCol);
::PutInOrder(nRow, rAddress.nRow);
::PutInOrder(nTab, rAddress.nTab);
}
void IncRow( SCROW nDelta = 1 )
constexpr void IncRow( SCROW nDelta = 1 )
{
nRow = sal::static_int_cast<SCROW>(nRow + nDelta);
nRow = static_cast<SCROW>(nRow + nDelta);
}
void IncCol( SCCOL nDelta = 1 )
constexpr void IncCol( SCCOL nDelta = 1 )
{
nCol = sal::static_int_cast<SCCOL>(nCol + nDelta);
nCol = static_cast<SCCOL>(nCol + nDelta);
}
void IncTab( SCTAB nDelta = 1 )
constexpr void IncTab( SCTAB nDelta = 1 )
{
nTab = sal::static_int_cast<SCTAB>(nTab + nDelta);
nTab = static_cast<SCTAB>(nTab + nDelta);
}
void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
constexpr void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
{
nColP = nCol;
nRowP = nRow;
@@ -358,13 +388,72 @@ public:
[[nodiscard]] SC_DLLPUBLIC bool Move( SCCOL nDeltaX, SCROW nDeltaY, SCTAB nDeltaZ,
ScAddress& rErrorPos, const ScDocument& rDoc );
inline bool operator==( const ScAddress& rAddress ) const;
inline bool operator!=( const ScAddress& rAddress ) const;
inline bool operator<( const ScAddress& rAddress ) const;
inline bool operator<=( const ScAddress& rAddress ) const;
inline bool lessThanByRow( const ScAddress& rAddress ) const;
constexpr bool operator==( const ScAddress& rAddress ) const
{
return nRow == rAddress.nRow && nCol == rAddress.nCol && nTab == rAddress.nTab;
}
inline size_t hash() const;
/** Less than ordered by tab,col,row. */
constexpr bool operator<(const ScAddress& rAddress) const
{
if (nTab == rAddress.nTab)
{
if (nCol == rAddress.nCol)
return nRow < rAddress.nRow;
else
return nCol < rAddress.nCol;
}
else
return nTab < rAddress.nTab;
}
constexpr bool operator<=( const ScAddress& rAddress ) const
{
return operator<(rAddress) || operator==(rAddress);
}
constexpr bool operator>(const ScAddress& rAddress) const
{
return !(operator<=(rAddress));
}
constexpr bool operator>=(const ScAddress& rAddress) const
{
return !(operator<(rAddress));
}
/** Less than ordered by tab,row,col as needed by row-wise import/export */
bool lessThanByRow(const ScAddress& rAddress) const
{
if (nTab == rAddress.nTab)
{
if (nRow == rAddress.nRow)
return nCol < rAddress.nCol;
else
return nRow < rAddress.nRow;
}
else
return nTab < rAddress.nTab;
}
size_t hash() const
{
#if SAL_TYPES_SIZEOFPOINTER == 8
// 16 bits for the columns, and 20 bits for the rows
return (static_cast<size_t>(nTab) << 36) ^
(static_cast<size_t>(nCol) << 20) ^
static_cast<size_t>(nRow);
#else
// Assume that there are not that many addresses with row > 2^16 AND column
// > 2^8 AND sheet > 2^8 so we won't have too many collisions.
if (nRow <= 0xffff)
return (static_cast<size_t>(nTab) << 24) ^
(static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
else
return (static_cast<size_t>(nTab) << 28) ^
(static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
#endif
}
/**
* Create a human-readable string representation of the cell address. You
@@ -390,90 +479,6 @@ inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT,
return stream;
}
inline void ScAddress::PutInOrder( ScAddress& rAddress )
{
::PutInOrder(nCol, rAddress.nCol);
::PutInOrder(nRow, rAddress.nRow);
::PutInOrder(nTab, rAddress.nTab);
}
inline void ScAddress::Set( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
{
nCol = nColP;
nRow = nRowP;
nTab = nTabP;
}
inline ScAddress& ScAddress::operator=( const ScAddress& rAddress )
{
nCol = rAddress.nCol;
nRow = rAddress.nRow;
nTab = rAddress.nTab;
return *this;
}
inline bool ScAddress::operator==( const ScAddress& rAddress ) const
{
return nRow == rAddress.nRow && nCol == rAddress.nCol && nTab == rAddress.nTab;
}
inline bool ScAddress::operator!=( const ScAddress& rAddress ) const
{
return !operator==( rAddress );
}
/** Less than ordered by tab,col,row. */
inline bool ScAddress::operator<( const ScAddress& rAddress ) const
{
if (nTab == rAddress.nTab)
{
if (nCol == rAddress.nCol)
return nRow < rAddress.nRow;
else
return nCol < rAddress.nCol;
}
else
return nTab < rAddress.nTab;
}
inline bool ScAddress::operator<=( const ScAddress& rAddress ) const
{
return operator<( rAddress ) || operator==( rAddress );
}
/** Less than ordered by tab,row,col as needed by row-wise import/export */
inline bool ScAddress::lessThanByRow( const ScAddress& rAddress ) const
{
if (nTab == rAddress.nTab)
{
if (nRow == rAddress.nRow)
return nCol < rAddress.nCol;
else
return nRow < rAddress.nRow;
}
else
return nTab < rAddress.nTab;
}
inline size_t ScAddress::hash() const
{
#if SAL_TYPES_SIZEOFPOINTER == 8
// 16 bits for the columns, and 20 bits for the rows
return (static_cast<size_t>(nTab) << 36) ^
(static_cast<size_t>(nCol) << 20) ^
static_cast<size_t>(nRow);
#else
// Assume that there are not that many addresses with row > 2^16 AND column
// > 2^8 AND sheet > 2^8 so we won't have too many collisions.
if (nRow <= 0xffff)
return (static_cast<size_t>(nTab) << 24) ^
(static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
else
return (static_cast<size_t>(nTab) << 28) ^
(static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
#endif
}
struct ScAddressHashFunctor
{
size_t operator()( const ScAddress & rAddress ) const
@@ -482,7 +487,7 @@ struct ScAddressHashFunctor
}
};
[[nodiscard]] inline bool ValidAddress( const ScAddress& rAddress, SCCOL nMaxCol, SCROW nMaxRow )
[[nodiscard]] constexpr bool ValidAddress(const ScAddress& rAddress, SCCOL nMaxCol, SCROW nMaxRow)
{
return ValidCol(rAddress.Col(), nMaxCol) && ValidRow(rAddress.Row(), nMaxRow) && ValidTab(rAddress.Tab());
}
+78
View File
@@ -0,0 +1,78 @@
/* -*- 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/.
*/
#include <address.hxx>
#include <cppunit/plugin/TestPlugIn.h>
// Compile time tests for ScAddress
static_assert(ScAddress() == ScAddress(0, 0, 0));
static_assert(ScAddress().IsValid() == true);
static_assert(ScAddress(ScAddress::INITIALIZE_INVALID).IsValid() == false);
// Equal, not Equal
// Format is Col, Row, Tab and Col has priority over Row
static_assert(ScAddress(0, 0, 0) != ScAddress(1, 0, 0)); // A1 != B1
static_assert(ScAddress(0, 0, 0) != ScAddress(0, 1, 0)); // A1 != A2
static_assert(ScAddress(0, 0, 0) != ScAddress(0, 0, 1)); // Sheet1:A1 != Sheet2:A1
static_assert(ScAddress(0, 0, 0) == ScAddress(0, 0, 0)); // A1 == A1
// Less
static_assert(!(ScAddress(1, 0, 0) < ScAddress(1, 0, 0))); // B1 < B1
static_assert(!(ScAddress(0, 1, 0) < ScAddress(0, 1, 0))); // A2 < A2
static_assert(!(ScAddress(0, 0, 1) < ScAddress(0, 0, 1))); // Sheet2:A1 < Sheet2:A1
static_assert(ScAddress(0, 0, 0) < ScAddress(1, 0, 0)); // A1 < B1
static_assert(ScAddress(0, 1, 0) < ScAddress(1, 0, 0)); // A2 < B1
static_assert(ScAddress(0, 10000, 0) < ScAddress(1, 0, 0)); // A10000 < B1
static_assert(ScAddress(0, 10000, 0) < ScAddress(1, 10000, 0)); // A10000 < B10000
static_assert(ScAddress(1, 0, 0) < ScAddress(1, 0, 1)); // Sheet1:A1 < Sheet2:A1
// Less or Equal
static_assert(ScAddress(1, 0, 0) <= ScAddress(1, 0, 0)); // B1 <= B1
static_assert(ScAddress(0, 1, 0) <= ScAddress(0, 1, 0)); // A2 <= A2
static_assert(ScAddress(0, 0, 1) <= ScAddress(0, 0, 1)); // Sheet2:A1 <= Sheet2:A1
static_assert(ScAddress(0, 0, 0) <= ScAddress(1, 0, 0)); // A1 <= B1
static_assert(ScAddress(0, 1, 0) <= ScAddress(1, 0, 0)); // A2 <= B1
static_assert(ScAddress(0, 10000, 0) <= ScAddress(1, 0, 0)); // A10000 <= B1
static_assert(ScAddress(0, 10000, 0) <= ScAddress(1, 10000, 0)); // A10000 <= B10000
static_assert(ScAddress(1, 0, 0) <= ScAddress(1, 0, 1)); // Sheet1:A1 <= Sheet2:A1
// More
static_assert(!(ScAddress(1, 0, 0) > ScAddress(1, 0, 0))); // B1 > B1
static_assert(!(ScAddress(0, 1, 0) > ScAddress(0, 1, 0))); // A2 > A2
static_assert(!(ScAddress(0, 0, 1) > ScAddress(0, 0, 1))); // Sheet1:A1 > Sheet2:A1
static_assert(ScAddress(1, 0, 0) > ScAddress(0, 0, 0)); // B1 > A1
static_assert(ScAddress(1, 0, 0) > ScAddress(0, 1, 0)); // B1 > A2
static_assert(ScAddress(1, 0, 0) > ScAddress(0, 10000, 0)); // B1 > A10000
static_assert(ScAddress(1, 10000, 0) > ScAddress(0, 10000, 0)); // B10000 > A10000
static_assert(ScAddress(1, 0, 1) > ScAddress(1, 0, 0)); // Sheet2:A1 > Sheet1:A1
// More or Equal
static_assert(ScAddress(1, 0, 0) >= ScAddress(1, 0, 0)); // B1 >= B1
static_assert(ScAddress(0, 1, 0) >= ScAddress(0, 1, 0)); // A2 >= A2
static_assert(ScAddress(0, 0, 1) >= ScAddress(0, 0, 1)); // Sheet1:A1 >= Sheet2:A1
static_assert(ScAddress(1, 0, 0) >= ScAddress(0, 0, 0)); // B1 >= A1
static_assert(ScAddress(1, 0, 0) >= ScAddress(0, 1, 0)); // B1 >= A2
static_assert(ScAddress(1, 0, 0) >= ScAddress(0, 10000, 0)); // B1 >= A10000
static_assert(ScAddress(1, 10000, 0) >= ScAddress(0, 10000, 0)); // B10000 >= A10000
static_assert(ScAddress(1, 0, 1) >= ScAddress(1, 0, 0)); // Sheet2:A1 >= Sheet1:A1
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */