1*a62be085SSadaf Ebrahimi #include "xmpmeta/xml/search.h"
2*a62be085SSadaf Ebrahimi
3*a62be085SSadaf Ebrahimi #include <stack>
4*a62be085SSadaf Ebrahimi #include <string>
5*a62be085SSadaf Ebrahimi
6*a62be085SSadaf Ebrahimi #include "android-base/logging.h"
7*a62be085SSadaf Ebrahimi #include "xmpmeta/xml/utils.h"
8*a62be085SSadaf Ebrahimi
9*a62be085SSadaf Ebrahimi using ::dynamic_depth::xmpmeta::xml::FromXmlChar;
10*a62be085SSadaf Ebrahimi
11*a62be085SSadaf Ebrahimi namespace dynamic_depth {
12*a62be085SSadaf Ebrahimi namespace xmpmeta {
13*a62be085SSadaf Ebrahimi namespace xml {
14*a62be085SSadaf Ebrahimi
DepthFirstSearch(const xmlDocPtr parent,const char * name)15*a62be085SSadaf Ebrahimi xmlNodePtr DepthFirstSearch(const xmlDocPtr parent, const char* name) {
16*a62be085SSadaf Ebrahimi return DepthFirstSearch(parent, "", name);
17*a62be085SSadaf Ebrahimi }
18*a62be085SSadaf Ebrahimi
DepthFirstSearch(const xmlDocPtr parent,const char * prefix,const char * name)19*a62be085SSadaf Ebrahimi xmlNodePtr DepthFirstSearch(const xmlDocPtr parent, const char* prefix,
20*a62be085SSadaf Ebrahimi const char* name) {
21*a62be085SSadaf Ebrahimi if (parent == nullptr || parent->children == nullptr) {
22*a62be085SSadaf Ebrahimi LOG(ERROR) << "XML doc was null or has no XML nodes";
23*a62be085SSadaf Ebrahimi return nullptr;
24*a62be085SSadaf Ebrahimi }
25*a62be085SSadaf Ebrahimi xmlNodePtr result;
26*a62be085SSadaf Ebrahimi for (xmlNodePtr node = parent->children; node != nullptr; node = node->next) {
27*a62be085SSadaf Ebrahimi result = DepthFirstSearch(node, prefix, name);
28*a62be085SSadaf Ebrahimi if (result != nullptr) {
29*a62be085SSadaf Ebrahimi return result;
30*a62be085SSadaf Ebrahimi }
31*a62be085SSadaf Ebrahimi }
32*a62be085SSadaf Ebrahimi LOG(WARNING) << "No node matching " << prefix << ":" << name << " was found";
33*a62be085SSadaf Ebrahimi return nullptr;
34*a62be085SSadaf Ebrahimi }
35*a62be085SSadaf Ebrahimi
DepthFirstSearch(const xmlNodePtr parent,const char * name)36*a62be085SSadaf Ebrahimi xmlNodePtr DepthFirstSearch(const xmlNodePtr parent, const char* name) {
37*a62be085SSadaf Ebrahimi return DepthFirstSearch(parent, "", name);
38*a62be085SSadaf Ebrahimi }
39*a62be085SSadaf Ebrahimi
DepthFirstSearch(const xmlNodePtr parent,const char * prefix,const char * name)40*a62be085SSadaf Ebrahimi xmlNodePtr DepthFirstSearch(const xmlNodePtr parent, const char* prefix,
41*a62be085SSadaf Ebrahimi const char* name) {
42*a62be085SSadaf Ebrahimi if (parent == nullptr) {
43*a62be085SSadaf Ebrahimi LOG(ERROR) << "XML node was null";
44*a62be085SSadaf Ebrahimi return nullptr;
45*a62be085SSadaf Ebrahimi }
46*a62be085SSadaf Ebrahimi std::stack<xmlNodePtr> node_stack;
47*a62be085SSadaf Ebrahimi node_stack.push(parent);
48*a62be085SSadaf Ebrahimi while (!node_stack.empty()) {
49*a62be085SSadaf Ebrahimi const xmlNodePtr current_node = node_stack.top();
50*a62be085SSadaf Ebrahimi node_stack.pop();
51*a62be085SSadaf Ebrahimi if (strcmp(FromXmlChar(current_node->name), name) == 0) {
52*a62be085SSadaf Ebrahimi if (!prefix || strlen(prefix) == 0) {
53*a62be085SSadaf Ebrahimi return current_node;
54*a62be085SSadaf Ebrahimi }
55*a62be085SSadaf Ebrahimi if (current_node->ns && current_node->ns->prefix &&
56*a62be085SSadaf Ebrahimi strcmp(FromXmlChar(current_node->ns->prefix), prefix) == 0) {
57*a62be085SSadaf Ebrahimi return current_node;
58*a62be085SSadaf Ebrahimi }
59*a62be085SSadaf Ebrahimi }
60*a62be085SSadaf Ebrahimi std::stack<xmlNodePtr> stack_to_reverse;
61*a62be085SSadaf Ebrahimi for (xmlNodePtr child = current_node->children; child != nullptr;
62*a62be085SSadaf Ebrahimi child = child->next) {
63*a62be085SSadaf Ebrahimi stack_to_reverse.push(child);
64*a62be085SSadaf Ebrahimi }
65*a62be085SSadaf Ebrahimi while (!stack_to_reverse.empty()) {
66*a62be085SSadaf Ebrahimi node_stack.push(stack_to_reverse.top());
67*a62be085SSadaf Ebrahimi stack_to_reverse.pop();
68*a62be085SSadaf Ebrahimi }
69*a62be085SSadaf Ebrahimi }
70*a62be085SSadaf Ebrahimi return nullptr;
71*a62be085SSadaf Ebrahimi }
72*a62be085SSadaf Ebrahimi
73*a62be085SSadaf Ebrahimi } // namespace xml
74*a62be085SSadaf Ebrahimi } // namespace xmpmeta
75*a62be085SSadaf Ebrahimi } // namespace dynamic_depth
76