summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@me.com>2019-05-07 21:16:10 +0200
committerArmin Le Grand <Armin.Le.Grand@me.com>2019-05-07 21:16:10 +0200
commit974feb26536435676f3135a2625477c90de2cb7a (patch)
tree1b1d215f6e28d6921d3140c3595529305cf448c5
parent792c0ba7b5c8be39c4a1023037d7977dd30615e3 (diff)
WIP: Stabilizing/simplifying clone()
Added clone() functionality to ItemControlBlock, makes it safer and less error-prone in terms of forgetting to overload correctly. Added make_unique to have more alternatives for changing local data in case of BufferedItem. Added clone() for ItemData to ItemAdministrator. Added quite some comments, too. Adapted examples in TestCases, adapted all current implementations Change-Id: Ia5aaafed700a3a003d8049fbb5978291235c6263
-rw-r--r--basctl/source/basicide/sbxitem.cxx12
-rw-r--r--include/item/base/ItemAdministrator.hxx19
-rw-r--r--include/item/base/ItemBase.hxx50
-rwxr-xr-xinclude/item/base/ItemBuffered.hxx53
-rwxr-xr-xinclude/item/base/ItemControlBlock.hxx13
-rw-r--r--include/item/simple/CntInt16.hxx2
-rw-r--r--include/item/simple/CntOUString.hxx2
-rwxr-xr-xinclude/svx/item/TransformAnchor.hxx2
-rw-r--r--item/source/base/ItemAdministrator.cxx32
-rw-r--r--item/source/base/ItemBase.cxx22
-rwxr-xr-xitem/source/base/ItemBuffered.cxx84
-rwxr-xr-xitem/source/base/ItemControlBlock.cxx9
-rw-r--r--item/source/simple/CntInt16.cxx7
-rw-r--r--item/source/simple/CntOUString.cxx7
-rw-r--r--item/test/ItemTest.cxx110
-rwxr-xr-xsvx/source/items/TransformAnchor.cxx7
16 files changed, 313 insertions, 118 deletions
diff --git a/basctl/source/basicide/sbxitem.cxx b/basctl/source/basicide/sbxitem.cxx
index 99b1ab024c8b..3618bcb5d8b8 100644
--- a/basctl/source/basicide/sbxitem.cxx
+++ b/basctl/source/basicide/sbxitem.cxx
@@ -31,6 +31,7 @@ namespace Item
{
static ::Item::ItemControlBlock aItemControlBlock(
[](){ return new Sbx(ScriptDocument::getApplicationScriptDocument()); },
+ [](const ItemBase& rRef){ return new Sbx(static_cast<const Sbx&>(rRef)); },
"Sbx");
return aItemControlBlock;
@@ -41,6 +42,17 @@ namespace Item
static ::Item::ItemAdministrator_vector aItemAdministrator_vector(
// hand over localized lambda call to construct a new instance of Item
[](){ return new Sbx::SbxData(ScriptDocument::getApplicationScriptDocument()); },
+ // hand over localized lambda call to clone an Item
+ [](const ItemData& rRef)
+ {
+ const SbxData& rData(static_cast<const SbxData&>(rRef));
+ return new SbxData(
+ rData.GetDocument(),
+ rData.GetLibName(),
+ rData.GetName(),
+ rData.GetMethodName(),
+ rData.GetType());
+ },
// hand over localized lambda operator==
[](ItemData* A, ItemData* B)
{
diff --git a/include/item/base/ItemAdministrator.hxx b/include/item/base/ItemAdministrator.hxx
index 18a3a6eb953a..dbe96a9de653 100644
--- a/include/item/base/ItemAdministrator.hxx
+++ b/include/item/base/ItemAdministrator.hxx
@@ -34,11 +34,14 @@ namespace Item
class ITEM_DLLPUBLIC ItemAdministrator
{
private:
- std::function<ItemBuffered::ItemData*()> m_aConstructItem;
+ std::function<ItemBuffered::ItemData*()> m_aConstructItemData;
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> m_aCloneItemData;
protected:
public:
- ItemAdministrator(std::function<ItemBuffered::ItemData*()> aConstructItem);
+ ItemAdministrator(
+ std::function<ItemBuffered::ItemData*()> aConstructItemData,
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> aCloneItemData);
virtual ~ItemAdministrator();
// noncopyable
@@ -51,6 +54,9 @@ namespace Item
// instance supplier
ItemBuffered::ItemData* createNewDataInstance() const;
+
+ // clone operator
+ ItemBuffered::ItemData* clone(const ItemBuffered::ItemData& rRef) const;
};
} // end of namespace Item
@@ -73,7 +79,8 @@ namespace Item
protected:
public:
ItemAdministrator_set(
- std::function<ItemBuffered::ItemData*()> aConstructItem,
+ std::function<ItemBuffered::ItemData*()> aConstructItemData,
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> aCloneItemData,
std::function<bool(ItemBuffered::ItemData*, ItemBuffered::ItemData*)> aLess);
// buffer accesses
@@ -101,7 +108,8 @@ namespace Item
protected:
public:
ItemAdministrator_unordered_set(
- std::function<ItemBuffered::ItemData*()> aConstructItem,
+ std::function<ItemBuffered::ItemData*()> aConstructItemData,
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> aCloneItemData,
std::function<size_t(ItemBuffered::ItemData*)> aHash,
std::function<bool(ItemBuffered::ItemData*, ItemBuffered::ItemData*)> aCompare);
@@ -139,7 +147,8 @@ namespace Item
public:
ItemAdministrator_vector(
- std::function<ItemBuffered::ItemData*()> aConstructItem,
+ std::function<ItemBuffered::ItemData*()> aConstructItemData,
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> aCloneItemData,
std::function<bool(ItemBuffered::ItemData*, ItemBuffered::ItemData*)> aSame);
// buffer accesses
diff --git a/include/item/base/ItemBase.hxx b/include/item/base/ItemBase.hxx
index b93d5b196ce9..f0f746b5a036 100644
--- a/include/item/base/ItemBase.hxx
+++ b/include/item/base/ItemBase.hxx
@@ -32,6 +32,39 @@ namespace Item
{
class ItemControlBlock;
+ // Baseclass for implementation of (refactored) Items. It is
+ // pure virtual (do not construct ItemBase itself). There
+ // are two kinds of Items now:
+ // (1) SimpleItems derived from ItemBase directly
+ // (2) BufferedItems derived from ItemBuffered
+ // Items in the old form were buffered at the ItemPool
+ // and needed as basic content the value, RefCnt, which
+ // and kind - thus the size of an incarnation will be not
+ // smaller than the naked item itself, the contrary. So
+ // where is the reason for buffering and keeping only one
+ // ref-conted instance of every possible incarnation?
+ // The new Item is similar, the buffered version (2) has
+ // the ItemControlBlock&, the item's value(s) itself and a
+ // refCounting of some kind. Thus the consequence is:
+ // As long as an Item including the ItemControlBlock& and
+ // it's data is smaller than the refCnted version, do not
+ // refCnt it, but profit from small footprint and simple
+ // copyability - derive from (1).
+ // Thus all new Items simple and small enough (ca. 3-4 'machine' words,
+ // depending on 32/64bit) should use ItemBase as base (see CntInt16
+ // as example)
+ // They should use ItemBuffered as soon as some relevant size
+ // is reached. That again will - due to the Item-incarnation
+ // referencing the ItemData - also have small footprint and simple
+ // copyability, but be a bit harder to implement.
+ // Note: All Items can be implemented either way, the diecision should
+ // be made upon size of one incarnation and copyability (some are better
+ // refCnted). (2) has all the tooling to do that in a unified way.
+ // For examples how to implement your Item, check
+ // item\test\ItemTest.cxx where for test purposes a simple two-
+ // value Item is implemented both ways, as example derived adding
+ // a third value, and derived to get a new ItemType for typeSafe
+ // future handling.
class ITEM_DLLPUBLIC ItemBase
{
public:
@@ -42,7 +75,7 @@ namespace Item
// PutValue/Any interface for automated instance creation from SfxType
// mechanism (UNO API and sfx2 stuff)
- virtual void putAnyValues(const AnyIDArgs& rArgs);
+ void putAnyValues(const AnyIDArgs& rArgs);
private:
// local reference to instance of ItemControlBlock for this
@@ -57,23 +90,28 @@ namespace Item
// mechanism (UNO API and sfx2 stuff)
virtual void putAnyValue(const css::uno::Any& rVal, sal_uInt8 nMemberId);
- public:
+ // constructor for derived classes, thus protected. Derived
+ // classes hand in their specific ItemControlBlock to be used
ItemBase(ItemControlBlock& rItemControlBlock);
+
+ public:
virtual ~ItemBase();
+ // copy constructor and assigment operator (both allowed)
ItemBase(const ItemBase&);
ItemBase& operator=(const ItemBase&);
+ // compare, != uses it internally and thus is not virtual
virtual bool operator==(const ItemBase&) const;
bool operator!=(const ItemBase&) const;
- // default interface
+ // default-value interface
const ItemBase& getDefault() const;
bool isDefault() const;
- // clone-op, secured by handing over a std::unique_ptr directly
- // to make explicit the ownership you get when calling this
- virtual std::unique_ptr<ItemBase> clone() const = 0;
+ // clone-op, secured by returning a std::unique_ptr to make
+ // explicit the ownership you get when calling this
+ std::unique_ptr<ItemBase> clone() const;
};
// static versions of default interface
diff --git a/include/item/base/ItemBuffered.hxx b/include/item/base/ItemBuffered.hxx
index 43727586ffbf..92401a028307 100755
--- a/include/item/base/ItemBuffered.hxx
+++ b/include/item/base/ItemBuffered.hxx
@@ -31,9 +31,17 @@ namespace Item
{
class ItemAdministrator;
+ // Baseclass for implementing buffered Items. The class is
+ // pure virtual and can/should not be incarnated directly,
+ // only derivatiohns from it.
+ // Please see include\item\base\ItemBase.hxx for more basic
+ // discussion about that.
class ITEM_DLLPUBLIC ItemBuffered : public ItemBase
{
public:
+ // This is the pattern for the ItemData block. It is by purpose
+ // included to class ItemBuffered to make clear that it's usage
+ // only makes sense inside that class
class ITEM_DLLPUBLIC ItemData
{
private:
@@ -42,10 +50,12 @@ namespace Item
sal_Int32 m_nRef;
protected:
+ // access to the ItemAAdministrator (see include\item\base\ItemAdministrator.hxx)
virtual ItemAdministrator& getItemAdministrator() const = 0;
// PutValue/Any interface for automated instance creation from SfxType
- // mechanism (UNO API and sfx2 stuff)
+ // mechanism (UNO API and sfx2 stuff). Default does nothing, but asserts
+ // for missing implementation
virtual void putAnyValue(const css::uno::Any& rVal, sal_uInt8 nMemberId);
public:
@@ -56,20 +66,29 @@ namespace Item
ItemData(const ItemData&) = delete;
ItemData& operator=(const ItemData&) = delete;
+ // compare Op - operator!= is using operator==
+ // so only operator== needs to be implemented
virtual bool operator==(const ItemData&) const;
bool operator!=(const ItemData&) const;
+
+ // clone-op, needs to create new instance and copy content.
+ // Call is forwarded to ItemAdministrator which needs a copy
+ // operator at construction time
+ ItemData* clone() const;
};
private:
+ // reference to the data block, will never be nullptr
ItemData* m_pItemData;
+ // internal acquire/release of DataBlock
void acquire();
void release();
- public:
+ protected:
// PutValue/Any interface for automated instance creation from SfxType
// mechanism (UNO API and sfx2 stuff)
- virtual void putAnyValues(const AnyIDArgs& rArgs);
+ virtual void putAnyValue(const css::uno::Any& rVal, sal_uInt8 nMemberId);
protected:
// Method to internally (thus protected) set a new ItemData
@@ -81,19 +100,33 @@ namespace Item
// hand-over allowed (!)
void setItemData(ItemData* pItemData);
- // access to ItemData instance - only const (!) and
- // only internal for derived classes to implement
- // data read access methods (Get-Methods)
- ItemData const& getItemData() const { return *m_pItemData; }
+ // guarantees local instance refCnt == 1, so only owner. Will
+ // execute needed actions when required.
+ // difference to setItemData is that it potentially has to
+ // clone a copy itself, thus setItemData may be more effective
+ void make_unique();
- public:
+ // access to ItemData instance. CAUTION! If you want to use this
+ // to change data at your derivation of ItemData, you *have* to
+ // use setItemData or make_unique to be safe (!)
+ ItemData& getItemData() const { return *m_pItemData; }
+
+ // constructor for derived classes, thus protected. Derived
+ // classes hand in their specific ItemControlBlock to be used
ItemBuffered(ItemControlBlock& rItemControlBlock);
- ItemBuffered(const ItemBuffered&);
+
+ public:
virtual ~ItemBuffered();
+
+ // copy constructor and assigment operator (both allowed).
+ // Both use the refCnted incarnation of ItemData and are
+ // complete
+ ItemBuffered(const ItemBuffered&);
ItemBuffered& operator=(const ItemBuffered&);
+ // compare, default implementation uses ItemData and
+ // is complete
virtual bool operator==(const ItemBase&) const;
- virtual std::unique_ptr<ItemBase> clone() const;
};
} // end of namespace Item
diff --git a/include/item/base/ItemControlBlock.hxx b/include/item/base/ItemControlBlock.hxx
index 80effd85a24a..cb55bd7f6581 100755
--- a/include/item/base/ItemControlBlock.hxx
+++ b/include/item/base/ItemControlBlock.hxx
@@ -35,23 +35,30 @@ namespace Item
class ITEM_DLLPUBLIC ItemControlBlock
{
private:
- std::unique_ptr<const ItemBase> m_aDefaultItem;
- std::function<ItemBase*()> m_aConstructDefaultItem;
- OUString m_aName;
+ std::unique_ptr<const ItemBase> m_aDefaultItem;
+ std::function<ItemBase*()> m_aConstructDefaultItem;
+ std::function<ItemBase*(const ItemBase&)> m_aCloneItem;
+ OUString m_aName;
public:
ItemControlBlock(
std::function<ItemBase*()>aConstructDefaultItem,
+ std::function<ItemBase*(const ItemBase&)>aCloneItem,
const OUString& rName);
ItemControlBlock();
const ItemBase& getDefault() const;
bool isDefault(const ItemBase& rItem) const;
+
const OUString& getName() const
{
return m_aName;
}
+ // clone-op, secured by returning a std::unique_ptr to make
+ // explicit the ownership you get when calling this
+ std::unique_ptr<ItemBase> clone(const ItemBase&) const;
+
std::unique_ptr<const ItemBase> createFromAny(const ItemBase::AnyIDArgs& rArgs);
};
} // end of namespace Item
diff --git a/include/item/simple/CntInt16.hxx b/include/item/simple/CntInt16.hxx
index 1ad85e0548f0..7a2da5efbe51 100644
--- a/include/item/simple/CntInt16.hxx
+++ b/include/item/simple/CntInt16.hxx
@@ -35,9 +35,7 @@ namespace Item
public:
CntInt16(sal_Int16 nVal = 0);
-
virtual bool operator==(const ItemBase&) const;
- virtual std::unique_ptr<ItemBase> clone() const;
sal_Int16 getValue() const { return m_nValue; }
void putValue(sal_Int16 nNew) { m_nValue = nNew; }
diff --git a/include/item/simple/CntOUString.hxx b/include/item/simple/CntOUString.hxx
index 2f8d2784e912..0b33c66578c0 100644
--- a/include/item/simple/CntOUString.hxx
+++ b/include/item/simple/CntOUString.hxx
@@ -32,9 +32,7 @@ namespace Item
public:
CntOUString(const rtl::OUString& rValue = rtl::OUString());
-
virtual bool operator==(const ItemBase&) const;
- virtual std::unique_ptr<ItemBase> clone() const;
const rtl::OUString& getValue() const { return m_aValue; }
void putValue(const rtl::OUString& rValue) { m_aValue = rValue; }
diff --git a/include/svx/item/TransformAnchor.hxx b/include/svx/item/TransformAnchor.hxx
index 4e31a25bff60..c4142bcba1b8 100755
--- a/include/svx/item/TransformAnchor.hxx
+++ b/include/svx/item/TransformAnchor.hxx
@@ -26,8 +26,6 @@ namespace Item
public:
TransformAnchor(RndStdIds nValue = RndStdIds::UNKNOWN);
- virtual std::unique_ptr<ItemBase> clone() const;
-
RndStdIds GetAnchorType() const { return static_cast<RndStdIds>(getValue()); }
};
} // end of namespace Item
diff --git a/item/source/base/ItemAdministrator.cxx b/item/source/base/ItemAdministrator.cxx
index a2ff76289839..b7cfae5400e6 100644
--- a/item/source/base/ItemAdministrator.cxx
+++ b/item/source/base/ItemAdministrator.cxx
@@ -13,10 +13,14 @@
namespace Item
{
- ItemAdministrator::ItemAdministrator(std::function<ItemBuffered::ItemData*()> aConstructItem)
- : m_aConstructItem(aConstructItem)
+ ItemAdministrator::ItemAdministrator(
+ std::function<ItemBuffered::ItemData*()> aConstructItemData,
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> aCloneItemData)
+ : m_aConstructItemData(aConstructItemData),
+ m_aCloneItemData(aCloneItemData)
{
- assert(nullptr != m_aConstructItem && "ItemAdministrator::ItemAdministrator called without valid constructItem lambda (!)");
+ assert(nullptr != m_aConstructItemData && "ItemAdministrator::ItemAdministrator called without valid ConstructItemData lambda (!)");
+ assert(nullptr != m_aCloneItemData && "ItemAdministrator::ItemAdministrator called without valid CloneItemData lambda (!)");
}
ItemAdministrator::~ItemAdministrator()
@@ -34,7 +38,12 @@ namespace Item
ItemBuffered::ItemData* ItemAdministrator::createNewDataInstance() const
{
- return m_aConstructItem();
+ return m_aConstructItemData();
+ }
+
+ ItemBuffered::ItemData* ItemAdministrator::clone(const ItemBuffered::ItemData& rRef) const
+ {
+ return m_aCloneItemData(rRef);
}
} // end of namespace Item
@@ -43,9 +52,10 @@ namespace Item
namespace Item
{
ItemAdministrator_set::ItemAdministrator_set(
- std::function<ItemBuffered::ItemData*()> aConstructItem,
+ std::function<ItemBuffered::ItemData*()> aConstructItemData,
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> aCloneItemData,
std::function<bool(ItemBuffered::ItemData*, ItemBuffered::ItemData*)> aLess)
- : ItemAdministrator(aConstructItem),
+ : ItemAdministrator(aConstructItemData, aCloneItemData),
m_aEntries(aLess)
{
}
@@ -76,10 +86,11 @@ namespace Item
namespace Item
{
ItemAdministrator_unordered_set::ItemAdministrator_unordered_set(
- std::function<ItemBuffered::ItemData*()> aConstructItem,
+ std::function<ItemBuffered::ItemData*()> aConstructItemData,
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> aCloneItemData,
std::function<size_t(ItemBuffered::ItemData*)> aHash,
std::function<bool(ItemBuffered::ItemData*, ItemBuffered::ItemData*)> aCompare)
- : ItemAdministrator(aConstructItem),
+ : ItemAdministrator(aConstructItemData, aCloneItemData),
m_aEntries(
0, // bucket_count -> not sure, want a system default. Will zero give me that?
aHash,
@@ -185,9 +196,10 @@ namespace Item
}
ItemAdministrator_vector::ItemAdministrator_vector(
- std::function<ItemBuffered::ItemData*()> aConstructItem,
+ std::function<ItemBuffered::ItemData*()> aConstructItemData,
+ std::function<ItemBuffered::ItemData*(const ItemBuffered::ItemData&)> aCloneItemData,
std::function<bool(ItemBuffered::ItemData*, ItemBuffered::ItemData*)> aSame)
- : ItemAdministrator(aConstructItem),
+ : ItemAdministrator(aConstructItemData, aCloneItemData),
m_aEntries(),
m_aFreeSlots(),
m_aSame(aSame)
diff --git a/item/source/base/ItemBase.cxx b/item/source/base/ItemBase.cxx
index 40be2aeb73f8..b4ca752fc08e 100644
--- a/item/source/base/ItemBase.cxx
+++ b/item/source/base/ItemBase.cxx
@@ -87,17 +87,16 @@ namespace Item
{
void ItemBase::putAnyValues(const AnyIDArgs& rArgs)
{
- if(!rArgs.empty())
+ // default implementation does spread given arguments to putAnyValue-call
+ for(const auto& arg : rArgs)
{
- for(const auto& arg : rArgs)
- {
- putAnyValue(arg.first, arg.second);
- }
+ putAnyValue(arg.first, arg.second);
}
}
void ItemBase::putAnyValue(const css::uno::Any& /*rVal*/, sal_uInt8 /*nMemberId*/)
{
+ // default has nothing to to
}
ItemBase::ItemBase(ItemControlBlock& rItemControlBlock)
@@ -114,22 +113,32 @@ namespace Item
{
}
- ItemBase& ItemBase::operator=(const ItemBase&)
+ ItemBase& ItemBase::operator=(const ItemBase& rRef)
{
+ // nothing to copy - type has to be identical
+ assert(typeid(const_cast<ItemBase&>(rRef)) == typeid(*this) && "Unequal types in ItemBase::operator= not allowed (!)");
return *this;
}
bool ItemBase::operator==(const ItemBase& rRef) const
{
// ptr-compare
+ assert(typeid(rRef) == typeid(*this) && "Unequal types in ItemBase::operator== not allowed (!)");
return (this == &rRef);
}
bool ItemBase::operator!=(const ItemBase& rRef) const
{
+ assert(typeid(rRef) == typeid(*this) && "Unequal types in ItemBase::operator!= not allowed (!)");
return !(*this == rRef);
}
+ std::unique_ptr<ItemBase> ItemBase::clone() const
+ {
+ // callback to ItemControlBlock
+ return m_rItemControlBlock.clone(*this);
+ }
+
const ItemBase& ItemBase::getDefault() const
{
// callback to ItemControlBlock
@@ -144,6 +153,7 @@ namespace Item
bool isDefault(const ItemBase& rCandidate)
{
+ // callback to ItemControlBlock
return rCandidate.m_rItemControlBlock.isDefault(rCandidate);
}
} // end of namespace Item
diff --git a/item/source/base/ItemBuffered.cxx b/item/source/base/ItemBuffered.cxx
index 0006672ee768..1c974f0fa589 100755
--- a/item/source/base/ItemBuffered.cxx
+++ b/item/source/base/ItemBuffered.cxx
@@ -33,13 +33,21 @@ namespace Item
bool ItemBuffered::ItemData::operator==(const ItemData& rRef) const
{
+ assert(typeid(rRef) == typeid(*this) && "Unequal types in ItemBuffered::ItemData::operator== not allowed (!)");
return (this == &rRef); // ptr-compare
}
bool ItemBuffered::ItemData::operator!=(const ItemData& rRef) const
{
+ assert(typeid(rRef) == typeid(*this) && "Unequal types in ItemBuffered::ItemData::operator!= not allowed (!)");
return !(*this == rRef);
}
+
+ ItemBuffered::ItemData* ItemBuffered::ItemData::clone() const
+ {
+ return getItemAdministrator().clone(*this);
+ }
+
} // end of namespace Item
///////////////////////////////////////////////////////////////////////////////
@@ -50,26 +58,32 @@ namespace Item
{
if(0 == m_pItemData->m_nRef)
{
- {
- ItemData* pAlternative = m_pItemData->getItemAdministrator().find_or_set(m_pItemData);
+ // no owner yet - grab it. Ensure uniqueness of incarnation. find_or_set
+ // will return an already existing equal incarnation if exists for this
+ // type
+ ItemData* pAlternative = m_pItemData->getItemAdministrator().find_or_set(m_pItemData);
- if(pAlternative != m_pItemData)
- {
- delete m_pItemData;
- m_pItemData = pAlternative;
- }
+ if(pAlternative != m_pItemData)
+ {
+ // if an incarnation already exists, delete suggested incarnation
+ // and also use existing one
+ delete m_pItemData;
+ m_pItemData = pAlternative;
}
}
+ // increse refCnt
m_pItemData->m_nRef++;
}
void ItemBuffered::release()
{
+ // decrease RefCnt
m_pItemData->m_nRef--;
if(0 == m_pItemData->m_nRef)
{
+ // no owner anymore - deregister at ItemAdministrator and delete
m_pItemData->getItemAdministrator().remove(m_pItemData);
delete m_pItemData;
}
@@ -79,41 +93,60 @@ namespace Item
{
assert(nullptr != pItemData && "ItemBuffered::setItemData called without ItemData instance (!)");
- if(pItemData == m_pItemData || (nullptr != pItemData && nullptr != m_pItemData && *pItemData == *m_pItemData))
+ if(pItemData == m_pItemData || // ptr-compare
+ (nullptr != pItemData && nullptr != m_pItemData // if both exist
+ && *pItemData == *m_pItemData)) // content-conmpare
{
// no data change - no need to set
delete pItemData;
}
else
{
+ // will be replaced
if(nullptr != m_pItemData)
{
+ // release if used
release();
}
+ // set instance locally
m_pItemData = pItemData;
+
+ // grep it
acquire();
}
}
- void ItemBuffered::putAnyValues(const AnyIDArgs& rArgs)
+ void ItemBuffered::make_unique()
{
- assert(nullptr != m_pItemData && "ItemBuffered::putAnyValues called but m_pItemData not set (!)");
+ assert(nullptr != m_pItemData && "ItemBuffered::make_unique called but m_pItemData not set (!)");
- if(!rArgs.empty())
+ if(m_pItemData->m_nRef > 1)
{
- ItemData* pNewItemData(m_pItemData->getItemAdministrator().createNewDataInstance());
- assert(nullptr != pNewItemData && "ItemBuffered::putAnyValues could not create new ItemData instance (!)");
+ // is not owned, need to create a copy
+ release();
- for(const auto& arg : rArgs)
- {
- pNewItemData->putAnyValue(arg.first, arg.second);
- }
+ // create copy and assign
+ m_pItemData = m_pItemData->clone();
- setItemData(pNewItemData);
+ // grep new instance
+ acquire();
}
}
+ void ItemBuffered::putAnyValue(const css::uno::Any& rVal, sal_uInt8 nMemberId)
+ {
+ assert(nullptr != m_pItemData && "ItemBuffered::putAnyValues called but m_pItemData not set (!)");
+
+ // make sure we are unique - would be nice to first test for change,
+ // but main usage of putAnyValues() is anyways uno api and thus will
+ // be appied to new instances - so potentially no cloning needed
+ make_unique();
+
+ // forward call to ItemData incarnation
+ m_pItemData->putAnyValue(rVal, nMemberId);
+ }
+
ItemBuffered::ItemBuffered(ItemControlBlock& rItemControlBlock)
: ItemBase(rItemControlBlock),
m_pItemData(nullptr)
@@ -126,22 +159,29 @@ namespace Item
m_pItemData(rRef.m_pItemData)
{
assert(nullptr != m_pItemData && "ItemBuffered::ItemBuffered copy-conatructor called but m_pItemData not set in source (!)");
+ // copy m_pItemData, increase refCnt
m_pItemData->m_nRef++;
}
ItemBuffered::~ItemBuffered()
{
assert(nullptr != m_pItemData && "ItemBuffered::~ItemBuffered called but m_pItemData not set (!)");
+ // decrease RefCnt
release();
}
ItemBuffered& ItemBuffered::operator=(const ItemBuffered& rRef)
{
- ItemBase::operator=(rRef);
assert(nullptr != m_pItemData && "ItemBuffered::operator= called but m_pItemData not set (!)");
+
+ // call baseclass (does nothing, just better style)
+ ItemBase::operator=(rRef);
+
+ // release (may delete if owner, copy from source, grab it)
release();
m_pItemData = rRef.m_pItemData;
acquire();
+
return *this;
}
@@ -154,12 +194,6 @@ namespace Item
m_pItemData == rTmpRef.m_pItemData || // ItemData ptr-compare
*m_pItemData == *rTmpRef.m_pItemData); // ItemData content compare
}
-
- std::unique_ptr<ItemBase> ItemBuffered::clone() const
- {
- // use copy constructor
- return std::unique_ptr<ItemBuffered>(new ItemBuffered(*this));
- }
} // end of namespace Item
///////////////////////////////////////////////////////////////////////////////
diff --git a/item/source/base/ItemControlBlock.cxx b/item/source/base/ItemControlBlock.cxx
index 38822aee0ea4..d4df2a72cc9c 100755
--- a/item/source/base/ItemControlBlock.cxx
+++ b/item/source/base/ItemControlBlock.cxx
@@ -17,17 +17,21 @@ namespace Item
{
ItemControlBlock::ItemControlBlock(
std::function<ItemBase*()>aConstructDefaultItem,
+ std::function<ItemBase*(const ItemBase&)>aCloneItem,
const OUString& rName)
: m_aDefaultItem(),
m_aConstructDefaultItem(aConstructDefaultItem),
+ m_aCloneItem(aCloneItem),
m_aName(rName)
{
assert(nullptr != m_aConstructDefaultItem && "nullptr not allowed, a Item-Constructor *is* required (!)");
+ assert(nullptr != aCloneItem && "nullptr not allowed, a Item-Cclone lambda *is* required (!)");
}
ItemControlBlock::ItemControlBlock()
: m_aDefaultItem(),
m_aConstructDefaultItem(),
+ m_aCloneItem(),
m_aName()
{
}
@@ -50,6 +54,11 @@ namespace Item
rItem.operator==(getDefault()); // content-compare
}
+ std::unique_ptr<ItemBase> ItemControlBlock::clone(const ItemBase& rRef) const
+ {
+ return std::unique_ptr<ItemBase>(m_aCloneItem(rRef));
+ }
+
std::unique_ptr<const ItemBase> ItemControlBlock::createFromAny(const ItemBase::AnyIDArgs& rArgs)
{
ItemBase* pNewInstance(m_aConstructDefaultItem());
diff --git a/item/source/simple/CntInt16.cxx b/item/source/simple/CntInt16.cxx
index d4069411f96b..e7549c50419a 100644
--- a/item/source/simple/CntInt16.cxx
+++ b/item/source/simple/CntInt16.cxx
@@ -19,6 +19,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new CntInt16(); },
+ [](const ItemBase& rRef){ return new CntInt16(static_cast<const CntInt16&>(rRef)); },
"CntInt16");
return aItemControlBlock;
@@ -41,12 +42,6 @@ namespace Item
return ItemBase::operator==(rRef) || // ptr-compare
getValue() == static_cast<const CntInt16&>(rRef).getValue();
}
-
- std::unique_ptr<ItemBase> CntInt16::clone() const
- {
- // use direct value(s) and std::make_unique
- return std::make_unique<CntInt16>(getValue());
- }
} // end of namespace Item
///////////////////////////////////////////////////////////////////////////////
diff --git a/item/source/simple/CntOUString.cxx b/item/source/simple/CntOUString.cxx
index e593e5282878..5975fee68c43 100644
--- a/item/source/simple/CntOUString.cxx
+++ b/item/source/simple/CntOUString.cxx
@@ -19,6 +19,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new CntOUString(); },
+ [](const ItemBase& rRef){ return new CntOUString(static_cast<const CntOUString&>(rRef)); },
"CntOUString");
return aItemControlBlock;
@@ -35,12 +36,6 @@ namespace Item
return ItemBase::operator==(rRef) || // ptr-compare
getValue() == static_cast<const CntOUString&>(rRef).getValue();
}
-
- std::unique_ptr<ItemBase> CntOUString::clone() const
- {
- // use direct value(s) and std::make_unique
- return std::make_unique<CntOUString>(getValue());
- }
} // end of namespace Item
///////////////////////////////////////////////////////////////////////////////
diff --git a/item/test/ItemTest.cxx b/item/test/ItemTest.cxx
index 3d990a16c14b..35483a160306 100644
--- a/item/test/ItemTest.cxx
+++ b/item/test/ItemTest.cxx
@@ -30,6 +30,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueSimple(); },
+ [](const ItemBase& rRef){ return new MultiValueSimple(static_cast<const MultiValueSimple&>(rRef)); },
"MultiValueSimple");
return aItemControlBlock;
@@ -62,12 +63,6 @@ namespace Item
getValueB() == static_cast<const MultiValueSimple&>(rRef).getValueB());
}
- virtual std::unique_ptr<ItemBase> clone() const
- {
- // use direct value(s) and std::make_unique
- return std::make_unique<MultiValueSimple>(getValueA(), getValueB());
- }
-
sal_Int16 getValueA() const
{
return m_nValueA;
@@ -93,6 +88,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueSimple_derivedClass(); },
+ [](const ItemBase& rRef){ return new MultiValueSimple_derivedClass(static_cast<const MultiValueSimple_derivedClass&>(rRef)); },
"MultiValueSimple_derivedClass");
return aItemControlBlock;
@@ -103,12 +99,6 @@ namespace Item
: MultiValueSimple(MultiValueSimple_derivedClass::GetStaticItemControlBlock(), nValA, nValB)
{
}
-
- virtual std::unique_ptr<ItemBase> clone() const
- {
- // use direct value(s) and std::make_unique
- return std::make_unique<MultiValueSimple_derivedClass>(getValueA(), getValueB());
- }
};
} // end of namespace Item
@@ -124,6 +114,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueSimple_plus(); },
+ [](const ItemBase& rRef){ return new MultiValueSimple_plus(static_cast<const MultiValueSimple_plus&>(rRef)); },
"MultiValueSimple_plus");
return aItemControlBlock;
@@ -152,12 +143,6 @@ namespace Item
getValueC() == static_cast<const MultiValueSimple_plus&>(rRef).getValueC();
}
- virtual std::unique_ptr<ItemBase> clone() const
- {
- // use direct value(s) and std::make_unique
- return std::make_unique<MultiValueSimple_plus>(getValueA(), getValueB(), getValueC());
- }
-
sal_Int64 getValueC() const
{
return m_nValueC;
@@ -178,6 +163,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueSimple_plus_derivedClass(); },
+ [](const ItemBase& rRef){ return new MultiValueSimple_plus_derivedClass(static_cast<const MultiValueSimple_plus_derivedClass&>(rRef)); },
"MultiValueSimple_plus_derivedClass");
return aItemControlBlock;
@@ -188,12 +174,6 @@ namespace Item
: MultiValueSimple_plus(MultiValueSimple_plus_derivedClass::GetStaticItemControlBlock(), nValA, nValB, nValC)
{
}
-
- virtual std::unique_ptr<ItemBase> clone() const
- {
- // use direct value(s) and std::make_unique
- return std::make_unique<MultiValueSimple_plus_derivedClass>(getValueA(), getValueB(), getValueC());
- }
};
} // end of namespace Item
@@ -209,6 +189,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueBuffered(); },
+ [](const ItemBase& rRef){ return new MultiValueBuffered(static_cast<const MultiValueBuffered&>(rRef)); },
"MultiValueBuffered");
return aItemControlBlock;
@@ -227,6 +208,12 @@ namespace Item
static ItemAdministrator_set aItemAdministrator_set(
// hand over localized lambda call to construct a new instance of Item
[](){ return new MultiValueData(0, 0); },
+ // hand over localized lambda call to clone an Item
+ [](const ItemData& rRef)
+ {
+ const MultiValueData& rData(static_cast<const MultiValueData&>(rRef));
+ return new MultiValueData(rData.getValueA(), rData.getValueB());
+ },
// hand over localized lambda operator< to have a sorted set
[](ItemData* A, ItemData* B)
{
@@ -264,6 +251,16 @@ namespace Item
{
return m_nValueB;
}
+
+ void setValueA(sal_Int16 nNew)
+ {
+ m_nValueA = nNew;
+ }
+
+ void setValueB(sal_Int32 nNew)
+ {
+ m_nValueB = nNew;
+ }
};
protected:
@@ -290,11 +287,43 @@ namespace Item
setItemData(new MultiValueData(nValueA, nValueB));
}
- sal_Int16 getValueA() const { return static_cast<MultiValueData const&>(getItemData()).getValueA(); }
- sal_Int32 getValueB() const { return static_cast<MultiValueData const&>(getItemData()).getValueB(); }
+ sal_Int16 getValueA() const
+ {
+ return static_cast<MultiValueData&>(getItemData()).getValueA();
+ }
+
+ sal_Int32 getValueB() const
+ {
+ return static_cast<MultiValueData&>(getItemData()).getValueB();
+ }
+
+ void setValueA(sal_Int16 nNewA)
+ {
+ setItemData(new MultiValueData(nNewA, getValueB()));
+ }
+
+ void setValueB(sal_Int32 nNewB)
+ {
+ setItemData(new MultiValueData(getValueA(), nNewB));
+ }
- void setValueA(sal_Int16 nNewA) { setItemData(new MultiValueData(nNewA, getValueB())); }
- void setValueB(sal_Int32 nNewB) { setItemData(new MultiValueData(getValueA(), nNewB)); }
+ void setValueAA(sal_Int16 nNew) const
+ {
+ if(nNew != getValueA())
+ {
+ const_cast<MultiValueBuffered*>(this)->make_unique();
+ static_cast<MultiValueData&>(getItemData()).setValueA(nNew);
+ }
+ }
+
+ void setValueBB(sal_Int32 nNew) const
+ {
+ if(nNew != getValueB())
+ {
+ const_cast<MultiValueBuffered*>(this)->make_unique();
+ static_cast<MultiValueData&>(getItemData()).setValueB(nNew);
+ }
+ }
};
} // end of namespace Item
@@ -311,6 +340,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueBuffered_derivedClass(); },
+ [](const ItemBase& rRef){ return new MultiValueBuffered_derivedClass(static_cast<const MultiValueBuffered_derivedClass&>(rRef)); },
"MultiValueBuffered_derivedClass");
return aItemControlBlock;
@@ -336,6 +366,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueBuffered_plus(); },
+ [](const ItemBase& rRef){ return new MultiValueBuffered_plus(static_cast<const MultiValueBuffered_plus&>(rRef)); },
"MultiValueBuffered_plus");
return aItemControlBlock;
@@ -353,6 +384,12 @@ namespace Item
static ItemAdministrator_set aItemAdministrator_set(
// hand over localized lambda call to construct a new instance of Item
[](){ return new MultiValueData_plus(0, 0, 0); },
+ // hand over localized lambda call to clone an Item
+ [](const ItemData& rRef)
+ {
+ const MultiValueData_plus& rData(static_cast<const MultiValueData_plus&>(rRef));
+ return new MultiValueData_plus(rData.getValueA(), rData.getValueB(), rData.getValueC());
+ },
// hand over localized lambda operator< to have a sorted set
[](ItemData* A, ItemData* B)
{
@@ -393,6 +430,11 @@ namespace Item
{
return m_nValueC;
}
+
+ void setValueC(sal_Int64 nNew)
+ {
+ m_nValueC = nNew;
+ }
};
protected:
@@ -411,9 +453,18 @@ namespace Item
setItemData(new MultiValueData_plus(nValueA, nValueB, nValueC));
}
- sal_Int64 getValueC() const { return static_cast<MultiValueData_plus const&>(getItemData()).getValueC(); }
+ sal_Int64 getValueC() const { return static_cast<MultiValueData_plus&>(getItemData()).getValueC(); }
void setValueC(sal_Int64 nNewC) { setItemData(new MultiValueData_plus(getValueA(), getValueB(), nNewC)); }
+
+ void setValueCC(sal_Int64 nNew) const
+ {
+ if(nNew != getValueC())
+ {
+ const_cast<MultiValueBuffered_plus*>(this)->make_unique();
+ static_cast<MultiValueData_plus&>(getItemData()).setValueC(nNew);
+ }
+ }
};
} // end of namespace Item
@@ -430,6 +481,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueBuffered_plus_derivedClass(); },
+ [](const ItemBase& rRef){ return new MultiValueBuffered_plus_derivedClass(static_cast<const MultiValueBuffered_plus_derivedClass&>(rRef)); },
"MultiValueBuffered_plus_derivedClass");
return aItemControlBlock;
diff --git a/svx/source/items/TransformAnchor.cxx b/svx/source/items/TransformAnchor.cxx
index 71d575fde32a..dc6ed0f05a11 100755
--- a/svx/source/items/TransformAnchor.cxx
+++ b/svx/source/items/TransformAnchor.cxx
@@ -20,6 +20,7 @@ namespace Item
{
static ItemControlBlock aItemControlBlock(
[](){ return new TransformAnchor(); },
+ [](const ItemBase& rRef){ return new TransformAnchor(static_cast<const TransformAnchor&>(rRef)); },
"TransformAnchor");
return aItemControlBlock;
@@ -31,12 +32,6 @@ namespace Item
static_cast<sal_Int16>(nValue))
{
}
-
- std::unique_ptr<ItemBase> TransformAnchor::clone() const
- {
- // use direct value(s) and std::make_unique
- return std::make_unique<TransformAnchor>(GetAnchorType());
- }
} // end of namespace Item
///////////////////////////////////////////////////////////////////////////////