summaryrefslogtreecommitdiff
path: root/chromeos-dbus-bindings/xml_interface_parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromeos-dbus-bindings/xml_interface_parser.cc')
-rw-r--r--chromeos-dbus-bindings/xml_interface_parser.cc123
1 files changed, 70 insertions, 53 deletions
diff --git a/chromeos-dbus-bindings/xml_interface_parser.cc b/chromeos-dbus-bindings/xml_interface_parser.cc
index dd30d43..2146ebd 100644
--- a/chromeos-dbus-bindings/xml_interface_parser.cc
+++ b/chromeos-dbus-bindings/xml_interface_parser.cc
@@ -9,7 +9,8 @@
#include <base/file_util.h>
#include <base/files/file_path.h>
#include <base/logging.h>
-#include <base/stl_util.h>
+#include <base/strings/string_util.h>
+#include <chromeos/strings/string_utils.h>
using std::string;
using std::vector;
@@ -47,13 +48,15 @@ const char XmlInterfaceParser::kMethodKindNormal[] = "normal";
const char XmlInterfaceParser::kMethodKindAsync[] = "async";
const char XmlInterfaceParser::kMethodKindRaw[] = "raw";
-bool XmlInterfaceParser::ParseXmlInterfaceFile(
- const base::FilePath& interface_file) {
- string contents;
- if (!base::ReadFileToString(interface_file, &contents)) {
- LOG(ERROR) << "Failed to read file " << interface_file.value();
- return false;
- }
+namespace {
+
+string GetElementPath(const vector<string>& path) {
+ return chromeos::string_utils::Join('/', path);
+}
+
+} // anonymous namespace
+
+bool XmlInterfaceParser::ParseXmlInterfaceFile(const std::string& contents) {
auto parser = XML_ParserCreate(nullptr);
XML_SetUserData(parser, this);
XML_SetElementHandler(parser,
@@ -87,28 +90,41 @@ void XmlInterfaceParser::OnOpenElement(
if (element_name == kNodeTag) {
CHECK(prev_element.empty() || prev_element == kNodeTag)
<< "Unexpected tag " << element_name << " inside " << prev_element;
+ // 'name' attribute is optional for <node> element.
+ string name;
+ GetElementAttribute(attributes, element_path_, kNameAttribute, &name);
+ // Treat object path of "/" as empty/unspecified, since that happens a lot
+ // in existing XML files. People don't know that 'name' can be omitted, so
+ // they use "/" to denote some fictional D-Bus path for the object.
+ base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name);
+ if (name == "/")
+ name.clear();
+ node_names_.push_back(name);
} else if (element_name == kInterfaceTag) {
CHECK_EQ(kNodeTag, prev_element)
<< "Unexpected tag " << element_name << " inside " << prev_element;
- string interface_name = GetValidatedElementName(attributes, kInterfaceTag);
- interfaces_.emplace_back(interface_name,
- std::vector<Interface::Method>{},
- std::vector<Interface::Signal>{},
- std::vector<Interface::Property>{});
+ string interface_name = GetValidatedElementName(attributes, element_path_);
+ Interface itf(interface_name,
+ std::vector<Interface::Method>{},
+ std::vector<Interface::Signal>{},
+ std::vector<Interface::Property>{});
+ itf.path = node_names_.back();
+ interfaces_.push_back(std::move(itf));
} else if (element_name == kMethodTag) {
CHECK_EQ(kInterfaceTag, prev_element)
<< "Unexpected tag " << element_name << " inside " << prev_element;
interfaces_.back().methods.push_back(
- Interface::Method(GetValidatedElementName(attributes, kMethodTag)));
+ Interface::Method(GetValidatedElementName(attributes, element_path_)));
} else if (element_name == kSignalTag) {
CHECK_EQ(kInterfaceTag, prev_element)
<< "Unexpected tag " << element_name << " inside " << prev_element;
interfaces_.back().signals.push_back(
- Interface::Signal(GetValidatedElementName(attributes, kSignalTag)));
+ Interface::Signal(GetValidatedElementName(attributes, element_path_)));
} else if (element_name == kPropertyTag) {
CHECK_EQ(kInterfaceTag, prev_element)
<< "Unexpected tag " << element_name << " inside " << prev_element;
- interfaces_.back().properties.push_back(ParseProperty(attributes));
+ interfaces_.back().properties.push_back(ParseProperty(attributes,
+ element_path_));
} else if (element_name == kArgumentTag) {
if (prev_element == kMethodTag) {
AddMethodArgument(attributes);
@@ -119,12 +135,11 @@ void XmlInterfaceParser::OnOpenElement(
<< " inside " << prev_element;
}
} else if (element_name == kAnnotationTag) {
- string element_path = prev_element + " " + element_name;
- string name = GetValidatedElementAttribute(attributes, element_path,
+ string name = GetValidatedElementAttribute(attributes, element_path_,
kNameAttribute);
// Value is optional. Default to empty string if omitted.
string value;
- GetElementAttribute(attributes, element_path, kValueAttribute, &value);
+ GetElementAttribute(attributes, element_path_, kValueAttribute, &value);
if (prev_element == kInterfaceTag) {
// Parse interface annotations...
} else if (prev_element == kMethodTag) {
@@ -172,13 +187,13 @@ void XmlInterfaceParser::OnCharData(const std::string& content) {
string* doc_string_ptr = nullptr;
string target_element = element_path_[element_path_.size() - 2];
if (target_element == kInterfaceTag) {
- doc_string_ptr = &(interfaces_.back().doc_string_);
+ doc_string_ptr = &(interfaces_.back().doc_string);
} else if (target_element == kMethodTag) {
- doc_string_ptr = &(interfaces_.back().methods.back().doc_string_);
+ doc_string_ptr = &(interfaces_.back().methods.back().doc_string);
} else if (target_element == kSignalTag) {
- doc_string_ptr = &(interfaces_.back().signals.back().doc_string_);
+ doc_string_ptr = &(interfaces_.back().signals.back().doc_string);
} else if (target_element == kPropertyTag) {
- doc_string_ptr = &(interfaces_.back().properties.back().doc_string_);
+ doc_string_ptr = &(interfaces_.back().properties.back().doc_string);
}
// If <tp:docstring> is attached to elements we don't care about, do nothing.
@@ -191,11 +206,10 @@ void XmlInterfaceParser::OnCharData(const std::string& content) {
void XmlInterfaceParser::AddMethodArgument(const XmlAttributeMap& attributes) {
string argument_direction;
+ vector<string> path = element_path_;
+ path.push_back(kArgumentTag);
bool is_direction_paramter_present = GetElementAttribute(
- attributes,
- string(kMethodTag) + " " + kArgumentTag,
- kDirectionAttribute,
- &argument_direction);
+ attributes, path, kDirectionAttribute, &argument_direction);
vector<Interface::Argument>* argument_list = nullptr;
if (!is_direction_paramter_present ||
argument_direction == kArgumentDirectionIn) {
@@ -205,12 +219,12 @@ void XmlInterfaceParser::AddMethodArgument(const XmlAttributeMap& attributes) {
} else {
LOG(FATAL) << "Unknown method argument direction " << argument_direction;
}
- argument_list->push_back(ParseArgument(attributes, kMethodTag));
+ argument_list->push_back(ParseArgument(attributes, element_path_));
}
void XmlInterfaceParser::AddSignalArgument(const XmlAttributeMap& attributes) {
interfaces_.back().signals.back().arguments.push_back(
- ParseArgument(attributes, kSignalTag));
+ ParseArgument(attributes, element_path_));
}
void XmlInterfaceParser::OnCloseElement(const string& element_name) {
@@ -218,19 +232,23 @@ void XmlInterfaceParser::OnCloseElement(const string& element_name) {
CHECK(!element_path_.empty());
CHECK_EQ(element_path_.back(), element_name);
element_path_.pop_back();
+ if (element_name == kNodeTag) {
+ CHECK(!node_names_.empty());
+ node_names_.pop_back();
+ }
}
// static
bool XmlInterfaceParser::GetElementAttribute(
const XmlAttributeMap& attributes,
- const string& element_type,
+ const vector<string>& element_path,
const string& element_key,
string* element_value) {
- if (!ContainsKey(attributes, element_key)) {
+ if (attributes.find(element_key) == attributes.end()) {
return false;
}
*element_value = attributes.find(element_key)->second;
- VLOG(1) << "Got " << element_type << " element with "
+ VLOG(1) << "Got " << GetElementPath(element_path) << " element with "
<< element_key << " = " << *element_value;
return true;
}
@@ -238,52 +256,51 @@ bool XmlInterfaceParser::GetElementAttribute(
// static
string XmlInterfaceParser::GetValidatedElementAttribute(
const XmlAttributeMap& attributes,
- const string& element_type,
+ const vector<string>& element_path,
const string& element_key) {
string element_value;
CHECK(GetElementAttribute(attributes,
- element_type,
+ element_path,
element_key,
&element_value))
- << element_type << " does not contain a " << element_key << " attribute";
- CHECK(!element_value.empty()) << element_type << " " << element_key
- << " attribute is empty";
+ << GetElementPath(element_path) << " does not contain a " << element_key
+ << " attribute";
+ CHECK(!element_value.empty()) << GetElementPath(element_path) << " "
+ << element_key << " attribute is empty";
return element_value;
}
// static
string XmlInterfaceParser::GetValidatedElementName(
const XmlAttributeMap& attributes,
- const string& element_type) {
- return GetValidatedElementAttribute(attributes, element_type, kNameAttribute);
+ const vector<string>& element_path) {
+ return GetValidatedElementAttribute(attributes, element_path, kNameAttribute);
}
// static
Interface::Argument XmlInterfaceParser::ParseArgument(
- const XmlAttributeMap& attributes, const string& element_type) {
- string element_and_argument = element_type + " " + kArgumentTag;
+ const XmlAttributeMap& attributes, const vector<string>& element_path) {
+ vector<string> path = element_path;
+ path.push_back(kArgumentTag);
string argument_name;
// Since the "name" field is optional, use the un-validated variant.
- GetElementAttribute(attributes,
- element_and_argument,
- kNameAttribute,
- &argument_name);
+ GetElementAttribute(attributes, path, kNameAttribute, &argument_name);
string argument_type = GetValidatedElementAttribute(
- attributes, element_and_argument, kTypeAttribute);
+ attributes, path, kTypeAttribute);
return Interface::Argument(argument_name, argument_type);
}
// static
Interface::Property XmlInterfaceParser::ParseProperty(
- const XmlAttributeMap& attributes) {
- string property_name = GetValidatedElementName(attributes,
- kPropertyTag);
- string property_type = GetValidatedElementAttribute(attributes,
- kPropertyTag,
+ const XmlAttributeMap& attributes,
+ const std::vector<std::string>& element_path) {
+ vector<string> path = element_path;
+ path.push_back(kPropertyTag);
+ string property_name = GetValidatedElementName(attributes, path);
+ string property_type = GetValidatedElementAttribute(attributes, path,
kTypeAttribute);
- string property_access = GetValidatedElementAttribute(attributes,
- kPropertyTag,
+ string property_access = GetValidatedElementAttribute(attributes, path,
kAccessAttribute);
return Interface::Property(property_name, property_type, property_access);
}