mirror of https://github.com/libAthena/athena.git
Use RAII context management for YAML vectors and records
This commit is contained in:
parent
9ccf9f596b
commit
2a4fc3e3b3
|
@ -110,20 +110,18 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
|
||||||
{
|
{
|
||||||
if (m_output)
|
if (m_output)
|
||||||
{
|
{
|
||||||
out << " /* " << m_fieldName << " */\n";
|
if (m_fieldName.size())
|
||||||
|
out << " /* " << m_fieldName << " */\n";
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case Type::EnterSubVector:
|
case Type::EnterSubVector:
|
||||||
if (!p)
|
if (!p)
|
||||||
out << " size_t __" << m_fieldName << "Count;\n " ATHENA_YAML_READER ".enterSubVector(\"" << m_fieldName << "\", __" << m_fieldName << "Count);\n";
|
out << " size_t __" << m_fieldName << "Count;\n if (auto __v = " ATHENA_YAML_READER ".enterSubVector(\"" << m_fieldName << "\", __" << m_fieldName << "Count))\n {\n";
|
||||||
else
|
else
|
||||||
out << " " ATHENA_YAML_WRITER ".enterSubVector(\"" << m_fieldName << "\");\n";
|
out << " if (auto __v = " ATHENA_YAML_WRITER ".enterSubVector(\"" << m_fieldName << "\"))\n {\n";
|
||||||
break;
|
break;
|
||||||
case Type::LeaveSubVector:
|
case Type::LeaveSubVector:
|
||||||
if (!p)
|
out << " }\n";
|
||||||
out << " " ATHENA_YAML_READER ".leaveSubVector();\n";
|
|
||||||
else
|
|
||||||
out << " " ATHENA_YAML_WRITER ".leaveSubVector();\n";
|
|
||||||
break;
|
break;
|
||||||
case Type::Value:
|
case Type::Value:
|
||||||
if (!p)
|
if (!p)
|
||||||
|
|
|
@ -179,6 +179,8 @@ class YAMLDocReader
|
||||||
std::vector<int> m_seqTrackerStack;
|
std::vector<int> m_seqTrackerStack;
|
||||||
yaml_parser_t m_parser;
|
yaml_parser_t m_parser;
|
||||||
std::unique_ptr<YAMLNode> ParseEvents(athena::io::IStreamReader* reader);
|
std::unique_ptr<YAMLNode> ParseEvents(athena::io::IStreamReader* reader);
|
||||||
|
void _leaveSubRecord();
|
||||||
|
void _leaveSubVector();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
YAMLDocReader();
|
YAMLDocReader();
|
||||||
|
@ -197,19 +199,40 @@ public:
|
||||||
inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
|
inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
|
||||||
std::unique_ptr<YAMLNode> releaseRootNode() { return std::move(m_rootNode); }
|
std::unique_ptr<YAMLNode> releaseRootNode() { return std::move(m_rootNode); }
|
||||||
|
|
||||||
bool enterSubRecord(const char* name);
|
class RecordRAII
|
||||||
void leaveSubRecord();
|
{
|
||||||
|
friend class YAMLDocReader;
|
||||||
|
YAMLDocReader* m_r = nullptr;
|
||||||
|
RecordRAII(YAMLDocReader* r) : m_r(r) {}
|
||||||
|
RecordRAII() = default;
|
||||||
|
public:
|
||||||
|
operator bool() const { return m_r != nullptr; }
|
||||||
|
~RecordRAII() { if (m_r) m_r->_leaveSubRecord(); }
|
||||||
|
};
|
||||||
|
friend class RecordRAII;
|
||||||
|
|
||||||
|
RecordRAII enterSubRecord(const char* name);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void enumerate(const char* name, T& record)
|
void enumerate(const char* name, T& record)
|
||||||
{
|
{
|
||||||
enterSubRecord(name);
|
if (auto rec = enterSubRecord(name))
|
||||||
record.read(*this);
|
record.read(*this);
|
||||||
leaveSubRecord();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool enterSubVector(const char* name, size_t& countOut);
|
class VectorRAII
|
||||||
void leaveSubVector();
|
{
|
||||||
|
friend class YAMLDocReader;
|
||||||
|
YAMLDocReader* m_r = nullptr;
|
||||||
|
VectorRAII(YAMLDocReader* r) : m_r(r) {}
|
||||||
|
VectorRAII() = default;
|
||||||
|
public:
|
||||||
|
operator bool() const { return m_r != nullptr; }
|
||||||
|
~VectorRAII() { if (m_r) m_r->_leaveSubVector(); }
|
||||||
|
};
|
||||||
|
friend class VectorRAII;
|
||||||
|
|
||||||
|
VectorRAII enterSubVector(const char* name, size_t& countOut);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
size_t enumerate(const char* name, std::vector<T>& vector,
|
size_t enumerate(const char* name, std::vector<T>& vector,
|
||||||
|
@ -219,17 +242,17 @@ public:
|
||||||
!std::is_same<T, atVec4f>::value>::type* = 0)
|
!std::is_same<T, atVec4f>::value>::type* = 0)
|
||||||
{
|
{
|
||||||
size_t countOut;
|
size_t countOut;
|
||||||
enterSubVector(name, countOut);
|
if (auto v = enterSubVector(name, countOut))
|
||||||
vector.clear();
|
|
||||||
vector.reserve(countOut);
|
|
||||||
for (size_t i=0 ; i<countOut ; ++i)
|
|
||||||
{
|
{
|
||||||
vector.emplace_back();
|
vector.clear();
|
||||||
enterSubRecord(nullptr);
|
vector.reserve(countOut);
|
||||||
vector.back().read(*this);
|
for (size_t i=0 ; i<countOut ; ++i)
|
||||||
leaveSubRecord();
|
{
|
||||||
|
vector.emplace_back();
|
||||||
|
if (auto rec = enterSubRecord(nullptr))
|
||||||
|
vector.back().read(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
leaveSubVector();
|
|
||||||
return countOut;
|
return countOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,12 +264,13 @@ public:
|
||||||
std::is_same<T, atVec4f>::value>::type* = 0)
|
std::is_same<T, atVec4f>::value>::type* = 0)
|
||||||
{
|
{
|
||||||
size_t countOut;
|
size_t countOut;
|
||||||
enterSubVector(name, countOut);
|
if (auto v = enterSubVector(name, countOut))
|
||||||
vector.clear();
|
{
|
||||||
vector.reserve(countOut);
|
vector.clear();
|
||||||
for (size_t i=0 ; i<countOut ; ++i)
|
vector.reserve(countOut);
|
||||||
vector.push_back(readVal<T>(name));
|
for (size_t i=0 ; i<countOut ; ++i)
|
||||||
leaveSubVector();
|
vector.push_back(readVal<T>(name));
|
||||||
|
}
|
||||||
return countOut;
|
return countOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,17 +279,17 @@ public:
|
||||||
std::function<void(YAMLDocReader&, T&)> readf)
|
std::function<void(YAMLDocReader&, T&)> readf)
|
||||||
{
|
{
|
||||||
size_t countOut;
|
size_t countOut;
|
||||||
enterSubVector(name, countOut);
|
if (auto v = enterSubVector(name, countOut))
|
||||||
vector.clear();
|
|
||||||
vector.reserve(countOut);
|
|
||||||
for (size_t i=0 ; i<countOut ; ++i)
|
|
||||||
{
|
{
|
||||||
vector.emplace_back();
|
vector.clear();
|
||||||
enterSubRecord(nullptr);
|
vector.reserve(countOut);
|
||||||
readf(*this, vector.back());
|
for (size_t i=0 ; i<countOut ; ++i)
|
||||||
leaveSubRecord();
|
{
|
||||||
|
vector.emplace_back();
|
||||||
|
if (auto rec = enterSubRecord(nullptr))
|
||||||
|
readf(*this, vector.back());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
leaveSubVector();
|
|
||||||
return countOut;
|
return countOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,6 +323,8 @@ class YAMLDocWriter
|
||||||
std::vector<YAMLNode*> m_subStack;
|
std::vector<YAMLNode*> m_subStack;
|
||||||
yaml_emitter_t m_emitter;
|
yaml_emitter_t m_emitter;
|
||||||
static bool RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node);
|
static bool RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node);
|
||||||
|
void _leaveSubRecord();
|
||||||
|
void _leaveSubVector();
|
||||||
public:
|
public:
|
||||||
YAMLDocWriter(const char* classType);
|
YAMLDocWriter(const char* classType);
|
||||||
~YAMLDocWriter();
|
~YAMLDocWriter();
|
||||||
|
@ -309,19 +335,40 @@ public:
|
||||||
|
|
||||||
inline YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
|
inline YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
|
||||||
|
|
||||||
void enterSubRecord(const char* name);
|
class RecordRAII
|
||||||
void leaveSubRecord();
|
{
|
||||||
|
friend class YAMLDocWriter;
|
||||||
|
YAMLDocWriter* m_w = nullptr;
|
||||||
|
RecordRAII(YAMLDocWriter* w) : m_w(w) {}
|
||||||
|
RecordRAII() = default;
|
||||||
|
public:
|
||||||
|
operator bool() const { return m_w != nullptr; }
|
||||||
|
~RecordRAII() { if (m_w) m_w->_leaveSubRecord(); }
|
||||||
|
};
|
||||||
|
friend class RecordRAII;
|
||||||
|
|
||||||
|
RecordRAII enterSubRecord(const char* name);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void enumerate(const char* name, T& record)
|
void enumerate(const char* name, T& record)
|
||||||
{
|
{
|
||||||
enterSubRecord(name);
|
if (auto rec = enterSubRecord(name))
|
||||||
record.write(*this);
|
record.write(*this);
|
||||||
leaveSubRecord();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void enterSubVector(const char* name);
|
class VectorRAII
|
||||||
void leaveSubVector();
|
{
|
||||||
|
friend class YAMLDocWriter;
|
||||||
|
YAMLDocWriter* m_w = nullptr;
|
||||||
|
VectorRAII(YAMLDocWriter* w) : m_w(w) {}
|
||||||
|
VectorRAII() = default;
|
||||||
|
public:
|
||||||
|
operator bool() const { return m_w != nullptr; }
|
||||||
|
~VectorRAII() { if (m_w) m_w->_leaveSubVector(); }
|
||||||
|
};
|
||||||
|
friend class VectorRAII;
|
||||||
|
|
||||||
|
VectorRAII enterSubVector(const char* name);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void enumerate(const char* name, const std::vector<T>& vector,
|
void enumerate(const char* name, const std::vector<T>& vector,
|
||||||
|
@ -333,14 +380,10 @@ public:
|
||||||
!std::is_same<T, atVec3d>::value &&
|
!std::is_same<T, atVec3d>::value &&
|
||||||
!std::is_same<T, atVec4d>::value>::type* = 0)
|
!std::is_same<T, atVec4d>::value>::type* = 0)
|
||||||
{
|
{
|
||||||
enterSubVector(name);
|
if (auto v = enterSubVector(name))
|
||||||
for (const T& item : vector)
|
for (const T& item : vector)
|
||||||
{
|
if (auto rec = enterSubRecord(nullptr))
|
||||||
enterSubRecord(nullptr);
|
item.write(*this);
|
||||||
item.write(*this);
|
|
||||||
leaveSubRecord();
|
|
||||||
}
|
|
||||||
leaveSubVector();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -353,24 +396,19 @@ public:
|
||||||
std::is_same<T, atVec3d>::value ||
|
std::is_same<T, atVec3d>::value ||
|
||||||
std::is_same<T, atVec4d>::value>::type* = 0)
|
std::is_same<T, atVec4d>::value>::type* = 0)
|
||||||
{
|
{
|
||||||
enterSubVector(name);
|
if (auto v = enterSubVector(name))
|
||||||
for (T item : vector)
|
for (T item : vector)
|
||||||
writeVal<T>(nullptr, item);
|
writeVal<T>(nullptr, item);
|
||||||
leaveSubVector();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void enumerate(const char* name, const std::vector<T>& vector,
|
void enumerate(const char* name, const std::vector<T>& vector,
|
||||||
std::function<void(YAMLDocWriter&, const T&)> writef)
|
std::function<void(YAMLDocWriter&, const T&)> writef)
|
||||||
{
|
{
|
||||||
enterSubVector(name);
|
if (auto v = enterSubVector(name))
|
||||||
for (const T& item : vector)
|
for (const T& item : vector)
|
||||||
{
|
if (auto rec = enterSubRecord(nullptr))
|
||||||
enterSubRecord(nullptr);
|
writef(*this, item);
|
||||||
writef(*this, item);
|
|
||||||
leaveSubRecord();
|
|
||||||
}
|
|
||||||
leaveSubVector();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename INTYPE>
|
template <typename INTYPE>
|
||||||
|
|
|
@ -589,21 +589,22 @@ err:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void YAMLDocWriter::enterSubRecord(const char* name)
|
YAMLDocWriter::RecordRAII YAMLDocWriter::enterSubRecord(const char* name)
|
||||||
{
|
{
|
||||||
YAMLNode* curSub = m_subStack.back();
|
YAMLNode* curSub = m_subStack.back();
|
||||||
if (curSub->m_type != YAML_MAPPING_NODE &&
|
if (curSub->m_type != YAML_MAPPING_NODE &&
|
||||||
curSub->m_type != YAML_SEQUENCE_NODE)
|
curSub->m_type != YAML_SEQUENCE_NODE)
|
||||||
return;
|
return {};
|
||||||
YAMLNode* newNode = new YAMLNode(YAML_MAPPING_NODE);
|
YAMLNode* newNode = new YAMLNode(YAML_MAPPING_NODE);
|
||||||
if (curSub->m_type == YAML_MAPPING_NODE)
|
if (curSub->m_type == YAML_MAPPING_NODE)
|
||||||
curSub->m_mapChildren.emplace_back(name?std::string(name):std::string(), std::unique_ptr<YAMLNode>(newNode));
|
curSub->m_mapChildren.emplace_back(name?std::string(name):std::string(), std::unique_ptr<YAMLNode>(newNode));
|
||||||
else if (curSub->m_type == YAML_SEQUENCE_NODE)
|
else if (curSub->m_type == YAML_SEQUENCE_NODE)
|
||||||
curSub->m_seqChildren.emplace_back(newNode);
|
curSub->m_seqChildren.emplace_back(newNode);
|
||||||
m_subStack.push_back(newNode);
|
m_subStack.push_back(newNode);
|
||||||
|
return RecordRAII{this};
|
||||||
}
|
}
|
||||||
|
|
||||||
void YAMLDocWriter::leaveSubRecord()
|
void YAMLDocWriter::_leaveSubRecord()
|
||||||
{
|
{
|
||||||
if (m_subStack.size() > 1)
|
if (m_subStack.size() > 1)
|
||||||
{
|
{
|
||||||
|
@ -633,21 +634,22 @@ void YAMLDocWriter::leaveSubRecord()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void YAMLDocWriter::enterSubVector(const char* name)
|
YAMLDocWriter::VectorRAII YAMLDocWriter::enterSubVector(const char* name)
|
||||||
{
|
{
|
||||||
YAMLNode* curSub = m_subStack.back();
|
YAMLNode* curSub = m_subStack.back();
|
||||||
if (curSub->m_type != YAML_MAPPING_NODE &&
|
if (curSub->m_type != YAML_MAPPING_NODE &&
|
||||||
curSub->m_type != YAML_SEQUENCE_NODE)
|
curSub->m_type != YAML_SEQUENCE_NODE)
|
||||||
return;
|
return {};
|
||||||
YAMLNode* newNode = new YAMLNode(YAML_SEQUENCE_NODE);
|
YAMLNode* newNode = new YAMLNode(YAML_SEQUENCE_NODE);
|
||||||
if (curSub->m_type == YAML_MAPPING_NODE)
|
if (curSub->m_type == YAML_MAPPING_NODE)
|
||||||
curSub->m_mapChildren.emplace_back(name?std::string(name):std::string(), std::unique_ptr<YAMLNode>(newNode));
|
curSub->m_mapChildren.emplace_back(name?std::string(name):std::string(), std::unique_ptr<YAMLNode>(newNode));
|
||||||
else if (curSub->m_type == YAML_SEQUENCE_NODE)
|
else if (curSub->m_type == YAML_SEQUENCE_NODE)
|
||||||
curSub->m_seqChildren.emplace_back(newNode);
|
curSub->m_seqChildren.emplace_back(newNode);
|
||||||
m_subStack.push_back(newNode);
|
m_subStack.push_back(newNode);
|
||||||
|
return VectorRAII{this};
|
||||||
}
|
}
|
||||||
|
|
||||||
void YAMLDocWriter::leaveSubVector()
|
void YAMLDocWriter::_leaveSubVector()
|
||||||
{
|
{
|
||||||
if (m_subStack.size() > 1)
|
if (m_subStack.size() > 1)
|
||||||
m_subStack.pop_back();
|
m_subStack.pop_back();
|
||||||
|
@ -1016,7 +1018,7 @@ bool YAMLDocReader::ValidateClassType(const char* expectedType)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool YAMLDocReader::enterSubRecord(const char* name)
|
YAMLDocReader::RecordRAII YAMLDocReader::enterSubRecord(const char* name)
|
||||||
{
|
{
|
||||||
YAMLNode* curSub = m_subStack.back();
|
YAMLNode* curSub = m_subStack.back();
|
||||||
if (curSub->m_type == YAML_SEQUENCE_NODE)
|
if (curSub->m_type == YAML_SEQUENCE_NODE)
|
||||||
|
@ -1025,7 +1027,11 @@ bool YAMLDocReader::enterSubRecord(const char* name)
|
||||||
m_subStack.push_back(curSub->m_seqChildren[seqIdx++].get());
|
m_subStack.push_back(curSub->m_seqChildren[seqIdx++].get());
|
||||||
if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE)
|
if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE)
|
||||||
m_seqTrackerStack.push_back(0);
|
m_seqTrackerStack.push_back(0);
|
||||||
return true;
|
return RecordRAII{this};
|
||||||
|
}
|
||||||
|
else if (!name)
|
||||||
|
{
|
||||||
|
atError("Expected YAML sequence");
|
||||||
}
|
}
|
||||||
for (const auto& item : curSub->m_mapChildren)
|
for (const auto& item : curSub->m_mapChildren)
|
||||||
{
|
{
|
||||||
|
@ -1034,13 +1040,13 @@ bool YAMLDocReader::enterSubRecord(const char* name)
|
||||||
m_subStack.push_back(item.second.get());
|
m_subStack.push_back(item.second.get());
|
||||||
if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE)
|
if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE)
|
||||||
m_seqTrackerStack.push_back(0);
|
m_seqTrackerStack.push_back(0);
|
||||||
return true;
|
return RecordRAII{this};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void YAMLDocReader::leaveSubRecord()
|
void YAMLDocReader::_leaveSubRecord()
|
||||||
{
|
{
|
||||||
if (m_subStack.size() > 1)
|
if (m_subStack.size() > 1)
|
||||||
{
|
{
|
||||||
|
@ -1050,7 +1056,7 @@ void YAMLDocReader::leaveSubRecord()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool YAMLDocReader::enterSubVector(const char* name, size_t& countOut)
|
YAMLDocReader::VectorRAII YAMLDocReader::enterSubVector(const char* name, size_t& countOut)
|
||||||
{
|
{
|
||||||
YAMLNode* curSub = m_subStack.back();
|
YAMLNode* curSub = m_subStack.back();
|
||||||
if (!name && curSub->m_type == YAML_SEQUENCE_NODE)
|
if (!name && curSub->m_type == YAML_SEQUENCE_NODE)
|
||||||
|
@ -1058,7 +1064,7 @@ bool YAMLDocReader::enterSubVector(const char* name, size_t& countOut)
|
||||||
m_subStack.push_back(curSub);
|
m_subStack.push_back(curSub);
|
||||||
m_seqTrackerStack.push_back(0);
|
m_seqTrackerStack.push_back(0);
|
||||||
countOut = curSub->m_seqChildren.size();
|
countOut = curSub->m_seqChildren.size();
|
||||||
return true;
|
return VectorRAII{this};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1078,15 +1084,15 @@ bool YAMLDocReader::enterSubVector(const char* name, size_t& countOut)
|
||||||
}
|
}
|
||||||
m_subStack.push_back(nextSub);
|
m_subStack.push_back(nextSub);
|
||||||
m_seqTrackerStack.push_back(0);
|
m_seqTrackerStack.push_back(0);
|
||||||
return true;
|
return VectorRAII{this};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
countOut = 0;
|
countOut = 0;
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void YAMLDocReader::leaveSubVector()
|
void YAMLDocReader::_leaveSubVector()
|
||||||
{
|
{
|
||||||
if (m_subStack.size() > 1)
|
if (m_subStack.size() > 1)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue