-
Notifications
You must be signed in to change notification settings - Fork 761
/
engine.texinfo
1645 lines (1241 loc) · 58.6 KB
/
engine.texinfo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
@node Engine, Register, Top Level, Top
@chapter Engine
@cindex The Engine
The Engine provides an interface to a financial engine with three basic
financial entities: Accounts, Transactions (known as Journal Entries in
accounting practice), and Splits (known as Ledger Entries). These three
entities are the central data structures of the GnuCash financial data
model.
In addition, the Engine provides the abstraction of Account Groups
(collections of related accounts) and GNCBooks. A GNCBook abstracts both
a set of related GnuCash data (financial entities plus additional
information such as budgets, per-file preferences, etc.) plus a
file-editing session allowing transparent support for locking and
implementation with other backends such as SQL.
The Engine code contains no GUI code whatsoever and is designed to
be created as a shared library for use by other programs.
@menu
* Engine Introduction::
* Using and Extending the Engine API::
* Globally Unique Identifiers::
* Numeric Library::
* Key-Value Pair Frames::
* Splits::
* Transactions::
* Accounts::
* Account Groups::
* GNCBooks::
* Scrub::
@end menu
@node Engine Introduction, Using and Extending the Engine API, Engine, Engine
@section Introduction
Splits (@pxref{Splits}), or "Ledger Entries" are the fundamental
accounting units. Each Split consists of a quantity (number of dollar
bills, number of shares, etc.), the price of that quantity (the price of
one dollar is 1.00 dollars, etc.), a Memo, a pointer to the parent
Transaction, a pointer to the debited Account, a reconciled flag and
timestamp, an "Action" field, and a key-value frame which can store
arbitrary data (@pxref{Key-Value Pair Frames}).
Transactions (@pxref{Transactions}) embody the notion of "double entry"
accounting. A Transaction consists of a date, a description, a number, a
list of one or more Splits, and a key-value frame. When double-entry
rules are enforced, the total value of the splits is zero. Note that if
there is just one split, its value must be zero for double-entry
accounting; this is useful because a zero-valued split can store a price
(useful for e.g. tracking stocks). If there are two splits, then the
value of one must be positive, the other negative: this denotes that one
account is credited, and another is debited by an equal amount. Positive
Split values are 'debits' and negative Split values are 'credits'.
Ensuring the Splits to 'add up' to zero causes a double-entry accounting
system to always balance.
The engine does not enforce double-entry accounting, but provides an API
to enable user-code to find unbalanced transactions and 'repair' them so
that they are in balance. @xref{Scrub}.
Note the sum of the values of Splits in a Transaction is always computed
with respect to a currency; thus splits can be balanced even when they
are in different currencies, as long as they share a common currency.
The conversion price is simply the price stored in the Split. This
feature allows currency-trading accounts to be established.
Every Split must point at its parent Transaction, and that Transaction
must in turn include that Split in the Transaction's list of Splits. A
Split can belong to at most one Transaction. These relationships are
forced by the engine. The engine user cannnot accidentally destroy this
relationship as long as they stick to using the API and never access
internal structures directly.
Splits are grouped into Accounts (@pxref{Accounts}) which are also known
as "Ledgers" in accouting practice. Each Account consists of a list of
Splits that debit that Account. To ensure consistency, if a Split points
at an Account, then the Account must point at the Split, and vice-versa.
A Split can belong to at most one Account. Besides merely containing a
list of Splits, the Account structure also give the Account a name, a
code number, description and notes fields, a key-value frame, a pointer
to the currency that is used for all splits in this account, and a
pointer to the "security" used for all splits in this account. The
"security" can be the name of a stock (e.g. "IBM", "McDonald's"), or
another currency (e.g. "USD", "GBP"). The security is used during
Transaction balancing to enable trading between accounts denominated in
different currencies, or to, for example, move stocks from one Account
to another.
Accounts can be arranged in a hierarchical tree. The nodes of the tree
are called "Account Groups" (@pxref{Account Groups}). By accounting
convention, the value of an Account is equal to the value of all of its
Splits plus the value of all of its sub-Accounts.
@node Using and Extending the Engine API, Globally Unique Identifiers, Engine Introduction, Engine
@section Using and Extending the Engine API
Engine API calls are named using a specific convention. For example,
the function to access the Memo field of a Split is
@code{xaccSplitGetMemo}. The prefix @code{xacc} comes
first@footnote{The @code{xacc} prefix is a historical artifact. GnuCash
was derived from X-Accountant by Robin Clark.}, followed by the name of
the entity for which the API call applies (@code{Split}), followed by
the action performed by the call (@code{Get}), followed by the name of
the field being accessed (@code{Memo}). Future API calls should conform
to this naming convention.
The formal arguments to Engine API calls always begin with the entity to
which the call applies. Thus, the arguments to @code{xaccSplitSetMemo}
are the @code{Split} pointer followed by the pointer to a memo
string. Future API calls should also conform to this convention.
Engine API calls should be implemented to behave as gracefully as
possible with unexpected input. Specifically, public API calls should
gracefully handle @code{NULL} pointer arguments. User code should be
able to handle @code{NULL} return values from Engine calls as well.
@node Globally Unique Identifiers, Numeric Library, Using and Extending the Engine API, Engine
@section Globally Unique Identifiers
@cindex Globally Unique Identifier
@tindex GUID
It is common for Engine structures to reference other Engine structures.
For example, an Account must reference its Splits, its parent Account
Group, and its child Account Group. Furthermore, other GnuCash modules
may need to reference Engine structures. For example, a GUI
implementation may wish to save a list of Accounts which the user has
open when the application exits in order to restore that same state upon
the next invocation.
One way to uniquely identify an Engine structure, at least while the
program is running, is using the C pointer which points to the
structure. C pointers have the advantage of speed, but also have some
disadvantages:
@itemize
@item
Pointers cannot be used in data files and are not persistant across
different program invocations.
@item
When an entity is destroyed, every other structure which references that
entity through a direct pointer must be immediately updated to prevent
illegal accesses.
@end itemize
The @dfn{GUID} (Globally Unique Identifier) provides a way to reference
Engine structures that is more flexible than C pointers. Each Engine
structure has an associated GUID which can be used to reference that
structure. Engine GUIDs have the following features:
@itemize
@item
The GUID is permanent, i.e., it persists between invocations of GnuCash.
@item
The GUID is guaranteed to be unique with the set of all Splits,
Transactions, and Accounts in the hierarchy of which the structure
is a member.
@item
With very high probability, the GUID is unique among all GUIDs
created by any invocation of GnuCash, all over the world.
@item
GUIDs can be efficiently encoded in a string representation.
@end itemize
@menu
* When to use GUIDs::
* GUID Types::
* How to use GUIDs::
* GUIDs and GnuCash Entities::
* The GUID Generator::
@end menu
@node When to use GUIDs, GUID Types, Globally Unique Identifiers, Globally Unique Identifiers
@subsection When to use GUIDs
@cindex When to use GUIDs
Although GUIDs are very flexible, the engine structures like Accounts
will probably continue to use C pointers for the forseeable future,
since they are much faster (and in certain respects more convenient)
than using GUIDs. In general, however, it is much safer to use GUIDs.
In particular, you should consider using GUIDs if any of the following
is true:
@itemize
@item
You need to save a reference to an engine structure in a file.
@item
You need to save a reference to an engine structure that could
be deleted in between accesses to the saved reference.
@end itemize
@node GUID Types, How to use GUIDs, When to use GUIDs, Globally Unique Identifiers
@subsection GUID Types
@tindex GNCIdType
The GUIDs in GnuCash are typed using the enum @code{GNCIdType}.
Possible values and their meanings for GUID types are:
@table @code
@item GNC_ID_NONE
The GUID does not currently refer to a GnuCash entity, though it
could refer to one in the future.
@item GNC_ID_NULL
The GUID does not, and never will, refer to a GnuCash entity.
@item GNC_ID_ACCOUNT
The GUID refers to an Account (@pxref{Accounts}).
@item GNC_ID_TRANS
The GUID refers to a Transation (@pxref{Transactions}).
@item GNC_ID_SPLIT
The GUID refers to a Split (@pxref{Splits}).
@end table
@deftypefun GNCIdType xaccGUIDType (const GUID * @var{guid})
Return the type associated with @var{guid}.
@end deftypefun
@deftypefun {const GUID *} xaccGUIDNull (void)
Return a GUID which is guaranteed to always have type @code{GNC_ID_NULL}.
@end deftypefun
@node How to use GUIDs, GUIDs and GnuCash Entities, GUID Types, Globally Unique Identifiers
@subsection How to use GUIDs
The Engine API functions which access the GUID for a specific entity
return a pointer to the GUID. @strong{Note:} Do not store the pointer
itself! Instead, store a copy of the GUID. Storing the pointer itself
would present some of the same problems as using the account pointer
directly. Example:
@example
@{
GUID saved_guid;
Account *account;
account = < something to get an Account pointer >
saved_guid = *xaccAccountGetGuid(account);
...
account = xaccAccountLookup(&saved_guid);
...
@}
@end example
You can compare two GUIDs for equality with the following function.
@deftypefun gboolean guid_equal(const GUID * @var{guid_1}, const GUID * @var{guid_2})
Compare two guids and return TRUE if they are both non-NULL and equal.
@end deftypefun
You can encode and decode GUIDs and their string representations using the
next two functions.
@deftypefun {char *} guid_to_string(const GUID * @var{guid})
Return a null-terminated string encoding of @var{guid}. String encodings
of identifiers are hex numbers printed only with the characters @code{0}
through @code{9} and @code{a} through @code{f}. The encoding will
always be @code{GUID_ENCODING_LENGTH} characters long. The returned
string should be freed when no longer needed.
@end deftypefun
@deftypefun gboolean string_to_guid(const char * @var{string}, GUID * @var{guid})
Given a string, decode an id into @var{guid} if @var{guid} is
non-NULL. The function returns TRUE if the string was a valid 32
character hexadecimal number. This function accepts both upper and lower
case hex digits. If the return value is FALSE, the effect on @var{guid}
is undefined.
@end deftypefun
@node GUIDs and GnuCash Entities, The GUID Generator, How to use GUIDs, Globally Unique Identifiers
@subsection GUIDs and GnuCash Entities
This section documents a low-level API for associating entities with
GUIDs. User code and general engine code should not use this API;
instead use the API documented in the sections for the specific GnuCash
entities such as Accounts and Transactions.
@deftypefun void xaccGUIDNew(GUID * @var{guid})
Generate a new guid. This function is guaranteed to return a guid that
is unique within the scope of all GnuCash entities being managed by the
the current invocation of GnuCash. GnuCash routines should always use
this function and not @code{guid_new}!
@end deftypefun
@deftypefun {void *} xaccLookupEntity(const GUID * @var{guid}, GNCIdType @var{entity_type})
Lookup an entity given an id and a type. If there is no entity
associated with the id, or if it has a different type, NULL is returned.
@end deftypefun
@deftypefun void xaccStoreEntity(void * @var{entity}, const GUID * @var{guid}, GNCIdType entity_type)
Store the given entity under the given id with the given type.
@end deftypefun
@deftypefun void xaccRemoveEntity(const GUID * @var{guid})
Remove any existing association between an entity and the given id. The
entity is not changed in any way.
@end deftypefun
@node The GUID Generator, , GUIDs and GnuCash Entities, Globally Unique Identifiers
@subsection The GUID Generator
@cindex The GUID Generator
GUIDs are created by the GUID generator. The API for this generator is
low-level and should not be used by user-code.
@deftypefun void guid_init (void)
Initialize the GUID generator with a variety of random sources including
common system files and /dev/random.
@end deftypefun
@deftypefun void guid_init_with_salt (const void * @var{salt}, size_t @var{salt_len})
Initialize the GUID generator with guid_init() and with the given
sequence of arbitrary binary data.
@end deftypefun
@deftypefun void guid_init_only_salt (const void * @var{salt}, size_t @var{salt_len})
Initialize the GUID generator using only the given sequence of arbitrary
binary data. This provides a way to reliably obtain a given sequence of
GUIDs.
@end deftypefun
@deftypefun void guid_new (GUID * @var{guid})
Create a new GUID and store it in @var{guid}. This is a low-level function!
GnuCash code should use @code{xaccGUIDNew}.
@end deftypefun
@node Numeric Library, Key-Value Pair Frames, Globally Unique Identifiers, Engine
@section Numeric Library
@cindex Numeric Library
@tindex gnc_numeric
Financial quantities in GnuCash (Split quantities and values) are stored
as exact quantities measured in the smallest denominational unit of the
appropriate currency. For example, 100.50 US Dollars would be stored as
(10050 / 100) US Dollars. GnuCash uses the @code{gnc_numeric} datatype
to store financial quantities.
The @code{gnc_numeric} API provides data types and functions for
manipulating exact numeric quantities. While the @code{gnc_numeric}
library was developed to represent and operate on exact financial
quantities in GnuCash, the library is also (hopefully) suitable for use
in any application where exact numeric representation for rational
numbers is needed.
A @code{gnc_numeric} value represents a number in rational form, with a
64-bit @code{long long} integer as numerator and denominator. If more
precision, a higher-precision representation of irrational numbers, or a
wider dynamic range is needed, a floating point format may be
appropriate. There are reasonable rational approximations to common
irrational constants (@pxref{Numeric Example}), but the transcendental
functions have not been implemented for @code{gnc_numeric} objects.
@menu
* Standard Numeric Arguments::
* Creating Numeric Objects::
* Basic Arithmetic Operations::
* Numeric Comparisons and Predicates::
* Numeric Denominator Conversion::
* Numeric Floating Point Conversion::
* Numeric String Conversion::
* Numeric Error Handling ::
* Numeric Example::
@end menu
@node Standard Numeric Arguments, Creating Numeric Objects, Numeric Library, Numeric Library
@subsection Standard Numeric Arguments
@cindex Standard Numeric Arguments
It is useful to specify a denominator in cases where it is known that
the output value is of constrained precision. For example, monetary
transactions must be executed in an integer number of the "smallest
currency unit" of the transaction. In US Dollars, the smallest currency
unit is the cent, and all monetary transactions must be done in units of
cents. Therefore, any fractional cents in a computed price must be
rounded away.
Most of the @code{gnc_numeric} arithmetic functions take two arguments
in addition to their numeric args: @var{denom}, which is the denominator
to use in the output @code{gnc_numeric object}, and @var{how}, which
describes how the arithmetic result is to be converted to that
denominator. This combination of output denominator and rounding policy
allows the results of financial and other exact computations to be
properly rounded to the appropriate units.
Valid values for @var{denom} are:
@table @code
@item n (positive int)
Use the number @code{n} as the denominator of the output value.
@item GNC_DENOM_RECIPROCAL (n)
Use the value @code{1/n} as the denominator of the output value.
@item GNC_DENOM_AUTO
Compute an appropriate denominator automatically. Flags in the @var{how}
argument will specify how to compute the denominator.
@end table
Valid values for @var{how} are bitwise combinations of zero or one
"rounding instructions" with zero or one "denominator types".
Rounding instructions control how fractional parts in the specified
denominator affect the result. For example, if a computed result is
"3/4" but the specified denominator for the return value is 2, should
the return value be "1/2" or "2/2"?
Possible rounding instructions are:
@table @code
@item GNC_RND_FLOOR
Round toward -infinity
@item GNC_RND_CEIL
Round toward +infinity
@item GNC_RND_TRUNC
Truncate fractions (round toward zero)
@item GNC_RND_PROMOTE
Promote fractions (round away from zero)
@item GNC_RND_ROUND
Use unbiased ("banker's") rounding. This rounds to the nearest integer,
and to the nearest even integer when there are two equidistant nearest
integers. This is generally the one you should use for financial
quantities.
@item GNC_RND_ROUND_HALF_UP
Round to the nearest integer, rounding away from zero when there are two
equidistant nearest integers.
@item GNC_RND_ROUND_HALF_DOWN
Round to the nearest integer, rounding toward zero when there are two
equidistant nearest integers.
@item GNC_RND_NEVER
Never round at all, and signal an error if there is a fractional result
in a computation.
@end table
The denominator type specifies how to compute a denominator if
@code{GNC_DENOM_AUTO} is specified as the @var{denom}. Valid denominator
types are:
@table @code
@item GNC_DENOM_EXACT
Use any denominator which gives an exactly correct ratio of numerator to
denominator. Use EXACT when you do not wish to lose any information in
the result but also do not want to spend any time finding the "best"
denominator.
@item GNC_DENOM_REDUCE
Reduce the result value by common factor elimination, using the smallest
possible value for the denominator that keeps the correct ratio. The
numerator and denominator of the result are relatively prime. This can
be computationally expensive for large fractions.
@item GNC_DENOM_LCD
Find the least common multiple of the arguments' denominators and use
that as the denominator of the result.
@item GNC_DENOM_FIXED
All arguments are required to have the same denominator, that
denominator is to be used in the output, and an error is to be signaled
if any argument has a different denominator.
@end table
To use traditional rational-number operational semantics (all results
are exact and are reduced to relatively-prime fractions) pass the
argument @code{GNC_DENOM_AUTO} as @var{denom} and @code{GNC_DENOM_REDUCE
| GNC_RND_NEVER} as @var{how}.
To enforce strict financial semantics (such that all operands must have
the same denominator as each other and as the result), use
@var{GNC_DENOM_AUTO} as @var{denom} and @code{GNC_DENOM_FIXED |
GNC_RND_NEVER} as @var{how}.
@node Creating Numeric Objects, Basic Arithmetic Operations, Standard Numeric Arguments, Numeric Library
@subsection Creating Numeric Objects
@cindex Creating Numeric Objects
@deftypefun gnc_numeric gnc_numeric_create (int @var{num}, int @var{denom})
Create a @code{gnc_numeric} object with a value of "@var{num} / @var{denom}".
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_zero ()
Create a @code{gnc_numeric} object with a value of 0.
@end deftypefun
@node Basic Arithmetic Operations, Numeric Comparisons and Predicates, Creating Numeric Objects, Numeric Library
@subsection Basic Arithmetic Operations
@cindex Basic Arithmetic Operations
See @ref{Standard Numeric Arguments} for a description of the @var{denom}
and @var{how} arguments to each arithmetic function.
@deftypefun gnc_numeric gnc_numeric_add (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how})
Return the sum of @var{a} and @var{b}.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_sub (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how})
Return "@var{a} - @var{b}".
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_mul (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how})
Return the product of @var{a} and @var{b}.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_div (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how})
Return "@var{a} / @var{b}".
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_neg (gnc_numeric @var{a})
Return "-@var{a}".
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_abs (gnc_numeric @var{a})
Return the absolute value of @var{a}.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_add_fixed (gnc_numeric @var{a}, gnc_numeric @var{b})
Equivalent to @code{gnc_numeric_add} on @var{a} and @var{b} with
@code{GNC_DENOM_AUTO} for @var{denom} and @code{GNC_DENOM_FIXED |
GNC_RND_NEVER} for @var{how}.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_sub_fixed (gnc_numeric @var{a}, gnc_numeric @var{b})
Equivalent to @code{gnc_numeric_sub} on @var{a} and @var{b} with
@code{GNC_DENOM_AUTO} for @var{denom} and @code{GNC_DENOM_FIXED |
GNC_RND_NEVER} for @var{how}.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_add_with_error (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how}, {gnc_numeric *} @var{error})
The same as @code{gnc_numeric_add}, but uses @var{error} for accumulating
conversion roundoff error.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_sub_with_error (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how}, {gnc_numeric *} @var{error})
The same as @code{gnc_numeric_sub}, but uses @var{error} for accumulating
conversion roundoff error.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_mul_with_error (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how}, {gnc_numeric *} @var{error})
The same as @code{gnc_numeric_mul}, but uses @var{error} for accumulating
conversion roundoff error.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_div_with_error (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how}, {gnc_numeric *} @var{error})
The same as @code{gnc_numeric_div}, but uses @var{error} for accumulating
conversion roundoff error.
@end deftypefun
@node Numeric Comparisons and Predicates, Numeric Denominator Conversion, Basic Arithmetic Operations, Numeric Library
@subsection Numeric Comparisons and Predicates
@cindex Numeric Comparisons and Predicates
@deftypefun int gnc_numeric_zero_p (gnc_numeric @var{a})
Returns 1 if @code{@var{a} == 0}, otherwise returns 0.
@end deftypefun
@deftypefun int gnc_numeric_positive_p (gnc_numeric @var{a})
Returns 1 if @code{@var{a} > 0}, otherwise returns 0.
@end deftypefun
@deftypefun int gnc_numeric_negative_p (gnc_numeric @var{a})
Returns 1 if @code{@var{a} > 0}, otherwise returns 0.
@end deftypefun
@deftypefun int gnc_numeric_compare (gnc_numeric @var{a}, gnc_numeric @var{b})
Returns +1 if @code{@var{a} > @var{b}}, -1 if @code{@var{b} > @var{a}}, 0 if @code{@var{a} == @var{b}}.
@end deftypefun
@deftypefun int gnc_numeric_eq (gnc_numeric @var{a}, gnc_numeric @var{b})
Returns 1 if @code{numerator(@var{a}) == numerator(@var{b})} and
@code{denominator(@var{a}) == denominator(@var{b})}, otherwise returns 0.
@end deftypefun
@deftypefun int gnc_numeric_equal (gnc_numeric @var{a}, gnc_numeric @var{b})
Returns 1 if the fraction represented by @var{a} is equal to the fraction
represented by @var{b}, otherwise returns 0.
@end deftypefun
@deftypefun int gnc_numeric_same (gnc_numeric @var{a}, gnc_numeric @var{b}, gint64 @var{denom}, gint @var{how})
Convert both @var{a} and @var{b} to @var{denom} (@pxref{Standard Numeric
Arguments} and compare numerators of the result.
@example
For example, if @code{@var{a} == 7/16} and @code{@var{b} == 3/4},
@code{gnc_numeric_same(@var{a}, @var{b}, 2, GNC_RND_TRUNC) == 1}
because both 7/16 and 3/4 round to 1/2 under truncation. However,
@code{gnc_numeric_same(@var{a}, @var{b}, 2, GNC_RND_ROUND) == 0}
because 7/16 rounds to 1/2 under unbiased rounding but 3/4 rounds
to 2/2.
@end example
@end deftypefun
@node Numeric Denominator Conversion, Numeric Floating Point Conversion, Numeric Comparisons and Predicates, Numeric Library
@subsection Numeric Denominator Conversion
@cindex Numeric Denominator Conversion
@deftypefun gnc_numeric gnc_numeric_convert (gnc_numeric @var{in}, gint64 @var{denom}, gint @var{how})
Convert @var{in} to the specified denominator under standard arguments
@var{denom} and @var{how}. @xref{Standard Numeric Arguments}.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_convert_with_error (gnc_numeric @var{in}, gint64 @var{denom}, gint @var{how}, {gnc_numeric *} @var{error})
Same as @code{gnc_numeric_convert}, but return a remainder value for
accumulating conversion error.
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_reduce (gnc_numeric @var{in})
Return @var{in} reduced by GCF reduction.
@end deftypefun
@node Numeric Floating Point Conversion, Numeric String Conversion, Numeric Denominator Conversion, Numeric Library
@subsection Numeric Floating Point Conversion
@cindex Numeric Floating Point Conversion
@deftypefun gnc_numeric double_to_gnc_numeric (double @var{arg}, gint64 @var{denom}, gint @var{how})
Convert a floating-point number to a @code{gnc_numeric}. Both @var{denom}
and @var{how} are used as in arithmetic, but @code{GNC_DENOM_AUTO} is
not recognized.
@end deftypefun
@deftypefun double gnc_numeric_to_double (gnc_numeric @var{arg})
Convert @var{arg} to a @code{double} value.
@end deftypefun
@node Numeric String Conversion, Numeric Error Handling , Numeric Floating Point Conversion, Numeric Library
@subsection Numeric String Conversion
@cindex Numeric String Conversion
@deftypefun {gchar *} gnc_numeric_to_string (gnc_numeric @var{n})
Return a string representation of @var{n}. The string must be
freed with @code{g_free}.
@end deftypefun
@deftypefun {const gchar *} string_to_gnc_numeric (const {gchar *} @var{str}, {gnc_numeric *} @var{n})
Read a @code{gnc_numeric} from @var{str}, skipping any leading
whitespace, and returning a pointer to just past the last byte
read. Return NULL on error.
@end deftypefun
@node Numeric Error Handling , Numeric Example, Numeric String Conversion, Numeric Library
@subsection Numeric Error Handling
@cindex Numeric Error Handling
@deftypefun int gnc_numeric_check (gnc_numeric @var{num})
Check @var{num} for the possibility that it is an error signal rather
than a proper value. Possible return codes are:
@table @code
@item GNC_ERROR_OK
No error condition
@item GNC_ERROR_ARG
An improper argument was passed to a function
@item GNC_ERROR_OVERFLOW
An overflow occurred while calculating a result
@item GNC_ERROR_DENOM_DIFF
@code{GNC_DENOM_FIXED} was specified, but argument denominators differed.
@item GNC_ERROR_REMAINDER
@code{GNC_RND_NEVER} was specified, but the result could not be
converted to the desired denominator without a remainder.
@end table
@end deftypefun
@deftypefun gnc_numeric gnc_numeric_error (int error_code)
Create a @code{gnc_numeric} object that signals the error condition
noted by @var{error_code} rather than a number.
@end deftypefun
@node Numeric Example, , Numeric Error Handling , Numeric Library
@subsection Numeric Example
@cindex Numeric Example
The following program finds the best @code{gnc_numeric} approximation to
the @file{math.h} constant @code{M_PI} given a maximum denominator. For
large denominators, the @code{gnc_numeric} approximation is accurate to
more decimal places than will generally be needed, but in some cases
this may not be good enough. For example,
@example
M_PI = 3.14159265358979323846
245850922 / 78256779 = 3.14159265358979311599 (16 sig figs)
3126535 / 995207 = 3.14159265358865047446 (12 sig figs)
355 / 113 = 3.14159292035398252096 (7 sig figs)
@end example
@example
#include <glib.h>
#include "gnc-numeric.h"
#include <math.h>
int
main(int argc, char ** argv)
@{
gnc_numeric approx, best;
double err, best_err=1.0;
double m_pi = M_PI;
gint64 denom;
gint64 max;
sscanf(argv[1], "%Ld", &max);
for (denom = 1; denom < max; denom++)
@{
approx = double_to_gnc_numeric (m_pi, denom, GNC_RND_ROUND);
err = m_pi - gnc_numeric_to_double (approx);
if (fabs (err) < fabs (best_err))
@{
best = approx;
best_err = err;
printf ("%Ld / %Ld = %.30f\n", gnc_numeric_num (best),
gnc_numeric_denom (best), gnc_numeric_to_double (best));
@}
@}
@}
@end example
@node Key-Value Pair Frames, Splits, Numeric Library, Engine
@section Key-Value Pair Frames
@cindex Key-Value Pairs
The number and types of data items which are associated with the
financial abstractions (Accounts, Transactions, and Splits) can vary
widely. For example, an Account which represents a user's checking
account might need to store the bank name, a telephone number, and a
username for online banking purposes. Another Account representing the
user's ownership of a stock might need to store information about
retrieving price quotes online such as the ticker symbol and the
exchange.
To meet this need for varying data storage, the GnuCash accounting
entities use Key-Value Pair Frames (hereafter referred to as the
datatype @code{kvp_frame}). A @code{kvp_frame} is a set of associations
between character strings (keys) and @code{kvp_value} structures. A
@code{kvp_value} is a union with possible types enumerated in the
@code{kvp_value_t} enum which indicates the type of data stored in a
@code{kvp_value} object.
@menu
* Key-Value Policy::
* kvp_frame::
* kvp_value::
* kvp_list::
@end menu
@node Key-Value Policy, kvp_frame, Key-Value Pair Frames, Key-Value Pair Frames
@subsection Key-Value Policy
@cindex Key-Value Policy
This section defines the policy that programmers should follow
when using key-value pairs to store information. Because of the
large amount of information which can potentially be stored using
this mechanism, it is important to follow these guidelines so
that order will be maintained.
The following rules should be followed for using key-value pairs:
@itemize
@item
The document @file{src/engine/kvp_doc.txt} should be used to document the
use of keys and values. Please consult this document before planning any
use of new keys.
@item
Key strings should be in all lower case with the '-' character
separating words. If possible, use only alphanumeric characters and
'-'. Example: @code{bank-info}. Because the '/' character is useful for
describing keys in sub-frames (@code{bank-info/routing-number}), do not
use the '/' character in key names.
@item
Favor longer, descriptive key strings over short ones. Example:
@code{online-banking-info} is better than @code{onln-bnk}.
@item
Make use of the fact that frames can be stored in frames. If a group
of keys are used for a related purpose, consider storing them together
in a sub-frame.
@item
Values should generally not be accessed directly through keys, but
should rather be accessed through specific API calls. The API calls
do not necessarily need to part a part of the Engine API. For example,
the GUI would probably define keys that the Engine does not need to
know about.
@item
The same key should not be used for different engine structures (Accounts,
Transactions, Splits), unless the key's value has the same type and the
same basic purpose.
@end itemize
@node kvp_frame, kvp_value, Key-Value Policy, Key-Value Pair Frames
@subsection kvp_frame
@tindex kvp_frame
A @code{kvp_frame} is the datatype used to associate key strings with
@code{kvp_value} objects (@pxref{kvp_value}).
@deftypefun kvp_frame* kvp_frame_new (void)
Create and initialize a new @code{kvp_frame} object and return
a pointer to it.
@end deftypefun
@deftypefun void kvp_frame_delete(kvp_frame * @var{frame})
Free all memory associated with @var{frame}.
@end deftypefun
@deftypefun kvp_frame* kvp_frame_copy(const kvp_frame * frame)
Return a deep copy of @var{frame}.
@end deftypefun
@deftypefun void kvp_frame_set_slot(kvp_frame * @var{frame}, const char * @var{key}, const kvp_value * @var{value})
Associate @var{key} with @var{value} in @var{frame}.
@end deftypefun
@deftypefun kvp_value* kvp_frame_get_slot(kvp_frame * @var{frame}, const char * @var{key})
Return the @code{kvp_value} object associated with @var{key}
in @var{frame} or return @code{NULL} if there is no association
for @var{key}. The value returned is not a copy.
@end deftypefun
@node kvp_value, kvp_list, kvp_frame, Key-Value Pair Frames
@subsection kvp_value
@tindex kvp_value
@tindex kvp_value_t
The @code{kvp_value} object stores the 'value' part of a key-value
association in a @code{kvp_frame} object.
@deftypefun void kvp_value_delete(kvp_value * @var{value})
Free all of the memory associated with @var{value}.
@end deftypefun
@deftypefun kvp_value* kvp_value_copy(const kvp_value * @var{value})
Return a deep copy of @var{value}.
@end deftypefun
@deftypefun kvp_value_t kvp_value_get_type(const kvp_value * @var{value})
Return the type of value stored in @var{value}.
@end deftypefun
A @code{kvp_value_t} enum must have one of the following values:
@table @code
@item KVP_TYPE_NONE
Indicates the abscence of a value in a @code{kvp_frame}.
@item KVP_TYPE_INT64
A @code{gint64} value.
@item KVP_TYPE_FLOAT64
A @code{double} value.
@item KVP_TYPE_STRING
A @code{char *} value of arbitrary length.
@item KVP_TYPE_GUID
A @code{GUID} value. @xref{Globally Unique Identifiers}.
@item KVP_TYPE_BINARY
Arbitrary binary data.
@item KVP_TYPE_LIST
A @code{kvp_list} item which contains a list of @code{kvp_value} items.
@item KVP_TYPE_FRAME
A @code{kvp_frame} object. Thus, frames may contain other frames in a
recursive manner.
@end table
@subsubsection Value Constructors
The following functions create and return @code{kvp_value} objects with
particular values. In the case of pointer arguments, deep copies are
performed.
@deftypefun kvp_value* kvp_value_new_int64(gint64 @var{value})
@end deftypefun
@deftypefun kvp_value* kvp_value_new_float64(double @var{value})
@end deftypefun
@deftypefun kvp_value* kvp_value_new_string(const char * @var{value})
@end deftypefun
@deftypefun kvp_value* kvp_value_new_guid(const GUID * @var{guid})
@end deftypefun
@deftypefun kvp_value* kvp_value_new_binary(const void * @var{data}, int @var{datasize})
@end deftypefun
@deftypefun kvp_value* kvp_value_new_list(const kvp_list * @var{value})
@end deftypefun
@deftypefun kvp_value* kvp_value_new_frame(const kvp_frame * @var{value});
@end deftypefun
@subsubsection Value Accessors
The following functions access the value of a given @code{kvp_value}
object. If the type of the object does not correspond to that named
in the function, @code{NULL}, @code{0}, or @code{0.0} is returned
as appropriate.
@deftypefun gint64 kvp_value_get_int64(const kvp_value * @var{value})
@end deftypefun
@deftypefun double kvp_value_get_float64(const kvp_value * @var{value})
@end deftypefun
@deftypefun char* kvp_value_get_string(const kvp_value * @var{value})
@end deftypefun
@deftypefun GUID* kvp_value_get_guid(const kvp_value * @var{value})
@end deftypefun
@deftypefun void* kvp_value_get_binary(const kvp_value * @var{value}, int * @var{size_return})
@end deftypefun
@deftypefun kvp_list* kvp_value_get_list(const kvp_value * @var{value})
@end deftypefun
@deftypefun kvp_frame* kvp_value_get_frame(const kvp_value * @var{value})
@end deftypefun
@node kvp_list, , kvp_value, Key-Value Pair Frames
@subsection kvp_list
@tindex kvp_list
A @code{kvp_list} object abstract a list of @code{kvp_value} objects.
@deftypefun kvp_list* kvp_list_new()
Return a newly allocated @code{kvp_list} object.
@end deftypefun
@deftypefun void kvp_list_delete(kvp_list * @var{list})
Free all memory associated with @var{list}, including the
@code{kvp_value} objects in @var{list}.
@end deftypefun
@deftypefun kvp_list* kvp_list_copy(const kvp_list * @var{list})
Return a deep copy of @var{list}.
@end deftypefun
@deftypefun gboolean kvp_list_null_p(const kvp_list * @var{list})
Return @code{TRUE} if @var{list} is the empty list.