Kaydet (Commit) 6c2f575f authored tarafından Armin Le Grand's avatar Armin Le Grand

WIP: Use ItemControlBlock as TypeInfo

Removed last big change to have a global static
ItemControlBlock registry. Thought about things
and what is needed/wanted is RTTI for the Items.
Instead of using typeid(T).hash_code() it is
equally possible to use the ItemControlBlock of
each Item - it exists once as global static
instance. So use it's address. That way e.g. the
ItemSet holding it *will* hjave a direct reference
to the ItemControlBlock, so no need for a global
registration.
Checked, tested, adapted, works.

Change-Id: I4c9b6bfe4ba6858b234238d6125793378574af87
üst 203d0f02
......@@ -32,7 +32,6 @@ namespace Item
static ::Item::ItemControlBlock aItemControlBlock(
[](){ return new Sbx(ScriptDocument::getApplicationScriptDocument()); },
[](const ItemBase& rRef){ return new Sbx(static_cast<const Sbx&>(rRef)); },
typeid(Sbx).hash_code(),
"Sbx");
return aItemControlBlock;
......
......@@ -101,7 +101,12 @@ namespace Item
// this way accessible for all incarnations - at the cost of
// one local reference
friend bool isDefault(const ItemBase& rCandidate);
friend class ItemSet;
ItemControlBlock& m_rItemControlBlock;
const ItemControlBlock& getItemControlBlock() const
{
return m_rItemControlBlock;
}
protected:
// PutValue/Any interface for automated instance creation from SfxType
......
......@@ -38,19 +38,14 @@ namespace Item
std::unique_ptr<const ItemBase> m_aDefaultItem;
std::function<ItemBase*()> m_aConstructDefaultItem;
std::function<ItemBase*(const ItemBase&)> m_aCloneItem;
size_t m_aHashCode;
OUString m_aName;
// EmptyItemControlBlock: default constructor *only* for internal use
ItemControlBlock();
public:
ItemControlBlock(
std::function<ItemBase*()>aConstructDefaultItem,
std::function<ItemBase*(const ItemBase&)>aCloneItem,
size_t aHashCode,
const OUString& rName);
~ItemControlBlock();
~ItemControlBlock() = default;
const ItemBase& getDefault() const;
bool isDefault(const ItemBase& rItem) const;
......@@ -60,23 +55,11 @@ namespace Item
return m_aName;
}
size_t getHashCode() const
{
return m_aHashCode;
}
// 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);
// static access to registered ItemControlBlocks
static ItemControlBlock* getItemControlBlock(size_t HashCode);
template< typename TItem > ItemControlBlock* getItemControlBlock()
{
return getItemControlBlock(typeid(TItem).HashCode());
}
};
} // end of namespace Item
......
......@@ -216,14 +216,14 @@ namespace Item
ModelSpecificItemValues::SharedPtr m_aModelSpecificIValues;
// the items as content
std::unordered_map<size_t, const ItemBase*> m_aItems;
std::unordered_map<const ItemControlBlock*, const ItemBase*> m_aItems;
// helpers for reduction of template member implementations,
// all based on typeid(<type>).hash_code()
const ItemBase* implGetStateAndItem(size_t hash_code, IState& rIState, bool bSearchParent) const;
void implInvalidateItem(size_t hash_code);
void implDisableItem(size_t hash_code);
bool implClearItem(size_t hash_code);
// all based on ItemControlBlock as unique identifier
const ItemBase* implGetStateAndItem(const ItemControlBlock& rICB, IState& rIState, bool bSearchParent) const;
void implInvalidateItem(const ItemControlBlock& rICB);
void implDisableItem(const ItemControlBlock& rICB);
bool implClearItem(const ItemControlBlock& rICB);
// ...or a given default
const ItemBase& implGetDefault(const ItemBase& rCurrent) const;
......@@ -262,49 +262,37 @@ namespace Item
// the compiler for each class.
// reduction uses local immp methods wherever possible, based
// on the fetched TypeID
template< typename TItem > void invalidateItem()
template< typename T > void invalidateItem()
{
implInvalidateItem(typeid(TItem).hash_code());
implInvalidateItem(T::GetStaticItemControlBlock());
}
template< typename TItem > void disableItem()
template< typename T > void disableItem()
{
implDisableItem(typeid(TItem).hash_code());
implDisableItem(T::GetStaticItemControlBlock());
}
template< typename TItem > const TItem& getDefault() const
template< typename T > const T& getDefault() const
{
return static_cast<const TItem&>(
return static_cast<const T&>(
implGetDefault(
Item::getDefault<TItem>()));
Item::getDefault<T>()));
}
template< typename TItem > StateAndItem<TItem> getStateAndItem(bool bSearchParent = true) const
template< typename T > StateAndItem<T> getStateAndItem(bool bSearchParent = true) const
{
IState aIState(IState::DEFAULT);
const ItemBase* pItem(implGetStateAndItem(typeid(TItem).hash_code(), aIState, bSearchParent));
// SfxItemState::DEFAULT
// SfxItemState::DONTCARE || SfxItemState::DISABLED -> should already be
// solved from ImplInvalidateItem/ImplDisableItem, but to have the
// fallback here additionally is never wrong
// in short: no specific ItemBase -> use default
if(nullptr == pItem)
{
return StateAndItem<TItem>(
aIState,
Item::getDefault<TItem>());
}
const ItemBase* pItem(implGetStateAndItem(T::GetStaticItemControlBlock(), aIState, bSearchParent));
// SfxItemState::SET
return StateAndItem<TItem>(
return StateAndItem<T>(
aIState,
*static_cast<const TItem*>(pItem));
*static_cast<const T*>(pItem));
}
template< typename TItem > bool clearItem()
template< typename T > bool clearItem()
{
return implClearItem(typeid(TItem).hash_code());
return implClearItem(T::GetStaticItemControlBlock());
}
};
} // end of namespace Item
......
......@@ -15,57 +15,17 @@
namespace Item
{
std::unordered_map<size_t, ItemControlBlock*>& getRegisteredItemControlBlocks()
{
// all globally registered ItemControlBlocks
static std::unordered_map<size_t, ItemControlBlock*> aItemControlBlocks;
return aItemControlBlocks;
}
ItemControlBlock::ItemControlBlock()
: m_aDefaultItem(),
m_aConstructDefaultItem(),
m_aCloneItem(),
m_aHashCode(0),
m_aName()
{
// EmptyItemControlBlock: *only* for internal use, fallback for
// extra-Items like ImplInvalidateItem/ImplDisableItem
// Do *not* register this instance at aItemControlBlocks (!)
}
ItemControlBlock::ItemControlBlock(
std::function<ItemBase*()>aConstructDefaultItem,
std::function<ItemBase*(const ItemBase&)>aCloneItem,
size_t aHashCode,
const OUString& rName)
: m_aDefaultItem(),
m_aConstructDefaultItem(aConstructDefaultItem),
m_aCloneItem(aCloneItem),
m_aHashCode(aHashCode),
m_aName(rName)
{
assert(nullptr != m_aConstructDefaultItem && "nullptr not allowed, a Item-Constructor *is* required (!)");
assert(nullptr != aCloneItem && "nullptr not allowed, a Item-Clone lambda *is* required (!)");
assert(size_t(0) != m_aHashCode && "NULL hash_code not allowed, a Item-identifier (usually typeid(T).hash_code()) *is* required (!)");
assert(getRegisteredItemControlBlocks().find(m_aHashCode) == getRegisteredItemControlBlocks().end()
&& "Constructed ItemControlBlock already globally registered - this hints to an error (!)");
// globally register new ItemControlBlock
getRegisteredItemControlBlocks()[m_aHashCode] = this;
}
ItemControlBlock::~ItemControlBlock()
{
assert((0 == m_aHashCode || // is the EmptyItemControlBlock
getRegisteredItemControlBlocks().find(m_aHashCode) != getRegisteredItemControlBlocks().end()) // or has to exist
&& "Destructed ItemControlBlock was not globally registered - this hints to an error (!)");
// since ItemControlBlocks themselves are static this can only happen when
// handling libs, e.g. lib shutdown and of course app shutdown. Nonetheless
// do this to avoid errors
if(0 != m_aHashCode) // do not forget default constructor -> EmptyItemControlBlock
{
getRegisteredItemControlBlocks().erase(getRegisteredItemControlBlocks().find(m_aHashCode));
}
}
const ItemBase& ItemControlBlock::getDefault() const
......@@ -97,23 +57,6 @@ namespace Item
pNewInstance->putAnyValues(rArgs);
return std::unique_ptr<const ItemBase>(pNewInstance);
}
ItemControlBlock* ItemControlBlock::getItemControlBlock(size_t hash_code)
{
if(size_t(0) != hash_code)
{
std::unordered_map<size_t, ItemControlBlock*>& rBlocks(getRegisteredItemControlBlocks());
const auto aCandidate(rBlocks.find(hash_code));
if(aCandidate != rBlocks.end())
{
return aCandidate->second;
}
}
static ItemControlBlock aEmptyItemControlBlock;
return &aEmptyItemControlBlock;
}
} // end of namespace Item
///////////////////////////////////////////////////////////////////////////////
......
......@@ -21,11 +21,24 @@ namespace Item
// helper class for an ImplInvalidateItem - placeholder for InvaidateState
// SfxItemState::DONTCARE -> IsInvalidItem -> pItem == INVALID_POOL_ITEM -> reinterpret_cast<SfxPoolItem*>(-1)
// the instance of this class is *never* returned in any way or helper data struture,
// but is *strictly* local. Thus also needs no 'static ItemControlBlock& GetStaticItemControlBlock()'
// but is *strictly* local
class ImplInvalidateItem : public ItemBase
{
public:
ImplInvalidateItem() : ItemBase(*ItemControlBlock::getItemControlBlock(0)) {}
static ItemControlBlock& GetStaticItemControlBlock()
{
static ItemControlBlock aItemControlBlock(
[](){ return new ImplInvalidateItem(); },
[](const ItemBase& rRef){ return new ImplInvalidateItem(static_cast<const ImplInvalidateItem&>(rRef)); },
"ImplInvalidateItem");
return aItemControlBlock;
}
ImplInvalidateItem()
: ItemBase(ImplInvalidateItem::GetStaticItemControlBlock())
{
}
};
static const ImplInvalidateItem aImplInvalidateItem;
......@@ -38,97 +51,124 @@ namespace Item
// helper class for a ImplDisableItem - placeholder for InvaidateState
// SfxItemState::DISABLED -> IsVoidItem() -> instance of SfxVoidItem, virtual bool IsVoidItem()
// the instance of this class is *never* returned in any way or helper data struture,
// but is *strictly* local. Thus also needs no 'static ItemControlBlock& GetStaticItemControlBlock()'
// but is *strictly* local
class ImplDisableItem : public ItemBase
{
public:
ImplDisableItem() : ItemBase(*ItemControlBlock::getItemControlBlock(0)) {}
static ItemControlBlock& GetStaticItemControlBlock()
{
static ItemControlBlock aItemControlBlock(
[](){ return new ImplDisableItem(); },
[](const ItemBase& rRef){ return new ImplDisableItem(static_cast<const ImplDisableItem&>(rRef)); },
"ImplDisableItem");
return aItemControlBlock;
}
ImplDisableItem()
: ItemBase(ImplDisableItem::GetStaticItemControlBlock())
{
}
};
static const ImplDisableItem aImplDisableItem;
return aImplDisableItem;
}
const ItemBase* ItemSet::implGetStateAndItem(size_t hash_code, IState& rIState, bool bSearchParent) const
const ItemBase* ItemSet::implGetStateAndItem(const ItemControlBlock& rICB, IState& rIState, bool bSearchParent) const
{
const auto aRetval(m_aItems.find(hash_code));
const auto aEntry(m_aItems.find(&rICB));
if(aRetval != m_aItems.end()) // && aRetval->second)
if(aEntry != m_aItems.end()) // && aEntry->second)
{
assert(nullptr != aRetval->second && "empty const ItemBase* in ItemSet (!)");
assert(nullptr != aEntry->second && "empty const ItemBase* in ItemSet (!)");
if(aRetval->second == &getInvalidateItem())
if(aEntry->second == &getInvalidateItem())
{
// SfxItemState::DONTCARE
rIState = IState::DONTCARE;
ItemControlBlock* pBlock(ItemControlBlock::getItemControlBlock(hash_code));
assert(nullptr != pBlock && "Could not find globally registered ItemControlBlock for given ItemType (!)");
return &implGetDefault(pBlock->getDefault());
return &implGetDefault(aEntry->first->getDefault());
}
if(aRetval->second == &getDisableItem())
if(aEntry->second == &getDisableItem())
{
// SfxItemState::DISABLED
rIState = IState::DISABLED;
ItemControlBlock* pBlock(ItemControlBlock::getItemControlBlock(hash_code));
assert(nullptr != pBlock && "Could not find globally registered ItemControlBlock for given ItemType (!)");
return &implGetDefault(pBlock->getDefault());
return &implGetDefault(aEntry->first->getDefault());
}
// SfxItemState::SET
rIState = IState::SET;
return aRetval->second;
return aEntry->second;
}
// not set
// not set locally
const ItemBase* pRetval(nullptr);
if(bSearchParent && m_aParent)
{
// continue searching in parent
return m_aParent->implGetStateAndItem(hash_code, rIState, bSearchParent);
pRetval = m_aParent->implGetStateAndItem(rICB, rIState, bSearchParent);
}
// SfxItemState::DEFAULT
// already handed in as default - no need to set explicitely // rIState = IState::DEFAULT;
return nullptr;
if(nullptr == pRetval)
{
// SfxItemState::DEFAULT
pRetval = &implGetDefault(rICB.getDefault());
}
return pRetval;
}
void ItemSet::implInvalidateItem(size_t hash_code)
void ItemSet::implInvalidateItem(const ItemControlBlock& rICB)
{
const auto aRetval(m_aItems.find(hash_code));
const auto aRetval(m_aItems.find(&rICB));
if(aRetval == m_aItems.end())
{
m_aItems[hash_code] = &getInvalidateItem();
m_aItems[&rICB] = &getInvalidateItem();
}
else
{
delete aRetval->second;
if(&getInvalidateItem() != aRetval->second && &getDisableItem() != aRetval->second)
{
delete aRetval->second;
}
aRetval->second = &getInvalidateItem();
}
}
void ItemSet::implDisableItem(size_t hash_code)
void ItemSet::implDisableItem(const ItemControlBlock& rICB)
{
const auto aRetval(m_aItems.find(hash_code));
const auto aRetval(m_aItems.find(&rICB));
if(aRetval == m_aItems.end())
{
m_aItems[hash_code] = &getDisableItem();
m_aItems[&rICB] = &getDisableItem();
}
else
{
delete aRetval->second;
if(&getInvalidateItem() != aRetval->second && &getDisableItem() != aRetval->second)
{
delete aRetval->second;
}
aRetval->second = &getDisableItem();
}
}
bool ItemSet::implClearItem(size_t hash_code)
bool ItemSet::implClearItem(const ItemControlBlock& rICB)
{
const auto aRetval(m_aItems.find(hash_code));
const auto aRetval(m_aItems.find(&rICB));
if(aRetval != m_aItems.end())
{
delete aRetval->second;
if(&getInvalidateItem() != aRetval->second && &getDisableItem() != aRetval->second)
{
delete aRetval->second;
}
m_aItems.erase(aRetval);
return true;
}
......@@ -198,17 +238,31 @@ namespace Item
bDefault = rItem.isDefault();
}
const size_t hash_code(typeid(rItem).hash_code());
const ItemControlBlock& rICB(rItem.getItemControlBlock());
if(bDefault)
{
// SfxItemState::DEFAULT is represented by not being set
m_aItems.erase(hash_code);
m_aItems.erase(&rICB);
}
else
{
// SfxItemState::SET
m_aItems[hash_code] = rItem.clone().release();
const auto aEntry(m_aItems.find(&rICB));
if(aEntry == m_aItems.end())
{
m_aItems[&rICB] = rItem.clone().release();
}
else
{
if(&getInvalidateItem() != aEntry->second && &getDisableItem() != aEntry->second)
{
delete aEntry->second;
}
aEntry->second = rItem.clone().release();
}
}
}
......@@ -245,7 +299,7 @@ namespace Item
if(nullptr == pNew)
{
m_aItems.erase(candidate.first);
implClearItem(*candidate.first);
}
else
{
......@@ -257,7 +311,11 @@ namespace Item
}
else
{
delete aRetval->second;
if(&getInvalidateItem() != aRetval->second && &getDisableItem() != aRetval->second)
{
delete aRetval->second;
}
aRetval->second = pNew;
}
}
......@@ -276,18 +334,14 @@ namespace Item
{
if(candidate.second == &getInvalidateItem())
{
ItemControlBlock* pBlock(ItemControlBlock::getItemControlBlock(candidate.first));
assert(nullptr != pBlock && "Could not find globally registered ItemControlBlock for given ItemType (!)");
aRetval.push_back(std::pair<const ItemBase*, ItemSet::IState>(
&implGetDefault(pBlock->getDefault()),
&implGetDefault(candidate.first->getDefault()),
IState::DONTCARE));
}
else if(candidate.second == &getDisableItem())
{
ItemControlBlock* pBlock(ItemControlBlock::getItemControlBlock(candidate.first));
assert(nullptr != pBlock && "Could not find globally registered ItemControlBlock for given ItemType (!)");
aRetval.push_back(std::pair<const ItemBase*, ItemSet::IState>(
&implGetDefault(pBlock->getDefault()),
&implGetDefault(candidate.first->getDefault()),
IState::DISABLED));
}
else
......@@ -316,15 +370,11 @@ namespace Item
{
if(IState::DONTCARE == eIState && candidate.second == &getInvalidateItem())
{
ItemControlBlock* pBlock(ItemControlBlock::getItemControlBlock(candidate.first));
assert(nullptr != pBlock && "Could not find globally registered ItemControlBlock for given ItemType (!)");
aRetval.push_back(&implGetDefault(pBlock->getDefault()));
aRetval.push_back(&implGetDefault(candidate.first->getDefault()));
}
else if(IState::DISABLED == eIState && candidate.second == &getDisableItem())
{
ItemControlBlock* pBlock(ItemControlBlock::getItemControlBlock(candidate.first));
assert(nullptr != pBlock && "Could not find globally registered ItemControlBlock for given ItemType (!)");
aRetval.push_back(&implGetDefault(pBlock->getDefault()));
aRetval.push_back(&implGetDefault(candidate.first->getDefault()));
}
else if(IState::SET == eIState)
{
......
......@@ -31,7 +31,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueSimple(); },
[](const ItemBase& rRef){ return new MultiValueSimple(static_cast<const MultiValueSimple&>(rRef)); },
typeid(MultiValueSimple).hash_code(),
"MultiValueSimple");
return aItemControlBlock;
......@@ -90,7 +89,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueSimple_derivedClass(); },
[](const ItemBase& rRef){ return new MultiValueSimple_derivedClass(static_cast<const MultiValueSimple_derivedClass&>(rRef)); },
typeid(MultiValueSimple_derivedClass).hash_code(),
"MultiValueSimple_derivedClass");
return aItemControlBlock;
......@@ -117,7 +115,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueSimple_plus(); },
[](const ItemBase& rRef){ return new MultiValueSimple_plus(static_cast<const MultiValueSimple_plus&>(rRef)); },
typeid(MultiValueSimple_plus).hash_code(),
"MultiValueSimple_plus");
return aItemControlBlock;
......@@ -167,7 +164,6 @@ 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)); },
typeid(MultiValueSimple_plus_derivedClass).hash_code(),
"MultiValueSimple_plus_derivedClass");
return aItemControlBlock;
......@@ -194,7 +190,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueBuffered(); },
[](const ItemBase& rRef){ return new MultiValueBuffered(static_cast<const MultiValueBuffered&>(rRef)); },
typeid(MultiValueBuffered).hash_code(),
"MultiValueBuffered");
return aItemControlBlock;
......@@ -346,7 +341,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueBuffered_derivedClass(); },
[](const ItemBase& rRef){ return new MultiValueBuffered_derivedClass(static_cast<const MultiValueBuffered_derivedClass&>(rRef)); },
typeid(MultiValueBuffered_derivedClass).hash_code(),
"MultiValueBuffered_derivedClass");
return aItemControlBlock;
......@@ -373,7 +367,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new MultiValueBuffered_plus(); },
[](const ItemBase& rRef){ return new MultiValueBuffered_plus(static_cast<const MultiValueBuffered_plus&>(rRef)); },
typeid(MultiValueBuffered_plus).hash_code(),
"MultiValueBuffered_plus");
return aItemControlBlock;
......@@ -489,7 +482,6 @@ 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)); },
typeid(MultiValueBuffered_plus_derivedClass).hash_code(),
"MultiValueBuffered_plus_derivedClass");
return aItemControlBlock;
......@@ -516,7 +508,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new CntInt16_derived(); },
[](const ItemBase& rRef){ return new CntInt16_derived(static_cast<const CntInt16_derived&>(rRef)); },
typeid(CntInt16_derived).hash_code(),
"CntInt16_derived");
return aItemControlBlock;
......@@ -543,7 +534,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new CntOUString_derived(); },
[](const ItemBase& rRef){ return new CntOUString_derived(static_cast<const CntOUString_derived&>(rRef)); },
typeid(CntOUString_derived).hash_code(),
"CntOUString_derived");
return aItemControlBlock;
......
......@@ -21,7 +21,6 @@ namespace Item
static ItemControlBlock aItemControlBlock(
[](){ return new TransformAnchor(); },
[](const ItemBase& rRef){ return new TransformAnchor(static_cast<const TransformAnchor&>(rRef)); },
typeid(TransformAnchor).hash_code(),
"TransformAnchor");
return aItemControlBlock;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment