1 /* Source code for modifying the gedcom object model.
2 Copyright (C) 2002 The Genes Development Team
3 This file is part of the Gedcom parser library.
4 Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2002.
6 The Gedcom parser library is free software; you can redistribute it
7 and/or modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The Gedcom parser library is distributed in the hope that it will be
12 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the Gedcom parser library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 #include "utf8tools.h"
29 #include "gom_internal.h"
31 /** If some characters cannot be converted by gom_get_string_for_locale(),
32 then these characters are by default replaced by the string "?". The
33 function gom_set_unknown() can configure the string to be used.
35 \param unknown The new replacement string for conversion failures
37 void gom_set_unknown(const char* unknown)
39 convert_set_unknown(unknown);
42 /** Returns the string from the Gedcom object model referenced by \c data
45 \param data The string from the Gedcom object model
46 \return The string in UTF-8 format (is in fact a pass-through operation)
48 char* gom_get_string(char* data)
53 /** Returns the string from the Gedcom object model referenced by \c data
54 in the encoding defined by the current locale.
56 Since the conversion from
57 UTF-8 to the locale encoding is not always possible, the function has a
58 second parameter that can return the number of conversion failures for the
61 \param data The string from the Gedcom object model
62 \param conversion_failures Pass a pointer to an integer if you want to know
63 the number of conversion failures (filled in on return). You can pass
64 \c NULL if you're not interested.
66 \return The string in the encoding defined by the current locale, with
67 unconvertible characters replaced by the "unknown string" (see
70 char* gom_get_string_for_locale(char* data, int* conversion_failures)
72 return convert_utf8_to_locale(gom_get_string(data), conversion_failures);
75 /** Sets the string from the Gedcom object model referenced by \c data to the
76 given input \c utf8_str, which must be a string in UTF-8 encoding.
78 The function makes a copy of the input string
79 to store it in the object model. It also takes care of deallocating the
80 old value of the data if needed.
82 Note that this function needs the \em address of the data variable, to
85 \param data The string from the Gedcom object model
86 \param utf8_str A new string, in UTF-8 encoding
88 \return The new value if successful, or \c NULL if an error occurred, e.g.:
89 - failure to allocate memory
90 - the given string is not a valid UTF-8 string
92 In the case of an error, the target data variable is not modified.
94 char* gom_set_string(char** data, const char* utf8_str)
99 if (utf8_str == NULL) {
103 if (!is_utf8_string(utf8_str)) {
104 gedcom_error(_("The input '%s' is not a valid UTF-8 string"), utf8_str);
107 newptr = strdup(utf8_str);
121 /** Sets the string from the Gedcom object model referenced by \c data to the
122 given input \c locale_str, which must be a string in the encoding defined
123 by the current locale.
125 The function makes a copy of the input string
126 to store it in the object model. It also takes care of deallocating the
127 old value of the data if needed.
129 Note that this function needs the \em address of the data variable, to
130 be able to modify it.
132 \param data The string from the Gedcom object model
133 \param locale_str A new string, in encoding defined by the current locale
135 \return The new value if successful, or \c NULL if an error occurred, e.g.:
136 - failure to allocate memory
137 - the given string is not a valid string for the current locale
139 In the case of an error, the target data variable is not modified.
141 char* gom_set_string_for_locale(char** data, const char* locale_str)
145 if (locale_str == NULL) {
146 result = gom_set_string(data, NULL);
149 char* utf8_str = convert_locale_to_utf8(locale_str);
152 gedcom_error(_("The input '%s' is not a valid string for the locale"),
155 result = gom_set_string(data, utf8_str);
161 void unref_xref_value(struct xref_value *xref)
164 gedcom_unlink_xref(xref->type, xref->string);
167 void UNREFALLFUNC(xref_list)(struct xref_list* obj)
170 struct xref_list* runner;
171 for (runner = obj; runner; runner = runner->next) {
172 unref_xref_value(runner->xref);
173 UNREFALLFUNC(user_data)(runner->extra);
178 void CLEANFUNC(xref_list)(struct xref_list *obj)
181 DESTROY_CHAIN_ELTS(user_data, obj->extra);
185 /** This function modifies a data variable in the Gedcom object model of
186 type struct xref_value to point to the given \c xref, taking care of
187 unreferencing the old value, and referencing the new value (resp.
188 decrementing and incrementing the reference count).
190 \param data The address of the xref_value member in the object model
191 \param xref The cross-reference key of an existing object, or \c NULL
192 \return The new value of the data variable, or \c NULL if an error
193 occurred, e.g. there was no record found with the given key
194 (in this case, the data variable is not changed).
196 struct xref_value* gom_set_xref(struct xref_value** data, const char* xref)
198 struct xref_value* result = NULL;
199 struct xref_value* newval = NULL;
203 newval = gedcom_get_by_xref(xref);
205 gedcom_error(_("No record found for xref '%s'"), xref);
208 /* Unreference the old value if not NULL */
210 result = gedcom_unlink_xref((*data)->type, (*data)->string);
214 /* Reference the new value if not NULL */
215 if (result != NULL && newval) {
216 result = gedcom_link_xref(newval->type, newval->string);
217 /* On error, perform rollback to old value (guaranteed to work) */
219 gedcom_link_xref((*data)->type, (*data)->string);
222 if (result != NULL) {
230 /** This function adds the given cross-reference to the end of the \c data
231 list, taking care of incrementing the reference count of the
234 \param data The address of the xref_list member in the object model
235 \param xref The cross-reference key of an existing object
237 \return The new entry in the \c data list, or \c NULL if an error occurred.
239 struct xref_list* gom_add_xref(struct xref_list** data, const char* xref)
241 struct xref_value* result = NULL;
242 struct xref_value* newval = NULL;
243 struct xref_list* xrl = NULL;
246 newval = gedcom_get_by_xref(xref);
248 gedcom_error(_("No record found for xref '%s'"), xref);
250 result = gedcom_link_xref(newval->type, newval->string);
251 if (result != NULL) {
252 MAKE_CHAIN_ELT(xref_list, *data, xrl);
253 if (xrl) xrl->xref = newval;
261 struct xref_list* find_xref(struct xref_list** data, const char* xref)
263 struct xref_list* result = NULL;
264 struct xref_value* xr = gedcom_get_by_xref(xref);
266 gedcom_error(_("No record found for xref '%s'"), xref);
268 struct xref_list* xrl;
269 for (xrl = *data ; xrl ; xrl = xrl->next) {
270 if (xrl->xref == xr) {
276 gedcom_error(_("Xref '%s' not part of chain"), xref);
281 /** This function removes the given cross-reference from the \c data
282 list, taking care of decrementing the reference count of the
285 \param data The address of the xref_list member in the object model
286 \param xref The cross-reference key of an existing object
288 \retval 0 if successful
289 \retval 1 if error (e.g. because not present in the list)
291 int gom_remove_xref(struct xref_list** data, const char* xref)
296 struct xref_list* xrl = find_xref(data, xref);
298 UNLINK_CHAIN_ELT(xref_list, *data, xrl);
299 gedcom_unlink_xref(xrl->xref->type, xrl->xref->string);
300 CLEANFUNC(xref_list)(xrl);
309 /** This function moves the given cross-reference up or down the \c data
312 If the cross-reference cannot be moved up (because the first in the list)
313 or down (because the last in the list), a warning is generated, but the
314 function still returns success.
316 \param dir The direction to move into
317 \param data The address of the xref_list member in the object model
318 \param xref The cross-reference key of an existing object
320 \retval 0 if successful
321 \retval 1 if error (e.g. because not present in the list)
323 int gom_move_xref(Gom_direction dir, struct xref_list** data, const char* xref)
328 struct xref_list* xrl = find_xref(data, xref);
330 MOVE_CHAIN_ELT(xref_list, dir, *data, xrl);