OpenCPN Partial API docs
catalog_parser.cpp
1 /******************************************************************************
2  *
3  * Project: OpenCPN
4  *
5  ***************************************************************************
6  * Copyright (C) 2019 Alec Leamas *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the *
20  * Free Software Foundation, Inc., *
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22  ***************************************************************************
23  */
24 
25 #include <sstream>
26 
27 #include <wx/log.h>
28 
29 #if defined(__MINGW32__) && defined(Yield)
30 #undef Yield // from win.h, conflicts with mingw headers
31 #endif
32 
33 #include "model/catalog_parser.h"
34 #include "model/ocpn_utils.h"
35 #include "model/catalog_handler.h"
36 #include "pugixml.hpp"
37 
38 static void add_node(pugi::xml_node root, const std::string& name,
39  const std::string& value) {
40  auto child = root.append_child(name.c_str());
41  child.append_child(pugi::node_pcdata).set_value(value.c_str());
42 }
43 
44 
46  pugi::xml_document doc;
47  auto root = doc.append_child("plugin");
48  root.append_attribute("version").set_value("1");
49 
50  add_node(root, "name", name);
51  add_node(root, "version", version);
52  add_node(root, "release", release);
53  add_node(root, "summary", summary);
54  add_node(root, "api-version", api_version);
55  add_node(root, "open-source", openSource ? "true" : "false");
56  add_node(root, "is-imported", is_imported ? "true" : "false");
57  add_node(root, "author", author);
58  add_node(root, "source", author);
59  add_node(root, "info-url", info_url);
60  add_node(root, "description", description);
61  add_node(root, "target", target);
62  add_node(root, "target-version", target_version);
63  add_node(root, "target-arch", target_arch);
64  add_node(root, "tarball-url", tarball_url);
65  add_node(root, "tarball-checksum", checksum);
66 
67  std::ostringstream ss;
68  doc.save(ss, " ");
69  return ss.str();
70 }
71 
72 static void ParseValue(pugi::xml_node node, const std::string& name,
73  std::string& value) {
74  auto child = node.child(name.c_str());
75  if (child) value = ocpn::trim(child.first_child().value());
76 }
77 
78 static void ParseBool(pugi::xml_node node, const std::string& name,
79  bool& value) {
80  auto child = node.child(name.c_str());
81  if (child) {
82  auto text = ocpn::trim(child.first_child().value());
83  value = text == "yes" || text == "true";
84  }
85 }
86 
87 bool ParsePlugin(pugi::xml_node root, PluginMetadata& plugin) {
88  ParseValue(root, "name", plugin.name);
89  ParseValue(root, "version", plugin.version);
90  ParseValue(root, "release", plugin.release);
91  ParseValue(root, "summary", plugin.summary);
92  ParseValue(root, "api-version", plugin.api_version);
93  ParseValue(root, "author", plugin.author);
94  ParseValue(root, "description", plugin.description);
95  ParseValue(root, "source", plugin.source);
96  ParseValue(root, "tarball-url", plugin.tarball_url);
97  ParseValue(root, "info-url", plugin.info_url);
98  ParseValue(root, "target", plugin.target);
99  ParseValue(root, "target-version", plugin.target_version);
100  ParseValue(root, "target-arch", plugin.target_arch);
101  ParseValue(root, "target-checksum", plugin.checksum);
102  ParseBool(root, "open-source", plugin.openSource);
103  ParseBool(root, "is-imported", plugin.is_imported);
104  return root.child("name") ? true : false;
105 }
106 
107 
108 bool ParsePlugin(const std::string& xml, PluginMetadata& plugin) {
109  pugi::xml_document doc;
110  doc.load_string(xml.c_str());
111  auto node = doc.child("plugin");
112  if (!node) {
113  wxLogWarning("Trying to parse plugin without root node");
114  return false;
115  }
116  return ParsePlugin(doc.child("plugin"), plugin);
117 }
118 
119 
120 bool ParseCatalog(const std::string xml, CatalogCtx* ctx) {
121  bool ok = true;
122  PluginMetadata* plugin = 0;
123 
124  pugi::xml_document doc;
125  doc.load_string(xml.c_str());
126 
127  pugi::xml_node nodes = doc.child("plugins");
128  for (pugi::xml_node node = nodes.first_child(); node;
129  node = node.next_sibling()) {
130  if (!strcmp(node.name(), "version") && ctx->version == "") {
131  ctx->version = ocpn::trim(node.first_child().value());
132  } else if (strcmp(node.name(), "date") == 0 && ctx->date == "") {
133  ctx->date = ocpn::trim(node.first_child().value());
134  } else if (strcmp(node.name(), "meta-url") == 0) {
135  ctx->meta_url = ocpn::trim(node.first_child().value());
136  } else if (!strcmp(node.name(), "plugin")) {
137  if (ctx->meta_url != "") {
138  ctx->meta_urls.push_back(ctx->meta_url);
139  ctx->meta_url = "";
140  } else {
141  if (plugin) {
142  ctx->plugins.push_back(*plugin);
143  delete plugin;
144  }
145  plugin = new PluginMetadata;
146  }
147  auto meta_url = node.child("meta-url");
148  if (meta_url) {
149  auto url = ocpn::trim(meta_url.first_child().value());
150  ctx->meta_url = url;
151  }
152  ParsePlugin(node, *plugin);
153  }
154  }
155  // capture last plugin
156  if (plugin) {
157  ctx->plugins.push_back(*plugin);
158  delete plugin;
159  } else {
160  if (ctx->meta_url != "") {
161  ctx->meta_urls.push_back(ctx->meta_url);
162  ctx->meta_url = "";
163  }
164  }
165  return true;
166 }
The result from parsing the xml catalog i.
Plugin metadata, reflects the xml format directly.
std::string to_string()
Return printable XML representation.