Poor man's RTTI is mostly gone.
Some checks failed
CI / ubuntu-latest-html-tests (push) Has been cancelled
CI / ubuntu-latest-no-tls (push) Has been cancelled
CI / ubuntu-latest-mbedtls2 (push) Has been cancelled
CI / ubuntu-latest-openssl-3 (push) Has been cancelled
CI / ubuntu-latest-with-old-std (push) Has been cancelled
CI / ubuntu-20-04-openssl-1-1 (push) Has been cancelled
CI / alpine-mbedtls-3_6_0 (push) Has been cancelled
CI / macOS-13-openssl-1-1 (push) Has been cancelled
CI / macOS-13-openssl-3 (push) Has been cancelled
CI / freebsd-14-openssl-3 (push) Has been cancelled
CI / windows-mbedtls (push) Has been cancelled
Some checks failed
CI / ubuntu-latest-html-tests (push) Has been cancelled
CI / ubuntu-latest-no-tls (push) Has been cancelled
CI / ubuntu-latest-mbedtls2 (push) Has been cancelled
CI / ubuntu-latest-openssl-3 (push) Has been cancelled
CI / ubuntu-latest-with-old-std (push) Has been cancelled
CI / ubuntu-20-04-openssl-1-1 (push) Has been cancelled
CI / alpine-mbedtls-3_6_0 (push) Has been cancelled
CI / macOS-13-openssl-1-1 (push) Has been cancelled
CI / macOS-13-openssl-3 (push) Has been cancelled
CI / freebsd-14-openssl-3 (push) Has been cancelled
CI / windows-mbedtls (push) Has been cancelled
I'm keeping the type-index to name mapping, for now.
This commit is contained in:
@ -27,13 +27,11 @@ using namespace lout;
|
|||||||
|
|
||||||
namespace dw {
|
namespace dw {
|
||||||
|
|
||||||
std::intptr_t AlignedTableCell::CLASS_ID = -1;
|
|
||||||
|
|
||||||
AlignedTableCell::AlignedTableCell (AlignedTableCell *ref, bool limitTextWidth):
|
AlignedTableCell::AlignedTableCell (AlignedTableCell *ref, bool limitTextWidth):
|
||||||
AlignedTextblock (limitTextWidth)
|
AlignedTextblock (limitTextWidth)
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::AlignedTableCell");
|
DBG_OBJ_CREATE ("dw::AlignedTableCell");
|
||||||
registerName ("dw::AlignedTableCell", typeid(*this), &CLASS_ID);
|
registerName ("dw::AlignedTableCell", typeid(*this));
|
||||||
|
|
||||||
/** \bug ignoreLine1OffsetSometimes does not work? */
|
/** \bug ignoreLine1OffsetSometimes does not work? */
|
||||||
//ignoreLine1OffsetSometimes = true;
|
//ignoreLine1OffsetSometimes = true;
|
||||||
|
@ -33,8 +33,6 @@ protected:
|
|||||||
void setMaxValue (int maxValue, int value);
|
void setMaxValue (int maxValue, int value);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
AlignedTableCell(AlignedTableCell *ref, bool limitTextWidth);
|
AlignedTableCell(AlignedTableCell *ref, bool limitTextWidth);
|
||||||
~AlignedTableCell();
|
~AlignedTableCell();
|
||||||
|
|
||||||
|
@ -58,13 +58,11 @@ void AlignedTextblock::List::unref(int pos)
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::intptr_t AlignedTextblock::CLASS_ID = -1;
|
|
||||||
|
|
||||||
AlignedTextblock::AlignedTextblock (bool limitTextWidth):
|
AlignedTextblock::AlignedTextblock (bool limitTextWidth):
|
||||||
Textblock (limitTextWidth)
|
Textblock (limitTextWidth)
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::AlignedTextblock");
|
DBG_OBJ_CREATE ("dw::AlignedTextblock");
|
||||||
registerName ("dw::AlignedTextblock", typeid(*this), &CLASS_ID);
|
registerName ("dw::AlignedTextblock", typeid(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlignedTextblock::setRefTextblock (AlignedTextblock *ref)
|
void AlignedTextblock::setRefTextblock (AlignedTextblock *ref)
|
||||||
|
@ -51,8 +51,6 @@ protected:
|
|||||||
void updateValue ();
|
void updateValue ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
~AlignedTextblock();
|
~AlignedTextblock();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,12 +131,10 @@ int ImageMapsList::link (object::Object *key, int x, int y)
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
std::intptr_t Image::CLASS_ID = -1;
|
|
||||||
|
|
||||||
Image::Image(const char *altText)
|
Image::Image(const char *altText)
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::Image");
|
DBG_OBJ_CREATE ("dw::Image");
|
||||||
registerName ("dw::Image", typeid(*this), &CLASS_ID);
|
registerName ("dw::Image", typeid(*this));
|
||||||
this->altText = altText ? dStrdup (altText) : NULL;
|
this->altText = altText ? dStrdup (altText) : NULL;
|
||||||
altTextWidth = -1; // not yet calculated
|
altTextWidth = -1; // not yet calculated
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
|
@ -145,8 +145,6 @@ protected:
|
|||||||
//core::Iterator *iterator (Content::Type mask, bool atEnd);
|
//core::Iterator *iterator (Content::Type mask, bool atEnd);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
Image(const char *altText);
|
Image(const char *altText);
|
||||||
~Image();
|
~Image();
|
||||||
|
|
||||||
|
@ -25,13 +25,11 @@
|
|||||||
|
|
||||||
namespace dw {
|
namespace dw {
|
||||||
|
|
||||||
std::intptr_t ListItem::CLASS_ID = -1;
|
|
||||||
|
|
||||||
ListItem::ListItem (ListItem *ref, bool limitTextWidth):
|
ListItem::ListItem (ListItem *ref, bool limitTextWidth):
|
||||||
AlignedTextblock (limitTextWidth)
|
AlignedTextblock (limitTextWidth)
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::ListItem");
|
DBG_OBJ_CREATE ("dw::ListItem");
|
||||||
registerName ("dw::ListItem", typeid(*this), &CLASS_ID);
|
registerName ("dw::ListItem", typeid(*this));
|
||||||
setRefTextblock (ref);
|
setRefTextblock (ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,6 @@ protected:
|
|||||||
void setMaxValue (int maxValue, int value);
|
void setMaxValue (int maxValue, int value);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
ListItem(ListItem *ref, bool limitTextWidth);
|
ListItem(ListItem *ref, bool limitTextWidth);
|
||||||
~ListItem();
|
~ListItem();
|
||||||
|
|
||||||
|
@ -38,12 +38,10 @@ const char *OOFAwareWidget::OOFM_NAME[NUM_OOFM] = {
|
|||||||
"FLOATS", "ABSOLUTE", "RELATIVE", "FIXED"
|
"FLOATS", "ABSOLUTE", "RELATIVE", "FIXED"
|
||||||
};
|
};
|
||||||
|
|
||||||
std::intptr_t OOFAwareWidget::CLASS_ID = -1;
|
|
||||||
|
|
||||||
OOFAwareWidget::OOFAwareWidget ()
|
OOFAwareWidget::OOFAwareWidget ()
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::oof::OOFAwareWidget");
|
DBG_OBJ_CREATE ("dw::oof::OOFAwareWidget");
|
||||||
registerName ("dw::oof::OOFAwareWidget", typeid(*this), &CLASS_ID);
|
registerName ("dw::oof::OOFAwareWidget", typeid(*this));
|
||||||
|
|
||||||
for (int i = 0; i < NUM_OOFM; i++) {
|
for (int i = 0; i < NUM_OOFM; i++) {
|
||||||
oofContainer[i] = NULL;
|
oofContainer[i] = NULL;
|
||||||
|
@ -195,8 +195,6 @@ public:
|
|||||||
SL_START, SL_BACKGROUND, SL_SC_BOTTOM, SL_IN_FLOW, SL_OOF_REF,
|
SL_START, SL_BACKGROUND, SL_SC_BOTTOM, SL_IN_FLOW, SL_OOF_REF,
|
||||||
SL_OOF_CONT, SL_SC_TOP, SL_END };
|
SL_OOF_CONT, SL_SC_TOP, SL_END };
|
||||||
|
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
OOFAwareWidget ();
|
OOFAwareWidget ();
|
||||||
~OOFAwareWidget ();
|
~OOFAwareWidget ();
|
||||||
|
|
||||||
|
@ -23,12 +23,10 @@
|
|||||||
|
|
||||||
namespace dw {
|
namespace dw {
|
||||||
|
|
||||||
std::intptr_t RegardingBorder::CLASS_ID = -1;
|
|
||||||
|
|
||||||
RegardingBorder::RegardingBorder ()
|
RegardingBorder::RegardingBorder ()
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::RegardingBorder");
|
DBG_OBJ_CREATE ("dw::RegardingBorder");
|
||||||
registerName ("dw::RegardingBorder", typeid(*this), &CLASS_ID);
|
registerName ("dw::RegardingBorder", typeid(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
RegardingBorder::~RegardingBorder ()
|
RegardingBorder::~RegardingBorder ()
|
||||||
|
@ -13,8 +13,6 @@ namespace dw {
|
|||||||
class RegardingBorder: public oof::OOFAwareWidget
|
class RegardingBorder: public oof::OOFAwareWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
RegardingBorder ();
|
RegardingBorder ();
|
||||||
~RegardingBorder ();
|
~RegardingBorder ();
|
||||||
};
|
};
|
||||||
|
@ -26,12 +26,10 @@
|
|||||||
|
|
||||||
namespace dw {
|
namespace dw {
|
||||||
|
|
||||||
std::intptr_t Ruler::CLASS_ID = -1;
|
|
||||||
|
|
||||||
Ruler::Ruler ()
|
Ruler::Ruler ()
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::Ruler");
|
DBG_OBJ_CREATE ("dw::Ruler");
|
||||||
registerName ("dw::Ruler", typeid(*this), &CLASS_ID);
|
registerName ("dw::Ruler", typeid(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ruler::~Ruler ()
|
Ruler::~Ruler ()
|
||||||
|
@ -30,8 +30,6 @@ protected:
|
|||||||
core::GettingWidgetAtPointContext *context);
|
core::GettingWidgetAtPointContext *context);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
Ruler ();
|
Ruler ();
|
||||||
~Ruler ();
|
~Ruler ();
|
||||||
|
|
||||||
|
@ -27,13 +27,11 @@ using namespace lout;
|
|||||||
|
|
||||||
namespace dw {
|
namespace dw {
|
||||||
|
|
||||||
std::intptr_t SimpleTableCell::CLASS_ID = -1;
|
|
||||||
|
|
||||||
SimpleTableCell::SimpleTableCell (bool limitTextWidth):
|
SimpleTableCell::SimpleTableCell (bool limitTextWidth):
|
||||||
Textblock (limitTextWidth)
|
Textblock (limitTextWidth)
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::SimpleTableCell");
|
DBG_OBJ_CREATE ("dw::SimpleTableCell");
|
||||||
registerName ("dw::SimpleTableCell", typeid(*this), &CLASS_ID);
|
registerName ("dw::SimpleTableCell", typeid(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleTableCell::~SimpleTableCell()
|
SimpleTableCell::~SimpleTableCell()
|
||||||
|
@ -24,8 +24,6 @@ protected:
|
|||||||
bool adjustExtraSpaceWhenCorrectingRequisitionByOOF ();
|
bool adjustExtraSpaceWhenCorrectingRequisitionByOOF ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
SimpleTableCell (bool limitTextWidth);
|
SimpleTableCell (bool limitTextWidth);
|
||||||
~SimpleTableCell ();
|
~SimpleTableCell ();
|
||||||
|
|
||||||
|
@ -29,12 +29,11 @@ using namespace lout;
|
|||||||
namespace dw {
|
namespace dw {
|
||||||
|
|
||||||
bool Table::adjustTableMinWidth = true;
|
bool Table::adjustTableMinWidth = true;
|
||||||
std::intptr_t Table::CLASS_ID = -1;
|
|
||||||
|
|
||||||
Table::Table(bool limitTextWidth)
|
Table::Table(bool limitTextWidth)
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::Table");
|
DBG_OBJ_CREATE ("dw::Table");
|
||||||
registerName ("dw::Table", typeid(*this), &CLASS_ID);
|
registerName ("dw::Table", typeid(*this));
|
||||||
setButtonSensitive(false);
|
setButtonSensitive(false);
|
||||||
|
|
||||||
this->limitTextWidth = limitTextWidth;
|
this->limitTextWidth = limitTextWidth;
|
||||||
|
@ -492,8 +492,6 @@ protected:
|
|||||||
void removeChild (Widget *child);
|
void removeChild (Widget *child);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
inline static void setAdjustTableMinWidth (bool adjustTableMinWidth)
|
inline static void setAdjustTableMinWidth (bool adjustTableMinWidth)
|
||||||
{ Table::adjustTableMinWidth = adjustTableMinWidth; }
|
{ Table::adjustTableMinWidth = adjustTableMinWidth; }
|
||||||
|
|
||||||
|
@ -43,8 +43,6 @@ using namespace lout::unicode;
|
|||||||
|
|
||||||
namespace dw {
|
namespace dw {
|
||||||
|
|
||||||
std::intptr_t Textblock::CLASS_ID = -1;
|
|
||||||
|
|
||||||
Textblock::WordImgRenderer::WordImgRenderer (Textblock *textblock,
|
Textblock::WordImgRenderer::WordImgRenderer (Textblock *textblock,
|
||||||
int wordNo)
|
int wordNo)
|
||||||
{
|
{
|
||||||
@ -206,7 +204,7 @@ void Textblock::setStretchabilityFactor (int stretchabilityFactor)
|
|||||||
Textblock::Textblock (bool limitTextWidth, bool treatAsInline)
|
Textblock::Textblock (bool limitTextWidth, bool treatAsInline)
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::Textblock");
|
DBG_OBJ_CREATE ("dw::Textblock");
|
||||||
registerName ("dw::Textblock", typeid(*this), &CLASS_ID);
|
registerName ("dw::Textblock", typeid(*this));
|
||||||
setButtonSensitive(true);
|
setButtonSensitive(true);
|
||||||
|
|
||||||
hasListitemValue = false;
|
hasListitemValue = false;
|
||||||
|
@ -864,8 +864,6 @@ protected:
|
|||||||
int getGeneratorRest (int oofmIndex);
|
int getGeneratorRest (int oofmIndex);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
static void setPenaltyHyphen (int penaltyHyphen);
|
static void setPenaltyHyphen (int penaltyHyphen);
|
||||||
static void setPenaltyHyphen2 (int penaltyHyphen2);
|
static void setPenaltyHyphen2 (int penaltyHyphen2);
|
||||||
static void setPenaltyEmDashLeft (int penaltyLeftEmDash);
|
static void setPenaltyEmDashLeft (int penaltyLeftEmDash);
|
||||||
|
4
dw/ui.cc
4
dw/ui.cc
@ -32,12 +32,10 @@ namespace ui {
|
|||||||
using namespace lout;
|
using namespace lout;
|
||||||
using namespace lout::object;
|
using namespace lout::object;
|
||||||
|
|
||||||
std::intptr_t Embed::CLASS_ID = -1;
|
|
||||||
|
|
||||||
Embed::Embed(Resource *resource)
|
Embed::Embed(Resource *resource)
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::core::ui::Embed");
|
DBG_OBJ_CREATE ("dw::core::ui::Embed");
|
||||||
registerName ("dw::core::ui::Embed", typeid(*this), &CLASS_ID);
|
registerName ("dw::core::ui::Embed", typeid(*this));
|
||||||
this->resource = resource;
|
this->resource = resource;
|
||||||
resource->setEmbed (this);
|
resource->setEmbed (this);
|
||||||
DBG_OBJ_ASSOC_CHILD (resource);
|
DBG_OBJ_ASSOC_CHILD (resource);
|
||||||
|
2
dw/ui.hh
2
dw/ui.hh
@ -251,8 +251,6 @@ protected:
|
|||||||
bool buttonPressImpl (core::EventButton *event);
|
bool buttonPressImpl (core::EventButton *event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
Embed(Resource *resource);
|
Embed(Resource *resource);
|
||||||
~Embed();
|
~Embed();
|
||||||
|
|
||||||
|
@ -73,12 +73,11 @@ void Widget::WidgetImgRenderer::draw (int x, int y, int width, int height)
|
|||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
bool Widget::adjustMinWidth = true;
|
bool Widget::adjustMinWidth = true;
|
||||||
std::intptr_t Widget::CLASS_ID = -1;
|
|
||||||
|
|
||||||
Widget::Widget ()
|
Widget::Widget ()
|
||||||
{
|
{
|
||||||
DBG_OBJ_CREATE ("dw::core::Widget");
|
DBG_OBJ_CREATE ("dw::core::Widget");
|
||||||
registerName ("dw::core::Widget", typeid(*this), &CLASS_ID);
|
registerName ("dw::core::Widget", typeid(*this));
|
||||||
|
|
||||||
DBG_OBJ_ASSOC_CHILD (&requisitionParams);
|
DBG_OBJ_ASSOC_CHILD (&requisitionParams);
|
||||||
DBG_OBJ_ASSOC_CHILD (&extremesParams);
|
DBG_OBJ_ASSOC_CHILD (&extremesParams);
|
||||||
|
@ -458,8 +458,6 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::intptr_t CLASS_ID;
|
|
||||||
|
|
||||||
inline static void setAdjustMinWidth (bool adjustMinWidth)
|
inline static void setAdjustMinWidth (bool adjustMinWidth)
|
||||||
{ Widget::adjustMinWidth = adjustMinWidth; }
|
{ Widget::adjustMinWidth = adjustMinWidth; }
|
||||||
|
|
||||||
|
@ -24,47 +24,7 @@
|
|||||||
namespace lout {
|
namespace lout {
|
||||||
namespace identity {
|
namespace identity {
|
||||||
|
|
||||||
// ------------------------
|
std::map< std::type_index, std::string > IdentifiableObject::classNames;
|
||||||
// IdentifiableObject
|
|
||||||
// ------------------------
|
|
||||||
|
|
||||||
using namespace object;
|
|
||||||
using namespace container::typed;
|
|
||||||
|
|
||||||
IdentifiableObject::Class::Class (IdentifiableObject::Class *parent, const std::type_index id,
|
|
||||||
const char *className)
|
|
||||||
: id( (std::intptr_t) id.name() )
|
|
||||||
{
|
|
||||||
this->parent = parent;
|
|
||||||
this->className = className;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IdentifiableObject::Class::intoStringBuffer(misc::StringBuffer *sb)
|
|
||||||
{
|
|
||||||
sb->append ("<class ");
|
|
||||||
sb->append (className);
|
|
||||||
sb->append (" (");
|
|
||||||
sb->appendInt (id);
|
|
||||||
sb->append (")");
|
|
||||||
|
|
||||||
if (parent) {
|
|
||||||
sb->append (", parent: ");
|
|
||||||
parent->intoStringBuffer (sb);
|
|
||||||
}
|
|
||||||
|
|
||||||
sb->append (">");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map< std::string, std::unique_ptr< IdentifiableObject::Class > > IdentifiableObject::classesByName;
|
|
||||||
|
|
||||||
std::map< std::intptr_t, IdentifiableObject::Class * > IdentifiableObject::classesById;
|
|
||||||
|
|
||||||
IdentifiableObject::Class *IdentifiableObject::currentlyConstructedClass;
|
|
||||||
|
|
||||||
IdentifiableObject::IdentifiableObject ()
|
|
||||||
{
|
|
||||||
currentlyConstructedClass = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IdentifiableObject::intoStringBuffer(misc::StringBuffer *sb)
|
void IdentifiableObject::intoStringBuffer(misc::StringBuffer *sb)
|
||||||
{
|
{
|
||||||
@ -76,23 +36,12 @@ void IdentifiableObject::intoStringBuffer(misc::StringBuffer *sb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief This method must be called in the constructor for the sub class.
|
* Register a name for a class.
|
||||||
* See class comment for details.
|
|
||||||
*/
|
*/
|
||||||
void IdentifiableObject::registerName (const char *className, const std::type_index index, std::intptr_t *classId)
|
void
|
||||||
|
IdentifiableObject::registerName( const char *const className, const std::type_index index )
|
||||||
{
|
{
|
||||||
if (not classesByName.contains( className )) {
|
classNames.insert( { index, className } );
|
||||||
classesByName.emplace( className,
|
|
||||||
std::make_unique< Class >( currentlyConstructedClass, index, className ) );
|
|
||||||
auto *const klass= classesByName.at( className ).get();
|
|
||||||
classesById[ klass->id ]= klass;
|
|
||||||
*classId = klass->id;
|
|
||||||
}
|
|
||||||
Class *const klass = classesByName.at( className ).get();
|
|
||||||
|
|
||||||
this->classId = klass->id;
|
|
||||||
*classId = klass->id;
|
|
||||||
currentlyConstructedClass = klass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace identity
|
} // namespace identity
|
||||||
|
112
lout/identity.hh
112
lout/identity.hh
@ -15,127 +15,35 @@
|
|||||||
namespace lout {
|
namespace lout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Some stuff to identify classes of objects at run-time.
|
* \brief This was a poor man's RTTI implementation.
|
||||||
*/
|
*/
|
||||||
namespace identity {
|
namespace identity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Instances of classes, which are sub classes of this class, may
|
* Hooks for class name inspection.
|
||||||
* be identified at run-time.
|
|
||||||
*
|
*
|
||||||
* <h3>Testing the class</h3>
|
* It began life as an RTTI clone. It did not support multiple inheritance.
|
||||||
*
|
*
|
||||||
* Since e.g. dw::Textblock is a sub class of IdentifiableObject, and
|
* It appeared to be a model of Java's `Object` system. It's mostly been migrated
|
||||||
* implemented in the correct way (as described below), for any given
|
* to use C++ RTTI and most use cases should be avoiding the `lout::contaner` stuff.
|
||||||
* IdentifiableObject the following test can be done:
|
|
||||||
*
|
|
||||||
* \code
|
|
||||||
* identity::IdentifiableObject *o;
|
|
||||||
* // ...
|
|
||||||
* bool isATextblock = o->instanceOf(dw::Textblock::CLASS_ID);
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* \em isATextblock is true, when \em o is an instance of dw::Textblock,
|
|
||||||
* or of a sub class of dw::Textblock. Otherwise, \em isATextblock is false.
|
|
||||||
*
|
|
||||||
* It is also possible to get the class identifier of an
|
|
||||||
* identity::IdentifiableObject, e.g.
|
|
||||||
*
|
|
||||||
* \code
|
|
||||||
* bool isOnlyATextblock = o->getClassId() == dw::Textblock::CLASS_ID;
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* would result in true, if o is an instance of dw::Textblock, but not an
|
|
||||||
* instance of a sub class of dw::Textblock.
|
|
||||||
*
|
|
||||||
* <h3>Defining Sub Classes</h3>
|
|
||||||
*
|
|
||||||
* Each direct or indirect sub class of IdentifiableObject must
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li> add a static int CLASS_ID with -1 as initial value, and
|
|
||||||
* <li> call registerName (\em name, &CLASS_ID) in the constructor, where
|
|
||||||
* \em name should be unique, e.g. the fully qualified class name.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* After this, <i>class</i>\::CLASS_ID refers to a number, which denotes the
|
|
||||||
* class. (If this is still -1, since the class has not yet been instantiated,
|
|
||||||
* any test will fail, which is correct.)
|
|
||||||
*
|
|
||||||
* <h3>Notes on implementation</h3>
|
|
||||||
*
|
|
||||||
* If there are some classes like this:
|
|
||||||
*
|
|
||||||
* \dot
|
|
||||||
* digraph G {
|
|
||||||
* node [shape=record, fontname=Helvetica, fontsize=10];
|
|
||||||
* edge [arrowhead="none", arrowtail="empty", labelfontname=Helvetica,
|
|
||||||
* labelfontsize=10, color="#404040", labelfontcolor="#000080"];
|
|
||||||
* fontname=Helvetica; fontsize=10;
|
|
||||||
* IdentifiableObject [color="#a0a0a0"];
|
|
||||||
* A;
|
|
||||||
* B [color="#a0a0a0"];
|
|
||||||
* C;
|
|
||||||
* IdentifiableObject -> A;
|
|
||||||
* IdentifiableObject -> B;
|
|
||||||
* B -> C;
|
|
||||||
* }
|
|
||||||
* \enddot
|
|
||||||
*
|
|
||||||
* <center>[\ref uml-legend "legend"]</center>
|
|
||||||
*
|
|
||||||
* and first, an instance of A, and then an instance of C is created, there
|
|
||||||
* will be the following calls of functions and constructors:
|
|
||||||
*
|
|
||||||
* <ol>
|
|
||||||
* <li> %IdentifiableObject ();
|
|
||||||
* <li> %registerName ("A", &A::CLASS_ID);
|
|
||||||
* <li> %IdentifiableObject ();
|
|
||||||
* <li> %registerName ("B", &B::CLASS_ID);
|
|
||||||
* <li> %registerName ("C", &C::CLASS_ID);
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* From this, the class hierarchy above can easily constructed, and stored
|
|
||||||
* in identity::IdentifiableObject::classesByName and
|
|
||||||
* in identity::IdentifiableObject::classesById. See the code for details.
|
|
||||||
*
|
|
||||||
* N.b. Multiple inheritance is not supported, the construction of the
|
|
||||||
* tree would become confused.
|
|
||||||
*/
|
*/
|
||||||
class IdentifiableObject: public object::Object
|
class IdentifiableObject: public object::Object
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
class Class final: public object::Object
|
// TODO: Use the Alepha facility for this, eventually...
|
||||||
{
|
static std::map< std::type_index, std::string > classNames;
|
||||||
public:
|
|
||||||
Class *parent;
|
|
||||||
std::intptr_t id;
|
|
||||||
const char *className;
|
|
||||||
|
|
||||||
Class (Class *parent, std::type_index id, const char *className);
|
|
||||||
|
|
||||||
void intoStringBuffer(misc::StringBuffer *sb);
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::map< std::string, std::unique_ptr< Class > > classesByName;
|
|
||||||
static std::map< std::intptr_t, Class * > classesById;
|
|
||||||
static Class *currentlyConstructedClass;
|
|
||||||
|
|
||||||
std::intptr_t classId;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void registerName (const char *className, std::type_index index, std::intptr_t *classId);
|
void registerName (const char *className, std::type_index index);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IdentifiableObject ();
|
void intoStringBuffer(misc::StringBuffer *sb) override;
|
||||||
|
|
||||||
void intoStringBuffer(misc::StringBuffer *sb);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Return the name, under which the class of this object was
|
* \brief Return the name, under which the class of this object was
|
||||||
* registered.
|
* registered.
|
||||||
*/
|
*/
|
||||||
const char *getClassName() { return classesById.at( classId )->className; }
|
const char *getClassName() { return classNames.at( typeid( *this ) ).c_str(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace identity
|
} // namespace identity
|
||||||
|
Reference in New Issue
Block a user