/* HomeBank -- Free, easy, personal accounting for everyone.
* Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
* HomeBank is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* HomeBank is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "homebank.h"
#include "hb-transaction.h"
#include "hb-split.h"
/****************************************************************************/
/* Debug macros */
/****************************************************************************/
#define MYDEBUG 0
#if MYDEBUG
#define DB(x) (x);
#else
#define DB(x);
#endif
/* our global datas */
extern struct HomeBank *GLOBALS;
extern struct Preferences *PREFS;
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
void da_split_free(Split *item)
{
if(item != NULL)
{
if(item->memo != NULL)
g_free(item->memo);
g_free(item);
}
}
Split *da_split_malloc(void)
{
return g_malloc0(sizeof(Split));
}
void da_split_destroy(GPtrArray *splits)
{
DB( g_print("da_split_destroy\n") );
if(splits != NULL)
g_ptr_array_free(splits, TRUE);
}
GPtrArray *da_split_new(void)
{
DB( g_print("da_split_new\n") );
return g_ptr_array_new_with_free_func((GDestroyNotify)da_split_free);
}
static GPtrArray *da_split_new_full(guint size)
{
DB( g_print("da_split_new\n") );
return g_ptr_array_new_full(size, (GDestroyNotify)da_split_free);
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
static gint da_splits_compare_func(gpointer a, gpointer b)
{
Split *sa = *(Split **)a;
Split *sb = *(Split **)b;
DB( g_print(" sort %d %s - %d %s\n", sa->pos, sa->memo, sb->pos, sb->memo) );
return sa->pos - sb->pos;
}
void da_splits_sort(GPtrArray *splits)
{
DB( g_print("da_splits_sort\n") );
if(splits == NULL)
{
//g_warning("NULL splits");
return;
}
g_ptr_array_sort(splits, (GCompareFunc) da_splits_compare_func);
}
guint da_splits_length(GPtrArray *splits)
{
DB( g_print("da_splits_length\n") );
if(splits == NULL)
{
//g_warning("NULL splits");
return 0;
}
return splits->len;
}
gboolean da_splits_remove(GPtrArray *splits, Split *item)
{
DB( g_print("da_splits_remove\n") );
if(splits == NULL)
{
g_warning("NULL splits");
return FALSE;
}
return g_ptr_array_remove(splits, item);
}
void da_splits_append(GPtrArray *splits, Split *item)
{
DB( g_print("da_splits_append\n") );
if(splits == NULL)
{
g_warning("NULL splits");
return;
}
if(splits->len <= TXN_MAX_SPLIT)
g_ptr_array_add (splits, item);
}
Split *da_splits_get(GPtrArray *splits, guint index)
{
return g_ptr_array_index(splits, index);
}
GPtrArray *da_splits_clone(GPtrArray *src_splits)
{
GPtrArray *new_splits;
guint i;
DB( g_print("da_splits_clone\n") );
if(src_splits == NULL)
{
//g_warning("NULL splits");
return NULL;
}
new_splits = da_split_new_full (src_splits->len);
for(i=0;ilen;i++)
{
Split *src, *new;
src = g_ptr_array_index(src_splits, i);
new = da_split_malloc ();
new->kcat = src->kcat;
new->memo = g_strdup(src->memo);
new->amount = src->amount;
da_splits_append (new_splits, new);
}
return new_splits;
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
guint da_splits_parse(GPtrArray *splits, gchar *cats, gchar *amounts, gchar *memos)
{
gchar **cat_a, **amt_a, **mem_a;
guint count, i;
Split *split;
if(splits == NULL)
return 0;
DB( g_print(" split parse %s :: %s :: %s\n", cats, amounts, memos) );
cat_a = g_strsplit (cats, "||", 0);
amt_a = g_strsplit (amounts, "||", 0);
mem_a = g_strsplit (memos, "||", 0);
count = g_strv_length(amt_a);
if( (count == g_strv_length(cat_a)) && (count == g_strv_length(mem_a)) )
{
for(i=0;ikcat = atoi(cat_a[i]);
split->memo = g_strdup(mem_a[i]);
split->amount = g_ascii_strtod(amt_a[i], NULL);
da_splits_append (splits, split);
}
}
else
{
g_warning("invalid split parse");
}
g_strfreev (mem_a);
g_strfreev (amt_a);
g_strfreev (cat_a);
return count;
}
guint da_splits_tostring(GPtrArray *splits, gchar **cats, gchar **amounts, gchar **memos)
{
guint i;
Split *split;
char buf[G_ASCII_DTOSTR_BUF_SIZE];
GString *cat_a, *amt_a , *mem_a;
if(splits == NULL)
return 0;
DB( g_print(" splits tostring\n") );
cat_a = g_string_new (NULL);
amt_a = g_string_new (NULL);
mem_a = g_string_new (NULL);
for(i=0;ilen;i++)
{
split = g_ptr_array_index(splits, i);
g_string_append_printf (cat_a, "%d", split->kcat);
g_string_append(amt_a, g_ascii_dtostr (buf, sizeof (buf), split->amount) );
g_string_append(mem_a, split->memo);
if((i+1) < splits->len)
{
g_string_append(cat_a, "||");
g_string_append(amt_a, "||");
g_string_append(mem_a, "||");
}
}
*cats = g_string_free(cat_a, FALSE);
*amounts = g_string_free(amt_a, FALSE);
*memos = g_string_free(mem_a, FALSE);
return i;
}
guint da_splits_consistency (GPtrArray *splits)
{
Split *split;
guint i;
if(splits == NULL)
return 0;
// check split category #1340142
for(i=0;ilen;i++)
{
split = g_ptr_array_index(splits, i);
if(da_cat_get(split->kcat) == NULL)
{
g_warning("split consistency: fixed invalid split cat %d", split->kcat);
split->kcat = 0;
}
}
return splits->len;
}