1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>Gedcom object model in C</title>
4 <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"></head><body text="#000000" bgcolor="#ffffff" link="#000099" vlink="#990099" alink="#000099">
6 <h1 align="center">Gedcom object model in C</h1>
12 <li><a href="#Main_functions">Main functions</a></li>
14 <li><a href="#Object_model_structure">Object model structure</a></li>
16 <li><a href="#Object_lists">Object lists</a><br>
23 <li><a href="#User_data">User data</a></li>
25 <li><a href="#Other_functions">Modifying the object model</a></li>
27 <li><a href="#Manipulating_strings">Manipulating strings</a></li><li><a href="#Adding_and_removing_records">Adding and removing records</a></li>
28 <li><a href="#Adding_rem_and_moving_xref">Adding, removing and moving cross-references</a><br>
30 <li><a href="#Adding_removing_and_moving">Adding, removing and moving sub-structures</a><br>
33 </ul><li><a href="#Writing_the_object_model_to_file">Writing the object model to file</a><br>
41 <li><a href="gomxref.html">C object model details</a><br>
47 <hr width="100%" size="2">
49 <h2><a name="Main_functions"></a>Main functions<br>
52 There are two ways to start with a GEDCOM object model (after having called <code>gedcom_init</code>): either by starting from scratch, or by starting from a given GEDCOM file. This is done via the following two functions:<br>
53 <blockquote><code>int <b>gom_parse_file</b> (const char* file_name);<br>
55 <blockquote>This initializes the object model by parsing the GEDCOM file given by <code>file_name</code>. It returns 0 on success and 1 on failure.<br>
58 <blockquote><code>int <b>gom_new_model</b> ();<br>
60 <blockquote>This starts an empty model. Actually, this is done by processing the file "<code>new.ged</code>" in the gedcom-parse data directory.<br>
63 In the GEDCOM object model, all the data is immediately available after calling <code>gom_parse_file()</code> or <code>gom_new_model()</code>. For this, an entire model based on C structs is used. These structs are documented <a href="file:///home/verthezp/src/external/gedcom-parse/doc/gomxref.html">here</a>,
64 and follow the GEDCOM syntax quite closely. Each of the records in
65 a GEDCOM file are modelled by a separate struct, and some common sub-structures
66 have their own struct definition.<br>
69 The following functions are available to get at these structs:<br>
71 <li>First, there are two functions to get the header record and the submission
72 record (there can be only one of them in a GEDCOM file):<br>
73 <blockquote><code>struct header* <b>gom_get_header</b>();<br>
74 struct submission* <b>gom_get_submission</b>();<br>
77 <li>Further, for each of the other records, there are two functions, one
78 to get the first of such records, and one to get a record via its cross-reference
79 tag in the GEDCOM file:<br>
80 <blockquote><code>struct XXX* <b>gom_get_first_XXX</b>();<br>
81 struct XXX* <b>gom_get_XXX_by_xref</b>(const char* xref);</code><br>
85 <blockquote>The <code><b>XXX</b></code> stands for one of the following: <code><b>family</b>, </code><code><b>individual</b>, <b>multimedia</b>, <b>note</b>, <b>repository</b>, <b>source</b>, <b>submitter</b>, <b>user_rec</b></code>.<br>
87 <hr width="100%" size="2">
88 <h2><a name="Object_model_structure"></a>Object model structure<br>
91 <h3><a name="Object_lists"></a>Object lists<br>
93 All records of a certain type are linked together in a linked list. The
94 above functions only give access to the first record of each linked list.
95 The others can be accessed by traversing the linked list via the <code>next</code> member of the structs. This means that e.g. the following piece of code will traverse the linked list of family records:<br>
96 <blockquote><code>struct family* fam;<br>
98 for (fam = gom_get_first_family() ; fam ; fam = fam->next) {<br>
102 The <code>next</code> member of the last element in the list is guaranteed to have the <code>NULL</code> value.<br>
104 Actually, the linked list is a doubly-linked list: each record also has a <code>previous</code> member. But for implementation reasons the behaviour of this <code>previous</code> member on the edges of the linked list will not be guaranteed, i.e. it can be circular or terminated with <code>NULL</code>, no assumptions can be made in the application code.<br>
106 This linked-list model applies also to all sub-structures of the main record structs, i.e. each struct that has a <code>next </code>and <code>previous</code>
107 member follows the above conventions. This means that the following
108 piece of code traverses all children of a family (see the details of the
109 different structs <a href="gomxref.html">here</a>):<br>
110 <blockquote><code>struct family* fam = ...;<br>
112 struct xref_list* xrl;<br>
113 for (xrl = fam->children ; xrl ; xrl = xrl->next) {<br>
117 Note that all character strings in the object model are encoded in UTF-8 (<a href="file:///home/verthezp/src/external/gedcom-parse/doc/encoding.html">Why UTF-8?</a>), but see <a href="#Manipulating_strings">below</a> for how to convert these automatically.<br>
118 <h3><a name="User_data"></a>User data</h3>
121 Each of the structs has an extra member called <code>extra</code> (of type <code>struct user_data*</code>).
122 This gathers all non-standard GEDCOM tags within the scope of the struct
123 in a flat linked list, no matter what the internal structure of the non-standard
124 tags is. Each element of the linked list has:<br>
126 <li>a level: the level number in the GEDCOM file</li>
127 <li>a tag: the tag given in the GEDCOM file</li>
128 <li>a value: the value, which can be a string value or a cross-reference value (one of the two will be non-NULL)<br>
131 This way, none of the information in the GEDCOM file is lost, even the non-standard information.<br>
133 <hr width="100%" size="2">
134 <h2><a name="Other_functions"></a>Modifying the object model</h2>Note that the date manipulations are described <a href="interface.html#date_value">here</a>.<br>
136 <h3><a name="Manipulating_strings"></a>Manipulating strings<br>
138 There are some functions available to retrieve and change strings in the
139 Gedcom object model, depending whether you use UTF-8 strings in your application
140 or locale-defined strings.<br>
142 The following functions retrieve and set the string in UTF-8 encoding:<br>
143 <blockquote><code>char* <b>gom_get_string</b> (char* data);<br>
144 char* <b>gom_set_string</b> (char** data, const char* str_in_utf8);</code><br>
146 The first function is in fact superfluous, because it just returns the <code>data</code>, but it is there for symmetry with the functions given below for the locale-defined input and output. <br>
148 The second function returns the new value if successful, or <code>NULL</code>
149 if an error occurred (e.g. failure to allocate memory or the given string is not a valid UTF-8 string). It makes a
150 copy of the input string to store it in the object model. It also takes
151 care of deallocating the old value of the data if needed. Note that
152 the set function needs the address of the data variable, to be able to modify
153 it. In the case of an error, the target data variable is not modified.<br>
155 Examples of use of these strings would be, e.g. for retrieving and setting the system ID in the header:<br>
156 <blockquote><code>struct header* head = gom_get_header();</code><code></code><br>
157 <code>char* oldvalue = gom_get_string(head->source.id);<br>
158 char* newvalue = "My_Gedcom_Tool";<br>
160 <code>if (gom_set_string(&head->source.id, newvalue)) {<br>
161 printf("Modified system id from %s to %s\n", oldvalue, newvalue);<br>
165 A second couple of functions retrieve and set the string in the format defined by the current locale:<br>
166 <blockquote><code>char* <b>gom_get_string_for_locale</b> (char* data, int* conversion_failures);<br>
167 char* <b>gom_set_string_for_locale</b> (char** data, const char* str_in_locale)</code>;<br>
169 The use of these functions is the same as the previous ones, but e.g. in
170 the "en_US" locale the string will be returned by the first function in the
171 ISO-8859-1 encoding and the second function expects the <code>str_in_locale</code> to be in this encoding. Conversion to and from UTF-8 for the object model is done on the fly.<br>
173 Since the conversion from UTF-8 to the locale encoding is not always possible,
174 the get function has a second parameter that can return the number of conversion
175 failures for the result string. Pass a pointer to an integer if you
176 want to know this. You can pass <code>NULL</code> if you're not interested. The function returns <code>NULL</code>
177 if an error occurred (e.g. if the given string is not a valid string for
178 the current locale); in that case the target data variable is not modified.<br>
180 <h3><a name="Adding_and_removing_records"></a>Adding and removing records</h3>
181 For each of the record types, there are two functions to add and remove records:
182 <blockquote><code>struct XXX* <b>gom_new_XXX</b>(const char* xref);<br>
183 int <b>gom_delete_XXX</b>(struct XXX* obj);</code><br>
187 The <code><b>XXX</b></code> stands for one of the following: <code><b>family</b>, </code><code><b>individual</b>, <b>multimedia</b>, <b>note</b>, <b>repository</b>, <b>source</b>, <b>submitter</b>, <b>user_rec</b></code>.<br>
189 For submission records, the <code><b>gom_delete_submission()</b></code> has no parameters (since there can be only one such object anyway).<br>
191 When creating new records, the application is responsible for making sure
192 that mandatory fields (according to the GEDCOM spec) are filled in afterwards.
193 In a later release, there will be checks in <code>gom_write_file</code> when something is missing.<br>
195 <h3><a name="Adding_rem_and_moving_xref"></a>Adding, removing and moving cross-references<br>
197 For struct members that are of type <code>struct xref_value</code>, the following function is available:<br>
198 <blockquote><code>struct xref_value* <b>gom_set_xref</b>(struct xref_value** data, const char* xref);</code><br>
200 This function modifies the <code>data</code> variable to point to the given <code>xref</code>, taking care of unreferencing the old value, and referencing the new value. If an error occurs, <code>NULL</code> is returned (and the <code>data</code> variable is not changed). If xref is <code>NULL</code>, the data is set to <code>NULL</code>.<br>
202 For struct members that are of type <code>struct xref_list</code>, the following functions are available:<br>
203 <blockquote><code>struct xref_list* <b>gom_add_xref</b>(struct xref_list** data, const char* xref);<br>
204 int <b> gom_remove_xref</b>(struct xref_list** data, const char* xref);<br>
205 int <b>gom_move_xref</b>(Gom_direction dir, </code><code>struct xref_list** data, const char* xref);</code><br>
207 The first function adds the given <code>xref</code> to the end of the <code>data</code> list. The second function removes the given <code>xref</code> from the <code>data</code> list (if present; if not present an error is generated and 1 is returned).<br>
209 The third function moves the given <code>xref </code>up or down the <code>data</code> list, depending on the <code>dir</code> parameter, which can be:<br>
211 <li><code>MOVE_UP</code></li>
212 <li><code>MOVE_DOWN</code></li>
214 Again, an error is generated and 1 is returned if the given xref is not part
215 of the list. If the xref cannot be moved up (because the first in the
216 list) or down (because the last in the list), a warning is generated, but
217 the function still returns success (0).<br>
218 <h3><a name="Adding_removing_and_moving"></a>Adding, removing and moving substructures<br>
220 For struct members that are just a single value, the following functions are available:<br>
221 <blockquote><code>struct XXX* <b>gom_set_new_XXX</b>(struct XXX** data);<br>
222 int <b>gom_delete_XXX</b>(struct XXX** data);</code><br>
224 This is the case for <b><code>XXX</code></b> equal to <b><code>address</code></b>, <b><code>change_date</code></b> or <b><code>place</code></b>. The first function creates a new substructure and assigns it to <code>data</code> (<code>NULL</code> is returned if there was already a value). The second function deletes the value from <code>data</code>.<br>
226 Note: for <code>change_date</code> structs there is also the following short-cut function, which updates the date and time directly:<br>
227 <blockquote><code>int <b>gom_update_timestamp</b> (struct change_date** obj, time_t tval);<br></code></blockquote>
228 For struct members that are a list (as described <a href="#Object_lists">here</a>), the following functions are available:<br>
229 <blockquote><code>struct XXX* <b>gom_add_new_XXX</b>(struct XXX** data);<br>
230 int <b>gom_remove_XXX</b>(struct XXX** data, struct XXX* obj);</code><br>
231 <code>int <b>gom_move_XXX</b>(Gom_direction dir, struct XXX** data, struct XXX* obj);</code><br>
234 This is the case for all <code>XXX</code> structs that have a <code>next</code> and <code>previous</code> member. The first function creates a new substructure and adds it to the end of the <code>data</code> list. The second function deletes the object from the <code>data</code> list (if present; if not present, an error is generated and 1 is returned).<br>
236 The third function moves the given <code>obj</code> up or down the <code>data</code> list, depending on the <code>dir</code> parameter, similar to the xref functions above.<br>
239 <hr width="100%" size="2">
240 <h2><a name="Writing_the_object_model_to_file"></a>Writing the object model to file<br>
242 Writing the current object model to a file is simply done using the following function:<br>
243 <blockquote><code>int <b>gom_write_file</b> (const char* filename, int* total_conv_fails);<br></code></blockquote>
244 This writes the model to the file <code>filename</code>. The second parameter can return the total number of conversion failures (pass <code>NULL</code><code></code> if you're not interested). The functions in <a href="usage.html#Controlling_some_settings">this section</a> can be used before <code>gom_write_file</code> to control some settings.<br>
246 Before you write the file, you can update the timestamp in the header using the following function:<br>
247 <blockquote><code>int <b>gom_header_update_timestamp</b> (time_t tval);<br></code></blockquote>
248 This sets the <code>date</code> and <code>time</code> fields of the header to the time indicated by <code>tval</code>.
249 The function returns 0 on success, non-zero if an error occurred. Typically,
250 the function would be used as follows, to set the current time in the timestamp:<br>
251 <blockquote><code>int result;<br>
252 result = gom_header_update_timestamp(time(NULL));</code><br>
254 <hr width="100%" size="2"><br>
256 <pre><font size="-1">$Id$<br>$Name$</font><br></pre>