LCOV - code coverage report
Current view: top level - libgnucash/backend/xml - sixtp-utils.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 17.3 % 162 28
Test Date: 2025-06-02 17:54:15 Functions: 37.0 % 27 10
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /********************************************************************
       2                 :             :  * sixtp-utils.c                                                    *
       3                 :             :  * Copyright (c) 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                 :             : 
      24                 :             : #include <guid.hpp>
      25                 :             : #include <config.h>
      26                 :             : 
      27                 :             : #include <ctype.h>
      28                 :             : #include <glib.h>
      29                 :             : #include <stdio.h>
      30                 :             : #include <stdlib.h>
      31                 :             : #include <string.h>
      32                 :             : 
      33                 :             : #include <time.h>
      34                 :             : #include <errno.h>
      35                 :             : 
      36                 :             : #ifndef HAVE_STRPTIME
      37                 :             : #include "strptime.h"
      38                 :             : #endif
      39                 :             : #include <gnc-date.h>
      40                 :             : 
      41                 :             : #include "sixtp.h"
      42                 :             : #include "sixtp-utils.h"
      43                 :             : 
      44                 :             : #include <charconv>
      45                 :             : #include <cctype>
      46                 :             : 
      47                 :             : static QofLogModule log_module = GNC_MOD_IO;
      48                 :             : 
      49                 :             : gboolean
      50                 :         767 : isspace_str (const gchar* str, int nomorethan)
      51                 :             : {
      52                 :         767 :     const gchar* cursor = str;
      53                 :        3026 :     while (*cursor && (nomorethan != 0))
      54                 :             :     {
      55                 :        2259 :         if (!isspace (*cursor))
      56                 :             :         {
      57                 :           0 :             return (FALSE);
      58                 :             :         }
      59                 :        2259 :         cursor++;
      60                 :        2259 :         nomorethan--;
      61                 :             :     }
      62                 :         767 :     return (TRUE);
      63                 :             : }
      64                 :             : 
      65                 :             : gboolean
      66                 :         767 : allow_and_ignore_only_whitespace (GSList* sibling_data,
      67                 :             :                                   gpointer parent_data,
      68                 :             :                                   gpointer global_data,
      69                 :             :                                   gpointer* result,
      70                 :             :                                   const char* text,
      71                 :             :                                   int length)
      72                 :             : {
      73                 :         767 :     return (isspace_str (text, length));
      74                 :             : }
      75                 :             : 
      76                 :             : gboolean
      77                 :           0 : generic_accumulate_chars (GSList* sibling_data,
      78                 :             :                           gpointer parent_data,
      79                 :             :                           gpointer global_data,
      80                 :             :                           gpointer* result,
      81                 :             : 
      82                 :             :                           const char* text,
      83                 :             :                           int length)
      84                 :             : {
      85                 :           0 :     gchar* copytxt = g_strndup (text, length);
      86                 :           0 :     g_return_val_if_fail (result, FALSE);
      87                 :             : 
      88                 :           0 :     *result = copytxt;
      89                 :           0 :     return (TRUE);
      90                 :             : }
      91                 :             : 
      92                 :             : 
      93                 :             : void
      94                 :           0 : generic_free_data_for_children (gpointer data_for_children,
      95                 :             :                                 GSList* data_from_children,
      96                 :             :                                 GSList* sibling_data,
      97                 :             :                                 gpointer parent_data,
      98                 :             :                                 gpointer global_data,
      99                 :             :                                 gpointer* result,
     100                 :             :                                 const gchar* tag)
     101                 :             : {
     102                 :           0 :     if (data_for_children) g_free (data_for_children);
     103                 :           0 : }
     104                 :             : 
     105                 :             : gchar*
     106                 :           0 : concatenate_child_result_chars (GSList* data_from_children)
     107                 :             : {
     108                 :             :     GSList* lp;
     109                 :           0 :     gchar* name = g_strdup ("");
     110                 :             : 
     111                 :           0 :     g_return_val_if_fail (name, NULL);
     112                 :             : 
     113                 :             :     /* child data lists are in reverse chron order */
     114                 :           0 :     data_from_children = g_slist_reverse (g_slist_copy (data_from_children));
     115                 :             : 
     116                 :           0 :     for (lp = data_from_children; lp; lp = lp->next)
     117                 :             :     {
     118                 :           0 :         sixtp_child_result* cr = (sixtp_child_result*) lp->data;
     119                 :           0 :         if (cr->type != SIXTP_CHILD_RESULT_CHARS)
     120                 :             :         {
     121                 :           0 :             PERR ("result type is not chars");
     122                 :           0 :             g_slist_free (data_from_children);
     123                 :           0 :             g_free (name);
     124                 :           0 :             return (NULL);
     125                 :             :         }
     126                 :             :         else
     127                 :             :         {
     128                 :             :             char* temp;
     129                 :           0 :             temp = g_strconcat (name, (gchar*) cr->data, nullptr);
     130                 :           0 :             g_free (name);
     131                 :           0 :             name = temp;
     132                 :             :         }
     133                 :             :     }
     134                 :           0 :     g_slist_free (data_from_children);
     135                 :           0 :     return (name);
     136                 :             : }
     137                 :             : 
     138                 :             : /****************************************************************************/
     139                 :             : /* string to data converters...
     140                 :             :  */
     141                 :             : 
     142                 :             : 
     143                 :             : template <typename T>
     144                 :        2247 : static bool parse_chars_into_num (const char* str, T* num_ptr)
     145                 :             : {
     146                 :        2247 :     if (!str || !num_ptr)
     147                 :           0 :         return false;
     148                 :             : 
     149                 :        2335 :     while (std::isspace (*str))
     150                 :          88 :         ++str;
     151                 :             : 
     152                 :        2247 :     const char* end_ptr = str + std::strlen (str);
     153                 :             : 
     154                 :        2247 :     auto res = std::from_chars (str, end_ptr, *num_ptr);
     155                 :        2247 :     if (res.ec != std::errc{})
     156                 :          10 :         return false;
     157                 :             : 
     158                 :        2333 :     while (std::isspace (*res.ptr))
     159                 :          96 :         ++res.ptr;
     160                 :             : 
     161                 :        2237 :     return (res.ptr == end_ptr);
     162                 :             : }
     163                 :             : 
     164                 :             : /*********/
     165                 :             : /* double
     166                 :             :  */
     167                 :             : 
     168                 :             : gboolean
     169                 :          22 : string_to_double (const char* str, double* result)
     170                 :             : {
     171                 :             : #if __cpp_lib_to_chars >= 201611L
     172                 :          22 :     return parse_chars_into_num<double>(str, result);
     173                 :             : #else
     174                 :             :     // because from_chars in cpp < 201611L cannot parse floats
     175                 :             :     char* endptr = nullptr;
     176                 :             :     g_return_val_if_fail (str && result, false);
     177                 :             :     *result = std::strtod (str, &endptr);
     178                 :             :     return (endptr != str);
     179                 :             : #endif
     180                 :             : }
     181                 :             : 
     182                 :             : /*********/
     183                 :             : /* gint64
     184                 :             :  */
     185                 :             : gboolean
     186                 :        2184 : string_to_gint64 (const gchar* str, gint64* v)
     187                 :             : {
     188                 :        2184 :     return parse_chars_into_num<gint64>(str, v);
     189                 :             : }
     190                 :             : 
     191                 :             : /*********/
     192                 :             : /* guint16
     193                 :             :  */
     194                 :             : gboolean
     195                 :          23 : string_to_guint16 (const gchar* str, guint16* v)
     196                 :             : {
     197                 :          23 :     return parse_chars_into_num<guint16>(str, v);
     198                 :             : }
     199                 :             : 
     200                 :             : /*********/
     201                 :             : /* guint
     202                 :             :  */
     203                 :             : gboolean
     204                 :          18 : string_to_guint (const gchar* str, guint* v)
     205                 :             : {
     206                 :          18 :     return parse_chars_into_num<guint>(str, v);
     207                 :             : }
     208                 :             : 
     209                 :             : /************/
     210                 :             : /* hex string
     211                 :             :  */
     212                 :             : 
     213                 :             : gboolean
     214                 :           0 : hex_string_to_binary (const gchar* str,  void** v, guint64* data_len)
     215                 :             : {
     216                 :             :     /* Convert a hex string to binary.  No whitespace allowed. */
     217                 :           0 :     const gchar* cursor = str;
     218                 :             :     guint64 str_len;
     219                 :           0 :     gboolean error = FALSE;
     220                 :             : 
     221                 :           0 :     g_return_val_if_fail (str, FALSE);
     222                 :           0 :     g_return_val_if_fail (v, FALSE);
     223                 :           0 :     g_return_val_if_fail (data_len, FALSE);
     224                 :             : 
     225                 :           0 :     str_len = strlen (str);
     226                 :             :     /* Since no whitespace is allowed and hex encoding is 2 text chars
     227                 :             :        per binary char, the result must be half the input size and the
     228                 :             :        input size must be even. */
     229                 :           0 :     if ((str_len % 2) != 0) return (FALSE);
     230                 :           0 :     *data_len = 0;
     231                 :           0 :     *v = g_new0 (char, str_len / 2);
     232                 :             : 
     233                 :           0 :     g_return_val_if_fail (*v, FALSE);
     234                 :             : 
     235                 :           0 :     while (*cursor && * (cursor + 1))
     236                 :             :     {
     237                 :             :         gchar tmpstr[2];
     238                 :             :         int tmpint;
     239                 :             : 
     240                 :           0 :         if (isspace (*cursor) || isspace (* (cursor + 1)))
     241                 :             :         {
     242                 :           0 :             error = TRUE;
     243                 :             :         }
     244                 :             :         else
     245                 :             :         {
     246                 :             :             int num_read;
     247                 :           0 :             tmpstr[0] = *cursor;
     248                 :           0 :             tmpstr[0] = * (cursor + 1);
     249                 :             : 
     250                 :           0 :             if ((sscanf (tmpstr, "%x%n", &tmpint, &num_read) < 1)
     251                 :           0 :                 || (num_read != 2))
     252                 :             :             {
     253                 :           0 :                 error = TRUE;
     254                 :             :             }
     255                 :             :             else
     256                 :             :             {
     257                 :           0 :                 * ((gchar*) (v + *data_len)) = tmpint;
     258                 :           0 :                 *data_len += 1;
     259                 :           0 :                 cursor += 2;
     260                 :             :             }
     261                 :             :         }
     262                 :             :     }
     263                 :             : 
     264                 :           0 :     if (error || (*data_len != (str_len / 2)))
     265                 :             :     {
     266                 :           0 :         g_free (*v);
     267                 :           0 :         *v = NULL;
     268                 :           0 :         *data_len = 0;
     269                 :           0 :         return (FALSE);
     270                 :             :     }
     271                 :             : 
     272                 :           0 :     return (TRUE);
     273                 :             : }
     274                 :             : 
     275                 :             : /***************************************************************************/
     276                 :             : /* simple chars only parser - just grabs all it's contained chars and
     277                 :             :    does what you specify in the end handler - if you pass NULL as the
     278                 :             :    end handler to simple_chars_only_parser_new, the characters are just
     279                 :             :    passed to the parent as a new string.
     280                 :             : 
     281                 :             :    input: NA
     282                 :             :    returns: gchar array allocated via g_new, etc.
     283                 :             : 
     284                 :             :    start: NA
     285                 :             :    chars: generic_accumulate_chars.
     286                 :             :    end: varies - default is to concatenate all accumulated chars and return.
     287                 :             : 
     288                 :             :    cleanup-result: g_free (for chars)
     289                 :             :    cleanup-chars: g_free (for chars)
     290                 :             :    fail: NA
     291                 :             :    result-fail: g_free (for chars)
     292                 :             :    chars-fail: g_free (for chars)
     293                 :             : 
     294                 :             :  */
     295                 :             : 
     296                 :             : gboolean
     297                 :           0 : generic_return_chars_end_handler (gpointer data_for_children,
     298                 :             :                                   GSList* data_from_children,
     299                 :             :                                   GSList* sibling_data,
     300                 :             :                                   gpointer parent_data,
     301                 :             :                                   gpointer global_data,
     302                 :             :                                   gpointer* result,
     303                 :             :                                   const gchar* tag)
     304                 :             : {
     305                 :           0 :     gchar* txt = NULL;
     306                 :             : 
     307                 :           0 :     txt = concatenate_child_result_chars (data_from_children);
     308                 :           0 :     g_return_val_if_fail (txt, FALSE);
     309                 :           0 :     *result = txt;
     310                 :           0 :     return (TRUE);
     311                 :             : }
     312                 :             : 
     313                 :             : 
     314                 :             : sixtp*
     315                 :           0 : simple_chars_only_parser_new (sixtp_end_handler end_handler)
     316                 :             : {
     317                 :           0 :     return sixtp_set_any (
     318                 :             :                sixtp_new (), FALSE,
     319                 :             :                SIXTP_END_HANDLER_ID, (end_handler
     320                 :             :                                       ? end_handler
     321                 :             :                                       : generic_return_chars_end_handler),
     322                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     323                 :             :                SIXTP_CLEANUP_RESULT_ID, sixtp_child_free_data,
     324                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     325                 :             :                SIXTP_RESULT_FAIL_ID, sixtp_child_free_data,
     326                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     327                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     328                 :             : }
     329                 :             : 
     330                 :             : /****************************************************************************/
     331                 :             : /* generic timespec handler for XML Version 1 files.
     332                 :             : 
     333                 :             :    A collection of node functions intended to parse a sub-node set
     334                 :             :    that looks like this:
     335                 :             : 
     336                 :             :      <date-posted>
     337                 :             :        <s>Mon, 05 Jun 2000 23:16:19 -0500</s>
     338                 :             :        <ns>658864000</ns>
     339                 :             :      </date-posted>
     340                 :             : 
     341                 :             :    and produce a time64.  The start handler for the top allocates
     342                 :             :    the time64 and passes it to the children.  The <s> block sets
     343                 :             :    the seconds and the <ns> block is ignored.  If
     344                 :             :    all goes well, returns the time64 as the result.
     345                 :             : */
     346                 :             : 
     347                 :             : /* Top level timespec node:
     348                 :             : 
     349                 :             :    input: user end handler *
     350                 :             :    returns: time64
     351                 :             : 
     352                 :             :    start: Allocates Time64ParseInfo* for data_for_children.
     353                 :             :    characters: none (whitespace only).
     354                 :             :    end: g_free Time64ParseInfo + any other actions
     355                 :             : 
     356                 :             :    cleanup-result: NA
     357                 :             :    cleanup-chars: NA
     358                 :             :    fail: g_free data_for_children.
     359                 :             :    result-fail: g_free data_for_children.
     360                 :             :    chars-fail: NA
     361                 :             : 
     362                 :             :  */
     363                 :             : 
     364                 :             : gboolean
     365                 :           0 : generic_timespec_start_handler (GSList* sibling_data, gpointer parent_data,
     366                 :             :                                 gpointer global_data,
     367                 :             :                                 gpointer* data_for_children, gpointer* result,
     368                 :             :                                 const gchar* tag, gchar** attrs)
     369                 :             : {
     370                 :           0 :     Time64ParseInfo* tsp = g_new0 (Time64ParseInfo, 1);
     371                 :           0 :     g_return_val_if_fail (tsp, FALSE);
     372                 :           0 :     *data_for_children = tsp;
     373                 :           0 :     return (TRUE);
     374                 :             : }
     375                 :             : 
     376                 :             : /* You can't use this function directly.  You have to call it from
     377                 :             :    your own end handler.  If it returns TRUE, *result will contain the
     378                 :             :    new timespec.  Otherwise, you can presume that everything's been
     379                 :             :    cleaned up properly and return FALSE.  */
     380                 :             : gboolean
     381                 :           0 : timespec_parse_ok (Time64ParseInfo* info)
     382                 :             : {
     383                 :           0 :     return info->s_block_count != 1;
     384                 :             : }
     385                 :             : 
     386                 :             : /* generic_timespec_end_handler - must be customized and provided by
     387                 :             :    the user. */
     388                 :             : 
     389                 :             : /* <s> (parent timespec-node)
     390                 :             : 
     391                 :             :    input: Time64ParseInfo *
     392                 :             :    returns: NA
     393                 :             : 
     394                 :             :    start: NA
     395                 :             :    characters: accumulate.
     396                 :             :    end: convert characters to secs part of input time64 and inc s_block_count.
     397                 :             : 
     398                 :             :    cleanup-result: NA
     399                 :             :    cleanup-chars: g_free data.
     400                 :             :    fail: NA
     401                 :             :    result-fail: NA
     402                 :             :    chars-fail: g_free data.
     403                 :             : 
     404                 :             :  */
     405                 :             : 
     406                 :             : gboolean
     407                 :           0 : generic_timespec_secs_end_handler (gpointer data_for_children,
     408                 :             :                                    GSList*  data_from_children, GSList* sibling_data,
     409                 :             :                                    gpointer parent_data, gpointer global_data,
     410                 :             :                                    gpointer* result, const gchar* tag)
     411                 :             : {
     412                 :           0 :     gchar* txt = NULL;
     413                 :           0 :     Time64ParseInfo* info = (Time64ParseInfo*) parent_data;
     414                 :             : 
     415                 :           0 :     g_return_val_if_fail (parent_data, FALSE);
     416                 :             : 
     417                 :           0 :     txt = concatenate_child_result_chars (data_from_children);
     418                 :           0 :     g_return_val_if_fail (txt, FALSE);
     419                 :             : 
     420                 :           0 :     info->time = gnc_iso8601_to_time64_gmt (txt);
     421                 :           0 :     g_free (txt);
     422                 :             : 
     423                 :             : // gnc_iso8601_to_time64_gmt returns INT64_MAX on failure.
     424                 :           0 :     g_return_val_if_fail (info->time < INT64_MAX, FALSE);
     425                 :             : 
     426                 :           0 :     info->s_block_count++;
     427                 :           0 :     return (TRUE);
     428                 :             : }
     429                 :             : 
     430                 :             : /* <s> (parent timespec-node)
     431                 :             : 
     432                 :             :    input: Time64ParseInfo *
     433                 :             :    returns: NA
     434                 :             : 
     435                 :             :    start: NA
     436                 :             :    characters: accumulate.
     437                 :             :    end: NA
     438                 :             : 
     439                 :             :    cleanup-result: NA
     440                 :             :    cleanup-chars: NA.
     441                 :             :    fail: NA
     442                 :             :    result-fail: NA
     443                 :             :    chars-fail: g_free data.
     444                 :             : 
     445                 :             :  */
     446                 :             : 
     447                 :             : gboolean
     448                 :           0 : generic_timespec_nsecs_end_handler (gpointer data_for_children,
     449                 :             :                                     GSList*  data_from_children, GSList* sibling_data,
     450                 :             :                                     gpointer parent_data, gpointer global_data,
     451                 :             :                                     gpointer* result, const gchar* tag)
     452                 :             : {
     453                 :           0 :     return TRUE;
     454                 :             : }
     455                 :             : 
     456                 :             : static sixtp*
     457                 :           0 : timespec_sixtp_new (sixtp_end_handler ender)
     458                 :             : {
     459                 :           0 :     return sixtp_set_any (
     460                 :             :                sixtp_new (), FALSE,
     461                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     462                 :             :                SIXTP_END_HANDLER_ID, ender,
     463                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     464                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     465                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     466                 :             : }
     467                 :             : 
     468                 :             : sixtp*
     469                 :           0 : generic_timespec_parser_new (sixtp_end_handler end_handler)
     470                 :             : {
     471                 :             :     sixtp* top_level =
     472                 :           0 :         sixtp_set_any (sixtp_new (), FALSE,
     473                 :             :                        SIXTP_START_HANDLER_ID, generic_timespec_start_handler,
     474                 :             :                        SIXTP_CHARACTERS_HANDLER_ID, allow_and_ignore_only_whitespace,
     475                 :             :                        SIXTP_END_HANDLER_ID, end_handler,
     476                 :             :                        SIXTP_CLEANUP_RESULT_ID, sixtp_child_free_data,
     477                 :             :                        SIXTP_FAIL_HANDLER_ID, generic_free_data_for_children,
     478                 :             :                        SIXTP_RESULT_FAIL_ID, sixtp_child_free_data,
     479                 :             :                        SIXTP_NO_MORE_HANDLERS);
     480                 :           0 :     g_return_val_if_fail (top_level, NULL);
     481                 :             : 
     482                 :           0 :     if (!sixtp_add_some_sub_parsers (
     483                 :             :             top_level, TRUE,
     484                 :             :             "s", timespec_sixtp_new (generic_timespec_secs_end_handler),
     485                 :             :             "ns", timespec_sixtp_new (generic_timespec_nsecs_end_handler),
     486                 :             :             NULL, NULL))
     487                 :             :     {
     488                 :           0 :         return NULL;
     489                 :             :     }
     490                 :             : 
     491                 :           0 :     return (top_level);
     492                 :             : }
     493                 :             : 
     494                 :             : /****************************************************************************/
     495                 :             : /* <?> generic guid handler...
     496                 :             : 
     497                 :             :    Attempts to parse the current accumulated characters data as a guid
     498                 :             :    and return it.
     499                 :             : 
     500                 :             :    input: NA
     501                 :             :    returns: GncGUID*
     502                 :             : 
     503                 :             :    start: NA
     504                 :             :    characters: return string copy for accumulation in end handler.
     505                 :             :    end: concatenate all chars and create and return GncGUID*, if possible.
     506                 :             : 
     507                 :             :    cleanup-result: g_free the GncGUID*
     508                 :             :    cleanup-chars: g_free the result string.
     509                 :             :    fail: NA
     510                 :             :    result-fail: g_free the GncGUID*
     511                 :             :    chars-fail: g_free the result string.
     512                 :             : 
     513                 :             :  */
     514                 :             : 
     515                 :             : gboolean
     516                 :           0 : generic_guid_end_handler (gpointer data_for_children,
     517                 :             :                           GSList*  data_from_children, GSList* sibling_data,
     518                 :             :                           gpointer parent_data, gpointer global_data,
     519                 :             :                           gpointer* result, const gchar* tag)
     520                 :             : {
     521                 :           0 :     gchar* txt = NULL;
     522                 :             :     GncGUID* gid;
     523                 :             :     gboolean ok;
     524                 :             : 
     525                 :           0 :     txt = concatenate_child_result_chars (data_from_children);
     526                 :           0 :     g_return_val_if_fail (txt, FALSE);
     527                 :             : 
     528                 :           0 :     gid = g_new (GncGUID, 1);
     529                 :           0 :     if (!gid)
     530                 :             :     {
     531                 :           0 :         g_free (txt);
     532                 :           0 :         return (FALSE);
     533                 :             :     }
     534                 :             : 
     535                 :           0 :     ok = string_to_guid (txt, gid);
     536                 :           0 :     g_free (txt);
     537                 :             : 
     538                 :           0 :     if (!ok)
     539                 :             :     {
     540                 :           0 :         PERR ("couldn't parse GncGUID");
     541                 :           0 :         g_free (gid);
     542                 :           0 :         return (FALSE);
     543                 :             :     }
     544                 :             : 
     545                 :           0 :     *result = gid;
     546                 :           0 :     return (TRUE);
     547                 :             : }
     548                 :             : 
     549                 :             : sixtp*
     550                 :           0 : generic_guid_parser_new (void)
     551                 :             : {
     552                 :           0 :     return sixtp_set_any (
     553                 :             :                sixtp_new (), FALSE,
     554                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     555                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     556                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     557                 :             :                SIXTP_END_HANDLER_ID, generic_guid_end_handler,
     558                 :             :                SIXTP_RESULT_FAIL_ID, sixtp_child_free_data,
     559                 :             :                SIXTP_CLEANUP_RESULT_ID, sixtp_child_free_data,
     560                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     561                 :             : }
     562                 :             : 
     563                 :             : /****************************************************************************/
     564                 :             : /* <?> generic gnc_numeric handler...
     565                 :             : 
     566                 :             :    Attempts to parse the current accumulated characters data as a
     567                 :             :    gnc_numeric and return it.
     568                 :             : 
     569                 :             :    input: NA
     570                 :             :    returns: gnc_numeric*
     571                 :             : 
     572                 :             :    start: NA
     573                 :             :    characters: return string copy for accumulation in end handler.
     574                 :             :    end: concatenate all chars and create and return gnc_numeric*, if possible.
     575                 :             : 
     576                 :             :    cleanup-result: g_free the gnc_numeric*
     577                 :             :    cleanup-chars: g_free the result string.
     578                 :             :    fail: NA
     579                 :             :    result-fail: g_free the gnc_numeric*
     580                 :             :    chars-fail: g_free the result string.
     581                 :             : 
     582                 :             :  */
     583                 :             : 
     584                 :             : gboolean
     585                 :           0 : generic_gnc_numeric_end_handler (gpointer data_for_children,
     586                 :             :                                  GSList*  data_from_children, GSList* sibling_data,
     587                 :             :                                  gpointer parent_data, gpointer global_data,
     588                 :             :                                  gpointer* result, const gchar* tag)
     589                 :             : {
     590                 :           0 :     gnc_numeric* num = NULL;
     591                 :           0 :     gchar* txt = NULL;
     592                 :           0 :     gboolean ok = FALSE;
     593                 :             : 
     594                 :           0 :     txt = concatenate_child_result_chars (data_from_children);
     595                 :             : 
     596                 :           0 :     if (txt)
     597                 :             :     {
     598                 :           0 :         num = g_new (gnc_numeric, 1);
     599                 :           0 :         if (num)
     600                 :             :         {
     601                 :           0 :             *num = gnc_numeric_from_string (txt);
     602                 :           0 :             if (!gnc_numeric_check (*num))
     603                 :             :             {
     604                 :           0 :                 ok = TRUE;
     605                 :           0 :                 *result = num;
     606                 :             :             }
     607                 :             :         }
     608                 :             :     }
     609                 :             : 
     610                 :           0 :     g_free (txt);
     611                 :           0 :     if (!ok)
     612                 :             :     {
     613                 :           0 :         PERR ("couldn't parse numeric quantity");
     614                 :           0 :         g_free (num);
     615                 :             :     }
     616                 :             : 
     617                 :           0 :     return (ok);
     618                 :             : }
     619                 :             : 
     620                 :             : sixtp*
     621                 :           0 : generic_gnc_numeric_parser_new (void)
     622                 :             : {
     623                 :           0 :     return sixtp_set_any (
     624                 :             :                sixtp_new (), FALSE,
     625                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     626                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     627                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     628                 :             :                SIXTP_END_HANDLER_ID, generic_gnc_numeric_end_handler,
     629                 :             :                SIXTP_RESULT_FAIL_ID, sixtp_child_free_data,
     630                 :             :                SIXTP_CLEANUP_RESULT_ID, sixtp_child_free_data,
     631                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     632                 :             : }
     633                 :             : 
     634                 :             : /***************************************************************************/
     635                 :             : 
     636                 :             : sixtp*
     637                 :           0 : restore_char_generator (sixtp_end_handler ender)
     638                 :             : {
     639                 :           0 :     return sixtp_set_any (
     640                 :             :                sixtp_new (), FALSE,
     641                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     642                 :             :                SIXTP_END_HANDLER_ID, ender,
     643                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     644                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     645                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     646                 :             : }
     647                 :             : 
     648                 :             : /***************************** END OF FILE *********************************/
        

Generated by: LCOV version 2.0-1