/* properly destroy string tokens that are strdup()ed on error */
%destructor { free($$); } NAME STRING value valuepart
/* properly destroy parse results on error */
-%destructor { pop_section(ctx); settings_section_destroy($$); } section_start section
-%destructor { settings_kv_destroy($$); } setting
+%destructor { pop_section(ctx); settings_section_destroy($$, NULL); } section_start section
+%destructor { settings_kv_destroy($$, NULL); } setting
/* there are two shift/reduce conflicts because of the "NAME = NAME" and
* "NAME {" ambiguity, and the "NAME =" rule) */
}
else
{ /* extend the existing section */
- settings_section_extend(existing, section);
- settings_section_destroy(section);
+ settings_section_extend(existing, section, NULL);
+ settings_section_destroy(section, NULL);
}
}
free(existing->value);
existing->value = kv->value;
kv->value = NULL;
- settings_kv_destroy(kv);
+ settings_kv_destroy(kv, NULL);
}
}
/*
* Described in header
*/
-void settings_kv_destroy(kv_t *this)
+void settings_kv_destroy(kv_t *this, array_t *contents)
{
free(this->key);
- free(this->value);
+ if (contents)
+ {
+ array_insert(contents, ARRAY_TAIL, this->value);
+ }
+ else
+ {
+ free(this->value);
+ }
free(this);
}
return this;
}
+static void section_destroy(section_t *section, int idx, array_t *contents)
+{
+ settings_section_destroy(section, contents);
+}
+
+static void kv_destroy(kv_t *kv, int idx, array_t *contents)
+{
+ settings_kv_destroy(kv, contents);
+}
+
/*
* Described in header
*/
-void settings_section_destroy(section_t *this)
+void settings_section_destroy(section_t *this, array_t *contents)
{
- array_destroy_function(this->sections, (void*)settings_section_destroy, NULL);
- array_destroy_function(this->kv, (void*)settings_kv_destroy, NULL);
+ array_destroy_function(this->sections, (void*)section_destroy, contents);
+ array_destroy_function(this->kv, (void*)kv_destroy, contents);
array_destroy(this->fallbacks);
free(this->name);
free(this);
/*
* Described in header
*/
-void settings_section_extend(section_t *base, section_t *extension)
+void settings_section_extend(section_t *base, section_t *extension,
+ array_t *contents)
{
enumerator_t *enumerator;
section_t *sec;
if (array_bsearch(base->sections, sec->name, settings_section_find,
&found) != -1)
{
- settings_section_extend(found, sec);
+ settings_section_extend(found, sec, contents);
}
else
{
kv_t *found;
if (array_bsearch(base->kv, kv->key, settings_kv_find, &found) != -1)
{
- free(found->value);
+ if (contents)
+ {
+ array_insert(contents, ARRAY_TAIL, found->value);
+ }
+ else
+ {
+ free(found->value);
+ }
found->value = kv->value;
kv->value = NULL;
}
* Destroy a key/value pair.
*
* @param this key/value pair to destroy
+ * @param contents optional array to store the value in
*/
-void settings_kv_destroy(kv_t *this);
+void settings_kv_destroy(kv_t *this, array_t *contents);
/**
* Create a section with the given name.
* Destroy a section.
*
* @param this section to destroy
+ * @param contents optional array to store values of removed key/value pairs
*/
-void settings_section_destroy(section_t *this);
+void settings_section_destroy(section_t *this, array_t *contents);
/**
* Extend the first section with the values and sub-sections of the second
*
* @param base base section to extend
* @param extension section whose data is extracted
+ * @param contents optional array to store replaced values in
*/
-void settings_section_extend(section_t *base, section_t *extension);
+void settings_section_extend(section_t *base, section_t *extension,
+ array_t *contents);
/**
* Callback to find a section by name