Merge pull request #19907 from benj5378/getAttribute

Base: make getAttribute template
This commit is contained in:
Chris Hennes
2025-05-12 10:39:55 -05:00
committed by GitHub
64 changed files with 834 additions and 677 deletions

View File

@@ -73,9 +73,9 @@ public:
* // read my Element
* reader.readElement("PropertyVector");
* // get the value of my Attribute
* _cVec.x = reader.getAttributeAsFloat("valueX");
* _cVec.y = reader.getAttributeAsFloat("valueY");
* _cVec.z = reader.getAttributeAsFloat("valueZ");
* _cVec.x = reader.getAttribute<double>("valueX");
* _cVec.y = reader.getAttribute<double>("valueY");
* _cVec.z = reader.getAttribute<double>("valueZ");
* }
* \endcode
*/
@@ -122,7 +122,7 @@ public:
* void PropertyMeshKernel::Restore(Base::XMLReader &reader)
* {
* reader.readElement("Mesh");
* std::string file (reader.getAttribute("file") );
* std::string file (reader.getAttribute<const char*>("file") );
*
* if(file == "")
* {

View File

@@ -118,39 +118,81 @@ unsigned int Base::XMLReader::getAttributeCount() const
return static_cast<unsigned int>(AttrMap.size());
}
long Base::XMLReader::getAttributeAsInteger(const char* AttrName, const char* defaultValue) const
namespace
{
return stol(getAttribute(AttrName, defaultValue));
}
unsigned long Base::XMLReader::getAttributeAsUnsigned(const char* AttrName,
const char* defaultValue) const
template<typename T>
T readerCast(const char* value)
{
return stoul(getAttribute(AttrName, defaultValue), nullptr);
if constexpr (std::is_same_v<T, const char*>) {
return value;
}
if constexpr (std::is_same_v<T, long>) {
return stol(value);
}
if constexpr (std::is_same_v<T, int>) {
return stoi(value);
}
if constexpr (std::is_same_v<T, unsigned long>) {
return stoul(value, nullptr);
}
if constexpr (std::is_same_v<T, double>) {
return stod(value, nullptr);
}
if constexpr (std::is_same_v<T, bool>) {
return std::string_view(value) != "0";
}
}
} // anonymous namespace
double Base::XMLReader::getAttributeAsFloat(const char* AttrName, const char* defaultValue) const
{
return stod(getAttribute(AttrName, defaultValue), nullptr);
}
const char* Base::XMLReader::getAttribute(const char* AttrName, // NOLINT
const char* defaultValue) const // NOLINT
template<typename T>
requires Base::XMLReader::instantiated<T>
T Base::XMLReader::getAttribute(const char* AttrName, T defaultValue) const
{
auto pos = AttrMap.find(AttrName);
if (pos != AttrMap.end()) {
return pos->second.c_str();
}
if (defaultValue) {
if (pos == AttrMap.end()) {
return defaultValue;
}
// wrong name, use hasAttribute if not sure!
std::ostringstream msg;
msg << "XML Attribute: \"" << AttrName << "\" not found";
throw Base::XMLAttributeError(msg.str());
const char* rawValue = pos->second.c_str();
return readerCast<T>(rawValue);
}
template<typename T>
requires Base::XMLReader::instantiated<T>
T Base::XMLReader::getAttribute(const char* AttrName) const
{
auto pos = AttrMap.find(AttrName);
if (pos == AttrMap.end()) {
// wrong name, use hasAttribute if not sure!
std::string msg = std::string("XML Attribute: \"") + AttrName + "\" not found";
throw Base::XMLAttributeError(msg);
}
const char* rawValue = pos->second.c_str();
return readerCast<T>(rawValue);
}
// Explicit template instantiation
template BaseExport bool Base::XMLReader::getAttribute<bool>(const char* AttrName,
bool defaultValue) const;
template BaseExport bool Base::XMLReader::getAttribute<bool>(const char* AttrName) const;
template BaseExport const char*
Base::XMLReader::getAttribute<const char*>(const char* AttrName, const char* defaultValue) const;
template BaseExport const char*
Base::XMLReader::getAttribute<const char*>(const char* AttrName) const;
template BaseExport double Base::XMLReader::getAttribute<double>(const char* AttrName,
double defaultValue) const;
template BaseExport double Base::XMLReader::getAttribute<double>(const char* AttrName) const;
template BaseExport int Base::XMLReader::getAttribute<int>(const char* AttrName,
int defaultValue) const;
template BaseExport int Base::XMLReader::getAttribute<int>(const char* AttrName) const;
template BaseExport long Base::XMLReader::getAttribute<long>(const char* AttrName,
long defaultValue) const;
template BaseExport long Base::XMLReader::getAttribute<long>(const char* AttrName) const;
template BaseExport unsigned long
Base::XMLReader::getAttribute<unsigned long>(const char* AttrName,
unsigned long defaultValue) const;
template BaseExport unsigned long
Base::XMLReader::getAttribute<unsigned long>(const char* AttrName) const;
bool Base::XMLReader::hasAttribute(const char* AttrName) const
{
return AttrMap.find(AttrName) != AttrMap.end();

View File

@@ -82,7 +82,7 @@ void PropertyString::Restore(Base::Reader &reader)
// read my Element
reader.readElement("String");
// get the value of my Attribute
_cValue = reader.getAttribute("value");
_cValue = reader.getAttribute<const char*>("value");
}
* \endcode
@@ -108,12 +108,12 @@ endl;
void PropertyContainer::Restore(Base::Reader &reader)
{
reader.readElement("Properties");
int Cnt = reader.getAttributeAsInteger("Count");
int Cnt = reader.getAttribute<long>("Count");
for(int i=0 ;i<Cnt ;i++)
{
reader.readElement("Property");
string PropName = reader.getAttribute("name");
string PropName = reader.getAttribute<const char*>("name");
Property* prop = getPropertyByName(PropName.c_str());
if(prop)
prop->Restore(reader);
@@ -227,23 +227,57 @@ public:
/// check if the read element has a special attribute
bool hasAttribute(const char* AttrName) const;
/// return the named attribute as an integer (does type checking); if missing return
/// defaultValue
long getAttributeAsInteger(const char* AttrName, const char* defaultValue = nullptr) const;
private:
// all explicit template instatiations - this is for getting
// a compile error, rather than linker error.
template<typename T>
static constexpr bool instantiated =
std::is_same_v<T, bool> || std::is_same_v<T, const char*> || std::is_same_v<T, double>
|| std::is_same_v<T, int> || std::is_same_v<T, long> || std::is_same_v<T, unsigned long>;
/// return the named attribute as unsigned integer (does type checking); if missing return
/// defaultValue
unsigned long getAttributeAsUnsigned(const char* AttrName,
const char* defaultValue = nullptr) const;
public:
/// return the named attribute as T (does type checking); if missing return defaultValue.
/// If defaultValue is not set, it will default to the default initilization of the
/// corresponding type; bool: false, int: 0, ... as if one had used defaultValue=bool{}
/// or defaultValue=int{}
// General template, mark delete as it's not implemented, and should not be used!
template<typename T>
requires Base::XMLReader::instantiated<T>
T getAttribute(const char* AttrName, T defaultValue) const;
/// return the named attribute as a double floating point (does type checking); if missing
/// return defaultValue
double getAttributeAsFloat(const char* AttrName, const char* defaultValue = nullptr) const;
/// No default? Will throw exception if not found!
template<typename T>
requires Base::XMLReader::instantiated<T>
T getAttribute(const char* AttrName) const;
/// return the named attribute as a double floating point (does type checking); if missing
/// return defaultValue
const char* getAttribute(const char* AttrName, const char* defaultValue = nullptr) const;
//@}
/// E.g. std::string, QString
template<typename T>
T getAttribute(const char* AttrName) const
{
return T(getAttribute<const char*>(AttrName));
}
/// E.g. std::string, QString
template<typename T>
T getAttribute(const char* AttrName, T defaultValue) const
{
return T(getAttribute<const char*>(AttrName, defaultValue));
}
/// Enum classes
template<typename T>
requires std::is_enum_v<T>
T getAttribute(const char* AttrName, T defaultValue) const
{
return static_cast<T>(
getAttribute<unsigned long>(AttrName, static_cast<unsigned long>(defaultValue)));
}
/// Enum classes
template<typename T>
requires std::is_enum_v<T>
T getAttribute(const char* AttrName) const
{
return static_cast<T>(getAttribute<unsigned long>(AttrName));
}
/** @name additional file reading */
//@{