GnuCash  5.6-150-g038405b370+
Data Structures | Functions
io-gncxml-v2.h File Reference

api for GnuCash version 2 XML-based file format More...

#include <glib.h>
#include "gnc-engine.h"

Go to the source code of this file.

Data Structures

struct  conv_type
 

Functions

gint gnc_xml2_find_ambiguous (const gchar *filename, GList *encodings, GHashTable **unique, GHashTable **ambiguous, GList **impossible)
 Read a file as plain byte stream to find words that are not completely ASCII. More...
 
gboolean gnc_xml2_parse_with_subst (GncXmlBackend *xml_be, QofBook *book, GHashTable *subst)
 Parse a file in push mode, but replace byte sequences in the file given a hash table of substitutions. More...
 

Detailed Description

api for GnuCash version 2 XML-based file format

Author
Initial code by James LewisMoss, 2001

Definition in file io-gncxml-v2.h.

Function Documentation

◆ gnc_xml2_find_ambiguous()

gint gnc_xml2_find_ambiguous ( const gchar *  filename,
GList *  encodings,
GHashTable **  unique,
GHashTable **  ambiguous,
GList **  impossible 
)

Read a file as plain byte stream to find words that are not completely ASCII.

On error, unique, ambiguous and impossible will be filled up to that point, -1 will be returned.

Parameters
filenameName of the file to read.
encodingsList of encodings to check words for, each begin one a GQuark in a pointer.
uniqueLocation used for a hash table for unique solutions, if not NULL. The byte sequence is the key, successful_conversion the value.
ambiguousLocation used for a hash table for ambiguous byte sequences, if not NULL. The byte sequences is the key, a list of successful_conversions the value.
impossibleLocation used for a list for undecodable byte sequences, if not NULL.
Returns
Size of impossible, -1 on error.

Definition at line 1790 of file io-gncxml-v2.cpp.

