/* $Id: cpl_propertylist.c,v 1.53 2007/12/11 08:54:24 scastro Exp $ * * This file is part of the ESO Common Pipeline Library * Copyright (C) 2001-2005 European Southern Observatory * * 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 the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * $Author: scastro $ * $Date: 2007/12/11 08:54:24 $ * $Revision: 1.53 $ * $Name: $ */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include "cpl_errorstate.h" #include "cpl_error.h" #include "cpl_propertylist_impl.h" #include "cpl_tools.h" #include "cpl_memory.h" #include "cpl_io.h" /** * @defgroup cpl_propertylist Property Lists * * This module implements a container for @em properties (see * @ref cpl_property) which can be used to store auxiliary values related to * another data object, an image or a table for instance. The property values * can be set and retrieved by their associated name and properties can be * added and removed from the list. The property list container is an ordered * sequence of properties. * * @par Synopsis: * @code * #include * @endcode */ /**@{*/ enum { FITS_STDKEY_MAX = 8, FITS_SVALUE_MAX = 68 }; /* * The property list type. */ struct _cpl_propertylist_ { cx_deque *properties; }; /* * Regular expresion filter type */ struct _cpl_regexp_ { regex_t re; cxbool invert; }; typedef struct _cpl_regexp_ cpl_regexp; /* * Private methods */ inline static cxint _cpl_propertylist_filter_regexp(cxcptr key, cxcptr filter) { const cpl_regexp *_filter = (const cpl_regexp *)filter; if (regexec(&_filter->re, key, (size_t)0, NULL, 0) == REG_NOMATCH) return _filter->invert == TRUE ? TRUE : FALSE; return _filter->invert == TRUE ? FALSE : TRUE; } inline static cxbool _cpl_propertylist_compare(const cpl_property *property, const char *name) { const cxchar *key = cpl_property_get_name(property); return strcmp(key, name) == 0 ? TRUE : FALSE; } inline static cxbool _cpl_propertylist_compare_start(const cpl_property *property, const char *part_name) { const cxchar *key = cpl_property_get_name(property); if (strstr(key, part_name) == key) return TRUE; return FALSE; } inline static cxbool _cpl_propertylist_compare_regexp(const cpl_property *property, cpl_regexp *re) { const cxchar *key = cpl_property_get_name(property); return _cpl_propertylist_filter_regexp(key, re); } inline static cx_deque_iterator _cpl_propertylist_find(const cpl_propertylist *self, const char *name) { cx_deque_iterator first, last; cpl_property *p; first = cx_deque_begin(self->properties); last = cx_deque_end(self->properties); while (first != last) { p = cx_deque_get(self->properties, first); if (_cpl_propertylist_compare(p, name)) break; first = cx_deque_next(self->properties, first); } return first; } inline static cpl_property * _cpl_propertylist_get(const cpl_propertylist *self, const char *name) { cx_deque_iterator pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) return NULL; return cx_deque_get(self->properties, pos); } inline static int _cpl_propertylist_insert(cpl_propertylist *self, const cxchar *where, cxbool after, const cxchar *name, cpl_type type, cxptr value) { cx_deque_iterator pos; cpl_property *property; /* * Find the position where value should be inserted. */ pos = _cpl_propertylist_find(self, where); if (pos == cx_deque_end(self->properties)) { return 1; } if (after) { pos = cx_deque_next(self->properties, pos); } /* * Create the property for value and fill it. */ property = cpl_property_new(name, type); if (!property) { return 1; } /* * Map property type to the driver function's argument type. */ switch (type) { case CPL_TYPE_CHAR: cpl_property_set_char(property, *((cxchar *)value)); break; case CPL_TYPE_BOOL: cpl_property_set_bool(property, *((cxint *)value)); break; case CPL_TYPE_INT: cpl_property_set_int(property, *((cxint *)value)); break; case CPL_TYPE_LONG: cpl_property_set_long(property, *((cxlong *)value)); break; case CPL_TYPE_FLOAT: cpl_property_set_float(property, *((cxfloat *)value)); break; case CPL_TYPE_DOUBLE: cpl_property_set_double(property, *((cxdouble *)value)); break; case CPL_TYPE_STRING: cpl_property_set_string(property, ((const cxchar *)value)); break; default: return 1; break; } /* * Insert it into the deque */ cx_deque_insert(self->properties, pos, property); return 0; } /* * The function converts the current FITS header referenced by the cfitsio * file pointer to a property list. If the header cannot be accessed, i.e. * the number of keywords cannot be determined, or a keyword cannot be read, * -1 is returned. If the header contains FITS keywords whose type cannot be * determined the function returns 2. If a keyword type is not supported the * return value is 3. */ inline static cxint _cpl_propertylist_from_fitsfile(cpl_propertylist *self, fitsfile *file, cx_compare_func filter, cxptr data) { register cxint i = 0; cxint status = 0; cxint nkeywords = 0; fits_get_hdrspace(file, &nkeywords, NULL, &status); if (status != 0) { return -1; } for (i = 0; i < nkeywords; i++) { cxchar type = '\0'; cxchar key[FLEN_KEYWORD] = ""; cxchar value[FLEN_VALUE] = ""; cxchar comment[FLEN_COMMENT] = ""; cpl_property *property = NULL; fits_read_keyn(file, i + 1, key, value, comment, &status); if ((status == KEY_NO_EXIST) || (status == KEY_OUT_BOUNDS)) { return -1; } cx_assert(status == 0); if (filter != NULL && filter(key, data) == FALSE) { continue; } /*FIXME: Check the following statement */ /* * Skip totally empty records. */ if ((key[0] == '\0') && (value[0] == '\0') && (comment[0] == '\0')) { continue; } fits_get_keytype(value, &type, &status); switch (status) { case 0: { if (type == 'C') { value[0] = ' '; value[strlen(value) - 1] = ' '; cx_strstrip(value); } break; } case VALUE_UNDEFINED: type = '\0'; status = 0; break; default: return 1; break; } /* * Create the property from the parsed FITS card. */ switch (type) { case 'L': { cxint ival = *value == 'T' ? 1 : 0; property = cpl_property_new(key, CPL_TYPE_BOOL); cpl_property_set_bool(property, ival); cpl_property_set_comment(property, comment); break; } case 'I': { cxint ival = 0; property = cpl_property_new(key, CPL_TYPE_INT); sscanf(value, "%d", &ival); cpl_property_set_int(property, ival); cpl_property_set_comment(property, comment); break; } case 'F': { cxdouble dval = 0.; property = cpl_property_new(key, CPL_TYPE_DOUBLE); sscanf(value, "%lf", &dval); cpl_property_set_double(property, dval); cpl_property_set_comment(property, comment); break; } case 'C': { property = cpl_property_new(key, CPL_TYPE_STRING); cpl_property_set_string(property, value); cpl_property_set_comment(property, comment); break; } case '\0': { /*FIXME: check the following statement*/ if (key[0] != '\0') { property = cpl_property_new(key, CPL_TYPE_STRING); } else { /* * FITS standard: blank keywords may be followed by * any ASCII text as it is for COMMENT and HISTORY. * * In order to preserve this header record it is * changed into COMMENT record, so that it can be * stored in the property list. */ property = cpl_property_new("COMMENT", CPL_TYPE_STRING); } cpl_property_set_string(property, comment); cpl_property_set_comment(property, ""); break; } case 'X': /* FIXME: Add support for complex keywords. */ default: return 2; break; } cx_deque_push_back(self->properties, property); } return 0; } /* * The function saves the current property list into a FITS file using cfitsio. * It will not save keys that match a regular expression given in filter. * If the header contains FITS keywords whose type cannot be * determined the function returns 1. If an error is returned by cfitsio, this * functions returns its error number. If all goes well it returns 0. */ inline static cxint _cpl_propertylist_to_fitsfile(fitsfile *file, const cpl_propertylist *self, cx_compare_func filter, cxptr data) { cx_deque_iterator first, last; first = cx_deque_begin(self->properties); last = cx_deque_end(self->properties); while (first != last) { const cpl_property *p = cpl_propertylist_get_const(self, first); const cxchar *name = cpl_property_get_name(p); const cxchar *comment = cpl_property_get_comment(p); cxint status = 0; cpl_type type = cpl_property_get_type(p); if (filter != NULL && filter(name, data) == TRUE) { first = cx_deque_next(self->properties, first); continue; } switch (type) { case CPL_TYPE_CHAR: { cxchar c = cpl_property_get_char(p); cxchar s[2]; s[0] = c; s[1] = '\0'; fits_write_key(file, TSTRING, (cxchar*)name, &s, (cxchar*)comment, &status); } break; case CPL_TYPE_BOOL: { cxbool b = cpl_property_get_bool(p); cxint value = b == TRUE ? 1 : 0; fits_write_key(file, TLOGICAL, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_INT: { cxint value = cpl_property_get_int(p); fits_write_key(file, TINT, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_LONG: { cxlong value = cpl_property_get_long(p); fits_write_key(file, TLONG, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_FLOAT: { cxfloat value = cpl_property_get_float(p); fits_write_key(file, TFLOAT, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_DOUBLE: { cxdouble value = cpl_property_get_double(p); fits_write_key(file, TDOUBLE, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_STRING: { const cxchar *value = cpl_property_get_string(p); if (strcmp(name, "COMMENT") == 0) { if(strcmp(value, "") == 0){ fits_write_comment(file, " ", &status); } else{ fits_write_comment(file, (cxchar *)value, &status); } } else if(strcmp(name, "HISTORY") == 0) { if(strcmp(value, "") == 0){ fits_write_history(file, " ", &status); } else{ fits_write_history(file, (cxchar *)value, &status); } } else { fits_write_key(file, TSTRING, (cxchar*)name, (cxchar*)value, (cxchar*)comment, &status); } } break; default: status = 1; break; } if (status != 0 ) { return status; } cx_assert(status == 0); first = cx_deque_next(self->properties, first); } return 0; } /* * Public methods */ /** * @brief * Create an empty property list. * * @return * The newly created property list. * * The function creates a new property list and returns a handle for it. * To destroy the returned property list object use the property list * destructor @b cpl_propertylist_delete(). * * @see cpl_propertylist_delete() */ cpl_propertylist * cpl_propertylist_new(void) { cpl_propertylist *self = cx_malloc(sizeof *self); self->properties = cx_deque_new(); return self; } /** * @brief * Create a copy of the given property list. * * @param self The property list to be copied. * * @return * The created copy or @c NULL in case an error occurred. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self is a NULL pointer. *
* @enderror * * The function creates a deep copy of the given property list @em self, * i.e the created copy and the original property list do not share any * resources. */ cpl_propertylist * cpl_propertylist_duplicate(const cpl_propertylist *self) { const cxchar *const _id = "cpl_propertylist_duplicate"; cx_deque_iterator first, last; cpl_propertylist *copy = NULL; if (self == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return NULL; } cx_assert(self->properties != NULL); copy = cpl_propertylist_new(); first = cx_deque_begin(self->properties); last = cx_deque_end(self->properties); while (first != last) { cpl_property *tmp = cx_deque_get(self->properties, first); cx_deque_push_back(copy->properties, cpl_property_duplicate(tmp)); first = cx_deque_next(self->properties, first); } return copy; } /** * @brief * Destroy a property list. * * @param self The property list to . * * @return * Nothing. * * The function destroys the property list @em self and its whole * contents. */ void cpl_propertylist_delete(cpl_propertylist *self) { if (self) { cx_deque_destroy(self->properties, (cx_free_func)cpl_property_delete); cx_free(self); } return; } /** * @brief * Get the current size of a property list. * * @param self A property list. * * @return * The property list's current size, or 0 if the list is empty. If an * error occurs the function returns 0 and sets an appropriate error * code. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self is a NULL pointer. *
* @enderror * * The function reports the current number of elements stored in the property * list @em self. */ long cpl_propertylist_get_size(const cpl_propertylist *self) { const cxchar *const _id = "cpl_propertylist_get_size"; if (self == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0L; } return (long) cx_deque_size(self->properties); } /** * @brief * Check whether a property list is empty. * * @param self A property list. * * @return * The function returns 1 if the list is empty, and 0 otherwise. * In case an error occurs the function returns -1 and sets an * appropriate error code. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self is a NULL pointer. *
* @enderror * * The function checks if @em self contains any properties. */ int cpl_propertylist_is_empty(const cpl_propertylist *self) { const cxchar *const _id = "cpl_propertylist_is_empty"; if (self == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return -1; } return cx_deque_empty(self->properties); } /** * @brief * Get the the type of a property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * The type of the stored value. If an error occurs the function returns * @c CPL_TYPE_INVALID and sets an appropriate error code. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function returns the type of the value stored in @em self with the * name @em name. If there is more than one property with the same @em name, * it takes the first one from the list. */ cpl_type cpl_propertylist_get_type(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_type"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_TYPE_INVALID; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_TYPE_INVALID; } return cpl_property_get_type(property); } /** * @brief * Check whether a property is present in a property list. * * @param self A property list. * @param name The property name to look up. * * @return * The function returns 1 if the property is present, or 0 otherwise. * If an error occurs the function returns 0 and sets an appropriate * error code. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function searches the property list @em self for a property with * the name @em name and reports whether it was found or not. */ int cpl_propertylist_has(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_has"; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0; } return _cpl_propertylist_get(self, name) != NULL ? 1 : 0; } /** * @brief * Modify the comment field of the given property list entry. * * @param self A property list. * @param name The property name to look up. * @param comment New comment string. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error code * otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its comment is replaced by * the string @em comment. The provided comment string may be @c NULL. * In this case an already existing comment is deleted. If there is more * than one property with the same @em name, it takes the first one from the * list. */ cpl_error_code cpl_propertylist_set_comment(cpl_propertylist *self, const char *name, const char *comment) { const cxchar *const _id = "cpl_propertylist_set_comment"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } cpl_property_set_comment(property, comment); return CPL_ERROR_NONE; } /** * @brief * Set the value of the given character property list entry. * * @param self A property list. * @param name The property name to look up. * @param value New character value. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error code * otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its character value is replaced * with the character @em value. If there is more than one property with * the same @em name, it takes the first one from the list. */ cpl_error_code cpl_propertylist_set_char(cpl_propertylist *self, const char *name, char value) { const cxchar *const _id = "cpl_propertylist_set_char"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } return cpl_property_set_char(property, value); } /** * @brief * Set the value of the given boolean property list entry. * * @param self A property list. * @param name The property name to look up. * @param value New boolean value. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error code * otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its boolean value is replaced * with the boolean @em value. If there is more than one property with * the same @em name, it takes the first one from the list. */ cpl_error_code cpl_propertylist_set_bool(cpl_propertylist *self, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_set_bool"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } return cpl_property_set_bool(property, value); } /** * @brief * Set the value of the given integer property list entry. * * @param self A property list. * @param name The property name to look up. * @param value New integer value. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error code * otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its integer value is replaced * with the integer @em value. If there is more than one property with * the same @em name, it takes the first one from the list. */ cpl_error_code cpl_propertylist_set_int(cpl_propertylist *self, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_set_int"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } return cpl_property_set_int(property, value); } /** * @brief * Set the value of the given long property list entry. * * @param self A property list. * @param name The property name to look up. * @param value New long value. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error code * otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its long value is replaced with * the long @em value. If there is more than one property with * the same @em name, it takes the first one from the list. */ cpl_error_code cpl_propertylist_set_long(cpl_propertylist *self, const char *name, long value) { const cxchar *const _id = "cpl_propertylist_set_long"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } return cpl_property_set_long(property, value); } /** * @brief * Set the value of the given float property list entry. * * @param self A property list. * @param name The property name to look up. * @param value New float value. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error code * otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its float value is replaced with * the float @em value. If there is more than one property with * the same @em name, it takes the first one from the list. */ cpl_error_code cpl_propertylist_set_float(cpl_propertylist *self, const char *name, float value) { const cxchar *const _id = "cpl_propertylist_set_float"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } return cpl_property_set_float(property, value); } /** * @brief * Set the value of the given double property list entry. * * @param self A property list. * @param name The property name to look up. * @param value New double value. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error code * otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its double value is replaced with * the double @em value. If there is more than one property with * the same @em name, it takes the first one from the list. */ cpl_error_code cpl_propertylist_set_double(cpl_propertylist *self, const char *name, double value) { const cxchar *const _id = "cpl_propertylist_set_double"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } return cpl_property_set_double(property, value); } /** * @brief * Set the value of the given string property list entry. * * @param self A property list. * @param name The property name to look up. * @param value New string value. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error code * otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its string value is replaced with * the string @em value. If there is more than one property with * the same @em name, it takes the first one from the list. */ cpl_error_code cpl_propertylist_set_string(cpl_propertylist *self, const char *name, const char *value) { const cxchar *const _id = "cpl_propertylist_set_string"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = _cpl_propertylist_get(self, name); if (property == NULL) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } return cpl_property_set_string(property, value); } /** * @brief * Access property list elements by index. * * @param self The property list to query. * @param position Index of the element to retrieve. * * @return * The function returns the property with index @em position, or @c NULL * if @em position is out of range. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self is a NULL pointer. *
* @enderror * * The function returns a handle for the property list element, the property, * with the index @em position. Numbering of property list elements extends from * 0 to @b cpl_propertylist_get_size() - 1. If @em position is less than 0 or * greater equal than @b cpl_propertylist_get_size() the function returns * @c NULL. */ const cpl_property * cpl_propertylist_get_const(const cpl_propertylist *self, long position) { const cxchar *const _id = "cpl_propertylist_get_const"; // register cxsize i = 0; cx_deque_iterator first, last; if (self == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return NULL; } if (position < 0) { return NULL; } first = cx_deque_begin(self->properties); last = cx_deque_end(self->properties); /* while (i < (cxsize)position && first != last) { first = cx_deque_next(self->properties, first); i++; }*/ if (first == last) { return NULL; } return cx_deque_get(self->properties, position); } /** * @brief * Access property list elements by index. * * @param self The property list to query. * @param position Index of the element to retrieve. * * @return * The function returns the property with index @em position, or @c NULL * if @em position is out of range. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self is a NULL pointer. *
* @enderror * * The function returns a handle for the property list element, the property, * with the index @em position. Numbering of property list elements extends from * 0 to @b cpl_propertylist_get_size() - 1. If @em position is less than 0 or * greater equal than @b cpl_propertylist_get_size() the function returns * @c NULL. */ cpl_property * cpl_propertylist_get(cpl_propertylist *self, long position) { cpl_errorstate prestate = cpl_errorstate_get(); cpl_property *property = (cpl_property *)cpl_propertylist_get_const(self, position); if (!cpl_errorstate_is_equal(prestate)) (void)cpl_error_set_where(cpl_func); return property; } /** * @brief * Get the comment of the given property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * The comment of the property list entry, or @c NULL. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its comment string is returned. * If an entry with the name @em name is not found, or if the entry has * no comment the function returns @c NULL. If there is more than one property * with the same @em name, it takes the first one from the list. */ const char * cpl_propertylist_get_comment(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_comment"; cpl_property *property; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return NULL; } property = _cpl_propertylist_get(self, name); if (!property) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return NULL; } return cpl_property_get_comment(property); } /** * @brief * Get the character value of the given property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * The character value stored in the list entry. The function returns '\\0' * if an error occurs and an appropriate error code is set. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
CPL_ERROR_TYPE_MISMATCH * The sought-after property name is not of type * @c CPL_TYPE_CHAR. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its character value is returned. * If there is more than one property with the same @em name, it takes the * first one from the list. */ char cpl_propertylist_get_char(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_char"; cxchar result; cpl_property *property; cpl_errorstate prevstate; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return '\0'; } property = _cpl_propertylist_get(self, name); if (!property) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return '\0'; } prevstate = cpl_errorstate_get(); result = cpl_property_get_char(property); /* * If an error occurred change any possible set location to this * function. */ if (!cpl_errorstate_is_equal(prevstate)) { cpl_error_set_where(_id); return '\0'; } return result; } /** * @brief * Get the boolean value of the given property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * The integer representation of the boolean value stored in * the list entry. @c TRUE is represented as non-zero value while * 0 indicates @c FALSE. The function returns 0 if an error occurs * and an appropriate error code is set. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
CPL_ERROR_TYPE_MISMATCH * The sought-after property name is not of type * @c CPL_TYPE_BOOL. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its boolean value is returned. * If there is more than one property with the same @em name, it takes the * first one from the list. */ int cpl_propertylist_get_bool(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_bool"; cxbool result; cpl_property *property; cpl_errorstate prevstate; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0; } property = _cpl_propertylist_get(self, name); if (!property) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return 0; } prevstate = cpl_errorstate_get(); result = cpl_property_get_bool(property); /* * If an error occurred change any possibly set location to this * function. */ if (!cpl_errorstate_is_equal(prevstate)) { cpl_error_set_where(_id); return 0; } return result == TRUE ? 1 : 0; } /** * @brief * Get the integer value of the given property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * The integer value stored in the list entry. The function returns 0 if * an error occurs and an appropriate error code is set. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
CPL_ERROR_TYPE_MISMATCH * The sought-after property name is not of type * @c CPL_TYPE_INT. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its integer value is returned. * If there is more than one property with the same @em name, it takes the * first one from the list. */ int cpl_propertylist_get_int(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_int"; cxint result; cpl_property *property; cpl_errorstate prevstate; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0; } property = _cpl_propertylist_get(self, name); if (!property) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return 0; } prevstate = cpl_errorstate_get(); result = cpl_property_get_int(property); /* * If an error occurred change any possibly set location to this * function. */ if (!cpl_errorstate_is_equal(prevstate)) { cpl_error_set_where(_id); return 0; } return result; } /** * @brief * Get the long value of the given property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * The long value stored in the list entry. The function returns 0 if * an error occurs and an appropriate error code is set. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
CPL_ERROR_TYPE_MISMATCH * The sought-after property name is not of type * @c CPL_TYPE_LONG. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its long value is returned. * If there is more than one property with the same @em name, it takes the * first one from the list. */ long cpl_propertylist_get_long(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_long"; cxlong result; cpl_property *property; cpl_errorstate prevstate; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0; } property = _cpl_propertylist_get(self, name); if (!property) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return 0; } prevstate = cpl_errorstate_get(); result = cpl_property_get_long(property); /* * If an error occurred change any possibly set location to this * function. */ if (!cpl_errorstate_is_equal(prevstate)) { cpl_error_set_where(_id); return 0; } return result; } /** * @brief * Get the float value of the given property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * The float value stored in the list entry. The function returns 0 if * an error occurs and an appropriate error code is set. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
CPL_ERROR_TYPE_MISMATCH * The sought-after property name is not of type * @c CPL_TYPE_FLOAT. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its float value is returned. * If there is more than one property with the same @em name, it takes the * first one from the list. */ float cpl_propertylist_get_float(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_float"; cxfloat result; cpl_property *property; cpl_errorstate prevstate; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0; } property = _cpl_propertylist_get(self, name); if (!property) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return 0; } prevstate = cpl_errorstate_get(); result = cpl_property_get_float(property); /* * If an error occurred change any possibly set location to this * function. */ if (!cpl_errorstate_is_equal(prevstate)) { cpl_error_set_where(_id); return 0; } return result; } /** * @brief * Get the double value of the given property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * The double value stored in the list entry. The function returns 0 if * an error occurs and an appropriate error code is set. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
CPL_ERROR_TYPE_MISMATCH * The sought-after property name is not of type * @c CPL_TYPE_DOUBLE. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, its double value is returned. * If there is more than one property with the same @em name, it takes the * first one from the list. */ double cpl_propertylist_get_double(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_double"; cxdouble result; cpl_property *property; cpl_errorstate prevstate; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0; } property = _cpl_propertylist_get(self, name); if (!property) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return 0; } prevstate = cpl_errorstate_get(); result = cpl_property_get_double(property); /* * If an error occurred change any possibly set location to this * function. */ if (!cpl_errorstate_is_equal(prevstate)) { cpl_error_set_where(_id); return 0; } return result; } /** * @brief * Get the string value of the given property list entry. * * @param self A property list. * @param name The property name to look up. * * @return * A handle to the string value stored in the list entry. The * function returns @c NULL if an error occurs and an appropriate * error code is set. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list self does not contain a property with * the name name. *
CPL_ERROR_TYPE_MISMATCH * The sought-after property name is not of type * @c CPL_TYPE_STRING. *
* @enderror * * The function searches the property list @em self for a property named * @em name. If it is present in the list, a handle to its string value * is returned. If there is more than one property with the same @em name, * it takes the first one from the list. */ const char * cpl_propertylist_get_string(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_string"; const cxchar *result; cpl_property *property; cpl_errorstate prevstate; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return NULL; } property = _cpl_propertylist_get(self, name); if (!property) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return NULL; } prevstate = cpl_errorstate_get(); result = cpl_property_get_string(property); /* * If an error occurred change any possibly set location to this * function. */ if (!cpl_errorstate_is_equal(prevstate)) { cpl_error_set_where(_id); return NULL; } return result; } /** * @brief * Insert a character value into a property list at the given position. * * @param self A property list. * @param here Name indicating the position at which the value is inserted. * @param name The property name to be assigned to the value. * @param value The character value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, here or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new character property with name @em name and * value @em value. The property is inserted into the property list * @em self at the position of the property named @em here. */ cpl_error_code cpl_propertylist_insert_char(cpl_propertylist *self, const char *here, const char *name, char value) { const cxchar *const _id = "cpl_propertylist_insert_char"; cxint status = 0; if (self == NULL || here == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, here, FALSE, name, CPL_TYPE_CHAR, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a boolean value into a property list at the given position. * * @param self A property list. * @param here Name indicating the position at which the value is inserted. * @param name The property name to be assigned to the value. * @param value The boolean value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, here or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new boolean property with name @em name and * value @em value. The property is inserted into the property list * @em self at the position of the property named @em here. */ cpl_error_code cpl_propertylist_insert_bool(cpl_propertylist *self, const char *here, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_insert_bool"; cxint status = 0; if (self == NULL || here == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, here, FALSE, name, CPL_TYPE_BOOL, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a integer value into a property list at the given position. * * @param self A property list. * @param here Name indicating the position at which the value is inserted. * @param name The property name to be assigned to the value. * @param value The integer value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, here or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new integer property with name @em name and * value @em value. The property is inserted into the property list * @em self at the position of the property named @em here. */ cpl_error_code cpl_propertylist_insert_int(cpl_propertylist *self, const char *here, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_insert_int"; cxint status = 0; if (self == NULL || here == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, here, FALSE, name, CPL_TYPE_INT, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a long value into a property list at the given position. * * @param self A property list. * @param here Name indicating the position at which the value is inserted. * @param name The property name to be assigned to the value. * @param value The long value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, here or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new long property with name @em name and * value @em value. The property is inserted into the property list * @em self at the position of the property named @em here. */ cpl_error_code cpl_propertylist_insert_long(cpl_propertylist *self, const char *here, const char *name, long value) { const cxchar *const _id = "cpl_propertylist_insert_long"; cxint status = 0; if (self == NULL || here == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, here, FALSE, name, CPL_TYPE_LONG, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a float value into a property list at the given position. * * @param self A property list. * @param here Name indicating the position at which the value is inserted. * @param name The property name to be assigned to the value. * @param value The float value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, here or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new float property with name @em name and * value @em value. The property is inserted into the property list * @em self at the position of the property named @em here. */ cpl_error_code cpl_propertylist_insert_float(cpl_propertylist *self, const char *here, const char *name, float value) { const cxchar *const _id = "cpl_propertylist_insert_float"; cxint status = 0; if (self == NULL || here == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, here, FALSE, name, CPL_TYPE_FLOAT, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a double value into a property list at the given position. * * @param self A property list. * @param here Name indicating the position at which the value is inserted. * @param name The property name to be assigned to the value. * @param value The double value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, here or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new double property with name @em name and * value @em value. The property is inserted into the property list * @em self at the position of the property named @em here. */ cpl_error_code cpl_propertylist_insert_double(cpl_propertylist *self, const char *here, const char *name, double value) { const cxchar *const _id = "cpl_propertylist_insert_char"; cxint status = 0; if (self == NULL || here == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, here, FALSE, name, CPL_TYPE_DOUBLE, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a string value into a property list at the given position. * * @param self A property list. * @param here Name indicating the position at which the value is inserted. * @param name The property name to be assigned to the value. * @param value The string value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, here or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new string property with name @em name and * value @em value. The property is inserted into the property list * @em self at the position of the property named @em here. */ cpl_error_code cpl_propertylist_insert_string(cpl_propertylist *self, const char *here, const char *name, const char *value) { const cxchar *const _id = "cpl_propertylist_insert_string"; cxint status = 0; if (self == NULL || here == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, here, FALSE, name, CPL_TYPE_STRING, (cxptr)value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a character value into a property list after the given position. * * @param self A property list. * @param after Name of the property after which the value is inserted. * @param name The property name to be assigned to the value. * @param value The character value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, after or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new character property with name @em name and * value @em value. The property is inserted into the property list * @em self after the property named @em after. */ cpl_error_code cpl_propertylist_insert_after_char(cpl_propertylist *self, const char *after, const char *name, char value) { const cxchar *const _id = "cpl_propertylist_insert_after_char"; cxint status = 0; if (self == NULL || after == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, after, TRUE, name, CPL_TYPE_CHAR, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a boolean value into a property list after the given position. * * @param self A property list. * @param after Name of the property after which the value is inserted. * @param name The property name to be assigned to the value. * @param value The boolean value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, after or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new boolean property with name @em name and * value @em value. The property is inserted into the property list * @em self after the property named @em after. */ cpl_error_code cpl_propertylist_insert_after_bool(cpl_propertylist *self, const char *after, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_insert_after_bool"; cxint status = 0; if (self == NULL || after == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, after, TRUE, name, CPL_TYPE_BOOL, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a integer value into a property list after the given position. * * @param self A property list. * @param after Name of the property after which the value is inserted. * @param name The property name to be assigned to the value. * @param value The integer value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, after or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new integer property with name @em name and * value @em value. The property is inserted into the property list * @em self after the property named @em after. */ cpl_error_code cpl_propertylist_insert_after_int(cpl_propertylist *self, const char *after, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_insert_after_int"; cxint status = 0; if (self == NULL || after == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, after, TRUE, name, CPL_TYPE_INT, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a long value into a property list after the given position. * * @param self A property list. * @param after Name of the property after which the value is inserted. * @param name The property name to be assigned to the value. * @param value The long value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, after or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new long property with name @em name and * value @em value. The property is inserted into the property list * @em self after the property named @em after. */ cpl_error_code cpl_propertylist_insert_after_long(cpl_propertylist *self, const char *after, const char *name, long value) { const cxchar *const _id = "cpl_propertylist_insert_after_long"; cxint status = 0; if (self == NULL || after == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, after, TRUE, name, CPL_TYPE_LONG, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a float value into a property list after the given position. * * @param self A property list. * @param after Name of the property after which the value is inserted. * @param name The property name to be assigned to the value. * @param value The float value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, after or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new float property with name @em name and * value @em value. The property is inserted into the property list * @em self after the property named @em after. */ cpl_error_code cpl_propertylist_insert_after_float(cpl_propertylist *self, const char *after, const char *name, float value) { const cxchar *const _id = "cpl_propertylist_insert_after_float"; cxint status = 0; if (self == NULL || after == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, after, TRUE, name, CPL_TYPE_FLOAT, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a double value into a property list after the given position. * * @param self A property list. * @param after Name of the property after which the value is inserted. * @param name The property name to be assigned to the value. * @param value The double value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, after or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new double property with name @em name and * value @em value. The property is inserted into the property list * @em self after the property named @em after. */ cpl_error_code cpl_propertylist_insert_after_double(cpl_propertylist *self, const char *after, const char *name, double value) { const cxchar *const _id = "cpl_propertylist_insert_after_double"; cxint status = 0; if (self == NULL || after == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, after, TRUE, name, CPL_TYPE_DOUBLE, &value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Insert a string value into a property list after the given position. * * @param self A property list. * @param after Name of the property after which the value is inserted. * @param name The property name to be assigned to the value. * @param value The string value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, after or name is a * NULL pointer. *
CPL_ERROR_UNSPECIFIED * A property with the name name could not be inserted * into self. *
* @enderror * * The function creates a new string property with name @em name and * value @em value. The property is inserted into the property list * @em self after the property named @em after. */ cpl_error_code cpl_propertylist_insert_after_string(cpl_propertylist *self, const char *after, const char *name, const char *value) { const cxchar *const _id = "cpl_propertylist_insert_after_string"; cxint status = 0; if (self == NULL || after == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = _cpl_propertylist_insert(self, after, TRUE, name, CPL_TYPE_STRING, (cxptr)value); if (status) { cpl_error_set(_id, CPL_ERROR_UNSPECIFIED); return CPL_ERROR_UNSPECIFIED; } return CPL_ERROR_NONE; } /** * @brief * Prepend a character value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The character value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new character property with name @em name and * value @em value. The property is prepended to the property list @em self. */ cpl_error_code cpl_propertylist_prepend_char(cpl_propertylist *self, const char *name, char value) { const cxchar *const _id = "cpl_propertylist_prepend_char"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_CHAR); cx_assert(property != NULL); cpl_property_set_char(property, value); cx_deque_push_front(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Prepend a boolean value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The boolean value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new boolean property with name @em name and * value @em value. The property is prepended to the property list @em self. */ cpl_error_code cpl_propertylist_prepend_bool(cpl_propertylist *self, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_prepend_bool"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_BOOL); cx_assert(property != NULL); cpl_property_set_bool(property, value); cx_deque_push_front(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Prepend a integer value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The integer value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new integer property with name @em name and * value @em value. The property is prepended to the property list @em self. */ cpl_error_code cpl_propertylist_prepend_int(cpl_propertylist *self, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_prepend_int"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_INT); cx_assert(property != NULL); cpl_property_set_int(property, value); cx_deque_push_front(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Prepend a long value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The long value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new long property with name @em name and * value @em value. The property is prepended to the property list @em self. */ cpl_error_code cpl_propertylist_prepend_long(cpl_propertylist *self, const char *name, long value) { const cxchar *const _id = "cpl_propertylist_prepend_long"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_LONG); cx_assert(property != NULL); cpl_property_set_long(property, value); cx_deque_push_front(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Prepend a float value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The float value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new float property with name @em name and * value @em value. The property is prepended to the property list @em self. */ cpl_error_code cpl_propertylist_prepend_float(cpl_propertylist *self, const char *name, float value) { const cxchar *const _id = "cpl_propertylist_prepend_float"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_FLOAT); cx_assert(property != NULL); cpl_property_set_float(property, value); cx_deque_push_front(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Prepend a double value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The double value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new double property with name @em name and * value @em value. The property is prepended to the property list @em self. */ cpl_error_code cpl_propertylist_prepend_double(cpl_propertylist *self, const char *name, double value) { const cxchar *const _id = "cpl_propertylist_prepend_double"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_DOUBLE); cx_assert(property != NULL); cpl_property_set_double(property, value); cx_deque_push_front(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Prepend a string value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The string value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new string property with name @em name and * value @em value. The property is prepended to the property list @em self. */ cpl_error_code cpl_propertylist_prepend_string(cpl_propertylist *self, const char *name, const char *value) { const cxchar *const _id = "cpl_propertylist_prepend_string"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_STRING); cx_assert(property != NULL); cpl_property_set_string(property, value); cx_deque_push_front(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Append a character value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The character value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new character property with name @em name and * value @em value. The property is appended to the property list @em self. */ cpl_error_code cpl_propertylist_append_char(cpl_propertylist *self, const char *name, char value) { const cxchar *const _id = "cpl_propertylist_append_char"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_CHAR); cx_assert(property != NULL); cpl_property_set_char(property, value); cx_deque_push_back(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Append a boolean value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The boolean value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new boolean property with name @em name and * value @em value. The property is appended to the property list @em self. */ cpl_error_code cpl_propertylist_append_bool(cpl_propertylist *self, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_append_bool"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_BOOL); cx_assert(property != NULL); cpl_property_set_bool(property, value); cx_deque_push_back(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Append an integer value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The integer value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new integer property with name @em name and * value @em value. The property is appended to the property list @em self. */ cpl_error_code cpl_propertylist_append_int(cpl_propertylist *self, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_append_int"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_INT); cx_assert(property != NULL); cpl_property_set_int(property, value); cx_deque_push_back(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Append a long value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The long value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new long property with name @em name and * value @em value. The property is appended to the property list @em self. */ cpl_error_code cpl_propertylist_append_long(cpl_propertylist *self, const char *name, long value) { const cxchar *const _id = "cpl_propertylist_append_long"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_LONG); cx_assert(property != NULL); cpl_property_set_long(property, value); cx_deque_push_back(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Append a float value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The float value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new float property with name @em name and * value @em value. The property is appended to the property list @em self. */ cpl_error_code cpl_propertylist_append_float(cpl_propertylist *self, const char *name, float value) { const cxchar *const _id = "cpl_propertylist_append_float"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_FLOAT); cx_assert(property != NULL); cpl_property_set_float(property, value); cx_deque_push_back(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Append a double value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The double value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new double property with name @em name and * value @em value. The property is appended to the property list @em self. */ cpl_error_code cpl_propertylist_append_double(cpl_propertylist *self, const char *name, double value) { const cxchar *const _id = "cpl_propertylist_append_double"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_DOUBLE); cx_assert(property != NULL); cpl_property_set_double(property, value); cx_deque_push_back(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Append a string value to a property list. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The string value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function creates a new string property with name @em name and * value @em value. The property is appended to the property list @em self. */ cpl_error_code cpl_propertylist_append_string(cpl_propertylist *self, const char *name, const char *value) { const cxchar *const _id = "cpl_propertylist_append_string"; cpl_property *property = NULL; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } property = cpl_property_new(name, CPL_TYPE_STRING); cx_assert(property != NULL); cpl_property_set_string(property, value); cx_deque_push_back(self->properties, property); return CPL_ERROR_NONE; } /** * @brief * Append a property list.. * * @param self A property list. * @param other The property to append. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self is a NULL pointer. *
* @enderror * * The function appends the property list @em other to the property list * @em self. */ cpl_error_code cpl_propertylist_append(cpl_propertylist *self, const cpl_propertylist *other) { const cxchar *const _id = "cpl_propertylist_append"; if (self == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } if (other != NULL) { cx_deque_const_iterator pos = cx_deque_begin(other->properties); while (pos != cx_deque_end(other->properties)) { const cpl_property *p = cx_deque_get(other->properties, pos); cx_deque_push_back(self->properties, cpl_property_duplicate(p)); pos = cx_deque_next(other->properties, pos); } } return CPL_ERROR_NONE; } /** * @brief * Erase the given property from a property list. * * @param self A property list. * @param name Name of the property to erase. * * @return * On success the function returns the number of erased entries. If * an error occurs the function returns 0 and an appropriate error * code is set. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
* @enderror * * The function searches the property with the name @em name in the property * list @em self and removes it. The property is destroyed. If @em self * contains multiple duplicates of a property named @em name, only the * first one is erased. */ int cpl_propertylist_erase(cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_erase"; cx_deque_iterator pos; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) { return 0; } cx_deque_erase(self->properties, pos, (cx_free_func)cpl_property_delete); return 1; } /** * @brief * Erase all properties with name matching a given regular expression. * * @param self A property list. * @param regexp Regular expression. * @param invert Flag inverting the sense of matching. * * @return * On success the function returns the number of erased entries or 0 if * no entries are erase. If an error occurs the function returns 0 and an * appropriate error code is set. If cpl-5.0 the function returns -1. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or regexp is a NULL * pointer. *
* @enderror * * The function searches for all the properties matching in the list * @em self and removes them. Whether a property matches or not depends on * the given regular expression @em regexp, and the flag @em invert. If * @em invert is @c 0, all properties matching @em regexp are removed from * the list. If @em invert is set to a non-zero value, all properties which * do not match @em regexp are erased. The removed properties are destroyed. * * The function expects POSIX 1003.2 compliant extended regular expressions. */ int cpl_propertylist_erase_regexp(cpl_propertylist *self, const char *regexp, int invert) { const cxchar *const _id = "cpl_propertylist_erase_regexp"; cxint status = 0; cxint count = 0; cx_deque_iterator first, last, pos; cpl_property *p; cpl_regexp filter; #if CPL_MAJOR_VERSION >= 5 if (self == NULL || regexp == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return -1; } status = regcomp(&filter.re, regexp, REG_EXTENDED | REG_NOSUB); if (status) { cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return -1; } #else if (self == NULL || regexp == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return 0; } status = regcomp(&filter.re, regexp, REG_EXTENDED | REG_NOSUB); if (status) { cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return 0; } #endif filter.invert = invert == 0 ? FALSE : TRUE; first = cx_deque_begin(self->properties); last = cx_deque_end(self->properties); while (first < cx_deque_end(self->properties)) { pos = first; p = cx_deque_get(self->properties, pos); if (_cpl_propertylist_compare_regexp(p, &filter) == TRUE) { cx_deque_erase(self->properties, pos, (cx_free_func)cpl_property_delete); count++; } else { first = cx_deque_next(self->properties, first); } } regfree(&filter.re); return count; } /** * @brief * Remove all properties from a property list. * * @param self A property list. * * @return Nothing. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self is a NULL pointer. *
* @enderror * * The function removes all properties from @em self. Each property * is properly deallocated. After calling this function @em self is * empty. */ void cpl_propertylist_empty(cpl_propertylist *self) { const cxchar *const _id = "cpl_propertylist_empty"; cx_deque_iterator first; if (self == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return; } first = cx_deque_begin(self->properties); /* cx_deque_end changes its value everytime cx_deque_erase() * is called. The elements are shifted from end to begin every * time an element is erased, therefore we always erase element * first with a value of 0. */ while (first < cx_deque_end(self->properties)) { cx_deque_iterator pos = first; cx_deque_erase(self->properties, pos, (cx_free_func)cpl_property_delete); } return; } /** * @brief * Update a property list with a character value. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The character value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of type CPL_TYPE_CHAR. *
* @enderror * * The function updates the property list @em self with the character value * @em value. This means, if a property with the name @em name exists already * its value is updated, otherwise a property with the name @em name is * created and added to @em self. The update will fail if a property with * the name @em name exists already which is not of type @c CPL_TYPE_CHAR. */ cpl_error_code cpl_propertylist_update_char(cpl_propertylist *self, const char *name, char value) { const cxchar *const _id = "cpl_propertylist_update_char"; cx_deque_iterator pos; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) { cpl_property *property = cpl_property_new(name, CPL_TYPE_CHAR); cx_assert(property != NULL); cpl_property_set_char(property, value); cx_deque_push_back(self->properties, property); } else { cpl_property *property = cx_deque_get(self->properties, pos); cx_assert(property != NULL); if (cpl_property_get_type(property) != CPL_TYPE_CHAR) { cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } cpl_property_set_char(property, value); } return CPL_ERROR_NONE; } /** * @brief * Update a property list with a boolean value. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The boolean value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of type CPL_TYPE_BOOL. *
* @enderror * * The function updates the property list @em self with the boolean value * @em value. This means, if a property with the name @em name exists already * its value is updated, otherwise a property with the name @em name is * created and added to @em self. The update will fail if a property with * the name @em name exists already which is not of type @c CPL_TYPE_BOOL. */ cpl_error_code cpl_propertylist_update_bool(cpl_propertylist *self, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_update_bool"; cx_deque_iterator pos; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) { cpl_property *property = cpl_property_new(name, CPL_TYPE_BOOL); cx_assert(property != NULL); cpl_property_set_bool(property, value); cx_deque_push_back(self->properties, property); } else { cpl_property *property = cx_deque_get(self->properties, pos); cx_assert(property != NULL); if (cpl_property_get_type(property) != CPL_TYPE_BOOL) { cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } cpl_property_set_bool(property, value); } return CPL_ERROR_NONE; } /** * @brief * Update a property list with a integer value. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The integer value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of type CPL_TYPE_INT. *
* @enderror * * The function updates the property list @em self with the integer value * @em value. This means, if a property with the name @em name exists already * its value is updated, otherwise a property with the name @em name is * created and added to @em self. The update will fail if a property with * the name @em name exists already which is not of type @c CPL_TYPE_INT. */ cpl_error_code cpl_propertylist_update_int(cpl_propertylist *self, const char *name, int value) { const cxchar *const _id = "cpl_propertylist_update_int"; cx_deque_iterator pos; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) { cpl_property *property = cpl_property_new(name, CPL_TYPE_INT); cx_assert(property != NULL); cpl_property_set_int(property, value); cx_deque_push_back(self->properties, property); } else { cpl_property *property = cx_deque_get(self->properties, pos); cx_assert(property != NULL); if (cpl_property_get_type(property) != CPL_TYPE_INT) { cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } cpl_property_set_int(property, value); } return CPL_ERROR_NONE; } /** * @brief * Update a property list with a long value. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The long value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of type CPL_TYPE_LONG. *
* @enderror * * The function updates the property list @em self with the long value * @em value. This means, if a property with the name @em name exists already * its value is updated, otherwise a property with the name @em name is * created and added to @em self. The update will fail if a property with * the name @em name exists already which is not of type @c CPL_TYPE_LONG. */ cpl_error_code cpl_propertylist_update_long(cpl_propertylist *self, const char *name, long value) { const cxchar *const _id = "cpl_propertylist_update_long"; cx_deque_iterator pos; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) { cpl_property *property = cpl_property_new(name, CPL_TYPE_LONG); cx_assert(property != NULL); cpl_property_set_long(property, value); cx_deque_push_back(self->properties, property); } else { cpl_property *property = cx_deque_get(self->properties, pos); cx_assert(property != NULL); if (cpl_property_get_type(property) != CPL_TYPE_LONG) { cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } cpl_property_set_long(property, value); } return CPL_ERROR_NONE; } /** * @brief * Update a property list with a float value. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The float value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of type CPL_TYPE_FLOAT. *
* @enderror * * The function updates the property list @em self with the float value * @em value. This means, if a property with the name @em name exists already * its value is updated, otherwise a property with the name @em name is * created and added to @em self. The update will fail if a property with * the name @em name exists already which is not of type @c CPL_TYPE_FLOAT. */ cpl_error_code cpl_propertylist_update_float(cpl_propertylist *self, const char *name, float value) { const cxchar *const _id = "cpl_propertylist_update_float"; cx_deque_iterator pos; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) { cpl_property *property = cpl_property_new(name, CPL_TYPE_FLOAT); cx_assert(property != NULL); cpl_property_set_float(property, value); cx_deque_push_back(self->properties, property); } else { cpl_property *property = cx_deque_get(self->properties, pos); cx_assert(property != NULL); if (cpl_property_get_type(property) != CPL_TYPE_FLOAT) { cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } cpl_property_set_float(property, value); } return CPL_ERROR_NONE; } /** * @brief * Update a property list with a double value. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The double value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of type CPL_TYPE_DOUBLE. *
* @enderror * * The function updates the property list @em self with the double value * @em value. This means, if a property with the name @em name exists already * its value is updated, otherwise a property with the name @em name is * created and added to @em self. The update will fail if a property with * the name @em name exists already which is not of type @c CPL_TYPE_DOUBLE. */ cpl_error_code cpl_propertylist_update_double(cpl_propertylist *self, const char *name, double value) { const cxchar *const _id = "cpl_propertylist_update_double"; cx_deque_iterator pos; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) { cpl_property *property = cpl_property_new(name, CPL_TYPE_DOUBLE); cx_assert(property != NULL); cpl_property_set_double(property, value); cx_deque_push_back(self->properties, property); } else { cpl_property *property = cx_deque_get(self->properties, pos); cx_assert(property != NULL); if (cpl_property_get_type(property) != CPL_TYPE_DOUBLE) { cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } cpl_property_set_double(property, value); } return CPL_ERROR_NONE; } /** * @brief * Update a property list with a string value. * * @param self A property list. * @param name The property name to be assigned to the value. * @param value The string value to store. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or name is a NULL * pointer. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of type CPL_TYPE_STRING. *
* @enderror * * The function updates the property list @em self with the string value * @em value. This means, if a property with the name @em name exists already * its value is updated, otherwise a property with the name @em name is * created and added to @em self. The update will fail if a property with * the name @em name exists already which is not of type @c CPL_TYPE_STRING. */ cpl_error_code cpl_propertylist_update_string(cpl_propertylist *self, const char *name, const char *value) { const cxchar *const _id = "cpl_propertylist_update_string"; cx_deque_iterator pos; if (self == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) { cpl_property *property = cpl_property_new(name, CPL_TYPE_STRING); cx_assert(property != NULL); cpl_property_set_string(property, value); cx_deque_push_back(self->properties, property); } else { cpl_property *property = cx_deque_get(self->properties, pos); cx_assert(property != NULL); if (cpl_property_get_type(property) != CPL_TYPE_STRING) { cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } cpl_property_set_string(property, value); } return CPL_ERROR_NONE; } /** * @brief * Copy a property from another property list. * * @param self A property list. * @param other The property list from which a property is copied. * @param name The name of the property to copy. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, other or name is a * NULL pointer. *
CPL_ERROR_DATA_NOT_FOUND * The property list other does not contain a property with the * name name. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of the same type as the property * which should be copied from other. *
* @enderror * * The function copies the property @em name from the property list * @em other to the property list @em self. If the property list @em self * does not already contain a property @em name the property is appended * to @em self. If a property @em name exists already in @em self the * function overwrites the contents of this property if and only if this * property is of the same type as the property to be copied from @em other. */ cpl_error_code cpl_propertylist_copy_property(cpl_propertylist *self, const cpl_propertylist *other, const char *name) { const cxchar *const _id = "cpl_propertylist_copy_property"; cx_deque_iterator spos; cx_deque_iterator tpos; if (self == NULL || other == NULL || name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } spos = _cpl_propertylist_find(other, name); if (spos == cx_deque_end(other->properties)) { cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return CPL_ERROR_DATA_NOT_FOUND; } tpos = _cpl_propertylist_find(self, name); if (tpos == cx_deque_end(self->properties)) { cpl_property *p = cpl_property_duplicate(cx_deque_get(other->properties, spos)); cx_deque_push_back(self->properties, p); } else { cpl_property *p = cx_deque_get(self->properties, tpos); cpl_property *_p = cx_deque_get(self->properties, spos); if (cpl_property_get_type(p) != cpl_property_get_type(_p)) { cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } switch (cpl_property_get_type(_p)) { case CPL_TYPE_CHAR: cpl_property_set_char(p, cpl_property_get_char(_p)); break; case CPL_TYPE_BOOL: cpl_property_set_bool(p, cpl_property_get_bool(_p)); break; case CPL_TYPE_INT: cpl_property_set_int(p, cpl_property_get_int(_p)); break; case CPL_TYPE_LONG: cpl_property_set_long(p, cpl_property_get_long(_p)); break; case CPL_TYPE_FLOAT: cpl_property_set_float(p, cpl_property_get_float(_p)); break; case CPL_TYPE_DOUBLE: cpl_property_set_double(p, cpl_property_get_double(_p)); break; case CPL_TYPE_STRING: cpl_property_set_string(p, cpl_property_get_string(_p)); break; default: /* This point should never be reached */ cx_error("%s: Unsupported type encountered!", CX_CODE_POS); break; } cpl_property_set_comment(p, cpl_property_get_comment(_p)); } return CPL_ERROR_NONE; } /** * @brief * Copy matching properties from another property list. * * @param self A property list. * @param other The property list from which a property is copied. * @param regexp The regular expression used to select properties. * @param invert Flag inverting the sense of matching. * * @return * The function returns @c CPL_ERROR_NONE on success or a CPL error * code otherwise. * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self, other or regexp is a * NULL pointer. *
CPL_ERROR_ILLEGAL_INPUT * The parameter regexp is an invalid regular expression. *
CPL_ERROR_TYPE_MISMATCH * The property list self contains a property with the * name name which is not of the same type as the property * which should be copied from other. *
* @enderror * * The function copies all properties with matching names from the property * list @em other to the property list @em self. If the flag @em invert is * zero, all properties whose names match the regular expression @em regexp * are copied. If @em invert is set to a non-zero value, all properties with * names not matching @em regexp are copied rather. The function expects * POSIX 1003.2 compliant extended regular expressions. * * If the property list @em self does not already contain one of the * properties to be copied this property is appended to @em self. If a * property to be copied exists already in @em self the function overwrites * the contents of this property. * * Before properties are copied from the property list @em other to @em self * the types of the properties are checked and if any type mismatch is * detected the function stops processing immediately. The property list * @em self is not at all modified in this case. * * @see cpl_propertylist_copy_property() */ cpl_error_code cpl_propertylist_copy_property_regexp(cpl_propertylist *self, const cpl_propertylist *other, const char *regexp, int invert) { const cxchar *const _id = "cpl_propertylist_copy_property_regexp"; cxint status; cxsize i; cxsize count = 0; cx_deque_const_iterator first, last; typedef struct _property_pair_ { cpl_property *s; cpl_property *t; } property_pair; property_pair *pairs = NULL; cpl_regexp filter; if (self == NULL || other == NULL || regexp == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } status = regcomp(&filter.re, regexp, REG_EXTENDED | REG_NOSUB); if (status) { cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return CPL_ERROR_ILLEGAL_INPUT; } filter.invert = invert == 0 ? FALSE : TRUE; count = cx_deque_size(other->properties); if (count == 0) { regfree(&filter.re); return CPL_ERROR_NONE; } pairs = cx_malloc(count * sizeof(property_pair)); cx_assert(pairs != NULL); count = 0; first = cx_deque_begin(other->properties); last = cx_deque_end(other->properties); while (first != last) { cpl_property *p = cx_deque_get(other->properties, first); if (_cpl_propertylist_compare_regexp(p, &filter) == TRUE) { const cxchar *name = cpl_property_get_name(p); cx_deque_const_iterator pos = _cpl_propertylist_find(self, name); cpl_property *_p = NULL; if (pos != cx_deque_end(self->properties)) { _p = cx_deque_get(self->properties, pos); if (cpl_property_get_type(p) != cpl_property_get_type(_p)) { regfree(&filter.re); cx_free(pairs); pairs = NULL; cpl_error_set(_id, CPL_ERROR_TYPE_MISMATCH); return CPL_ERROR_TYPE_MISMATCH; } } pairs[count].s = p; pairs[count].t = _p; ++count; } first = cx_deque_next(other->properties, first); } regfree(&filter.re); for (i = 0; i < count; i++) { if (pairs[i].t == NULL) { cpl_property *p = cpl_property_duplicate(pairs[i].s); cx_deque_push_back(self->properties, p); } else { switch (cpl_property_get_type(pairs[i].s)) { case CPL_TYPE_CHAR: cpl_property_set_char(pairs[i].t, cpl_property_get_char(pairs[i].s)); break; case CPL_TYPE_BOOL: cpl_property_set_bool(pairs[i].t, cpl_property_get_bool(pairs[i].s)); break; case CPL_TYPE_INT: cpl_property_set_int(pairs[i].t, cpl_property_get_int(pairs[i].s)); break; case CPL_TYPE_LONG: cpl_property_set_long(pairs[i].t, cpl_property_get_long(pairs[i].s)); break; case CPL_TYPE_FLOAT: cpl_property_set_float(pairs[i].t, cpl_property_get_float(pairs[i].s)); break; case CPL_TYPE_DOUBLE: cpl_property_set_double(pairs[i].t, cpl_property_get_double(pairs[i].s)); break; case CPL_TYPE_STRING: cpl_property_set_string(pairs[i].t, cpl_property_get_string(pairs[i].s)); break; default: /* This point should never be reached */ cx_free(pairs); cx_error("%s: Unsupported type encountered!", CX_CODE_POS); break; } } } cx_free(pairs); return CPL_ERROR_NONE; } /** * @brief * Sort a property list. * * @param self The property list to sort. * @param compare The function used to compare two properties. * * @return * The function returns @c CPL_ERROR_NONE on success, or a CPL error code * otherwise. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self is a NULL pointer. *
* @enderror * * The function sorts the property list @em self in place, using the function * @em compare to determine whether a property is less, equal or greater than * another one. * * The function @em compare must be of the type cpl_propertylist_compare_func. * * @see * cpl_propertylist_compare_func */ /*cpl_error_code cpl_propertylist_sort(cpl_propertylist* self, int (*compare)(const void*, const void*))*/ cpl_error_code cpl_propertylist_sort(cpl_propertylist* self, cpl_propertylist_compare_func compare) { const cxchar *const _id = "cpl_propertylist_sort"; cx_deque_compare _compare = (cx_deque_compare)compare; if (self == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } cx_deque_sort(self->properties, _compare); return CPL_ERROR_NONE; } /** * @brief * Create a property list from a file. * * @param name Name of the input file. * @param position Index of the data set to read. * * @return * The function returns the newly created property list or @c NULL if an * error occurred. * * @error * * * * * * * * * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter name is a NULL pointer. *
CPL_ERROR_ILLEGAL_INPUT * The position is less than 0 or the properties cannot be * read from the file name. *
CPL_ERROR_FILE_IO * The file name does not exist. *
CPL_ERROR_BAD_FILE_FORMAT * The file name is not a valid FITS file. *
CPL_ERROR_DATA_NOT_FOUND * The requested data set at index position does not exist. *
* @enderror * * The function reads the properties of the data set with index @em position * from the file @em name. * * Currently only the FITS file format is supported. The property list is * created by reading the FITS keywords from extension @em position. The * numbering of the data sections starts from 0. * When creating the property list from a FITS header, any keyword without * a value like undefined keywords for instance are not transformed into * a property. * * @see cpl_propertylist_load_regexp() */ cpl_propertylist * cpl_propertylist_load(const char *name, int position) { const cxchar *const _id = "cpl_propertylist_load"; cxint status = 0; cxint hdu_position = position + 1; cxint hdu_type = ANY_HDU; cpl_propertylist *self; fitsfile *file = NULL; if (name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return NULL; } if (position < 0) { cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return NULL; } fits_open_diskfile(&file, (cxchar*)name, READONLY, &status); if (status == FILE_NOT_OPENED) { status = 0; fits_close_file(file, &status); cpl_error_set(_id, CPL_ERROR_FILE_IO); return NULL; } else { if (status != 0) { status = 0; fits_close_file(file, &status); cpl_error_set(_id, CPL_ERROR_BAD_FILE_FORMAT); return NULL; } } fits_movabs_hdu(file, hdu_position, &hdu_type, &status); if ((status == BAD_HDU_NUM) || (status == END_OF_FILE)) { status = 0; fits_close_file(file, &status); cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return NULL; } self = cpl_propertylist_new(); cx_assert(self != NULL); status = _cpl_propertylist_from_fitsfile(self, file, NULL, NULL); if (status != 0) { cpl_propertylist_delete(self); status = 0; fits_close_file(file, &status); cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return NULL; } cx_assert(status == 0); fits_close_file(file, &status); return self; } /** * @brief * Create a filtered property list from a file. * * @param name Name of the input file. * @param position Index of the data set to read. * @param regexp Regular expression used to filter properties. * @param invert Flag inverting the sense of matching property names. * * @return * The function returns the newly created property list or @c NULL if an * error occurred. * * @error * * * * * * * * * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The parameter name or the parameter regexp is a * NULL pointer. *
CPL_ERROR_ILLEGAL_INPUT * The position is less than 0, the properties cannot be * read from the file name, or regexp is not a valid * extended regular expression. *
CPL_ERROR_FILE_IO * The file name does not exist. *
CPL_ERROR_BAD_FILE_FORMAT * The file name is not a valid FITS file. *
CPL_ERROR_DATA_NOT_FOUND * The requested data set at index position does not exist. *
* @enderror * * The function reads all properties of the data set with index @em position * with matching names from the file @em name. If the flag @em invert is zero, * all properties whose names match the regular expression @em regexp are * read. If @em invert is set to a non-zero value, all properties with * names not matching @em regexp are read rather. The function expects * POSIX 1003.2 compliant extended regular expressions. * * Currently only the FITS file format is supported. The property list is * created by reading the FITS keywords from extension @em position. * The numbering of the data sections starts from 0. * * When creating the property list from a FITS header, any keyword without * a value like undefined keywords for instance are not transformed into * a property. FITS format specific keyword prefixes (e.g. @c HIERARCH) must * not be part of the given pattern string @em regexp, but only the actual * FITS keyword name may be given. * * @see cpl_propertylist_load() */ cpl_propertylist * cpl_propertylist_load_regexp(const char *name, int position, const char *regexp, int invert) { const cxchar *const _id = "cpl_propertylist_load_regexp"; cxint status = 0; cxint hdu_position = position + 1; cxint hdu_type = ANY_HDU; cpl_propertylist *self; cpl_regexp filter; fitsfile *file = NULL; if (name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return NULL; } if (position < 0) { cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return NULL; } /* * Set up the regular expression filter */ status = regcomp(&filter.re, regexp, REG_EXTENDED | REG_NOSUB); if (status) { cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return NULL; } filter.invert = invert == 0 ? FALSE : TRUE; fits_open_diskfile(&file, (cxchar*)name, READONLY, &status); if (status == FILE_NOT_OPENED) { status = 0; fits_close_file(file, &status); regfree(&filter.re); cpl_error_set(_id, CPL_ERROR_FILE_IO); return NULL; } else { if (status != 0) { status = 0; fits_close_file(file, &status); regfree(&filter.re); cpl_error_set(_id, CPL_ERROR_BAD_FILE_FORMAT); return NULL; } } fits_movabs_hdu(file, hdu_position, &hdu_type, &status); if ((status == BAD_HDU_NUM) || (status == END_OF_FILE)) { status = 0; fits_close_file(file, &status); regfree(&filter.re); cpl_error_set(_id, CPL_ERROR_DATA_NOT_FOUND); return NULL; } self = cpl_propertylist_new(); cx_assert(self != NULL); status = _cpl_propertylist_from_fitsfile(self, file, _cpl_propertylist_filter_regexp, &filter); if (status != 0) { cpl_propertylist_delete(self); regfree(&filter.re); status = 0; fits_close_file(file, &status); cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return NULL; } regfree(&filter.re); cx_assert(status == 0); fits_close_file(file, &status); return self; } /** * @internal * @brief * Write a property list to a FITS file. * * @param file The FITS file to write to. * @param properties The property list to write to the file. * @param to_rm The regular expression used to filter properties * * @return * The function returns @c CPL_ERROR_NONE on success, or an appropriate * error code otherwise. * * This function takes a sorted property list and appends it to the * provided FITS file. All properties with names matching the regular expression * @c to_rm will not be copied to the output. The function expects * POSIX 1003.2 compliant extended regular expressions. */ cpl_error_code cpl_propertylist_to_fitsfile(fitsfile *file, const cpl_propertylist *self, const char *to_rm) { const cxchar *const _id = "cpl_propertylist_to_fitsfile"; int rstatus = 0; cpl_regexp filter; if ((file == NULL) || (self == NULL)) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return CPL_ERROR_NULL_INPUT; } if (cpl_propertylist_is_empty(self)){ return CPL_ERROR_NONE; } /* * If regular expression filter exists */ if (to_rm != NULL) { rstatus = regcomp(&filter.re, to_rm, REG_EXTENDED | REG_NOSUB); if (rstatus) { cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return CPL_ERROR_ILLEGAL_INPUT; } filter.invert = 0; rstatus = _cpl_propertylist_to_fitsfile(file, self, _cpl_propertylist_filter_regexp, &filter); if (rstatus == 1) { regfree(&filter.re); rstatus = 0; cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT); return CPL_ERROR_ILLEGAL_INPUT; } if (rstatus > 1){ regfree(&filter.re); return cpl_error_set_message_macro(cpl_func, CPL_ERROR_UNSPECIFIED, __FILE__,__LINE__, "CFITSIO error (%d): %s", rstatus, cpl_tools_get_cfitsio_msg(rstatus)); } regfree(&filter.re); } else { cx_deque_iterator first, last; first = cx_deque_begin(self->properties); last = cx_deque_end(self->properties); while (first != last) { const cpl_property *p = cpl_propertylist_get_const(self, first); const cxchar *name = cpl_property_get_name(p); const cxchar *comment = cpl_property_get_comment(p); cxint status = 0; cpl_type type = cpl_property_get_type(p); switch (type) { case CPL_TYPE_CHAR: { cxchar c = cpl_property_get_char(p); cxchar s[2]; s[0] = c; s[1] = '\0'; fits_write_key(file, TSTRING, (cxchar*)name, &s, (cxchar*)comment, &status); } break; case CPL_TYPE_BOOL: { cxbool b = cpl_property_get_bool(p); cxint value = b == TRUE ? 1 : 0; fits_write_key(file, TLOGICAL, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_INT: { cxint value = cpl_property_get_int(p); fits_write_key(file, TINT, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_LONG: { cxlong value = cpl_property_get_long(p); fits_write_key(file, TLONG, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_FLOAT: { cxfloat value = cpl_property_get_float(p); fits_write_key(file, TFLOAT, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_DOUBLE: { cxdouble value = cpl_property_get_double(p); fits_write_key(file, TDOUBLE, (cxchar*)name, &value, (cxchar*)comment, &status); } break; case CPL_TYPE_STRING: { const cxchar *value = cpl_property_get_string(p); if (strcmp(name, "COMMENT") == 0) { if(strcmp(value, "") == 0){ fits_write_comment(file, " ", &status); } else{ fits_write_comment(file, (cxchar *)value, &status); } } else if(strcmp(name, "HISTORY") == 0) { if(strcmp(value, "") == 0){ fits_write_history(file, " ", &status); } else{ fits_write_history(file, (cxchar *)value, &status); } } else { fits_write_key(file, TSTRING, (cxchar*)name, (cxchar*)value, (cxchar*)comment, &status); } } break; default: status = 1; break; } if (status != 0){ return cpl_error_set_message_macro(_id, CPL_ERROR_UNSPECIFIED, __FILE__,__LINE__, "CFITSIO error (%d): %s", status, cpl_tools_get_cfitsio_msg(status)); } cx_assert(status == 0); first = cx_deque_next(self->properties, first); } } return CPL_ERROR_NONE; } /** * @internal * @brief * Create a property list from a cfitsio FITS file. * * @param file FITS file pointing to the header to convert. * * @return The function returns the created property list, or @c NULL * in case of an error. * * The function converts the FITS keywords from the current HDU of the FITS * file @em file into properties and puts them into a property list. * * The special FITS keyword END indicating the end of a FITS header is not * transformed into a property, but simply ignored. * * In case of an error, an appropriate error code is set. If a FITS header * card cannot be parsed the error code is set to @c CPL_ERROR_ILLEGAL_INPUT * or to @c CPL_ERROR_INVALID_TYPE if a FITS keyword type is not supported. * If @em file is @c NULL the error code is set to @c CPL_ERROR_NULL_INPUT. */ cpl_propertylist * cpl_propertylist_from_fitsfile(fitsfile *file) { register cxint status; cpl_propertylist *self; cpl_ensure(file != NULL, CPL_ERROR_NULL_INPUT, NULL); self = cpl_propertylist_new(); cx_assert(self != NULL); status = _cpl_propertylist_from_fitsfile(self, file, NULL, NULL); if (status != 0) { cpl_propertylist_delete(self); cpl_ensure(0, status == -1 ? CPL_ERROR_ILLEGAL_INPUT : CPL_ERROR_INVALID_TYPE, NULL); } return self; } /** * @brief * Access property list elements by property name. * * @param self The property list to query. * @param name The name of the property to retrieve. * * @return * The function returns the property with name @em name, or @c NULL * if it does not exist. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or the name is a NULL pointer. *
* @enderror * * The function returns a handle to the property list element, the property, * with the name @em name. If more than one property exist with the same * @em name, then the first one found will be returned. */ const cpl_property * cpl_propertylist_get_property_const(const cpl_propertylist *self, const char *name) { const cxchar *const _id = "cpl_propertylist_get_property_const"; cx_deque_iterator pos; if (self == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return NULL; } if (name == NULL) { cpl_error_set(_id, CPL_ERROR_NULL_INPUT); return NULL; } pos = _cpl_propertylist_find(self, name); if (pos == cx_deque_end(self->properties)) return NULL; return cx_deque_get(self->properties, pos); } /** * @brief * Access property list elements by property name. * * @param self The property list to query. * @param name The name of the property to retrieve. * * @return * The function returns the property with name @em name, or @c NULL * if it does not exist. * * @error * * * * * *
CPL_ERROR_NULL_INPUT * The parameter self or the name is a NULL pointer. *
* @enderror * * The function returns a handle to the property list element, the property, * with the name @em name. If more than one property exist with the same * @em name, then the first one found will be returned. */ cpl_property * cpl_propertylist_get_property(cpl_propertylist *self, const char *name) { cpl_errorstate prestate = cpl_errorstate_get(); cpl_property *property = (cpl_property *)cpl_propertylist_get_property_const(self, name); if (!cpl_errorstate_is_equal(prestate)) (void)cpl_error_set_where(cpl_func); return property; } /** * @brief * Save a property list to a FITS file * * @param self The property list to save or NULL if empty * @param filename Name of the file to write * @param mode The desired output options (combined with bitwise or) * * @return * CPL_ERROR_NONE or the relevant #_cpl_error_code_ on error * * @error * * * * * * * * * * * * * *
CPL_ERROR_NULL_INPUT * The filename is a NULL pointer. *
CPL_ERROR_ILLEGAL_INPUT * The parameter mode is invalid. *
CPL_ERROR_FILE_IO * The file cannot be written or accessed. *
* @enderror * * This function saves a property list to a FITS file, using cfitsio. * The data unit is empty. * * Supported output modes are CPL_IO_DEFAULT (create a new file) and * CPL_IO_EXTEND (append to an existing file) */ cpl_error_code cpl_propertylist_save(const cpl_propertylist * self, const char * filename, unsigned mode) { fitsfile * fptr ; char * sval ; int fio_status=0 ; int ival ; /* Check entries */ cpl_ensure_code(filename, CPL_ERROR_NULL_INPUT) ; cpl_ensure_code(mode <= CPL_IO_MAX, CPL_ERROR_ILLEGAL_INPUT) ; /* Switch on the mode */ if (mode == CPL_IO_EXTEND) { /* Append */ /* Open the file */ fits_open_file(&fptr, filename, READWRITE, &fio_status); if (fio_status != 0) { cpl_ensure_code(0, CPL_ERROR_FILE_IO) ; } /* Create minimal header */ fits_create_hdu(fptr, &fio_status); fits_write_key(fptr, TSTRING, (char*)"XTENSION", (char*)"Empty", (char*)"FITS Empty Extension", &fio_status) ; ival = 16 ; fits_write_key(fptr, TINT, (char*)"BITPIX", &ival, (char*)"Bits per pixel", &fio_status); ival = 0 ; fits_write_key(fptr, TINT, (char*)"NAXIS", &ival, (char*)"Empty unit", &fio_status); if (fio_status != 0) { fits_close_file(fptr, &fio_status) ; cpl_ensure_code(0, CPL_ERROR_FILE_IO) ; } /* Add the property list */ if (cpl_fits_add_properties(fptr, self, CPL_FITS_BADKEYS_EXT "|" CPL_FITS_COMPRKEYS) != CPL_ERROR_NONE) { fits_close_file(fptr, &fio_status) ; cpl_ensure_code(0, CPL_ERROR_ILLEGAL_INPUT) ; } } else { /* PDU */ /* Create the file */ sval = cpl_sprintf("!%s", filename) ; fits_create_file(&fptr, sval, &fio_status); cpl_free(sval) ; if (fio_status != 0) { fits_close_file(fptr, &fio_status) ; cpl_ensure_code(0, CPL_ERROR_FILE_IO) ; } /* Create minimal header */ fits_create_hdu(fptr, &fio_status); ival = 1 ; fits_write_key(fptr, TLOGICAL, (char*)"SIMPLE", &ival, (char*)"Fits format", &fio_status); ival = 16 ; fits_write_key(fptr, TINT, (char*)"BITPIX", &ival, (char*)"Bits per pixel", &fio_status); ival = 0 ; fits_write_key(fptr, TINT, (char*)"NAXIS", &ival, (char*)"Empty unit", &fio_status); ival = 1 ; fits_write_key(fptr, TLOGICAL, (char*)"EXTEND", &ival, (char*)"There may be FITS extensions", &fio_status); /* Add DATE */ fits_write_date(fptr, &fio_status); /* Check */ if (fio_status != 0) { fits_close_file(fptr, &fio_status) ; cpl_ensure_code(0, CPL_ERROR_FILE_IO) ; } /* Add the property list */ if (cpl_fits_add_properties(fptr, self, CPL_FITS_BADKEYS_PRIM "|" CPL_FITS_COMPRKEYS) != CPL_ERROR_NONE) { fits_close_file(fptr, &fio_status) ; cpl_ensure_code(0, CPL_ERROR_ILLEGAL_INPUT) ; } } /* Close and write on disk */ fits_close_file(fptr, &fio_status) ; return CPL_ERROR_NONE ; } /**@}*/