Merge pull request #19907 from benj5378/getAttribute
Base: make getAttribute template
This commit is contained in:
@@ -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 == "")
|
||||
* {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 */
|
||||
//@{
|
||||
|
||||
Reference in New Issue
Block a user