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 1789 of file io-gncxml-v2.cpp.

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

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