12double parseProbability(
const std::string &text,
const std::string &node_name) {
14 std::size_t consumed = 0;
15 double value = std::stod(text, &consumed);
16 while (consumed < text.size() &&
17 std::isspace(
static_cast<unsigned char>(text[consumed])) != 0) {
20 if (consumed != text.size()) {
21 throw FaultTreeError(
"basic event '" + node_name +
22 "' has a malformed failureProbability '" + text +
"'");
25 }
catch (
const std::invalid_argument &) {
26 throw FaultTreeError(
"basic event '" + node_name +
27 "' has a malformed failureProbability '" + text +
"'");
28 }
catch (
const std::out_of_range &) {
29 throw FaultTreeError(
"basic event '" + node_name +
30 "' has an out-of-range failureProbability '" + text +
"'");
34int parseK(
const std::string &text,
const std::string &node_name) {
35 if (text.empty()) {
return 0; }
37 std::size_t consumed = 0;
38 int value = std::stoi(text, &consumed);
39 if (consumed != text.size()) {
40 throw FaultTreeError(
"K/N gate '" + node_name +
"' has a malformed k '" +
44 }
catch (
const std::invalid_argument &) {
45 throw FaultTreeError(
"K/N gate '" + node_name +
"' has a malformed k '" +
47 }
catch (
const std::out_of_range &) {
48 throw FaultTreeError(
"K/N gate '" + node_name +
"' has an out-of-range k '" +
55std::string parseNode(
const xml::Element &element, FaultTree &tree) {
56 if (element.attribute(
"id") ==
nullptr) {
return {}; }
58 const xml::Element *info = element.child(
"node");
59 if (info ==
nullptr) {
60 throw FaultTreeError(
"an ftaNode is missing its <node> definition");
62 const std::string *name_attr = info->attribute(
"name");
63 if (name_attr ==
nullptr || name_attr->empty()) {
64 throw FaultTreeError(
"an ftaNode is missing its node name");
66 const std::string name = *name_attr;
70 if (tree.hasNode(name)) {
return name; }
72 const std::string type = element.attributeOr(
"type",
"");
76 if (type ==
"2" || type ==
"3") {
77 if (element.child(
"linkedBBN") !=
nullptr) {
78 throw FaultTreeError(
"basic event '" + name +
79 "' is linked to a BBN variable, which this "
80 "quantifier does not support");
84 parseProbability(element.attributeOr(
"failureProbability",
"0"), name);
85 }
else if (type ==
"4") {
86 const xml::Element *link = element.child(
"transferUpFTADiagram");
87 if (link ==
nullptr) {
88 throw FaultTreeError(
"transfer gate '" + name +
89 "' has no transferUpFTADiagram reference");
91 const std::string ref = link->attributeOr(
"ref",
"");
93 throw FaultTreeError(
"transfer gate '" + name +
"' has an empty reference");
98 node.children.push_back(ref);
99 }
else if (type ==
"5") {
105 }
else if (type ==
"0" || type ==
"1" || type ==
"6" || type ==
"7") {
108 }
else if (type ==
"1") {
110 }
else if (type ==
"6") {
115 node.k = parseK(element.attributeOr(
"k",
""), name);
117 for (
const auto &child : element.children) {
118 if (child.name !=
"ftaNode") {
continue; }
119 std::string child_name = parseNode(child, tree);
120 if (!child_name.empty()) { node.children.push_back(child_name); }
125 throw FaultTreeError(
"node '" + name +
"' has unsupported type '" + type +
"'");
128 tree.addNode(std::move(node));
134FaultTree buildFromRoot(
const xml::Element &root,
const std::string &origin) {
135 if (root.name !=
"ftaDiagram") {
136 throw FaultTreeError(
"expected a <ftaDiagram> root in " + origin +
137 ", found <" + root.name +
">");
142 for (
const auto &child : root.children) {
143 if (child.name !=
"ftaNode") {
continue; }
144 std::string name = parseNode(child, tree);
147 if (!name.empty() && top.empty()) { top = name; }
149 if (top.empty()) {
throw FaultTreeError(origin +
" has no top node"); }
159 return buildFromRoot(
xml::parse(text),
"the fault tree diagram");
A fault tree: nodes keyed by name, plus a designated top event.
Reader that turns a GeNIe/SMILE .fta fault tree document into a validated faulttree::FaultTree.
Element parseFile(const std::string &path)
Element parse(const std::string &text)
FaultTree parseFtaFile(const std::string &path)
Parses a .fta file from disk.
FaultTree parseFtaString(const std::string &text)
Parses .fta content held in memory.
@ Or
fails when any input fails (.fta type 1)
@ KofN
fails when at least k inputs fail (.fta type 6)
@ Basic
basic event, quantified by probability
@ Not
fails when its single input does not (.fta type 7)
@ And
fails when every input fails (.fta type 0)
Minimal XML reader used by the .fta parser: the Element tree, its lookup helpers, and parse() / parse...