mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
merge cahnges from the cap-gains5 development branch,
consisting primarily of enhance KVP functionality, including better support for lists of values, and the implementation of a 'bag' for holding collection of (un-named) data. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@9317 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
c4f465d164
commit
ef6b5dad26
@ -233,44 +233,21 @@ xaccCloneAccount (const Account *from, QofBook *book)
|
||||
Account *
|
||||
xaccAccountLookupTwin (Account *acc, QofBook *book)
|
||||
{
|
||||
KvpValue *v_ncopies;
|
||||
int i, ncopies = 0;
|
||||
KvpFrame *fr;
|
||||
GUID * twin_guid;
|
||||
Account * twin;
|
||||
|
||||
if (!acc || !book) return NULL;
|
||||
ENTER (" ");
|
||||
|
||||
v_ncopies = kvp_frame_get_slot_path (acc->kvp_data, "gemini", "ncopies", NULL);
|
||||
if (!v_ncopies) return NULL;
|
||||
ncopies = kvp_value_get_gint64 (v_ncopies);
|
||||
for (i=0; i<ncopies; i++)
|
||||
{
|
||||
GUID * book_guid;
|
||||
KvpValue *v_book_guid;
|
||||
char buff[80];
|
||||
fr = gnc_kvp_bag_find_by_guid (acc->kvp_data, "gemini",
|
||||
"book_guid", &book->guid);
|
||||
|
||||
sprintf (buff, "%d", i);
|
||||
v_book_guid = kvp_frame_get_slot_path (acc->kvp_data,
|
||||
"gemini", buff, "book_guid", NULL);
|
||||
if (!v_book_guid) continue;
|
||||
book_guid = kvp_value_get_guid (v_book_guid);
|
||||
twin_guid = kvp_frame_get_guid (fr, "acct_guid");
|
||||
twin = xaccAccountLookup (twin_guid, book);
|
||||
|
||||
if (guid_equal(book_guid, &book->guid))
|
||||
{
|
||||
Account *twin;
|
||||
GUID * acct_guid;
|
||||
KvpValue *v_acct_guid;
|
||||
|
||||
v_acct_guid = kvp_frame_get_slot_path (acc->kvp_data,
|
||||
"gemini", buff, "acct_guid", NULL);
|
||||
if (!v_acct_guid) return NULL;
|
||||
acct_guid = kvp_value_get_guid (v_acct_guid);
|
||||
|
||||
twin = xaccAccountLookup (acct_guid, book);
|
||||
return twin;
|
||||
}
|
||||
}
|
||||
LEAVE (" ");
|
||||
return NULL;
|
||||
LEAVE (" found twin=%p", twin);
|
||||
return twin;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@ -2190,17 +2167,10 @@ xaccAccountGetTaxUSCode (Account *account)
|
||||
void
|
||||
xaccAccountSetTaxUSCode (Account *account, const char *code)
|
||||
{
|
||||
KvpFrame *frame;
|
||||
|
||||
if (!account)
|
||||
return;
|
||||
if (!account) return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
|
||||
frame = kvp_frame_get_frame (account->kvp_data, "tax-US", NULL);
|
||||
|
||||
kvp_frame_set_slot_nc (frame, "code",
|
||||
code ? kvp_value_new_string (code) : NULL);
|
||||
kvp_frame_set_str (account->kvp_data, "/tax-US/code", code);
|
||||
|
||||
mark_account (account);
|
||||
account->core_dirty = TRUE;
|
||||
@ -2210,33 +2180,17 @@ xaccAccountSetTaxUSCode (Account *account, const char *code)
|
||||
const char *
|
||||
xaccAccountGetTaxUSPayerNameSource (Account *account)
|
||||
{
|
||||
KvpValue *value;
|
||||
|
||||
if (!account)
|
||||
return FALSE;
|
||||
|
||||
value = kvp_frame_get_slot_path (account->kvp_data,
|
||||
"tax-US", "payer-name-source", NULL);
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
return kvp_value_get_string (value);
|
||||
if (!account) return NULL;
|
||||
return kvp_frame_get_string (account->kvp_data, "/tax-US/payer-name-source");
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountSetTaxUSPayerNameSource (Account *account, const char *source)
|
||||
{
|
||||
KvpFrame *frame;
|
||||
|
||||
if (!account)
|
||||
return;
|
||||
if (!account) return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
|
||||
frame = kvp_frame_get_frame (account->kvp_data, "tax-US", NULL);
|
||||
|
||||
kvp_frame_set_slot_nc (frame, "payer-name-source",
|
||||
source ? kvp_value_new_string (source) : NULL);
|
||||
kvp_frame_set_str (account->kvp_data, "/tax-US/payer-name-source", source);
|
||||
|
||||
mark_account (account);
|
||||
account->core_dirty = TRUE;
|
||||
@ -2539,14 +2493,11 @@ xaccAccountGetReconcileLastDate (Account *account, time_t *last_date)
|
||||
void
|
||||
xaccAccountSetReconcileLastDate (Account *account, time_t last_date)
|
||||
{
|
||||
KvpFrame *frame;
|
||||
if (!account)
|
||||
return;
|
||||
if (!account) return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
frame = kvp_frame_get_frame (account->kvp_data, "reconcile-info", NULL);
|
||||
kvp_frame_set_slot_nc (frame, "last-date",
|
||||
kvp_value_new_gint64 (last_date));
|
||||
kvp_frame_set_gint64 (account->kvp_data,
|
||||
"/reconcile-info/last-date", last_date);
|
||||
|
||||
mark_account (account);
|
||||
account->core_dirty = TRUE;
|
||||
@ -2586,16 +2537,15 @@ void
|
||||
xaccAccountSetReconcileLastInterval (Account *account, int months, int days)
|
||||
{
|
||||
KvpFrame *frame;
|
||||
if (!account)
|
||||
return;
|
||||
if (!account) return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
frame = kvp_frame_get_frame (account->kvp_data, "reconcile-info",
|
||||
"last-interval", NULL);
|
||||
kvp_frame_set_slot_nc (frame, "months",
|
||||
kvp_value_new_gint64 (months));
|
||||
kvp_frame_set_slot_nc (frame, "days",
|
||||
kvp_value_new_gint64 (days));
|
||||
|
||||
frame = kvp_frame_get_frame (account->kvp_data,
|
||||
"/reconcile-info/last-interval");
|
||||
|
||||
kvp_frame_set_gint64 (frame, "months", months);
|
||||
kvp_frame_set_gint64 (frame, "days", days);
|
||||
|
||||
mark_account (account);
|
||||
account->core_dirty = TRUE;
|
||||
@ -2637,16 +2587,13 @@ void
|
||||
xaccAccountSetReconcilePostponeDate (Account *account,
|
||||
time_t postpone_date)
|
||||
{
|
||||
KvpFrame *frame;
|
||||
if (!account)
|
||||
return;
|
||||
if (!account) return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
frame = kvp_frame_get_frame (account->kvp_data,
|
||||
"reconcile-info", "postpone", NULL);
|
||||
|
||||
kvp_frame_set_slot_nc (frame, "date",
|
||||
kvp_value_new_gint64 (postpone_date));
|
||||
/* XXX this should be using timespecs, not gints !! */
|
||||
kvp_frame_set_gint64 (account->kvp_data,
|
||||
"/reconcile-info/postpone/date", postpone_date);
|
||||
|
||||
mark_account (account);
|
||||
account->core_dirty = TRUE;
|
||||
@ -2689,16 +2636,11 @@ void
|
||||
xaccAccountSetReconcilePostponeBalance (Account *account,
|
||||
gnc_numeric balance)
|
||||
{
|
||||
KvpFrame *frame;
|
||||
if (!account)
|
||||
return;
|
||||
if (!account) return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
frame = kvp_frame_get_frame (account->kvp_data,
|
||||
"reconcile-info", "postpone", NULL);
|
||||
|
||||
kvp_frame_set_slot_nc (frame, "balance",
|
||||
kvp_value_new_gnc_numeric (balance));
|
||||
kvp_frame_set_gnc_numeric (account->kvp_data,
|
||||
"/reconcile-info/postpone/balance", balance);
|
||||
|
||||
mark_account (account);
|
||||
account->core_dirty = TRUE;
|
||||
@ -2763,18 +2705,15 @@ xaccAccountGetAutoInterestXfer (Account *account, gboolean default_value)
|
||||
void
|
||||
xaccAccountSetAutoInterestXfer (Account *account, gboolean option)
|
||||
{
|
||||
KvpFrame *frame;
|
||||
if (!account)
|
||||
return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
frame = kvp_frame_get_frame (account->kvp_data,
|
||||
"reconcile-info", NULL);
|
||||
|
||||
/* FIXME: need KVP_TYPE_BOOLEAN for this someday */
|
||||
|
||||
kvp_frame_set_slot_nc (frame, "auto-interest-transfer",
|
||||
kvp_value_new_string (option ? "true" : "false"));
|
||||
kvp_frame_set_str (account->kvp_data,
|
||||
"/reconcile-info/auto-interest-transfer",
|
||||
(option ? "true" : "false"));
|
||||
|
||||
mark_account (account);
|
||||
account->core_dirty = TRUE;
|
||||
@ -2904,19 +2843,16 @@ dxaccAccountGetQuoteTZ(Account *acc)
|
||||
void
|
||||
xaccAccountSetReconcileChildrenStatus(Account *account, gboolean status)
|
||||
{
|
||||
KvpFrame *frame;
|
||||
if (!account)
|
||||
return;
|
||||
if (!account) return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
|
||||
frame = kvp_frame_get_frame (account->kvp_data, "reconcile-info", NULL);
|
||||
kvp_frame_set_slot_nc (frame,
|
||||
"include-children",
|
||||
status ? kvp_value_new_gint64 (status) : NULL);
|
||||
/* XXX FIXME: someday this should use KVP_TYPE_BOOLEAN */
|
||||
kvp_frame_set_gint64 (account->kvp_data,
|
||||
"/reconcile-info/include-children", status);
|
||||
|
||||
account->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit (account);
|
||||
return;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
|
@ -598,7 +598,7 @@ find_nearest_equity_acct (Account *acc)
|
||||
AccountGroup *parent;
|
||||
Account *next_up, *candidate;
|
||||
|
||||
/* see if we can find an equity account that is peered to this account */
|
||||
/* See if we can find an equity account that is peered to this account */
|
||||
parent = xaccAccountGetParent (acc);
|
||||
g_return_val_if_fail (parent, NULL);
|
||||
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include "gnc-numeric.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "kvp_frame.h"
|
||||
#include "kvp-util-p.h"
|
||||
#include "Account.h"
|
||||
#include "Scrub3.h"
|
||||
#include "Transaction.h"
|
||||
#include "TransactionP.h"
|
||||
@ -125,48 +127,118 @@ xaccScrubSubSplitPrice (Split *split)
|
||||
|
||||
/* ================================================================= */
|
||||
|
||||
#if LATER
|
||||
/* Remove the guid of b from a */
|
||||
static void
|
||||
remove_guids (Split *sa, Split *sb)
|
||||
{
|
||||
KvpFrame *ksub;
|
||||
|
||||
/* Find and remove the matching guid's */
|
||||
ksub = gnc_kvp_bag_find_by_guid (sa->kvp_data, "lot-split",
|
||||
"peer_guid", &sb->guid);
|
||||
if (!ksub)
|
||||
{
|
||||
PERR ("merging splits that didn't have correct gemini values!");
|
||||
return;
|
||||
}
|
||||
gnc_kvp_bag_remove_frame (sa->kvp_data, "lot-split", ksub);
|
||||
kvp_frame_delete (ksub);
|
||||
}
|
||||
|
||||
/* The 'merge_splits() routine causes the amount & value of sb
|
||||
* to be merged into sa; it then destroys sb. It also performs
|
||||
* some other misc cleanup */
|
||||
|
||||
static void
|
||||
merge_splits (Split *sa, Split *sb)
|
||||
{
|
||||
Account *act;
|
||||
Transaction *txn;
|
||||
gnc_numeric amt, val;
|
||||
|
||||
act = xaccSplitGetAccount (sb);
|
||||
xaccAccountBeginEdit (act);
|
||||
|
||||
txn = sa->parent;
|
||||
xaccTransBeginEdit (txn);
|
||||
/* whack kvp of b, remove gem kvp of a */
|
||||
/* whack memo etc. b */
|
||||
/* set reconsile to no */
|
||||
/* add amounts, values */
|
||||
|
||||
/* Remove the guid of sb from the 'gemini' of sa */
|
||||
remove_guids (sa, sb);
|
||||
|
||||
/* Add amount of sb into sa, ditto for value. */
|
||||
amt = xaccSplitGetAmount (sa);
|
||||
amt = gnc_numeric_add_fixed (amt, xaccSplitGetAmount (sb));
|
||||
xaccSplitSetAmount (sa, amt);
|
||||
|
||||
val = xaccSplitGetValue (sa);
|
||||
val = gnc_numeric_add_fixed (val, xaccSplitGetValue (sb));
|
||||
xaccSplitSetValue (sa, val);
|
||||
|
||||
/* Set reconcile to no; after this much violence,
|
||||
* no way its reconciled. */
|
||||
xaccSplitSetReconcile (sa, NREC);
|
||||
|
||||
/* Finally, delete sb */
|
||||
xaccSplitDestroy(sb);
|
||||
|
||||
xaccTransCommitEdit (txn);
|
||||
|
||||
xaccAccountCommitEdit (act);
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
xaccScrubMergeSubSplits (Split *split)
|
||||
{
|
||||
gboolean rc = FALSE;
|
||||
Transaction *txn;
|
||||
KvpFrame *sf;
|
||||
SplitList *node;
|
||||
GNCLot *lot;
|
||||
|
||||
sf = is_subsplit (split);
|
||||
if (!sf) return;
|
||||
if (!sf) return FALSE;
|
||||
|
||||
txn = split->parent;
|
||||
lot = xaccSplitGetLot (split);
|
||||
|
||||
ENTER (" ");
|
||||
for (node=split->parent->splits; node; node=node->next)
|
||||
restart:
|
||||
for (node=txn->splits; node; node=node->next)
|
||||
{
|
||||
Split *s = node->data;
|
||||
if (xaccSplitGetLot (s) != lot) continue;
|
||||
|
||||
/* OK, this split is in the same lot (and thus same account)
|
||||
* as the indicated split. It must be a subsplit. Merge the
|
||||
* as the indicated split. It must be a subsplit (although
|
||||
* we should double-check the kvp's to be sure). Merge the
|
||||
* two back together again. */
|
||||
merge_splits (split, s);
|
||||
rc = TRUE;
|
||||
goto restart;
|
||||
}
|
||||
LEAVE (" ");
|
||||
LEAVE (" splits merged=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
gboolean
|
||||
xaccScrubMergeTxnSubSplits (Transaction *txn)
|
||||
{
|
||||
gboolean rc = FALSE;
|
||||
SplitList *node;
|
||||
|
||||
if (!txn) return FALSE;
|
||||
|
||||
ENTER (" ");
|
||||
restart:
|
||||
for (node=txn->splits; node; node=node->next)
|
||||
{
|
||||
Split *s = node->data;
|
||||
if (!xaccScrubMergeSubSplits(s)) continue;
|
||||
|
||||
rc = TRUE;
|
||||
goto restart;
|
||||
}
|
||||
LEAVE (" splits merged=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================== END OF FILE ========================= */
|
||||
|
@ -50,5 +50,23 @@
|
||||
*/
|
||||
void xaccScrubSubSplitPrice (Split *split);
|
||||
|
||||
/** The xaccScrubMergeSubSplits() routine will merge together
|
||||
* all of the splits that were at one time split off from this
|
||||
* split, but are no longer needed to be kept separate. Splits
|
||||
* migt be split up if they need to be divided over multiple
|
||||
* lots; they can be merged back together if the lots change.
|
||||
* In particular, two sub-splits may be merged if they are in
|
||||
* the same lot, or in no lot. Note that, by definition, all
|
||||
* subsplits belong to the same transaction.
|
||||
*
|
||||
* The routine returns TRUE if a merger was performed, else
|
||||
* it returns FALSE.
|
||||
*
|
||||
* The xaccScrubMergeTxnSubSplits() routine does the same, except
|
||||
* that it does it for all of the splits in the transaction.
|
||||
*/
|
||||
gboolean xaccScrubMergeSubSplits (Split *split);
|
||||
gboolean xaccScrubMergeTxnSubSplits (Transaction *txn);
|
||||
|
||||
#endif /* XACC_SCRUB3_H */
|
||||
/** @} */
|
||||
|
@ -2696,17 +2696,20 @@ xaccTransGetNotes (const Transaction *trans)
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
/* The posted date is kept in sync using a lazy-evaluation scheme.
|
||||
* If xaccTransactionSetDatePosted() is called, the date change is
|
||||
* accepted, and the split is marked date-dirty. If the posted date
|
||||
* is queried for (using GetDatePosted()), then the transaction is
|
||||
* evaluated. If its a gains-transaction, then it's date is copied
|
||||
* from the source transaction that created the gains.
|
||||
/** The xaccScrubGainsDate() routine is used to keep the posted date
|
||||
* of gains splis in sync with the posted date of the transaction
|
||||
* that caused the gains.
|
||||
*
|
||||
* The posted date is kept in sync using a lazy-evaluation scheme.
|
||||
* If xaccTransactionSetDatePosted() is called, the date change is
|
||||
* accepted, and the split is marked date-dirty. If the posted date
|
||||
* is queried for (using GetDatePosted()), then the transaction is
|
||||
* evaluated. If its a gains-transaction, then it's date is copied
|
||||
* from the source transaction that created the gains.
|
||||
*/
|
||||
|
||||
|
||||
static inline void
|
||||
handle_gains_date (Transaction *trans)
|
||||
xaccScrubGainsDate (Transaction *trans)
|
||||
{
|
||||
SplitList *node;
|
||||
Timespec ts = {0,0};
|
||||
@ -2750,7 +2753,7 @@ time_t
|
||||
xaccTransGetDate (const Transaction *trans)
|
||||
{
|
||||
if (!trans) return 0;
|
||||
handle_gains_date((Transaction *) trans); /* XXX wrong not const ! */
|
||||
xaccScrubGainsDate((Transaction *) trans); /* XXX wrong not const ! */
|
||||
return (trans->date_posted.tv_sec);
|
||||
}
|
||||
|
||||
@ -2758,7 +2761,7 @@ void
|
||||
xaccTransGetDatePostedTS (const Transaction *trans, Timespec *ts)
|
||||
{
|
||||
if (!trans || !ts) return;
|
||||
handle_gains_date((Transaction *) trans); /* XXX wrong not const ! */
|
||||
xaccScrubGainsDate((Transaction *) trans); /* XXX wrong not const ! */
|
||||
*ts = (trans->date_posted);
|
||||
}
|
||||
|
||||
@ -2774,7 +2777,7 @@ xaccTransRetDatePostedTS (const Transaction *trans)
|
||||
{
|
||||
Timespec ts = {0, 0};
|
||||
if (!trans) return ts;
|
||||
handle_gains_date((Transaction *) trans); /* XXX wrong not const ! */
|
||||
xaccScrubGainsDate((Transaction *) trans); /* XXX wrong not const ! */
|
||||
return (trans->date_posted);
|
||||
}
|
||||
|
||||
|
@ -407,13 +407,13 @@ xaccSplitAssignToLot (Split *split,
|
||||
/* Add kvp markup to indicate that these two splits used
|
||||
* to be one before being 'split'
|
||||
*/
|
||||
gnc_kvp_array (split->kvp_data, "/lot-split", now,
|
||||
"peer_guid", xaccSplitGetGUID (new_split),
|
||||
NULL);
|
||||
gnc_kvp_bag_add (split->kvp_data, "lot-split", now,
|
||||
"peer_guid", xaccSplitGetGUID (new_split),
|
||||
NULL);
|
||||
|
||||
gnc_kvp_array (new_split->kvp_data, "/lot-split", now,
|
||||
"peer_guid", xaccSplitGetGUID (split),
|
||||
NULL);
|
||||
gnc_kvp_bag_add (new_split->kvp_data, "lot-split", now,
|
||||
"peer_guid", xaccSplitGetGUID (split),
|
||||
NULL);
|
||||
|
||||
xaccSplitSetAmount (new_split, amt_b);
|
||||
xaccSplitSetValue (new_split, val_b);
|
||||
|
@ -81,6 +81,7 @@ gnc_log_init (void)
|
||||
{
|
||||
fout = stderr;
|
||||
fout = stdout;
|
||||
fout = fopen ("/tmp/gnucash.trace", "w");
|
||||
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, fh_printer, fout);
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,9 @@
|
||||
* outside of the engine.
|
||||
*/
|
||||
|
||||
/** The gnc_kvp_array() routine is used to maintain a list of pointers
|
||||
* in a kvp tree.
|
||||
/** The gnc_kvp_bag_add() routine is used to maintain a collection
|
||||
* of pointers in a kvp tree.
|
||||
*
|
||||
* The thing being pointed at is uniquely identified by its GUID.
|
||||
* This routine is typically used to create a linked list, and/or
|
||||
* a collection of pointers to objects that are 'related' to each
|
||||
@ -47,22 +48,53 @@
|
||||
* the corresponding GUID pointer (const GUID *). Terminate the varargs
|
||||
* with a NULL as the last string argument.
|
||||
*
|
||||
* The actual 'pointer' is stored in an array in a subdirectory
|
||||
* of the directory 'path'.
|
||||
* The size of the array is in /ncopies. The pointer is stored in
|
||||
* /<n>/<name> where <n> = ncopies -1, <name> was passed as an argument.
|
||||
* In addition, the date is logged. Thus, for example:
|
||||
* The actual 'pointer' is stored in a subdirectory in a bag located at
|
||||
* the node directory 'path'. A 'bag' is merely a collection of
|
||||
* (unamed) values. The name of our bag is 'path'. A bag can contain
|
||||
* any kind of values, including frames. This routine will create a
|
||||
* frame, and put it in the bag. The frame will contain named data
|
||||
* from the subroutine arguments. Thus, for example:
|
||||
*
|
||||
* gnc_kvp_array (kvp, "foo", secs, "acct_guid", aguid,
|
||||
* "book_guid", bguid, NULL);
|
||||
* will increment /foo/ncopies, and will store aguid in
|
||||
* /foo/<n>/acct_guid and bguid in /foo/<n>/book_guid, where <n> = ncopies-1
|
||||
*
|
||||
* will create a frame containing "/acct_guid" and "/book_guid", whose
|
||||
* values are aguid and bguid respecitvely. The frame will also
|
||||
* contain "/date", whose value will be secs. This frame will be
|
||||
* placed into the bag located at "foo".
|
||||
*
|
||||
* This routine returns a pointer to the frame that was created, or
|
||||
* NULL if an error occured.
|
||||
*/
|
||||
|
||||
void gnc_kvp_array (KvpFrame *kvp_root, const char *path, time_t secs,
|
||||
KvpFrame * gnc_kvp_bag_add (KvpFrame *kvp_root, const char *path, time_t secs,
|
||||
const char *first_name, ...);
|
||||
|
||||
/* Equivalent to gnc_kvp_array(kvp_root, "gemini", secs, firstname, ...); */
|
||||
/* Equivalent to gnc_kvp_bag_add(kvp_root, "gemini", secs, firstname, ...); */
|
||||
void gnc_kvp_gemini (KvpFrame *kvp_root, time_t secs,
|
||||
const char *first_name, ...);
|
||||
|
||||
|
||||
/** The gnc_kvp_bag_find_by_guid() routine examines the bag pointed
|
||||
* located at root. It looks for a frame in that bag that has the
|
||||
* guid value of "desired_guid" filed under the key name "guid_name".
|
||||
* If it finds that matching guid, then it returns a pointer to
|
||||
* the KVP frame that contains it. If it is not found, or if there
|
||||
* is any other error, NULL is returned.
|
||||
*/
|
||||
|
||||
KvpFrame * gnc_kvp_bag_find_by_guid (KvpFrame *root, const char * path,
|
||||
const char *guid_name, GUID *desired_guid);
|
||||
|
||||
|
||||
/** Remove the given frame from the bag. The frame is removed,
|
||||
* however, it is not deleted. Note that the frame pointer must
|
||||
* be a pointer to the actual frame (for example, as returned by
|
||||
* gnc_kvp_bag_find_by_guid() for by gnc_kvp_bag_add()), and not
|
||||
* some copy of the frame.
|
||||
*/
|
||||
|
||||
void gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path,
|
||||
KvpFrame *fr);
|
||||
|
||||
#endif /* XACC_KVP_UTIL_P_H */
|
||||
|
@ -33,46 +33,19 @@
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
static void
|
||||
static KvpFrame *
|
||||
gnc_kvp_array_va (KvpFrame *kvp_root, const char * path,
|
||||
time_t secs, const char * first_name, va_list ap)
|
||||
{
|
||||
char buff[80];
|
||||
KvpFrame *cwd, *pwd;
|
||||
KvpValue *v_ncopies;
|
||||
gint64 ncopies = 0;
|
||||
KvpFrame *cwd;
|
||||
Timespec ts;
|
||||
const char *name;
|
||||
|
||||
if (!kvp_root) return;
|
||||
if (!first_name) return;
|
||||
if (!kvp_root) return NULL;
|
||||
if (!first_name) return NULL;
|
||||
|
||||
if (!path)
|
||||
{
|
||||
pwd = kvp_root;
|
||||
}
|
||||
else
|
||||
{
|
||||
pwd = kvp_frame_get_frame_slash (kvp_root, path);
|
||||
if (!pwd) return; /* error: can't ever happen */
|
||||
}
|
||||
|
||||
/* Find, increment, store number of copies */
|
||||
v_ncopies = kvp_frame_get_slot (pwd, "ncopies");
|
||||
if (v_ncopies)
|
||||
{
|
||||
ncopies = kvp_value_get_gint64 (v_ncopies);
|
||||
}
|
||||
|
||||
ncopies ++;
|
||||
kvp_frame_set_gint64 (pwd, "ncopies", ncopies);
|
||||
|
||||
/* OK, now create subdirectory and put the actual data */
|
||||
--ncopies;
|
||||
sprintf (buff, GNC_SCANF_LLD, (long long int) ncopies);
|
||||
|
||||
/* Create subdirectory and put the actual data */
|
||||
cwd = kvp_frame_new();
|
||||
kvp_frame_set_slot_nc(pwd, buff, kvp_value_new_frame_nc(cwd));
|
||||
|
||||
/* Record the time */
|
||||
ts.tv_sec = secs;
|
||||
@ -81,7 +54,6 @@ gnc_kvp_array_va (KvpFrame *kvp_root, const char * path,
|
||||
|
||||
/* Loop over the args */
|
||||
name = first_name;
|
||||
|
||||
while (name)
|
||||
{
|
||||
const GUID *guid;
|
||||
@ -91,18 +63,24 @@ gnc_kvp_array_va (KvpFrame *kvp_root, const char * path,
|
||||
|
||||
name = va_arg (ap, const char *);
|
||||
}
|
||||
|
||||
/* Attach cwd into the array */
|
||||
kvp_frame_add_frame_nc (kvp_root, path, cwd);
|
||||
return cwd;
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
void
|
||||
gnc_kvp_array (KvpFrame *pwd, const char * path,
|
||||
time_t secs, const char *first_name, ...)
|
||||
KvpFrame *
|
||||
gnc_kvp_bag_add (KvpFrame *pwd, const char * path,
|
||||
time_t secs, const char *first_name, ...)
|
||||
{
|
||||
KvpFrame *cwd;
|
||||
va_list ap;
|
||||
va_start (ap, first_name);
|
||||
gnc_kvp_array_va (pwd, path, secs, first_name, ap);
|
||||
cwd = gnc_kvp_array_va (pwd, path, secs, first_name, ap);
|
||||
va_end (ap);
|
||||
return cwd;
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
@ -116,6 +94,78 @@ gnc_kvp_gemini (KvpFrame *kvp_root, time_t secs, const char *first_name, ...)
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
#define MATCH_GUID(elt) { \
|
||||
KvpFrame *fr = kvp_value_get_frame (elt); \
|
||||
if (fr) { \
|
||||
GUID *guid = kvp_frame_get_guid (fr, guid_name); \
|
||||
if (guid && guid_equal (desired_guid, guid)) return fr; \
|
||||
} \
|
||||
}
|
||||
|
||||
KvpFrame *
|
||||
gnc_kvp_bag_find_by_guid (KvpFrame *root, const char * path,
|
||||
const char *guid_name, GUID *desired_guid)
|
||||
{
|
||||
KvpValue *arr;
|
||||
KvpValueType valtype;
|
||||
GList *node;
|
||||
|
||||
arr = kvp_frame_get_value (root, path);
|
||||
valtype = kvp_value_get_type (arr);
|
||||
if (KVP_TYPE_FRAME == valtype)
|
||||
{
|
||||
MATCH_GUID (arr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Its gotta be a single isolated frame, or a list of them. */
|
||||
if (KVP_TYPE_GLIST != valtype) return NULL;
|
||||
|
||||
for (node = kvp_value_get_glist(arr); node; node=node->next)
|
||||
{
|
||||
KvpValue *va = node->data;
|
||||
MATCH_GUID (va);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
#define KILL_MATCH(elt) \
|
||||
if (fr == kvp_value_get_frame (elt)) { \
|
||||
KvpValue *old_val = kvp_frame_replace_value_nc (root, path, NULL); \
|
||||
kvp_value_replace_frame_nc (old_val, NULL); \
|
||||
kvp_value_delete (old_val); \
|
||||
return; \
|
||||
}
|
||||
|
||||
void
|
||||
gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path, KvpFrame *fr)
|
||||
{
|
||||
KvpValue *arr;
|
||||
KvpValueType valtype;
|
||||
GList *node;
|
||||
|
||||
arr = kvp_frame_get_value (root, path);
|
||||
valtype = kvp_value_get_type (arr);
|
||||
if (KVP_TYPE_FRAME == valtype)
|
||||
{
|
||||
KILL_MATCH (arr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Its gotta be a single isolated frame, or a list of them. */
|
||||
if (KVP_TYPE_GLIST != valtype) return;
|
||||
|
||||
for (node = kvp_value_get_glist(arr); node; node=node->next)
|
||||
{
|
||||
KvpValue *va = node->data;
|
||||
KILL_MATCH (va);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
/*
|
||||
* See header for docs.
|
||||
|
@ -159,36 +159,30 @@ Use: GUID of the split that records the capital gains for this split.
|
||||
-----------------------
|
||||
|
||||
Name: /gemini/
|
||||
Type: kvp_frame
|
||||
Type: kvp_glist
|
||||
Entities: Account, Book
|
||||
Use: kvp subdirectory holding identification of accounts or books
|
||||
Use: kvp bag holding frames that identify accounts or books
|
||||
that are copies of this account.
|
||||
|
||||
Name: /gemini/ncopies
|
||||
Type: int64
|
||||
Entities: Account, Book
|
||||
Use: number of subdirectories containing copy info.
|
||||
|
||||
Name: /gemini/0/
|
||||
Name: /gemini/*
|
||||
Type: kvp_frame
|
||||
Entities: Account, Book
|
||||
Use: subdirectory holding identification of the first copied account.
|
||||
Other copies would appear in directories /gemini/1/, /gemini/2/,
|
||||
etc.
|
||||
Use: bag value holds a frame that identifies a single copied account.
|
||||
Other copies would appear in other bag values.
|
||||
|
||||
Name: /gemini/0/acct_guid
|
||||
Name: /gemini/*/acct_guid
|
||||
Type: guid
|
||||
Entities: Account
|
||||
Use: guid of another account that is a copy of this one.
|
||||
|
||||
Name: /gemini/0/book_guid
|
||||
Name: /gemini/*/book_guid
|
||||
Type: guid
|
||||
Entities: Account, Book
|
||||
Use: When this appears in an account, then it contains the guid of
|
||||
the book that the other account belongs to. When this appears
|
||||
in a book, then this is the guid of the other book.
|
||||
|
||||
Name: /gemini/0/date
|
||||
Name: /gemini/*/date
|
||||
Type: timespec
|
||||
Entities: Account, Book
|
||||
Use: date that the copy was created.
|
||||
@ -268,13 +262,13 @@ Use: The next unused lot id number, used to autogenerate
|
||||
|
||||
|
||||
Name: /lot-split/
|
||||
Type: kvp_frame
|
||||
Type: kvp_glist
|
||||
Entities: Split
|
||||
Use: A gemini-style kvp subdirectory holding identification of splits
|
||||
that were split off of this split. See /gemini/ for additional
|
||||
doco's.
|
||||
Use: A bag of kvp frames holding identification of splits
|
||||
that were split off of this split. Same style as the
|
||||
/gemini/, look there for additional doco's.
|
||||
|
||||
Name: /lot-split/0/peer_guid
|
||||
Name: /lot-split/*/peer_guid
|
||||
Type: GUID
|
||||
Entities: Split
|
||||
Use: The GUID of the peer split which was split from this split.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
/********************************************************************\
|
||||
* kvp_frame.h -- Implements a key-value frame system *
|
||||
* This program 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 *
|
||||
@ -20,7 +21,7 @@
|
||||
/** @addtogroup Engine
|
||||
@{ */
|
||||
/** @file kvp_frame.h
|
||||
@brief A key-value frame system for gnucash
|
||||
@brief A key-value frame system
|
||||
@author Copyright (C) 2000 Bill Gribble
|
||||
@author Copyright (C) 2003 Linas Vepstas <linas@linas.org>
|
||||
*/
|
||||
@ -70,7 +71,10 @@ typedef struct _KvpFrame KvpFrame;
|
||||
* KvpValueType enum. */
|
||||
typedef struct _KvpValue KvpValue;
|
||||
|
||||
/** Enum to enumerate possible types in the union KvpValue */
|
||||
/** Enum to enumerate possible types in the union KvpValue
|
||||
* XXX FIXME TODO: People have asked for boolean values,
|
||||
* e.g. in xaccAccountSetAutoInterestXfer
|
||||
*/
|
||||
typedef enum {
|
||||
KVP_TYPE_GINT64,
|
||||
KVP_TYPE_DOUBLE,
|
||||
@ -114,19 +118,83 @@ gboolean kvp_frame_is_empty(KvpFrame * frame);
|
||||
/*@}*/
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/** @name KvpFrame Value Storing */
|
||||
/** @name KvpFrame Basic Value Storing */
|
||||
/*@{*/
|
||||
|
||||
/** The kvp_frame_set_str() routine will store a string at the indicated path.
|
||||
* If not all frame components of the path exist, they are created.
|
||||
* */
|
||||
/** The kvp_frame_set_gint64() routine will store the value of the
|
||||
* gint64 at the indicated path. If not all frame components of
|
||||
* the path exist, they are created.
|
||||
*
|
||||
* Similarly, the set_double, set_numeric, and set_timespec
|
||||
* routines perform the same function, for each of the respective
|
||||
* types.
|
||||
*/
|
||||
void kvp_frame_set_gint64(KvpFrame * frame, const char * path, gint64 ival);
|
||||
void kvp_frame_set_double(KvpFrame * frame, const char * path, double dval);
|
||||
void kvp_frame_set_gnc_numeric(KvpFrame * frame, const char * path, gnc_numeric nval);
|
||||
void kvp_frame_set_str(KvpFrame * frame, const char * path, const char* str);
|
||||
void kvp_frame_set_guid(KvpFrame * frame, const char * path, const GUID *guid);
|
||||
void kvp_frame_set_timespec(KvpFrame * frame, const char * path, Timespec ts);
|
||||
|
||||
/** The kvp_frame_set_str() routine will store a copy of the string
|
||||
* at the indicated path. If not all frame components of the path
|
||||
* exist, they are created. If there was another string previously
|
||||
* stored at that path, the old copy is deleted.
|
||||
*
|
||||
* Similarly, the set_guid and set_frame will make copies and
|
||||
* store those. Old copies, if any, are deleted.
|
||||
*
|
||||
* The kvp_frame_set_frame_nc() routine works as above, but does
|
||||
* *NOT* copy the frame.
|
||||
*/
|
||||
void kvp_frame_set_str(KvpFrame * frame, const char * path, const char* str);
|
||||
void kvp_frame_set_guid(KvpFrame * frame, const char * path, const GUID *guid);
|
||||
|
||||
void kvp_frame_set_frame(KvpFrame *frame, const char *path, KvpFrame *chld);
|
||||
void kvp_frame_set_frame_nc(KvpFrame *frame, const char *path, KvpFrame *chld);
|
||||
|
||||
/** The kvp_frame_set_value() routine copies the value into the frame,
|
||||
* at the location 'path'. If the path contains slashes '/', these
|
||||
* are assumed to represent a sequence of keys. The returned value
|
||||
* is a pointer to the actual frame into which the value was inserted;
|
||||
* it is NULL if the frame couldn't be found (and thus the value wasn't
|
||||
* inserted). The old value at this location, if any, is destroyed.
|
||||
*
|
||||
* Pointers passed as arguments into this routine are the responsibility
|
||||
* of the caller; the pointers are *not* taken over or managed.
|
||||
*/
|
||||
KvpFrame * kvp_frame_set_value(KvpFrame * frame,
|
||||
const char * path, const KvpValue * value);
|
||||
/**
|
||||
* The kvp_frame_set_value_nc() routine puts the value (without copying
|
||||
* it) into the frame, putting it at the location 'path'. If the path
|
||||
* contains slashes '/', these are assumed to represent a sequence of keys.
|
||||
* The returned value is a pointer to the actual frame into which the value
|
||||
* was inserted; it is NULL if the frame couldn't be found (and thus the
|
||||
* value wasn't inserted). The old value at this location, if any,
|
||||
* is destroyed.
|
||||
*
|
||||
* This routine is handy for avoiding excess memory allocations & frees.
|
||||
* Note that because the KvpValue was grabbed, you can't just delete
|
||||
* unless you remove the key as well (or unless you replace the value).
|
||||
*/
|
||||
KvpFrame * kvp_frame_set_value_nc(KvpFrame * frame,
|
||||
const char * path, KvpValue * value);
|
||||
|
||||
/** The kvp_frame_replace_value_nc() routine places the new value
|
||||
* at the indicated path. It returns the old value, if any.
|
||||
* It returns NULL if there was an error, or if there was no
|
||||
* old value. If the path doesn't exist, it is created, unless
|
||||
* new_value is NULL. Passing in a NULL new_value has the
|
||||
* effect of deleting the trailing slot (i.e. the trailing path
|
||||
* element).
|
||||
*/
|
||||
KvpValue * kvp_frame_replace_value_nc (KvpFrame * frame, const char * slot,
|
||||
KvpValue * new_value);
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name KvpFrame URL handling */
|
||||
/*@{*/
|
||||
/** The kvp_frame_add_url_encoding() routine will parse the
|
||||
* value string, assuming it to be URL-encoded in the standard way,
|
||||
* turning it into a set of key-value pairs, and adding those to the
|
||||
@ -142,6 +210,62 @@ void kvp_frame_set_timespec(KvpFrame * frame, const char * path, Timespec ts);
|
||||
void kvp_frame_add_url_encoding (KvpFrame *frame, const char *enc);
|
||||
/*@}*/
|
||||
|
||||
/** @name KvpFrame Glist Bag Storing */
|
||||
/*@{*/
|
||||
|
||||
/** The kvp_frame_add_gint64() routine will add the value of the
|
||||
* gint64 to the glist bag of values at the indicated path.
|
||||
* If not all frame components of the path exist, they are
|
||||
* created. If the value previously stored at this path was
|
||||
* not a glist bag, then a bag will be formed there, the old
|
||||
* value placed in the bag, and the new value added to the bag.
|
||||
*
|
||||
* Similarly, the add_double, add_numeric, and add_timespec
|
||||
* routines perform the same function, for each of the respective
|
||||
* types.
|
||||
*/
|
||||
void kvp_frame_add_gint64(KvpFrame * frame, const char * path, gint64 ival);
|
||||
void kvp_frame_add_double(KvpFrame * frame, const char * path, double dval);
|
||||
void kvp_frame_add_gnc_numeric(KvpFrame * frame, const char * path, gnc_numeric nval);
|
||||
void kvp_frame_add_timespec(KvpFrame * frame, const char * path, Timespec ts);
|
||||
|
||||
/** The kvp_frame_add_str() routine will add a copy of the string
|
||||
* to the glist bag at the indicated path. If not all frame components
|
||||
* of the path exist, they are created. If there was another
|
||||
* item previously stored at that path, then the path is converted
|
||||
* to a bag, and the old value, along with the new value, is added
|
||||
* to the bag.
|
||||
*
|
||||
* Similarly, the add_guid and add_frame will make copies and
|
||||
* add those.
|
||||
*
|
||||
* The kvp_frame_add_frame_nc() routine works as above, but does
|
||||
* *NOT* copy the frame.
|
||||
*/
|
||||
void kvp_frame_add_str(KvpFrame * frame, const char * path, const char* str);
|
||||
void kvp_frame_add_guid(KvpFrame * frame, const char * path, const GUID *guid);
|
||||
|
||||
void kvp_frame_add_frame(KvpFrame *frame, const char *path, KvpFrame *chld);
|
||||
void kvp_frame_add_frame_nc(KvpFrame *frame, const char *path, KvpFrame *chld);
|
||||
|
||||
/* The kvp_frame_add_value() routine will add a copy of the value
|
||||
* to the glist bag at the indicated path. If not all frame components
|
||||
* of the path exist, they are created. If there was another
|
||||
* item previously stored at that path, then the path is converted
|
||||
* to a bag, and the old value, along with the new value, is added
|
||||
* to the bag. This routine returns the pointer to the last frame
|
||||
* (the actual frame to which the value was added), or NULL if there
|
||||
* was an error of any sort (typically, a parse error in the path).
|
||||
*
|
||||
* The *_nc() routine is analogous, except that it doesn't copy the
|
||||
* value.
|
||||
*/
|
||||
KvpFrame * kvp_frame_add_value(KvpFrame * frame, const char * path, KvpValue *value);
|
||||
KvpFrame * kvp_frame_add_value_nc(KvpFrame * frame, const char * path, KvpValue *value);
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/** @name KvpFrame Value Fetching */
|
||||
/*@{*/
|
||||
@ -152,12 +276,24 @@ void kvp_frame_add_url_encoding (KvpFrame *frame, const char *enc);
|
||||
asked for, then a NULL or a zero is returned. So, for example,
|
||||
asking for a string when the path stored an int will return a NULL.
|
||||
In some future date, this may be changed to a looser type system,
|
||||
such as perl's automatic re-typing.
|
||||
such as perl's automatic re-typing (e.g. an integer value might be
|
||||
converted to a printed string representing that value).
|
||||
|
||||
If any part of the path does not exist, then NULL or zero will be
|
||||
returned.
|
||||
|
||||
The values returned for GUID, binary, GList, KvpFrame and string
|
||||
are "non-copying" -- the returned item is the actual item stored.
|
||||
Do not delete this item unless you take the required care to avoid
|
||||
possible bad pointer derefrences (i.e. core dumps).
|
||||
possible bad pointer derefrences (i.e. core dumps). Also, be
|
||||
careful anging on to those references if you are also storing
|
||||
at the same path names: the referenced item will be freed during
|
||||
the store.
|
||||
|
||||
That is, if you get a string value (or guid, binary or frame),
|
||||
and then store something else at that path, the string that you've
|
||||
gotten will be freed during the store (internally, by the set_*()
|
||||
routines), and you will be left hanging onto an invalid pointer.
|
||||
*/
|
||||
|
||||
gint64 kvp_frame_get_gint64(const KvpFrame *frame, const char *path);
|
||||
@ -168,20 +304,25 @@ GUID * kvp_frame_get_guid(const KvpFrame *frame, const char *path);
|
||||
void * kvp_frame_get_binary(const KvpFrame *frame, const char *path,
|
||||
guint64 * size_return);
|
||||
Timespec kvp_frame_get_timespec(const KvpFrame *frame, const char *path);
|
||||
KvpValue * kvp_frame_get_value(const KvpFrame *frame, const char *path);
|
||||
KvpFrame * kvp_frame_get_frame(const KvpFrame *frame, const char *path);
|
||||
|
||||
/** This routine returns the last frame of the path.
|
||||
* If the frame path doesn't exist, it is created.
|
||||
* Note that this is *VERY DIFFERENT FROM* like kvp_frame_get_frame()
|
||||
*/
|
||||
KvpFrame * kvp_frame_get_frame (KvpFrame *frame, const char *,...);
|
||||
KvpFrame * kvp_frame_get_frame_path (KvpFrame *frame, const char *,...);
|
||||
|
||||
/** This routine return the last frame of the path.
|
||||
* If the frame path doesn't exist, it is created.
|
||||
* Note that this is *VERY DIFFERENT FROM* like kvp_frame_get_frame()
|
||||
*/
|
||||
KvpFrame * kvp_frame_get_frame_gslist (KvpFrame *frame,
|
||||
GSList *key_path);
|
||||
|
||||
/** This routine return the last frame of the path.
|
||||
* If the frame path doesn't exist, it is created.
|
||||
* Note that this is *VERY DIFFERENT FROM* like kvp_frame_get_frame()
|
||||
*
|
||||
* The kvp_frame_get_frame_slash() routine takes a single string
|
||||
* where the keys are separated by slashes; thus, for example:
|
||||
@ -200,37 +341,31 @@ KvpFrame * kvp_frame_get_frame_slash (KvpFrame *frame,
|
||||
|
||||
/** You probably shouldn't be using these low-level routines */
|
||||
|
||||
/** The kvp_frame_set_slot_slash() routine copies the value into the frame,
|
||||
* at the location 'path'. If the path contains slashes '/', these
|
||||
* are assumed to represent a sequence of keys. The returned value
|
||||
* is a pointer to the actual frame into which the value was inserted;
|
||||
* it is NULL if the frame couldn't be found (and thus the value wasn't
|
||||
* inserted).
|
||||
/** All of the kvp_frame_set_slot_*() routines set the slot values
|
||||
* "destructively", in that if there was an old value there, that
|
||||
* old value is destroyed (and the memory freed). Thus, one
|
||||
* should not hang on to value pointers, as these will get
|
||||
* trashed if set_slot is called on the corresponding key.
|
||||
*
|
||||
* Pointers passed as arguments into this routine are the responsibility
|
||||
* of the caller; the pointers are *not* taken over or managed.
|
||||
* If you want the old value, use kvp_frame_replace_slot().
|
||||
*/
|
||||
KvpFrame * kvp_frame_set_slot_slash(KvpFrame * frame,
|
||||
const char * path, const KvpValue * value);
|
||||
/**
|
||||
* The kvp_frame_set_slot_slash_nc() routine puts the value (without copying
|
||||
* it) into the frame, putting it at the location 'path'. If the path
|
||||
* contains slashes '/', these are assumed to represent a sequence of keys.
|
||||
* The returned value is a pointer to the actual frame into which the value
|
||||
* was inserted; it is NULL if the frame couldn't be found (and thus the
|
||||
* value wasn't inserted).
|
||||
*
|
||||
* This routine is handy for avoiding excess memory allocations & frees.
|
||||
* Note that because the KvpValue was grabbed, you can't just delete
|
||||
* unless you remove the key as well (or unless you replace the value).
|
||||
|
||||
/** The kvp_frame_replace_slot_nc() routine places the new value into
|
||||
* the indicated frame, for the given key. It returns the old
|
||||
* value, if any. It returns NULL if the slot doesn't exist,
|
||||
* if there was some other an error, or if there was no old value.
|
||||
* Passing in a NULL new_value has the effect of deleting that
|
||||
* slot.
|
||||
*/
|
||||
KvpFrame * kvp_frame_set_slot_slash_nc(KvpFrame * frame,
|
||||
const char * path, KvpValue * value);
|
||||
KvpValue * kvp_frame_replace_slot_nc (KvpFrame * frame, const char * slot,
|
||||
KvpValue * new_value);
|
||||
|
||||
|
||||
/** The kvp_frame_set_slot() routine copies the value into the frame,
|
||||
* associating it with a copy of 'key'. Pointers passed as arguments
|
||||
* into kvp_frame_set_slot are the responsibility of the caller;
|
||||
* the pointers are *not* taken over or managed.
|
||||
* the pointers are *not* taken over or managed. The old value at
|
||||
* this location, if any, is destroyed.
|
||||
*/
|
||||
void kvp_frame_set_slot(KvpFrame * frame,
|
||||
const char * key, const KvpValue * value);
|
||||
@ -240,21 +375,24 @@ void kvp_frame_set_slot(KvpFrame * frame,
|
||||
* routine is handy for avoiding excess memory allocations & frees.
|
||||
* Note that because the KvpValue was grabbed, you can't just delete
|
||||
* unless you remove the key as well (or unless you replace the value).
|
||||
* The old value at this location, if any, is destroyed.
|
||||
*/
|
||||
void kvp_frame_set_slot_nc(KvpFrame * frame,
|
||||
const char * key, KvpValue * value);
|
||||
|
||||
/** The kvp_frame_set_slot_path() routine walks the hierarchy,
|
||||
* using the key values to pick each branch. When the terminal node
|
||||
* is reached, the value is copied into it.
|
||||
* using the key values to pick each branch. When the terminal
|
||||
* node is reached, the value is copied into it. The old value
|
||||
* at this location, if any, is destroyed.
|
||||
*/
|
||||
void kvp_frame_set_slot_path (KvpFrame *frame,
|
||||
const KvpValue *value,
|
||||
const char *first_key, ...);
|
||||
|
||||
/** The kvp_frame_set_slot_path_gslist() routine walks the hierarchy,
|
||||
* using the key values to pick each branch. When the terminal node
|
||||
* is reached, the value is copied into it.
|
||||
* using the key values to pick each branch. When the terminal node
|
||||
* is reached, the value is copied into it. The old value at this
|
||||
* location, if any, is destroyed.
|
||||
*/
|
||||
void kvp_frame_set_slot_path_gslist (KvpFrame *frame,
|
||||
const KvpValue *value,
|
||||
@ -268,7 +406,9 @@ void kvp_frame_set_slot_path_gslist (KvpFrame *frame,
|
||||
/** You probably shouldn't be using these low-level routines */
|
||||
|
||||
/** Returns the KvpValue in the given KvpFrame 'frame' that is
|
||||
* associated with 'key'.
|
||||
* associated with 'key'. If there is no key in the frame, NULL
|
||||
* is returned. If the value associated with the key is NULL,
|
||||
* NULL is returned.
|
||||
*
|
||||
* Pointers passed as arguments into get_slot are the responsibility
|
||||
* of the caller. Pointers returned by get_slot are owned by the
|
||||
@ -297,22 +437,30 @@ gint kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb);
|
||||
|
||||
gint double_compare(double v1, double v2);
|
||||
|
||||
/** list convenience funcs. */
|
||||
/** @name KvpValue List Convenience Functions */
|
||||
/*@{*/
|
||||
/** You probably shouldn't be using these low-level routines */
|
||||
|
||||
/** kvp_glist_compare() compares <b>GLists of kvp_values</b> (not to
|
||||
* be confused with GLists of something else): it iterates over
|
||||
* the list elements, performing a kvp_value_compare on each.
|
||||
*/
|
||||
gint kvp_glist_compare(const GList * list1, const GList * list2);
|
||||
|
||||
/** kvp_glist_copy() performs a deep copy of a <b>GList of
|
||||
* kvp_frame's</b> (not to be confused with GLists of something
|
||||
/** kvp_glist_copy() performs a deep copy of a <b>GList of
|
||||
* kvp_values</b> (not to be confused with GLists of something
|
||||
* else): same as mapping kvp_value_copy() over the elements and
|
||||
* then copying the spine.
|
||||
*/
|
||||
GList * kvp_glist_copy(const GList * list);
|
||||
|
||||
/** kvp_glist_delete() performs a deep delete of a <b>GList of
|
||||
* kvp_frame's</b> (not to be confused with GLists of something
|
||||
* kvp_values</b> (not to be confused with GLists of something
|
||||
* else): same as mapping * kvp_value_delete() over the elements
|
||||
* and then deleting the GList.
|
||||
*/
|
||||
void kvp_glist_delete(GList * list);
|
||||
/*@}*/
|
||||
|
||||
|
||||
/** @name KvpValue Constructors */
|
||||
@ -331,11 +479,11 @@ KvpValue * kvp_value_new_string(const char * value);
|
||||
KvpValue * kvp_value_new_guid(const GUID * guid);
|
||||
KvpValue * kvp_value_new_timespec(Timespec timespec);
|
||||
KvpValue * kvp_value_new_binary(const void * data, guint64 datasize);
|
||||
KvpValue * kvp_value_new_frame(const KvpFrame * value);
|
||||
|
||||
/** Creates a KvpValue from a <b>GList of kvp_value's</b>! (Not to be
|
||||
* confused with GList's of something else!) */
|
||||
KvpValue * kvp_value_new_glist(const GList * value);
|
||||
KvpValue * kvp_value_new_frame(const KvpFrame * value);
|
||||
|
||||
/** value constructors (non-copying - KvpValue takes pointer ownership)
|
||||
values *must* have been allocated via glib allocators! (gnew, etc.) */
|
||||
@ -358,21 +506,30 @@ void kvp_value_delete(KvpValue * value);
|
||||
|
||||
/** This is a deep value copy. */
|
||||
KvpValue * kvp_value_copy(const KvpValue * value);
|
||||
|
||||
/** replace old frame value with new, return old frame */
|
||||
KvpFrame * kvp_value_replace_frame_nc(KvpValue *value, KvpFrame * newframe);
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
/** @name KvpValue Value access */
|
||||
/*@{*/
|
||||
/** You probably shouldn't be using these low-level routines */
|
||||
/** Value accessors. Those for GUID, binary, GList, KvpFrame and
|
||||
string are non-copying -- the caller can modify the value directly.
|
||||
|
||||
Note that the above non-copying list did not include the
|
||||
get_string() function. But in fact that function has always been a
|
||||
non-copying one -- therefore don't free the result unless you want
|
||||
to delete the whole KvpFrame by yourself. */
|
||||
KvpValueType kvp_value_get_type(const KvpValue * value);
|
||||
|
||||
|
||||
/** Value accessors. Those for GUID, binary, GList, KvpFrame and
|
||||
* string are non-copying -- the caller can modify the value
|
||||
* directly. Just don't free it, or you screw up everything.
|
||||
* Note that if another value is stored at the key location
|
||||
* that this value came from, then this value will be
|
||||
* uncermoniously deleted, and you will be left pointing to
|
||||
* garbage. So don't store values at the same time you are
|
||||
* examining thier contents.
|
||||
*/
|
||||
|
||||
gint64 kvp_value_get_gint64(const KvpValue * value);
|
||||
double kvp_value_get_double(const KvpValue * value);
|
||||
gnc_numeric kvp_value_get_numeric(const KvpValue * value);
|
||||
|
Loading…
Reference in New Issue
Block a user