Branch data Line data Source code
1 : : /********************************************************************
2 : : * sixtp-dom-generators.c *
3 : : * Copyright 2001 Gnumatic, Inc. *
4 : : * *
5 : : * This program is free software; you can redistribute it and/or *
6 : : * modify it under the terms of the GNU General Public License as *
7 : : * published by the Free Software Foundation; either version 2 of *
8 : : * the License, or (at your option) any later version. *
9 : : * *
10 : : * This program is distributed in the hope that it will be useful, *
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 : : * GNU General Public License for more details. *
14 : : * *
15 : : * You should have received a copy of the GNU General Public License*
16 : : * along with this program; if not, contact: *
17 : : * *
18 : : * Free Software Foundation Voice: +1-617-542-5942 *
19 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
20 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
21 : : * *
22 : : ********************************************************************/
23 : : #include <glib.h>
24 : : #include <config.h>
25 : :
26 : : #include <gnc-date.h>
27 : : #include <cstdint>
28 : :
29 : : #include "gnc-xml-helper.h"
30 : : #include "sixtp-dom-generators.h"
31 : : #include "sixtp-utils.h"
32 : :
33 : : #include <kvp-frame.hpp>
34 : : #include <gnc-datetime.hpp>
35 : :
36 : : static QofLogModule log_module = GNC_MOD_IO;
37 : :
38 : : xmlNodePtr
39 : 0 : boolean_to_dom_tree (const char* tag, gboolean val)
40 : : {
41 : 0 : return text_to_dom_tree (tag, val ? "TRUE" : "FALSE");
42 : : }
43 : :
44 : : xmlNodePtr
45 : 2041 : text_to_dom_tree (const char* tag, const char* str)
46 : : {
47 : 2041 : g_return_val_if_fail (tag, NULL);
48 : 2041 : g_return_val_if_fail (str, NULL);
49 : :
50 : 2041 : xmlNodePtr result = xmlNewNode (NULL, BAD_CAST tag);
51 : 2041 : g_return_val_if_fail (result, NULL);
52 : :
53 : 2041 : gchar* newstr = g_strdup (str);
54 : 2041 : xmlNodeAddContent (result, checked_char_cast (newstr));
55 : 2041 : g_free (newstr);
56 : :
57 : 2041 : return result;
58 : : }
59 : :
60 : : xmlNodePtr
61 : 293 : int_to_dom_tree (const char* tag, gint64 val)
62 : : {
63 : : gchar* text;
64 : : xmlNodePtr result;
65 : :
66 : 293 : text = g_strdup_printf ("%" G_GINT64_FORMAT, val);
67 : 293 : g_return_val_if_fail (text, NULL);
68 : 293 : result = text_to_dom_tree (tag, text);
69 : 293 : g_free (text);
70 : 293 : return result;
71 : : }
72 : :
73 : : xmlNodePtr
74 : 2 : guint_to_dom_tree (const char* tag, guint an_int)
75 : : {
76 : : gchar* text;
77 : : xmlNodePtr result;
78 : :
79 : 2 : text = g_strdup_printf ("%u", an_int);
80 : 2 : g_return_val_if_fail (text, NULL);
81 : 2 : result = text_to_dom_tree (tag, text);
82 : 2 : g_free (text);
83 : 2 : return result;
84 : : }
85 : :
86 : :
87 : : xmlNodePtr
88 : 1258 : guid_to_dom_tree (const char* tag, const GncGUID* gid)
89 : : {
90 : : char guid_str[GUID_ENCODING_LENGTH + 1];
91 : : xmlNodePtr ret;
92 : :
93 : 1258 : ret = xmlNewNode (NULL, BAD_CAST tag);
94 : :
95 : 1258 : xmlSetProp (ret, BAD_CAST "type", BAD_CAST "guid");
96 : :
97 : 1258 : if (!guid_to_string_buff (gid, guid_str))
98 : : {
99 : 0 : PERR ("guid_to_string_buff failed\n");
100 : 0 : return NULL;
101 : : }
102 : :
103 : 1258 : xmlNodeAddContent (ret, BAD_CAST guid_str);
104 : :
105 : 1258 : return ret;
106 : : }
107 : :
108 : : xmlNodePtr
109 : 1169 : commodity_ref_to_dom_tree (const char* tag, const gnc_commodity* c)
110 : : {
111 : : xmlNodePtr ret;
112 : : gchar* name_space, *mnemonic;
113 : :
114 : 1169 : g_return_val_if_fail (c, NULL);
115 : :
116 : 1169 : ret = xmlNewNode (NULL, BAD_CAST tag);
117 : :
118 : 1169 : if (!gnc_commodity_get_namespace (c) || !gnc_commodity_get_mnemonic (c))
119 : : {
120 : 0 : return NULL;
121 : : }
122 : 1169 : name_space = g_strdup (gnc_commodity_get_namespace (c));
123 : 1169 : mnemonic = g_strdup (gnc_commodity_get_mnemonic (c));
124 : 1169 : xmlNewTextChild (ret, NULL, BAD_CAST "cmdty:space",
125 : 1169 : checked_char_cast (name_space));
126 : 1169 : xmlNewTextChild (ret, NULL, BAD_CAST "cmdty:id",
127 : 1169 : checked_char_cast (mnemonic));
128 : 1169 : g_free (name_space);
129 : 1169 : g_free (mnemonic);
130 : 1169 : return ret;
131 : : }
132 : :
133 : : xmlNodePtr
134 : 664 : time64_to_dom_tree (const char* tag, const time64 time)
135 : : {
136 : : xmlNodePtr ret;
137 : 664 : g_return_val_if_fail (time != INT64_MAX, NULL);
138 : 664 : auto date_str = GncDateTime(time).format_iso8601();
139 : 664 : if (date_str.empty())
140 : 0 : return NULL;
141 : 664 : date_str += " +0000"; //Tack on a UTC offset to mollify GnuCash for Android
142 : 664 : ret = xmlNewNode (NULL, BAD_CAST tag);
143 : 664 : xmlNewTextChild (ret, NULL, BAD_CAST "ts:date",
144 : 664 : checked_char_cast (const_cast<char*>(date_str.c_str())));
145 : 664 : return ret;
146 : 664 : }
147 : :
148 : : xmlNodePtr
149 : 8 : gdate_to_dom_tree (const char* tag, const GDate* date)
150 : : {
151 : : xmlNodePtr ret;
152 : 8 : gchar* date_str = NULL;
153 : :
154 : 8 : g_return_val_if_fail (date, NULL);
155 : 8 : date_str = g_new (gchar, 512);
156 : :
157 : 8 : g_date_strftime (date_str, 512, "%Y-%m-%d", date);
158 : :
159 : 8 : ret = xmlNewNode (NULL, BAD_CAST tag);
160 : :
161 : 8 : xmlNewTextChild (ret, NULL, BAD_CAST "gdate", checked_char_cast (date_str));
162 : :
163 : 8 : g_free (date_str);
164 : :
165 : 8 : return ret;
166 : : }
167 : :
168 : : xmlNodePtr
169 : 675 : gnc_numeric_to_dom_tree (const char* tag, const gnc_numeric* num)
170 : : {
171 : : xmlNodePtr ret;
172 : : gchar* numstr;
173 : :
174 : 675 : g_return_val_if_fail (num, NULL);
175 : :
176 : 675 : numstr = gnc_numeric_to_string (*num);
177 : 675 : g_return_val_if_fail (numstr, NULL);
178 : :
179 : 675 : ret = xmlNewNode (NULL, BAD_CAST tag);
180 : :
181 : 675 : xmlNodeAddContent (ret, checked_char_cast (numstr));
182 : :
183 : 675 : g_free (numstr);
184 : :
185 : 675 : return ret;
186 : : }
187 : :
188 : : gchar*
189 : 0 : double_to_string (double value)
190 : : {
191 : : gchar* numstr;
192 : 0 : numstr = g_strdup_printf ("%24.18g", value);
193 : :
194 : 0 : if (!numstr)
195 : : {
196 : 0 : return NULL;
197 : :
198 : : }
199 : : else
200 : : {
201 : 0 : return g_strstrip (numstr);
202 : : }
203 : : }
204 : :
205 : : static void
206 : 1749 : add_text_to_node (xmlNodePtr node, const gchar* type, gchar* val)
207 : : {
208 : 1749 : xmlSetProp (node, BAD_CAST "type", BAD_CAST type);
209 : 1749 : xmlNodeSetContent (node, checked_char_cast (val));
210 : 1749 : }
211 : :
212 : : static void add_kvp_slot (const char* key, KvpValue* value, void* data);
213 : :
214 : : static void
215 : 2744 : add_kvp_value_node (xmlNodePtr node, const gchar* tag, KvpValue* val)
216 : : {
217 : : xmlNodePtr val_node;
218 : :
219 : 2744 : switch (val->get_type ())
220 : : {
221 : 482 : case KvpValue::Type::STRING:
222 : : {
223 : 482 : auto newstr = g_strdup (val->get<const char*> ());
224 : 964 : val_node = xmlNewTextChild (node, NULL, BAD_CAST tag,
225 : 482 : checked_char_cast (newstr));
226 : 482 : g_free (newstr);
227 : 482 : break;
228 : : }
229 : 2 : case KvpValue::Type::TIME64:
230 : 2 : val_node = NULL;
231 : 2 : break;
232 : 2 : case KvpValue::Type::GDATE:
233 : : {
234 : 2 : auto d = val->get<GDate> ();
235 : 2 : val_node = gdate_to_dom_tree (tag, &d);
236 : 2 : xmlAddChild (node, val_node);
237 : 2 : break;
238 : : }
239 : 2258 : default:
240 : 2258 : val_node = xmlNewTextChild (node, NULL, BAD_CAST tag, NULL);
241 : 2258 : break;
242 : : }
243 : :
244 : 2744 : switch (val->get_type ())
245 : : {
246 : 862 : case KvpValue::Type::INT64:
247 : : {
248 : 862 : char *int_str = g_strdup_printf ("%" G_GINT64_FORMAT, val->get<int64_t> ());
249 : 862 : add_text_to_node (val_node, "integer", int_str);
250 : 862 : g_free (int_str);
251 : 862 : break;
252 : : }
253 : 0 : case KvpValue::Type::DOUBLE:
254 : : {
255 : 0 : char *dbl_str = double_to_string (val->get<double> ());
256 : 0 : add_text_to_node (val_node, "double", dbl_str);
257 : 0 : g_free (dbl_str);
258 : 0 : break;
259 : : }
260 : 446 : case KvpValue::Type::NUMERIC:
261 : : {
262 : 446 : char *num_str = gnc_numeric_to_string (val->get<gnc_numeric> ());
263 : 446 : add_text_to_node (val_node, "numeric", num_str);
264 : 446 : g_free (num_str);
265 : 446 : break;
266 : : }
267 : 482 : case KvpValue::Type::STRING:
268 : 482 : xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "string");
269 : 482 : break;
270 : 441 : case KvpValue::Type::GUID:
271 : : {
272 : : gchar guidstr[GUID_ENCODING_LENGTH + 1];
273 : 441 : guid_to_string_buff (val->get<GncGUID*> (), guidstr);
274 : 441 : add_text_to_node (val_node, "guid", guidstr);
275 : 441 : break;
276 : : }
277 : : /* Note: The type attribute must remain 'timespec' to maintain
278 : : * compatibility.
279 : : */
280 : 2 : case KvpValue::Type::TIME64:
281 : : {
282 : 2 : auto t = val->get<Time64> ();
283 : 2 : val_node = time64_to_dom_tree (tag, t.t);
284 : 2 : xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "timespec");
285 : 2 : xmlAddChild (node, val_node);
286 : 2 : break;
287 : : }
288 : 2 : case KvpValue::Type::GDATE:
289 : 2 : xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "gdate");
290 : 2 : break;
291 : 254 : case KvpValue::Type::GLIST:
292 : 254 : xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "list");
293 : 1014 : for (auto cursor = val->get<GList*> (); cursor; cursor = cursor->next)
294 : : {
295 : 760 : auto val = static_cast<KvpValue*> (cursor->data);
296 : 760 : add_kvp_value_node (val_node, "slot:value", val);
297 : : }
298 : 254 : break;
299 : 255 : case KvpValue::Type::FRAME:
300 : : {
301 : 255 : xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "frame");
302 : :
303 : 255 : auto frame = val->get<KvpFrame*> ();
304 : 255 : if (!frame)
305 : 0 : break;
306 : 255 : frame->for_each_slot_temp (&add_kvp_slot, val_node);
307 : 255 : break;
308 : : }
309 : 0 : default:
310 : 0 : break;
311 : : }
312 : 2744 : }
313 : :
314 : : static void
315 : 1984 : add_kvp_slot (const char* key, KvpValue* value, void* data)
316 : : {
317 : 1984 : auto newkey = g_strdup ((gchar*)key);
318 : 1984 : auto node = static_cast<xmlNodePtr> (data);
319 : 1984 : auto slot_node = xmlNewChild (node, NULL, BAD_CAST "slot", NULL);
320 : :
321 : 1984 : xmlNewTextChild (slot_node, NULL, BAD_CAST "slot:key",
322 : 1984 : checked_char_cast (newkey));
323 : 1984 : g_free (newkey);
324 : 1984 : add_kvp_value_node (slot_node, "slot:value", value);
325 : 1984 : }
326 : :
327 : : xmlNodePtr
328 : 1395 : qof_instance_slots_to_dom_tree (const char* tag, const QofInstance* inst)
329 : : {
330 : : xmlNodePtr ret;
331 : 1395 : KvpFrame* frame = qof_instance_get_slots (inst);
332 : 1395 : if (!frame || frame->empty())
333 : 1160 : return nullptr;
334 : :
335 : 235 : ret = xmlNewNode (nullptr, BAD_CAST tag);
336 : 235 : frame->for_each_slot_temp (&add_kvp_slot, ret);
337 : 235 : return ret;
338 : : }
|