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

Generated by: LCOV version 2.0-1