LCOV - code coverage report
Current view: top level - libgnucash/backend/xml - sixtp-utils.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 14.6 % 157 23
Test Date: 2025-12-13 05:48:56 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                 :        2268 : static bool parse_chars_into_num (std::string_view sv, T* num_ptr)
     145                 :             : {
     146                 :        2268 :     if (!num_ptr)
     147                 :           0 :         return false;
     148                 :             : 
     149                 :        2356 :     while (!sv.empty() && std::isspace (sv.front ())) sv.remove_prefix (1);
     150                 :        2364 :     while (!sv.empty() && std::isspace (sv.back ())) sv.remove_suffix (1);
     151                 :             : 
     152                 :        2268 :     auto res = std::from_chars (sv.begin(), sv.end(), *num_ptr);
     153                 :        2268 :     return (res.ec == std::errc{} && res.ptr == sv.end());
     154                 :             : }
     155                 :             : 
     156                 :             : /*********/
     157                 :             : /* double
     158                 :             :  */
     159                 :             : 
     160                 :             : gboolean
     161                 :          22 : string_to_double (std::string_view sv, double* result)
     162                 :             : {
     163                 :             : #if __cpp_lib_to_chars >= 201611L
     164                 :          22 :     return parse_chars_into_num<double>(sv, result);
     165                 :             : #else
     166                 :             :     // because from_chars in cpp < 201611L cannot parse floats
     167                 :             :     g_return_val_if_fail (result, false);
     168                 :             :     std::string str{sv};
     169                 :             :     char* endptr = nullptr;
     170                 :             :     *result = std::strtod (str.c_str(), &endptr);
     171                 :             :     return (endptr != str.c_str());
     172                 :             : #endif
     173                 :             : }
     174                 :             : 
     175                 :             : /*********/
     176                 :             : /* gint64
     177                 :             :  */
     178                 :             : gboolean
     179                 :        2205 : string_to_gint64 (std::string_view sv, gint64* v)
     180                 :             : {
     181                 :        2205 :     return parse_chars_into_num<gint64>(sv, v);
     182                 :             : }
     183                 :             : 
     184                 :             : /*********/
     185                 :             : /* guint16
     186                 :             :  */
     187                 :             : gboolean
     188                 :          23 : string_to_guint16 (std::string_view sv, guint16* v)
     189                 :             : {
     190                 :          23 :     return parse_chars_into_num<guint16>(sv, v);
     191                 :             : }
     192                 :             : 
     193                 :             : /*********/
     194                 :             : /* guint
     195                 :             :  */
     196                 :             : gboolean
     197                 :          18 : string_to_guint (std::string_view sv, guint* v)
     198                 :             : {
     199                 :          18 :     return parse_chars_into_num<guint>(sv, v);
     200                 :             : }
     201                 :             : 
     202                 :             : /************/
     203                 :             : /* hex string
     204                 :             :  */
     205                 :             : 
     206                 :             : gboolean
     207                 :           0 : hex_string_to_binary (const gchar* str,  void** v, guint64* data_len)
     208                 :             : {
     209                 :             :     /* Convert a hex string to binary.  No whitespace allowed. */
     210                 :           0 :     const gchar* cursor = str;
     211                 :             :     guint64 str_len;
     212                 :           0 :     gboolean error = FALSE;
     213                 :             : 
     214                 :           0 :     g_return_val_if_fail (str, FALSE);
     215                 :           0 :     g_return_val_if_fail (v, FALSE);
     216                 :           0 :     g_return_val_if_fail (data_len, FALSE);
     217                 :             : 
     218                 :           0 :     str_len = strlen (str);
     219                 :             :     /* Since no whitespace is allowed and hex encoding is 2 text chars
     220                 :             :        per binary char, the result must be half the input size and the
     221                 :             :        input size must be even. */
     222                 :           0 :     if ((str_len % 2) != 0) return (FALSE);
     223                 :           0 :     *data_len = 0;
     224                 :           0 :     *v = g_new0 (char, str_len / 2);
     225                 :             : 
     226                 :           0 :     g_return_val_if_fail (*v, FALSE);
     227                 :             : 
     228                 :           0 :     while (*cursor && * (cursor + 1))
     229                 :             :     {
     230                 :             :         gchar tmpstr[2];
     231                 :             :         int tmpint;
     232                 :             : 
     233                 :           0 :         if (isspace (*cursor) || isspace (* (cursor + 1)))
     234                 :             :         {
     235                 :           0 :             error = TRUE;
     236                 :             :         }
     237                 :             :         else
     238                 :             :         {
     239                 :             :             int num_read;
     240                 :           0 :             tmpstr[0] = *cursor;
     241                 :           0 :             tmpstr[0] = * (cursor + 1);
     242                 :             : 
     243                 :           0 :             if ((sscanf (tmpstr, "%x%n", &tmpint, &num_read) < 1)
     244                 :           0 :                 || (num_read != 2))
     245                 :             :             {
     246                 :           0 :                 error = TRUE;
     247                 :             :             }
     248                 :             :             else
     249                 :             :             {
     250                 :           0 :                 * ((gchar*) (v + *data_len)) = tmpint;
     251                 :           0 :                 *data_len += 1;
     252                 :           0 :                 cursor += 2;
     253                 :             :             }
     254                 :             :         }
     255                 :             :     }
     256                 :             : 
     257                 :           0 :     if (error || (*data_len != (str_len / 2)))
     258                 :             :     {
     259                 :           0 :         g_free (*v);
     260                 :           0 :         *v = NULL;
     261                 :           0 :         *data_len = 0;
     262                 :           0 :         return (FALSE);
     263                 :             :     }
     264                 :             : 
     265                 :           0 :     return (TRUE);
     266                 :             : }
     267                 :             : 
     268                 :             : /***************************************************************************/
     269                 :             : /* simple chars only parser - just grabs all it's contained chars and
     270                 :             :    does what you specify in the end handler - if you pass NULL as the
     271                 :             :    end handler to simple_chars_only_parser_new, the characters are just
     272                 :             :    passed to the parent as a new string.
     273                 :             : 
     274                 :             :    input: NA
     275                 :             :    returns: gchar array allocated via g_new, etc.
     276                 :             : 
     277                 :             :    start: NA
     278                 :             :    chars: generic_accumulate_chars.
     279                 :             :    end: varies - default is to concatenate all accumulated chars and return.
     280                 :             : 
     281                 :             :    cleanup-result: g_free (for chars)
     282                 :             :    cleanup-chars: g_free (for chars)
     283                 :             :    fail: NA
     284                 :             :    result-fail: g_free (for chars)
     285                 :             :    chars-fail: g_free (for chars)
     286                 :             : 
     287                 :             :  */
     288                 :             : 
     289                 :             : gboolean
     290                 :           0 : generic_return_chars_end_handler (gpointer data_for_children,
     291                 :             :                                   GSList* data_from_children,
     292                 :             :                                   GSList* sibling_data,
     293                 :             :                                   gpointer parent_data,
     294                 :             :                                   gpointer global_data,
     295                 :             :                                   gpointer* result,
     296                 :             :                                   const gchar* tag)
     297                 :             : {
     298                 :           0 :     gchar* txt = NULL;
     299                 :             : 
     300                 :           0 :     txt = concatenate_child_result_chars (data_from_children);
     301                 :           0 :     g_return_val_if_fail (txt, FALSE);
     302                 :           0 :     *result = txt;
     303                 :           0 :     return (TRUE);
     304                 :             : }
     305                 :             : 
     306                 :             : 
     307                 :             : sixtp*
     308                 :           0 : simple_chars_only_parser_new (sixtp_end_handler end_handler)
     309                 :             : {
     310                 :           0 :     return sixtp_set_any (
     311                 :             :                sixtp_new (), FALSE,
     312                 :             :                SIXTP_END_HANDLER_ID, (end_handler
     313                 :             :                                       ? end_handler
     314                 :             :                                       : generic_return_chars_end_handler),
     315                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     316                 :             :                SIXTP_CLEANUP_RESULT_ID, sixtp_child_free_data,
     317                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     318                 :             :                SIXTP_RESULT_FAIL_ID, sixtp_child_free_data,
     319                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     320                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     321                 :             : }
     322                 :             : 
     323                 :             : /****************************************************************************/
     324                 :             : /* generic timespec handler for XML Version 1 files.
     325                 :             : 
     326                 :             :    A collection of node functions intended to parse a sub-node set
     327                 :             :    that looks like this:
     328                 :             : 
     329                 :             :      <date-posted>
     330                 :             :        <s>Mon, 05 Jun 2000 23:16:19 -0500</s>
     331                 :             :        <ns>658864000</ns>
     332                 :             :      </date-posted>
     333                 :             : 
     334                 :             :    and produce a time64.  The start handler for the top allocates
     335                 :             :    the time64 and passes it to the children.  The <s> block sets
     336                 :             :    the seconds and the <ns> block is ignored.  If
     337                 :             :    all goes well, returns the time64 as the result.
     338                 :             : */
     339                 :             : 
     340                 :             : /* Top level timespec node:
     341                 :             : 
     342                 :             :    input: user end handler *
     343                 :             :    returns: time64
     344                 :             : 
     345                 :             :    start: Allocates Time64ParseInfo* for data_for_children.
     346                 :             :    characters: none (whitespace only).
     347                 :             :    end: g_free Time64ParseInfo + any other actions
     348                 :             : 
     349                 :             :    cleanup-result: NA
     350                 :             :    cleanup-chars: NA
     351                 :             :    fail: g_free data_for_children.
     352                 :             :    result-fail: g_free data_for_children.
     353                 :             :    chars-fail: NA
     354                 :             : 
     355                 :             :  */
     356                 :             : 
     357                 :             : gboolean
     358                 :           0 : generic_timespec_start_handler (GSList* sibling_data, gpointer parent_data,
     359                 :             :                                 gpointer global_data,
     360                 :             :                                 gpointer* data_for_children, gpointer* result,
     361                 :             :                                 const gchar* tag, gchar** attrs)
     362                 :             : {
     363                 :           0 :     Time64ParseInfo* tsp = g_new0 (Time64ParseInfo, 1);
     364                 :           0 :     g_return_val_if_fail (tsp, FALSE);
     365                 :           0 :     *data_for_children = tsp;
     366                 :           0 :     return (TRUE);
     367                 :             : }
     368                 :             : 
     369                 :             : /* You can't use this function directly.  You have to call it from
     370                 :             :    your own end handler.  If it returns TRUE, *result will contain the
     371                 :             :    new timespec.  Otherwise, you can presume that everything's been
     372                 :             :    cleaned up properly and return FALSE.  */
     373                 :             : gboolean
     374                 :           0 : timespec_parse_ok (Time64ParseInfo* info)
     375                 :             : {
     376                 :           0 :     return info->s_block_count != 1;
     377                 :             : }
     378                 :             : 
     379                 :             : /* generic_timespec_end_handler - must be customized and provided by
     380                 :             :    the user. */
     381                 :             : 
     382                 :             : /* <s> (parent timespec-node)
     383                 :             : 
     384                 :             :    input: Time64ParseInfo *
     385                 :             :    returns: NA
     386                 :             : 
     387                 :             :    start: NA
     388                 :             :    characters: accumulate.
     389                 :             :    end: convert characters to secs part of input time64 and inc s_block_count.
     390                 :             : 
     391                 :             :    cleanup-result: NA
     392                 :             :    cleanup-chars: g_free data.
     393                 :             :    fail: NA
     394                 :             :    result-fail: NA
     395                 :             :    chars-fail: g_free data.
     396                 :             : 
     397                 :             :  */
     398                 :             : 
     399                 :             : gboolean
     400                 :           0 : generic_timespec_secs_end_handler (gpointer data_for_children,
     401                 :             :                                    GSList*  data_from_children, GSList* sibling_data,
     402                 :             :                                    gpointer parent_data, gpointer global_data,
     403                 :             :                                    gpointer* result, const gchar* tag)
     404                 :             : {
     405                 :           0 :     gchar* txt = NULL;
     406                 :           0 :     Time64ParseInfo* info = (Time64ParseInfo*) parent_data;
     407                 :             : 
     408                 :           0 :     g_return_val_if_fail (parent_data, FALSE);
     409                 :             : 
     410                 :           0 :     txt = concatenate_child_result_chars (data_from_children);
     411                 :           0 :     g_return_val_if_fail (txt, FALSE);
     412                 :             : 
     413                 :           0 :     info->time = gnc_iso8601_to_time64_gmt (txt);
     414                 :           0 :     g_free (txt);
     415                 :             : 
     416                 :             : // gnc_iso8601_to_time64_gmt returns INT64_MAX on failure.
     417                 :           0 :     g_return_val_if_fail (info->time < INT64_MAX, FALSE);
     418                 :             : 
     419                 :           0 :     info->s_block_count++;
     420                 :           0 :     return (TRUE);
     421                 :             : }
     422                 :             : 
     423                 :             : /* <s> (parent timespec-node)
     424                 :             : 
     425                 :             :    input: Time64ParseInfo *
     426                 :             :    returns: NA
     427                 :             : 
     428                 :             :    start: NA
     429                 :             :    characters: accumulate.
     430                 :             :    end: NA
     431                 :             : 
     432                 :             :    cleanup-result: NA
     433                 :             :    cleanup-chars: NA.
     434                 :             :    fail: NA
     435                 :             :    result-fail: NA
     436                 :             :    chars-fail: g_free data.
     437                 :             : 
     438                 :             :  */
     439                 :             : 
     440                 :             : gboolean
     441                 :           0 : generic_timespec_nsecs_end_handler (gpointer data_for_children,
     442                 :             :                                     GSList*  data_from_children, GSList* sibling_data,
     443                 :             :                                     gpointer parent_data, gpointer global_data,
     444                 :             :                                     gpointer* result, const gchar* tag)
     445                 :             : {
     446                 :           0 :     return TRUE;
     447                 :             : }
     448                 :             : 
     449                 :             : static sixtp*
     450                 :           0 : timespec_sixtp_new (sixtp_end_handler ender)
     451                 :             : {
     452                 :           0 :     return sixtp_set_any (
     453                 :             :                sixtp_new (), FALSE,
     454                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     455                 :             :                SIXTP_END_HANDLER_ID, ender,
     456                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     457                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     458                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     459                 :             : }
     460                 :             : 
     461                 :             : sixtp*
     462                 :           0 : generic_timespec_parser_new (sixtp_end_handler end_handler)
     463                 :             : {
     464                 :             :     sixtp* top_level =
     465                 :           0 :         sixtp_set_any (sixtp_new (), FALSE,
     466                 :             :                        SIXTP_START_HANDLER_ID, generic_timespec_start_handler,
     467                 :             :                        SIXTP_CHARACTERS_HANDLER_ID, allow_and_ignore_only_whitespace,
     468                 :             :                        SIXTP_END_HANDLER_ID, end_handler,
     469                 :             :                        SIXTP_CLEANUP_RESULT_ID, sixtp_child_free_data,
     470                 :             :                        SIXTP_FAIL_HANDLER_ID, generic_free_data_for_children,
     471                 :             :                        SIXTP_RESULT_FAIL_ID, sixtp_child_free_data,
     472                 :             :                        SIXTP_NO_MORE_HANDLERS);
     473                 :           0 :     g_return_val_if_fail (top_level, NULL);
     474                 :             : 
     475                 :           0 :     if (!sixtp_add_some_sub_parsers (
     476                 :             :             top_level, TRUE,
     477                 :             :             "s", timespec_sixtp_new (generic_timespec_secs_end_handler),
     478                 :             :             "ns", timespec_sixtp_new (generic_timespec_nsecs_end_handler),
     479                 :             :             NULL, NULL))
     480                 :             :     {
     481                 :           0 :         return NULL;
     482                 :             :     }
     483                 :             : 
     484                 :           0 :     return (top_level);
     485                 :             : }
     486                 :             : 
     487                 :             : /****************************************************************************/
     488                 :             : /* <?> generic guid handler...
     489                 :             : 
     490                 :             :    Attempts to parse the current accumulated characters data as a guid
     491                 :             :    and return it.
     492                 :             : 
     493                 :             :    input: NA
     494                 :             :    returns: GncGUID*
     495                 :             : 
     496                 :             :    start: NA
     497                 :             :    characters: return string copy for accumulation in end handler.
     498                 :             :    end: concatenate all chars and create and return GncGUID*, if possible.
     499                 :             : 
     500                 :             :    cleanup-result: g_free the GncGUID*
     501                 :             :    cleanup-chars: g_free the result string.
     502                 :             :    fail: NA
     503                 :             :    result-fail: g_free the GncGUID*
     504                 :             :    chars-fail: g_free the result string.
     505                 :             : 
     506                 :             :  */
     507                 :             : 
     508                 :             : gboolean
     509                 :           0 : generic_guid_end_handler (gpointer data_for_children,
     510                 :             :                           GSList*  data_from_children, GSList* sibling_data,
     511                 :             :                           gpointer parent_data, gpointer global_data,
     512                 :             :                           gpointer* result, const gchar* tag)
     513                 :             : {
     514                 :           0 :     gchar* txt = NULL;
     515                 :             :     GncGUID* gid;
     516                 :             :     gboolean ok;
     517                 :             : 
     518                 :           0 :     txt = concatenate_child_result_chars (data_from_children);
     519                 :           0 :     g_return_val_if_fail (txt, FALSE);
     520                 :             : 
     521                 :           0 :     gid = g_new (GncGUID, 1);
     522                 :           0 :     if (!gid)
     523                 :             :     {
     524                 :           0 :         g_free (txt);
     525                 :           0 :         return (FALSE);
     526                 :             :     }
     527                 :             : 
     528                 :           0 :     ok = string_to_guid (txt, gid);
     529                 :           0 :     g_free (txt);
     530                 :             : 
     531                 :           0 :     if (!ok)
     532                 :             :     {
     533                 :           0 :         PERR ("couldn't parse GncGUID");
     534                 :           0 :         g_free (gid);
     535                 :           0 :         return (FALSE);
     536                 :             :     }
     537                 :             : 
     538                 :           0 :     *result = gid;
     539                 :           0 :     return (TRUE);
     540                 :             : }
     541                 :             : 
     542                 :             : sixtp*
     543                 :           0 : generic_guid_parser_new (void)
     544                 :             : {
     545                 :           0 :     return sixtp_set_any (
     546                 :             :                sixtp_new (), FALSE,
     547                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     548                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     549                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     550                 :             :                SIXTP_END_HANDLER_ID, generic_guid_end_handler,
     551                 :             :                SIXTP_RESULT_FAIL_ID, sixtp_child_free_data,
     552                 :             :                SIXTP_CLEANUP_RESULT_ID, sixtp_child_free_data,
     553                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     554                 :             : }
     555                 :             : 
     556                 :             : /****************************************************************************/
     557                 :             : /* <?> generic gnc_numeric handler...
     558                 :             : 
     559                 :             :    Attempts to parse the current accumulated characters data as a
     560                 :             :    gnc_numeric and return it.
     561                 :             : 
     562                 :             :    input: NA
     563                 :             :    returns: gnc_numeric*
     564                 :             : 
     565                 :             :    start: NA
     566                 :             :    characters: return string copy for accumulation in end handler.
     567                 :             :    end: concatenate all chars and create and return gnc_numeric*, if possible.
     568                 :             : 
     569                 :             :    cleanup-result: g_free the gnc_numeric*
     570                 :             :    cleanup-chars: g_free the result string.
     571                 :             :    fail: NA
     572                 :             :    result-fail: g_free the gnc_numeric*
     573                 :             :    chars-fail: g_free the result string.
     574                 :             : 
     575                 :             :  */
     576                 :             : 
     577                 :             : gboolean
     578                 :           0 : generic_gnc_numeric_end_handler (gpointer data_for_children,
     579                 :             :                                  GSList*  data_from_children, GSList* sibling_data,
     580                 :             :                                  gpointer parent_data, gpointer global_data,
     581                 :             :                                  gpointer* result, const gchar* tag)
     582                 :             : {
     583                 :           0 :     gnc_numeric* num = NULL;
     584                 :           0 :     gchar* txt = NULL;
     585                 :           0 :     gboolean ok = FALSE;
     586                 :             : 
     587                 :           0 :     txt = concatenate_child_result_chars (data_from_children);
     588                 :             : 
     589                 :           0 :     if (txt)
     590                 :             :     {
     591                 :           0 :         num = g_new (gnc_numeric, 1);
     592                 :           0 :         if (num)
     593                 :             :         {
     594                 :           0 :             *num = gnc_numeric_from_string (txt);
     595                 :           0 :             if (!gnc_numeric_check (*num))
     596                 :             :             {
     597                 :           0 :                 ok = TRUE;
     598                 :           0 :                 *result = num;
     599                 :             :             }
     600                 :             :         }
     601                 :             :     }
     602                 :             : 
     603                 :           0 :     g_free (txt);
     604                 :           0 :     if (!ok)
     605                 :             :     {
     606                 :           0 :         PERR ("couldn't parse numeric quantity");
     607                 :           0 :         g_free (num);
     608                 :             :     }
     609                 :             : 
     610                 :           0 :     return (ok);
     611                 :             : }
     612                 :             : 
     613                 :             : sixtp*
     614                 :           0 : generic_gnc_numeric_parser_new (void)
     615                 :             : {
     616                 :           0 :     return sixtp_set_any (
     617                 :             :                sixtp_new (), FALSE,
     618                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     619                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     620                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     621                 :             :                SIXTP_END_HANDLER_ID, generic_gnc_numeric_end_handler,
     622                 :             :                SIXTP_RESULT_FAIL_ID, sixtp_child_free_data,
     623                 :             :                SIXTP_CLEANUP_RESULT_ID, sixtp_child_free_data,
     624                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     625                 :             : }
     626                 :             : 
     627                 :             : /***************************************************************************/
     628                 :             : 
     629                 :             : sixtp*
     630                 :           0 : restore_char_generator (sixtp_end_handler ender)
     631                 :             : {
     632                 :           0 :     return sixtp_set_any (
     633                 :             :                sixtp_new (), FALSE,
     634                 :             :                SIXTP_CHARACTERS_HANDLER_ID, generic_accumulate_chars,
     635                 :             :                SIXTP_END_HANDLER_ID, ender,
     636                 :             :                SIXTP_CLEANUP_CHARS_ID, sixtp_child_free_data,
     637                 :             :                SIXTP_CHARS_FAIL_ID, sixtp_child_free_data,
     638                 :           0 :                SIXTP_NO_MORE_HANDLERS);
     639                 :             : }
     640                 :             : 
     641                 :             : /***************************** END OF FILE *********************************/
        

Generated by: LCOV version 2.0-1