xref: /aosp_15_r20/external/dynamic_depth/internal/xmpmeta/xml/search.cc (revision a62be0856e8e1158f43b03e41bbad10f4d005fde)
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