1793 {
1794  GList* iconv_list = NULL, *conv_list = NULL, *iter;
1795  iconv_item_type* iconv_item = NULL, *ascii = NULL;
1796  const gchar* enc;
1797  GHashTable* processed = NULL;
1798  gint n_impossible = 0;
1799  GError* error = NULL;
1800  gboolean clean_return = FALSE;
1801 
1802  auto [file, thread] = try_gz_open (filename, "r",
1803  is_gzipped_file (filename), FALSE);
1804  if (file == NULL)
1805  {
1806  PWARN ("Unable to open file %s", filename);
1807  goto cleanup_find_ambs;
1808  }
1809 
1810  /* we need ascii */
1811  ascii = g_new (iconv_item_type, 1);
1812  ascii->encoding = g_quark_from_string ("ASCII");
1813  ascii->iconv = g_iconv_open ("UTF-8", "ASCII");
1814  if (ascii->iconv == (GIConv) - 1)
1815  {
1816  PWARN ("Unable to open ASCII ICONV conversion descriptor");
1817  goto cleanup_find_ambs;
1818  }
1819 
1820  /* call iconv_open on encodings */
1821  for (iter = encodings; iter; iter = iter->next)
1822  {
1823  iconv_item = g_new (iconv_item_type, 1);
1824  iconv_item->encoding = GPOINTER_TO_UINT (iter->data);
1825  if (iconv_item->encoding == ascii->encoding)
1826  {
1827  continue;
1828  }
1829 
1830  enc = g_quark_to_string (iconv_item->encoding);
1831  iconv_item->iconv = g_iconv_open ("UTF-8", enc);
1832  if (iconv_item->iconv == (GIConv) - 1)
1833  {
1834  PWARN ("Unable to open IConv conversion descriptor for '%s'", enc);
1835  g_free (iconv_item);
1836  goto cleanup_find_ambs;
1837  }
1838  else
1839  {
1840  iconv_list = g_list_prepend (iconv_list, iconv_item);
1841  }
1842  }
1843 
1844  /* prepare data containers */
1845  if (unique)
1846  *unique = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1847  (GDestroyNotify) conv_free);
1848  if (ambiguous)
1849  *ambiguous = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1850  (GDestroyNotify) conv_list_free);
1851  if (impossible)
1852  *impossible = NULL;
1853  processed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1854 
1855  /* loop through lines */
1856  while (1)
1857  {
1858  gchar line[256], *word, *utf8;
1859  gchar** word_array, **word_cursor;
1860  conv_type* conv = NULL;
1861 
1862  if (!fgets (line, sizeof (line) - 1, file))
1863  {
1864  if (feof (file))
1865  {
1866  break;
1867  }
1868  else
1869  {
1870  goto cleanup_find_ambs;
1871  }
1872  }
1873 
1874  g_strchomp (line);
1875  replace_character_references (line);
1876  word_array = g_strsplit_set (line, "> <", 0);
1877 
1878  /* loop through words */
1879  for (word_cursor = word_array; *word_cursor; word_cursor++)
1880  {
1881  word = *word_cursor;
1882  if (!word)
1883  continue;
1884 
1885  utf8 = g_convert_with_iconv (word, -1, ascii->iconv,
1886  NULL, NULL, &error);
1887  if (utf8)
1888  {
1889  /* pure ascii */
1890  g_free (utf8);
1891  continue;
1892  }
1893  g_error_free (error);
1894  error = NULL;
1895 
1896  if (g_hash_table_lookup_extended (processed, word, NULL, NULL))
1897  {
1898  /* already processed */
1899  continue;
1900  }
1901 
1902  /* loop through encodings */
1903  conv_list = NULL;
1904  for (iter = iconv_list; iter; iter = iter->next)
1905  {
1906  iconv_item = static_cast<decltype (iconv_item)> (iter->data);
1907  utf8 = g_convert_with_iconv (word, -1, iconv_item->iconv,
1908  NULL, NULL, &error);
1909  if (utf8)
1910  {
1911  conv = g_new (conv_type, 1);
1912  conv->encoding = iconv_item->encoding;
1913  conv->utf8_string = utf8;
1914  conv_list = g_list_prepend (conv_list, conv);
1915  }
1916  else
1917  {
1918  g_error_free (error);
1919  error = NULL;
1920  }
1921  }
1922 
1923  /* no successful conversion */
1924  if (!conv_list)
1925  {
1926  if (impossible)
1927  *impossible = g_list_append (*impossible, g_strdup (word));
1928  n_impossible++;
1929  }
1930 
1931  /* more than one successful conversion */
1932  else if (conv_list->next)
1933  {
1934  if (ambiguous)
1935  {
1936  g_hash_table_insert (*ambiguous, g_strdup (word), conv_list);
1937  }
1938  else
1939  {
1940  conv_list_free (conv_list);
1941  }
1942  }
1943 
1944  /* only one successful conversion */
1945  else
1946  {
1947  if (unique)
1948  {
1949  g_hash_table_insert (*unique, g_strdup (word), conv);
1950  }
1951  else
1952  {
1953  conv_free (conv);
1954  }
1955  g_list_free (conv_list);
1956  }
1957 
1958  g_hash_table_insert (processed, g_strdup (word), NULL);
1959  }
1960  g_strfreev (word_array);
1961  }
1962 
1963  clean_return = TRUE;
1964 
1965 cleanup_find_ambs:
1966 
1967  if (iconv_list)
1968  {
1969  for (iter = iconv_list; iter; iter = iter->next)
1970  {
1971  if (iter->data)
1972  {
1973  g_iconv_close (((iconv_item_type*) iter->data)->iconv);
1974  g_free (iter->data);
1975  }
1976  }
1977  g_list_free (iconv_list);
1978  }
1979  if (processed)
1980  g_hash_table_destroy (processed);
1981  if (ascii)
1982  g_free (ascii);
1983  if (file)
1984  {
1985  fclose (file);
1986  if (thread)
1987  g_thread_join (thread);
1988  }
1989 
1990  return (clean_return) ? n_impossible : -1;
1991 }
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250

◆ gnc_xml2_parse_with_subst()

gboolean gnc_xml2_parse_with_subst ( GncXmlBackend xml_be,
QofBook *  book,
GHashTable *  subst 
)

Parse a file in push mode, but replace byte sequences in the file given a hash table of substitutions.

Parameters
substhash table with keys and values of type gchar*

Definition at line 2129 of file io-gncxml-v2.cpp.

2130 {
2131  push_data_type* push_data;
2132  gboolean success;
2133 
2134  push_data = g_new (push_data_type, 1);
2135  push_data->filename = xml_be->get_filename();
2136  push_data->subst = subst;
2137 
2138  success = qof_session_load_from_xml_file_v2_full (
2139  xml_be, book, (sixtp_push_handler) parse_with_subst_push_handler,
2140  push_data, GNC_BOOK_XML2_FILE);
2141  g_free (push_data);
2142 
2143  if (success)
2144  qof_instance_set_dirty (QOF_INSTANCE (book));
2145 
2146  return success;
2147 }