GnuCash  5.6-150-g038405b370+
sixtp-dom-generators.cpp
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 
25 #define __EXTENSIONS__
26 
27 #include <config.h>
28 
29 #include <gnc-date.h>
30 #include <cstdint>
31 
32 #include "gnc-xml-helper.h"
33 #include "sixtp-dom-generators.h"
34 #include "sixtp-utils.h"
35 
36 #include <kvp-frame.hpp>
37 #include <gnc-datetime.hpp>
38 
39 static QofLogModule log_module = GNC_MOD_IO;
40 
41 xmlNodePtr
42 boolean_to_dom_tree (const char* tag, gboolean val)
43 {
44  return text_to_dom_tree (tag, val ? "TRUE" : "FALSE");
45 }
46 
47 xmlNodePtr
48 text_to_dom_tree (const char* tag, const char* str)
49 {
50  g_return_val_if_fail (tag, NULL);
51  g_return_val_if_fail (str, NULL);
52 
53  xmlNodePtr result = xmlNewNode (NULL, BAD_CAST tag);
54  g_return_val_if_fail (result, NULL);
55 
56  gchar* newstr = g_strdup (str);
57  xmlNodeAddContent (result, checked_char_cast (newstr));
58  g_free (newstr);
59 
60  return result;
61 }
62 
63 xmlNodePtr
64 int_to_dom_tree (const char* tag, gint64 val)
65 {
66  gchar* text;
67  xmlNodePtr result;
68 
69  text = g_strdup_printf ("%" G_GINT64_FORMAT, val);
70  g_return_val_if_fail (text, NULL);
71  result = text_to_dom_tree (tag, text);
72  g_free (text);
73  return result;
74 }
75 
76 xmlNodePtr
77 guint_to_dom_tree (const char* tag, guint an_int)
78 {
79  gchar* text;
80  xmlNodePtr result;
81 
82  text = g_strdup_printf ("%u", an_int);
83  g_return_val_if_fail (text, NULL);
84  result = text_to_dom_tree (tag, text);
85  g_free (text);
86  return result;
87 }
88 
89 
90 xmlNodePtr
91 guid_to_dom_tree (const char* tag, const GncGUID* gid)
92 {
93  char guid_str[GUID_ENCODING_LENGTH + 1];
94  xmlNodePtr ret;
95 
96  ret = xmlNewNode (NULL, BAD_CAST tag);
97 
98  xmlSetProp (ret, BAD_CAST "type", BAD_CAST "guid");
99 
100  if (!guid_to_string_buff (gid, guid_str))
101  {
102  PERR ("guid_to_string_buff failed\n");
103  return NULL;
104  }
105 
106  xmlNodeAddContent (ret, BAD_CAST guid_str);
107 
108  return ret;
109 }
110 
111 xmlNodePtr
112 commodity_ref_to_dom_tree (const char* tag, const gnc_commodity* c)
113 {
114  xmlNodePtr ret;
115  gchar* name_space, *mnemonic;
116 
117  g_return_val_if_fail (c, NULL);
118 
119  ret = xmlNewNode (NULL, BAD_CAST tag);
120 
122  {
123  return NULL;
124  }
125  name_space = g_strdup (gnc_commodity_get_namespace (c));
126  mnemonic = g_strdup (gnc_commodity_get_mnemonic (c));
127  xmlNewTextChild (ret, NULL, BAD_CAST "cmdty:space",
128  checked_char_cast (name_space));
129  xmlNewTextChild (ret, NULL, BAD_CAST "cmdty:id",
130  checked_char_cast (mnemonic));
131  g_free (name_space);
132  g_free (mnemonic);
133  return ret;
134 }
135 
136 xmlNodePtr
137 time64_to_dom_tree (const char* tag, const time64 time)
138 {
139  xmlNodePtr ret;
140  g_return_val_if_fail (time != INT64_MAX, NULL);
141  auto date_str = GncDateTime(time).format_iso8601();
142  if (date_str.empty())
143  return NULL;
144  date_str += " +0000"; //Tack on a UTC offset to mollify GnuCash for Android
145  ret = xmlNewNode (NULL, BAD_CAST tag);
146  xmlNewTextChild (ret, NULL, BAD_CAST "ts:date",
147  checked_char_cast (const_cast<char*>(date_str.c_str())));
148  return ret;
149 }
150 
151 xmlNodePtr
152 gdate_to_dom_tree (const char* tag, const GDate* date)
153 {
154  xmlNodePtr ret;
155  gchar* date_str = NULL;
156 
157  g_return_val_if_fail (date, NULL);
158  date_str = g_new (gchar, 512);
159 
160  g_date_strftime (date_str, 512, "%Y-%m-%d", date);
161 
162  ret = xmlNewNode (NULL, BAD_CAST tag);
163 
164  xmlNewTextChild (ret, NULL, BAD_CAST "gdate", checked_char_cast (date_str));
165 
166  g_free (date_str);
167 
168  return ret;
169 }
170 
171 xmlNodePtr
172 gnc_numeric_to_dom_tree (const char* tag, const gnc_numeric* num)
173 {
174  xmlNodePtr ret;
175  gchar* numstr;
176 
177  g_return_val_if_fail (num, NULL);
178 
179  numstr = gnc_numeric_to_string (*num);
180  g_return_val_if_fail (numstr, NULL);
181 
182  ret = xmlNewNode (NULL, BAD_CAST tag);
183 
184  xmlNodeAddContent (ret, checked_char_cast (numstr));
185 
186  g_free (numstr);
187 
188  return ret;
189 }
190 
191 gchar*
192 double_to_string (double value)
193 {
194  gchar* numstr;
195  numstr = g_strdup_printf ("%24.18g", value);
196 
197  if (!numstr)
198  {
199  return NULL;
200 
201  }
202  else
203  {
204  return g_strstrip (numstr);
205  }
206 }
207 
208 static void
209 add_text_to_node (xmlNodePtr node, const gchar* type, gchar* val)
210 {
211  xmlSetProp (node, BAD_CAST "type", BAD_CAST type);
212  xmlNodeSetContent (node, checked_char_cast (val));
213 }
214 
215 static void add_kvp_slot (const char* key, KvpValue* value, void* data);
216 
217 static void
218 add_kvp_value_node (xmlNodePtr node, const gchar* tag, KvpValue* val)
219 {
220  xmlNodePtr val_node;
221 
222  switch (val->get_type ())
223  {
224  case KvpValue::Type::STRING:
225  {
226  auto newstr = g_strdup (val->get<const char*> ());
227  val_node = xmlNewTextChild (node, NULL, BAD_CAST tag,
228  checked_char_cast (newstr));
229  g_free (newstr);
230  break;
231  }
232  case KvpValue::Type::TIME64:
233  val_node = NULL;
234  break;
235  case KvpValue::Type::GDATE:
236  {
237  auto d = val->get<GDate> ();
238  val_node = gdate_to_dom_tree (tag, &d);
239  xmlAddChild (node, val_node);
240  break;
241  }
242  default:
243  val_node = xmlNewTextChild (node, NULL, BAD_CAST tag, NULL);
244  break;
245  }
246 
247  switch (val->get_type ())
248  {
249  case KvpValue::Type::INT64:
250  {
251  char *int_str = g_strdup_printf ("%" G_GINT64_FORMAT, val->get<int64_t> ());
252  add_text_to_node (val_node, "integer", int_str);
253  g_free (int_str);
254  break;
255  }
256  case KvpValue::Type::DOUBLE:
257  {
258  char *dbl_str = double_to_string (val->get<double> ());
259  add_text_to_node (val_node, "double", dbl_str);
260  g_free (dbl_str);
261  break;
262  }
263  case KvpValue::Type::NUMERIC:
264  {
265  char *num_str = gnc_numeric_to_string (val->get<gnc_numeric> ());
266  add_text_to_node (val_node, "numeric", num_str);
267  g_free (num_str);
268  break;
269  }
270  case KvpValue::Type::STRING:
271  xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "string");
272  break;
273  case KvpValue::Type::GUID:
274  {
275  gchar guidstr[GUID_ENCODING_LENGTH + 1];
276  guid_to_string_buff (val->get<GncGUID*> (), guidstr);
277  add_text_to_node (val_node, "guid", guidstr);
278  break;
279  }
280  /* Note: The type attribute must remain 'timespec' to maintain
281  * compatibility.
282  */
283  case KvpValue::Type::TIME64:
284  {
285  auto t = val->get<Time64> ();
286  val_node = time64_to_dom_tree (tag, t.t);
287  xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "timespec");
288  xmlAddChild (node, val_node);
289  break;
290  }
291  case KvpValue::Type::GDATE:
292  xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "gdate");
293  break;
294  case KvpValue::Type::GLIST:
295  xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "list");
296  for (auto cursor = val->get<GList*> (); cursor; cursor = cursor->next)
297  {
298  auto val = static_cast<KvpValue*> (cursor->data);
299  add_kvp_value_node (val_node, "slot:value", val);
300  }
301  break;
302  case KvpValue::Type::FRAME:
303  {
304  xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "frame");
305 
306  auto frame = val->get<KvpFrame*> ();
307  if (!frame)
308  break;
309  frame->for_each_slot_temp (&add_kvp_slot, val_node);
310  break;
311  }
312  default:
313  break;
314  }
315 }
316 
317 static void
318 add_kvp_slot (const char* key, KvpValue* value, void* data)
319 {
320  auto newkey = g_strdup ((gchar*)key);
321  auto node = static_cast<xmlNodePtr> (data);
322  auto slot_node = xmlNewChild (node, NULL, BAD_CAST "slot", NULL);
323 
324  xmlNewTextChild (slot_node, NULL, BAD_CAST "slot:key",
325  checked_char_cast (newkey));
326  g_free (newkey);
327  add_kvp_value_node (slot_node, "slot:value", value);
328 }
329 
330 xmlNodePtr
331 qof_instance_slots_to_dom_tree (const char* tag, const QofInstance* inst)
332 {
333  xmlNodePtr ret;
334  KvpFrame* frame = qof_instance_get_slots (inst);
335  if (!frame || frame->empty())
336  return nullptr;
337 
338  ret = xmlNewNode (nullptr, BAD_CAST tag);
339  frame->for_each_slot_temp (&add_kvp_slot, ret);
340  return ret;
341 }
std::string format_iso8601() const
Format the GncDateTime into a gnucash-style iso8601 string in UTC.
GnuCash DateTime class.
Date and Time handling routines.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
Retrieve the namespace for the specified commodity.
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition: guid.cpp:173
gchar * gnc_numeric_to_string(gnc_numeric n)
Convert to string.
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition: guid.h:84
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
The type used to store guids in C.
Definition: guid.h:75