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)
|
||||
{
|
||||
out << " /* " << m_fieldName << " */\n";
|
||||
if (m_fieldName.size())
|
||||
out << " /* " << m_fieldName << " */\n";
|
||||
switch (m_type)
|
||||
{
|
||||
case Type::EnterSubVector:
|
||||
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
|
||||
out << " " ATHENA_YAML_WRITER ".enterSubVector(\"" << m_fieldName << "\");\n";
|
||||
out << " if (auto __v = " ATHENA_YAML_WRITER ".enterSubVector(\"" << m_fieldName << "\"))\n {\n";
|
||||
break;
|
||||
case Type::LeaveSubVector:
|
||||
if (!p)
|
||||
out << " " ATHENA_YAML_READER ".leaveSubVector();\n";
|
||||
else
|
||||
out << " " ATHENA_YAML_WRITER ".leaveSubVector();\n";
|
||||
out << " }\n";
|
||||
break;
|
||||
case Type::Value:
|
||||
if (!p)
|
||||
|
|
|
@ -179,6 +179,8 @@ class YAMLDocReader
|
|||
std::vector<int> m_seqTrackerStack;
|
||||
yaml_parser_t m_parser;
|
||||
std::unique_ptr<YAMLNode> ParseEvents(athena::io::IStreamReader* reader);
|
||||
void _leaveSubRecord();
|
||||
void _leaveSubVector();
|
||||
|
||||
public:
|
||||
YAMLDocReader();
|
||||
|
@ -197,19 +199,40 @@ public:
|
|||
inline const YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
|
||||
std::unique_ptr<YAMLNode> releaseRootNode() { return std::move(m_rootNode); }
|
||||
|
||||
bool enterSubRecord(const char* name);
|
||||
void leaveSubRecord();
|
||||
class RecordRAII
|
||||
{
|
||||
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>
|
||||
void enumerate(const char* name, T& record)
|
||||
{
|
||||
enterSubRecord(name);
|
||||
record.read(*this);
|
||||
leaveSubRecord();
|
||||
if (auto rec = enterSubRecord(name))
|
||||
record.read(*this);
|
||||
}
|
||||
|
||||
bool enterSubVector(const char* name, size_t& countOut);
|
||||
void leaveSubVector();
|
||||
class VectorRAII
|
||||
{
|
||||
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>
|
||||
size_t enumerate(const char* name, std::vector<T>& vector,
|
||||
|
@ -219,17 +242,17 @@ public:
|
|||
!std::is_same<T, atVec4f>::value>::type* = 0)
|
||||
{
|
||||
size_t countOut;
|
||||
enterSubVector(name, countOut);
|
||||
vector.clear();
|
||||
vector.reserve(countOut);
|
||||
for (size_t i=0 ; i<countOut ; ++i)
|
||||
if (auto v = enterSubVector(name, countOut))
|
||||
{
|
||||
vector.emplace_back();
|
||||
enterSubRecord(nullptr);
|
||||
vector.back().read(*this);
|
||||
leaveSubRecord();
|
||||
vector.clear();
|
||||
vector.reserve(countOut);
|
||||
for (size_t i=0 ; i<countOut ; ++i)
|
||||
{
|
||||
vector.emplace_back();
|
||||
if (auto rec = enterSubRecord(nullptr))
|
||||
vector.back().read(*this);
|
||||
}
|
||||
}
|
||||
leaveSubVector();
|
||||
return countOut;
|
||||
}
|
||||
|
||||
|
@ -241,12 +264,13 @@ public:
|
|||
std::is_same<T, atVec4f>::value>::type* = 0)
|
||||
{
|
||||
size_t countOut;
|
||||
enterSubVector(name, countOut);
|
||||
vector.clear();
|
||||
vector.reserve(countOut);
|
||||
for (size_t i=0 ; i<countOut ; ++i)
|
||||
vector.push_back(readVal<T>(name));
|
||||
leaveSubVector();
|
||||
if (auto v = enterSubVector(name, countOut))
|
||||
{
|
||||
vector.clear();
|
||||
vector.reserve(countOut);
|
||||
for (size_t i=0 ; i<countOut ; ++i)
|
||||
vector.push_back(readVal<T>(name));
|
||||
}
|
||||
return countOut;
|
||||
}
|
||||
|
||||
|
@ -255,17 +279,17 @@ public:
|
|||
std::function<void(YAMLDocReader&, T&)> readf)
|
||||
{
|
||||
size_t countOut;
|
||||
enterSubVector(name, countOut);
|
||||
vector.clear();
|
||||
vector.reserve(countOut);
|
||||
for (size_t i=0 ; i<countOut ; ++i)
|
||||
if (auto v = enterSubVector(name, countOut))
|
||||
{
|
||||
vector.emplace_back();
|
||||
enterSubRecord(nullptr);
|
||||
readf(*this, vector.back());
|
||||
leaveSubRecord();
|
||||
vector.clear();
|
||||
vector.reserve(countOut);
|
||||
for (size_t i=0 ; i<countOut ; ++i)
|
||||
{
|
||||
vector.emplace_back();
|
||||
if (auto rec = enterSubRecord(nullptr))
|
||||
readf(*this, vector.back());
|
||||
}
|
||||
}
|
||||
leaveSubVector();
|
||||
return countOut;
|
||||
}
|
||||
|
||||
|
@ -299,6 +323,8 @@ class YAMLDocWriter
|
|||
std::vector<YAMLNode*> m_subStack;
|
||||
yaml_emitter_t m_emitter;
|
||||
static bool RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node);
|
||||
void _leaveSubRecord();
|
||||
void _leaveSubVector();
|
||||
public:
|
||||
YAMLDocWriter(const char* classType);
|
||||
~YAMLDocWriter();
|
||||
|
@ -309,19 +335,40 @@ public:
|
|||
|
||||
inline YAMLNode* getCurNode() const { return m_subStack.empty() ? nullptr : m_subStack.back(); }
|
||||
|
||||
void enterSubRecord(const char* name);
|
||||
void leaveSubRecord();
|
||||
class RecordRAII
|
||||
{
|
||||
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>
|
||||
void enumerate(const char* name, T& record)
|
||||
{
|
||||
enterSubRecord(name);
|
||||
record.write(*this);
|
||||
leaveSubRecord();
|
||||
if (auto rec = enterSubRecord(name))
|
||||
record.write(*this);
|
||||
}
|
||||
|
||||
void enterSubVector(const char* name);
|
||||
void leaveSubVector();
|
||||
class VectorRAII
|
||||
{
|
||||
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>
|
||||
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, atVec4d>::value>::type* = 0)
|
||||
{
|
||||
enterSubVector(name);
|
||||
for (const T& item : vector)
|
||||
{
|
||||
enterSubRecord(nullptr);
|
||||
item.write(*this);
|
||||
leaveSubRecord();
|
||||
}
|
||||
leaveSubVector();
|
||||
if (auto v = enterSubVector(name))
|
||||
for (const T& item : vector)
|
||||
if (auto rec = enterSubRecord(nullptr))
|
||||
item.write(*this);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
@ -353,24 +396,19 @@ public:
|
|||
std::is_same<T, atVec3d>::value ||
|
||||
std::is_same<T, atVec4d>::value>::type* = 0)
|
||||
{
|
||||
enterSubVector(name);
|
||||
for (T item : vector)
|
||||
writeVal<T>(nullptr, item);
|
||||
leaveSubVector();
|
||||
if (auto v = enterSubVector(name))
|
||||
for (T item : vector)
|
||||
writeVal<T>(nullptr, item);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void enumerate(const char* name, const std::vector<T>& vector,
|
||||
std::function<void(YAMLDocWriter&, const T&)> writef)
|
||||
{
|
||||
enterSubVector(name);
|
||||
for (const T& item : vector)
|
||||
{
|
||||
enterSubRecord(nullptr);
|
||||
writef(*this, item);
|
||||
leaveSubRecord();
|
||||
}
|
||||
leaveSubVector();
|
||||
if (auto v = enterSubVector(name))
|
||||
for (const T& item : vector)
|
||||
if (auto rec = enterSubRecord(nullptr))
|
||||
writef(*this, item);
|
||||
}
|
||||
|
||||
template <typename INTYPE>
|
||||
|
|
|
@ -589,21 +589,22 @@ err:
|
|||
return false;
|
||||
}
|
||||
|
||||
void YAMLDocWriter::enterSubRecord(const char* name)
|
||||
YAMLDocWriter::RecordRAII YAMLDocWriter::enterSubRecord(const char* name)
|
||||
{
|
||||
YAMLNode* curSub = m_subStack.back();
|
||||
if (curSub->m_type != YAML_MAPPING_NODE &&
|
||||
curSub->m_type != YAML_SEQUENCE_NODE)
|
||||
return;
|
||||
return {};
|
||||
YAMLNode* newNode = new YAMLNode(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));
|
||||
else if (curSub->m_type == YAML_SEQUENCE_NODE)
|
||||
curSub->m_seqChildren.emplace_back(newNode);
|
||||
m_subStack.push_back(newNode);
|
||||
return RecordRAII{this};
|
||||
}
|
||||
|
||||
void YAMLDocWriter::leaveSubRecord()
|
||||
void YAMLDocWriter::_leaveSubRecord()
|
||||
{
|
||||
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();
|
||||
if (curSub->m_type != YAML_MAPPING_NODE &&
|
||||
curSub->m_type != YAML_SEQUENCE_NODE)
|
||||
return;
|
||||
return {};
|
||||
YAMLNode* newNode = new YAMLNode(YAML_SEQUENCE_NODE);
|
||||
if (curSub->m_type == YAML_MAPPING_NODE)
|
||||
curSub->m_mapChildren.emplace_back(name?std::string(name):std::string(), std::unique_ptr<YAMLNode>(newNode));
|
||||
else if (curSub->m_type == YAML_SEQUENCE_NODE)
|
||||
curSub->m_seqChildren.emplace_back(newNode);
|
||||
m_subStack.push_back(newNode);
|
||||
return VectorRAII{this};
|
||||
}
|
||||
|
||||
void YAMLDocWriter::leaveSubVector()
|
||||
void YAMLDocWriter::_leaveSubVector()
|
||||
{
|
||||
if (m_subStack.size() > 1)
|
||||
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();
|
||||
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());
|
||||
if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE)
|
||||
m_seqTrackerStack.push_back(0);
|
||||
return true;
|
||||
return RecordRAII{this};
|
||||
}
|
||||
else if (!name)
|
||||
{
|
||||
atError("Expected YAML sequence");
|
||||
}
|
||||
for (const auto& item : curSub->m_mapChildren)
|
||||
{
|
||||
|
@ -1034,13 +1040,13 @@ bool YAMLDocReader::enterSubRecord(const char* name)
|
|||
m_subStack.push_back(item.second.get());
|
||||
if (m_subStack.back()->m_type == YAML_SEQUENCE_NODE)
|
||||
m_seqTrackerStack.push_back(0);
|
||||
return true;
|
||||
return RecordRAII{this};
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
void YAMLDocReader::leaveSubRecord()
|
||||
void YAMLDocReader::_leaveSubRecord()
|
||||
{
|
||||
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();
|
||||
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_seqTrackerStack.push_back(0);
|
||||
countOut = curSub->m_seqChildren.size();
|
||||
return true;
|
||||
return VectorRAII{this};
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1078,15 +1084,15 @@ bool YAMLDocReader::enterSubVector(const char* name, size_t& countOut)
|
|||
}
|
||||
m_subStack.push_back(nextSub);
|
||||
m_seqTrackerStack.push_back(0);
|
||||
return true;
|
||||
return VectorRAII{this};
|
||||
}
|
||||
}
|
||||
}
|
||||
countOut = 0;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
void YAMLDocReader::leaveSubVector()
|
||||
void YAMLDocReader::_leaveSubVector()
|
||||
{
|
||||
if (m_subStack.size() > 1)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue