/* $Id: cpl_array.c,v 1.18 2007/09/03 13:05:17 cizzo Exp $ * * This file is part of the ESO Common Pipeline Library * Copyright (C) 2001-2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * $Author: cizzo $ * $Date: 2007/09/03 13:05:17 $ * $Revision: 1.18 $ * $Name: $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "cpl_memory.h" #include #include "cpl_tools.h" #include #include #include /** * @defgroup cpl_array Arrays * * This module provides functions to create, destroy and use a @em cpl_array. * * @par Synopsis: * @code * #include * @endcode */ /**@{*/ /* * The array type (private); */ struct _cpl_array_ { cpl_column *column; }; /** * @brief * Create a new array of given type. * * @param length Number of elements in array. * @param type Type of array * * @return Pointer to the new array, or @c NULL in case of error. * * This function allocates memory for an array, its type is assigned, * and its number of elements is allocated. Only arrays of types * @c CPL_TYPE_INT, @c CPL_TYPE_FLOAT, @c CPL_TYPE_DOUBLE, and * @c CPL_TYPE_STRING, are supported. An error @c CPL_ERROR_INVALID_TYPE * is set in case other types are specified. All array elements are * initially flagged as invalid. If a negative length is specified, * an error @c CPL_ERROR_ILLEGAL_INPUT is set. Zero length arrays are * allowed. */ cpl_array *cpl_array_new(int length, cpl_type type) { const char *fid = "cpl_array_new"; cpl_column *column; cpl_array *array; switch(type) { case CPL_TYPE_INT: column = cpl_column_new_int(length); break; case CPL_TYPE_FLOAT: column = cpl_column_new_float(length); break; case CPL_TYPE_DOUBLE: column = cpl_column_new_double(length); break; case CPL_TYPE_STRING: column = cpl_column_new_string(length); break; default: cpl_error_set(fid, CPL_ERROR_INVALID_TYPE); return NULL; } if (column == NULL) { cpl_error_set_where(fid); return NULL; } array = cpl_calloc(1, sizeof(cpl_array)); array->column = column; return array; } /** * @brief * Create a new @em integer array from existing data. * * @param data Existing data buffer. * @param length Number of elements in array. * * @return Pointer to the new array, or @c NULL in case of error. * * This function creates a new @em integer array that will encapsulate * the given data. Note that the size of the data buffer is not checked in * any way, and that the data values are all considered valid: invalid * values should be marked using the functions @c cpl_array_set_invalid() * The data array is not copied, so it should never be deallocated: to * deallocate it, the function @c cpl_array_delete() should be called * instead. Alternatively, the function @c cpl_array_unwrap() might be * used, and the data array deallocated afterwards. A zero or negative * length is illegal, and would cause an error @c CPL_ERROR_ILLEGAL_INPUT * to be set. An input @c NULL pointer would set an error * @c CPL_ERROR_NULL_INPUT. * * @note * Functions that handle arrays assume that an array data buffer * is dinamically allocated: with a statically allocated data buffer * any function implying memory handling (@c cpl_array_set_size(), * @c cpl_array_delete(), etc.) would crash the program. This means * that a static data buffer should never be passed to this function * if memory handling is planned. In case of a static data buffer, * only the @c cpl_array_unwrap() destructor can be used. */ cpl_array *cpl_array_wrap_int(int *data, int length) { const char *fid = "cpl_array_wrap_int"; cpl_column *column; cpl_array *array; column = cpl_column_wrap_int(data, length); if (column == NULL) { cpl_error_set_where(fid); return NULL; } array = cpl_calloc(1, sizeof(cpl_array)); array->column = column; return array; } /** * @brief * Create a new @em float array from existing data. * * @param data Existing data buffer. * @param length Number of elements in array. * * @return Pointer to the new array, or @c NULL in case of error. * * See documentation of function @c cpl_array_wrap_int(). */ cpl_array *cpl_array_wrap_float(float *data, int length) { const char *fid = "cpl_array_wrap_float"; cpl_column *column; cpl_array *array; column = cpl_column_wrap_float(data, length); if (column == NULL) { cpl_error_set_where(fid); return NULL; } array = cpl_calloc(1, sizeof(cpl_array)); array->column = column; return array; } /** * @brief * Create a new @em double array from existing data. * * @param data Existing data buffer. * @param length Number of elements in array. * * @return Pointer to the new array, or @c NULL in case of error. * * See documentation of function @c cpl_array_wrap_int(). */ cpl_array *cpl_array_wrap_double(double *data, int length) { const char *fid = "cpl_array_wrap_double"; cpl_column *column; cpl_array *array; column = cpl_column_wrap_double(data, length); if (column == NULL) { cpl_error_set_where(fid); return NULL; } array = cpl_calloc(1, sizeof(cpl_array)); array->column = column; return array; } /** * @brief * Create a new character string array from existing data. * * @param data Existing data buffer. * @param length Number of elements in array. * * @return Pointer to the new array, or @c NULL in case of error. * * See documentation of function @c cpl_array_wrap_int(). */ cpl_array *cpl_array_wrap_string(char **data, int length) { const char *fid = "cpl_array_wrap_string"; cpl_column *column; cpl_array *array; column = cpl_column_wrap_string(data, length); if (column == NULL) { cpl_error_set_where(fid); return NULL; } array = cpl_calloc(1, sizeof(cpl_array)); array->column = column; return array; } /** * @brief * Copy buffer of numerical data to a numerical array. * * @param array Existing array. * @param data Existing data buffer. * * @return @c CPL_ERROR_NONE on success. If the array is not numerical, * a @c CPL_ERROR_INVALID_TYPE is returned. At any @c NULL input * pointer a @c CPL_ERROR_NULL_INPUT would be returned. * * The input data are copied into the specified array. If the type of the * accessed array is not @em CPL_TYPE_DOUBLE, the data values will be * truncated according to C casting rules. The size of the input data * buffer is not checked in any way, and the values are all considered * valid: invalid values should be marked using the functions * @c cpl_array_set_invalid(). If @em N is the length of the array, * the first @em N values of the input data buffer would be copied to * the column buffer. If the array had length zero, no values would * be copied. */ cpl_error_code cpl_array_copy_data(cpl_array *array, const double *data) { const char *fid = "cpl_array_copy_data"; if (data == 0x0 || array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (cpl_column_copy_data(array->column, data)) { cpl_error_set_where(fid); return cpl_error_get_code(); } return CPL_ERROR_NONE; } /** * @brief * Copy existing data to an @em integer array. * * @param array Existing array. * @param data Existing data buffer. * * @return @c CPL_ERROR_NONE on success. If the input array is not * of type @c CPL_TYPE_INT, a @c CPL_ERROR_TYPE_MISMATCH is returned. * At any @c NULL input pointer a @c CPL_ERROR_NULL_INPUT would be * returned. * * The input data are copied into the specified array. The size of the * input data buffer is not checked in any way, and the data values are all * considered valid: invalid values should be marked using the functions * @c cpl_array_set_invalid(). If @em N is the length of the array, the * first @em N values of the input data buffer would be copied to the * array buffer. If the array had length zero, no values would be copied. */ cpl_error_code cpl_array_copy_data_int(cpl_array *array, const int *data) { const char *fid = "cpl_array_copy_data_int"; if (data == 0x0 || array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (cpl_column_copy_data_int(array->column, data)) { cpl_error_set_where(fid); return cpl_error_get_code(); } return CPL_ERROR_NONE; } /** * @brief * Copy existing data to a @em float array. * * @param array Existing array. * @param data Existing data buffer. * * @return @c CPL_ERROR_NONE on success. If the input array is not of * type @c CPL_TYPE_FLOAT, a @c CPL_ERROR_TYPE_MISMATCH is returned. * At any @c NULL input pointer a @c CPL_ERROR_NULL_INPUT would be * returned. * * See documentation of function @c cpl_array_copy_data_int(). */ cpl_error_code cpl_array_copy_data_float(cpl_array *array, const float *data) { const char *fid = "cpl_array_copy_data_float"; if (data == 0x0 || array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (cpl_column_copy_data_float(array->column, data)) { cpl_error_set_where(fid); return cpl_error_get_code(); } return CPL_ERROR_NONE; } /** * @brief * Copy existing data to a @em double array. * * @param array Existing array. * @param data Existing data buffer. * * @return @c CPL_ERROR_NONE on success. If the input array is not of * type @c CPL_TYPE_DOUBLE, a @c CPL_ERROR_TYPE_MISMATCH is returned. * At any @c NULL input pointer a @c CPL_ERROR_NULL_INPUT would be * returned. * * See documentation of function @c cpl_array_copy_data_int(). */ cpl_error_code cpl_array_copy_data_double(cpl_array *array, const double *data) { const char *fid = "cpl_array_copy_data_double"; if (data == 0x0 || array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (cpl_column_copy_data_double(array->column, data)) { cpl_error_set_where(fid); return cpl_error_get_code(); } return CPL_ERROR_NONE; } /** * @brief * Copy existing data to a @em string array. * * @param array Existing array. * @param data Existing data buffer. * * @return @c CPL_ERROR_NONE on success. If the input array is not of * type @c CPL_TYPE_STRING, a @c CPL_ERROR_TYPE_MISMATCH is returned. * At any @c NULL input pointer a @c CPL_ERROR_NULL_INPUT would be * returned. * * See documentation of function @c cpl_array_copy_data_int(). * * The input data are copied into the specified array. The size of the * input buffer is not checked in any way. The strings pointed by the input * buffer are all duplicated, while the strings contained in the array * are released before being overwritten. */ cpl_error_code cpl_array_copy_data_string(cpl_array *array, const char **data) { const char *fid = "cpl_column_copy_data_string"; if (data == 0x0 || array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (cpl_column_copy_data_string(array->column, data)) { cpl_error_set_where(fid); return cpl_error_get_code(); } return CPL_ERROR_NONE; } /** * @brief * Delete an array. * * @param array Array to be deleted. * * @return Nothing. * * This function deletes an array. If the input array is @c NULL, * nothing is done, and no error is set. */ void cpl_array_delete(cpl_array *array) { if (array != NULL) { cpl_column_delete(array->column); cpl_free(array); } } /** * @brief * Delete an array, without losing the data buffer. * * @param array Array to be deleted. * * @return Pointer to the internal data buffer. * * This function deletes an array, but its data buffer is not destroyed. * Supposedly, the developer knows that the data are static, or the * developer holds the pointer to the data obtained with the functions * @c cpl_array_get_data_int(), @c cpl_array_get_data_float(), etc. * If the input array is @c NULL, nothing is done, and no error is set. */ void *cpl_array_unwrap(cpl_array *array) { void *d = NULL; if (array != NULL) { d = cpl_column_unwrap(array->column); cpl_free(array); } return d; } /** * @brief * Get the length of an array. * * @param array Input array. * * @return Length of array, or zero. The latter case can occur either * with an array having zero length, or if a @c NULL array is passed to * the function, but in the latter case a @c CPL_ERROR_NULL_INPUT is set. * * If the array is @em NULL, zero is returned. */ int cpl_array_get_size(const cpl_array *array) { if (array) return cpl_column_get_size(array->column); cpl_error_set("cpl_array_get_size", CPL_ERROR_NULL_INPUT); return 0; } /** * @brief * Get the type of an array. * * @param array Input array * * @return Type of array, or @c CPL_TYPE_INVALID if a @c NULL array is * passed to the function. * * If the array is @c NULL, @c CPL_ERROR_NULL_INPUT is set. */ cpl_type cpl_array_get_type(const cpl_array *array) { if (array) return cpl_column_get_type(array->column); cpl_error_set("cpl_array_get_type", CPL_ERROR_NULL_INPUT); return CPL_TYPE_INVALID; } /** * @brief * Check if an array contains at least one invalid element. * * @param array Array to inquire. * * @return 1 if the array contains at least one invalid element, 0 if not, * -1 in case of error. * * Check if there are invalid elements in an array. If the input array is a * @c NULL pointer, a @c CPL_ERROR_NULL_INPUT is set. */ int cpl_array_has_invalid(const cpl_array *array) { const char *fid = "cpl_array_has_invalid"; if (array == 0x0) { cpl_error_set(fid, CPL_ERROR_NULL_INPUT); return -1; } return cpl_column_has_invalid(array->column); } /** * @brief * Check if an array contains at least one valid value. * * @param array Array to inquire. * * @return 1 if the array contains at least one valid value, 0 if not * -1 in case of error. * * Check if there are valid values in an array. If the input array is a * @c NULL pointer, a @c CPL_ERROR_NULL_INPUT is set. */ int cpl_array_has_valid(const cpl_array *array) { const char *fid = "cpl_array_has_valid"; if (array == 0x0) { cpl_error_set(fid, CPL_ERROR_NULL_INPUT); return -1; } return cpl_column_has_valid(array->column); } /** * @brief * Count number of invalid elements in an array. * * @param array Array to inquire. * * @return Number of invalid elements in an array. -1 is always returned * in case of error. * * Count number of invalid elements in an array. If the array itself is * a @c NULL pointer, an error @c CPL_ERROR_NULL_INPUT is set. */ int cpl_array_count_invalid(const cpl_array *array) { const char *fid = "cpl_array_count_invalid"; if (array == 0x0) { cpl_error_set(fid, CPL_ERROR_NULL_INPUT); return -1; } return cpl_column_count_invalid(array->column); } /** * @brief * Get a pointer to @c integer array data. * * @param array Array to get the data from. * * @return Pointer to @c integer array data. If @em array contains no * data (zero length), a @c NULL is returned. If @em array is a @c NULL, * a @c NULL is returned, and an error is set. * * If the array is not of type @c CPL_TYPE_INT, a * @c CPL_ERROR_TYPE_MISMATCH is set. * * @note * Use at your own risk: direct manipulation of array data rules * out any check performed by the array object interface, and may * introduce inconsistencies between the array information maintained * internally and the actual array data. */ int *cpl_array_get_data_int(cpl_array *array) { cpl_errorstate prestate = cpl_errorstate_get(); int *data = (int *)cpl_array_get_data_int_const(array); if (!cpl_errorstate_is_equal(prestate)) cpl_error_set_where(cpl_func); return data; } /** * @brief * Get a pointer to constant @c integer array data. * * @param array Constant array to get the data from. * * @return Pointer to constant @c integer array data. If @em array contains * no data (zero length), a @c NULL is returned. If @em array is a @c NULL, * a @c NULL is returned, and an error is set. * * If the array is not of type @c CPL_TYPE_INT, a * @c CPL_ERROR_TYPE_MISMATCH is set. */ const int *cpl_array_get_data_int_const(const cpl_array *array) { const int *data = NULL; if (array == 0x0) { cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT); return NULL; } data = cpl_column_get_data_int_const(array->column); if (data == NULL) cpl_error_set_where(cpl_func); return data; } /** * @brief * Get a pointer to @c float array data. * * @param array Array to get the data from. * * @return Pointer to @c float array data. If @em array contains no * data (zero length), a @c NULL is returned. If @em array is a @c NULL, * a @c NULL is returned, and an error is set. * * If the array is not of type @c CPL_TYPE_FLOAT, a * @c CPL_ERROR_TYPE_MISMATCH is set. * * See documentation of function cpl_array_get_data_int(). */ float *cpl_array_get_data_float(cpl_array *array) { cpl_errorstate prestate = cpl_errorstate_get(); float *data = (float *)cpl_array_get_data_float_const(array); if (!cpl_errorstate_is_equal(prestate)) cpl_error_set_where(cpl_func); return data; } /** * @brief * Get a pointer to constant @em float array data. * * @param array Constant array to get the data from. * * @return Pointer to constant @em float array data. If @em array contains no * data (zero length), a @c NULL is returned. If @em array is a @c NULL, * a @c NULL is returned, and an error is set. * * If the array is not of type @c CPL_TYPE_FLOAT, a * @c CPL_ERROR_TYPE_MISMATCH is set. * * See documentation of function cpl_array_get_data_int_const(). */ const float *cpl_array_get_data_float_const(const cpl_array *array) { const float *data = NULL; if (array == 0x0) { cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT); return NULL; } data = cpl_column_get_data_float_const(array->column); if (data == NULL) cpl_error_set_where(cpl_func); return data; } /** * @brief * Get a pointer to @c double array data. * * @param array Array to get the data from. * * @return Pointer to @c double array data. If @em array contains no * data (zero length), a @c NULL is returned. If @em array is a @c NULL, * a @c NULL is returned, and an error is set. * * If the array is not of type @c CPL_TYPE_DOUBLE, a * @c CPL_ERROR_TYPE_MISMATCH is set. * * See documentation of function cpl_array_get_data_int(). */ double *cpl_array_get_data_double(cpl_array *array) { cpl_errorstate prestate = cpl_errorstate_get(); double *data = (double *)cpl_array_get_data_double_const(array); if (!cpl_errorstate_is_equal(prestate)) cpl_error_set_where(cpl_func); return data; } /** * @brief * Get a pointer to constant @em double array data. * * @param array Constant array to get the data from. * * @return Pointer to constant @em double array data. If @em array contains no * data (zero length), a @c NULL is returned. If @em array is a @c NULL, * a @c NULL is returned, and an error is set. * * If the array is not of type @c CPL_TYPE_DOUBLE, a * @c CPL_ERROR_TYPE_MISMATCH is set. * * See documentation of function cpl_array_get_data_int_const(). */ const double *cpl_array_get_data_double_const(const cpl_array *array) { const double *data = NULL; if (array == 0x0) { cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT); return NULL; } data = cpl_column_get_data_double_const(array->column); if (data == NULL) cpl_error_set_where(cpl_func); return data; } /* * This is a private function, to be used only by other CPL functions, * and listed in cpl_array_impl.h */ const cpl_column *cpl_array_get_column_const(const cpl_array *array) { if (array == 0x0) { cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT); return NULL; } return array->column; } cpl_column *cpl_array_get_column(cpl_array *array) { if (array == 0x0) { cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT); return NULL; } return array->column; } /* * This is a private function, to be used only by other CPL functions, * and listed in cpl_array_impl.h */ cpl_error_code cpl_array_set_column(cpl_array *array, const cpl_column *column) { if (array == 0x0) return cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT); if (array->column) cpl_column_delete(array->column); array->column = (cpl_column *)column; return CPL_ERROR_NONE; } /** * @brief * Get a pointer to @em string array data. * * @param array Array to get the data from. * * @return Pointer to @em string array data. If @em array contains no * data (zero length), a @c NULL is returned. If @em array is a @c NULL, * a @c NULL is returned, and an error is set. * * If the array is not of type @c CPL_TYPE_STRING, a * @c CPL_ERROR_TYPE_MISMATCH is set. * * See documentation of function cpl_array_get_data_int(). */ char **cpl_array_get_data_string(cpl_array *array) { cpl_errorstate prestate = cpl_errorstate_get(); char **data = (char **)cpl_array_get_data_string_const(array); if (!cpl_errorstate_is_equal(prestate)) cpl_error_set_where(cpl_func); return data; } /** * @brief * Get a pointer to constant @em string array data. * * @param array Constant array to get the data from. * * @return Pointer to constant @em string array data. If @em array contains no * data (zero length), a @c NULL is returned. If @em array is a @c NULL, * a @c NULL is returned, and an error is set. * * If the array is not of type @c CPL_TYPE_STRING, a * @c CPL_ERROR_TYPE_MISMATCH is set. * * See documentation of function cpl_array_get_data_int(). */ const char **cpl_array_get_data_string_const(const cpl_array *array) { const char **data = NULL; if (array == 0x0) { cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT); return NULL; } data = cpl_column_get_data_string_const(array->column); if (data == NULL) cpl_error_set_where(cpl_func); return data; } /** * @brief * Read a value from a numerical array. * * @param array Array to be accessed. * @param indx Position of element to be read. * @param null Flag indicating null values, or error condition. * * @return Value read. In case of an invalid array element, or in * case of error, 0.0 is returned. * * Read a value from a numerical array. A @c CPL_ERROR_NULL_INPUT is set in * case @em array is a @c NULL pointer. A @c CPL_ERROR_INVALID_TYPE is set * in case a non-numerical array is accessed. @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is set if the @em indx is outside the array range. Indexes are * counted starting from 0. If the input array has length zero, * @c CPL_ERROR_ACCESS_OUT_OF_RANGE is always set. The @em null * flag is used to indicate whether the accessed array element is * valid (0) or invalid (1). The null flag also signals an error * condition (-1). The @em null argument can be left to @c NULL. */ double cpl_array_get(const cpl_array *array, int indx, int *null) { const char *fid = "cpl_array_get"; cpl_errorstate prestate = cpl_errorstate_get(); double data; if (array == 0x0) { cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (null) *null = -1; return 0.0; } data = cpl_column_get(array->column, indx, null); if (!cpl_errorstate_is_equal(prestate)) cpl_error_set_where(fid); return data; } /** * @brief * Read a value from an @em integer array. * * @param array Array to be accessed. * @param indx Position of element to be read. * @param null Flag indicating null values, or error condition. * * @return Integer value read. In case of an invalid array element, or in * case of error, 0 is returned. * * Read a value from an array of type @c CPL_TYPE_INT. If @em array is a * @c NULL pointer a @c CPL_ERROR_NULL_INPUT is set. If the array is not * of the expected type, a @c CPL_ERROR_TYPE_MISMATCH is set. If @em indx * is outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is set. * Indexes are counted starting from 0. If the input array has length zero, * the @c CPL_ERROR_ACCESS_OUT_OF_RANGE is always set. If the @em null * flag is a valid pointer, it is used to indicate whether the accessed * array element is valid (0) or invalid (1). The null flag also signals * an error condition (-1). */ int cpl_array_get_int(const cpl_array *array, int indx, int *null) { const char *fid = "cpl_array_get_int"; cpl_errorstate prestate = cpl_errorstate_get(); int data; if (array == 0x0) { cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (null) *null = -1; return 0.0; } data = cpl_column_get_int(array->column, indx, null); if (!cpl_errorstate_is_equal(prestate)) cpl_error_set_where(fid); return data; } /** * @brief * Read a value from a @em float array. * * @param array Array to be accessed. * @param indx Position of element to be read. * @param null Flag indicating null values, or error condition. * * @return Array value read. In case of an invalid array element, or in * case of error, 0.0 is returned. * * Read a value from an array of type @c CPL_TYPE_FLOAT. See the * documentation of the function cpl_array_get_int(). */ float cpl_array_get_float(const cpl_array *array, int indx, int *null) { const char *fid = "cpl_array_get_float"; cpl_errorstate prestate = cpl_errorstate_get(); float data; if (array == 0x0) { cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (null) *null = -1; return 0.0; } data = cpl_column_get_float(array->column, indx, null); if (!cpl_errorstate_is_equal(prestate)) cpl_error_set_where(fid); return data; } /** * @brief * Read a value from a @em double array. * * @param array Array to be accessed. * @param indx Position of element to be read. * @param null Flag indicating null values, or error condition. * * @return Array value read. In case of an invalid array element, or in * case of error, 0.0 is returned. * * Read a value from an array of type @c CPL_TYPE_DOUBLE. See the * documentation of the function cpl_array_get_int(). */ double cpl_array_get_double(const cpl_array *array, int indx, int *null) { const char *fid = "cpl_array_get_double"; cpl_errorstate prestate = cpl_errorstate_get(); double data; if (array == 0x0) { cpl_error_set(fid, CPL_ERROR_NULL_INPUT); if (null) *null = -1; return 0.0; } data = cpl_column_get_double(array->column, indx, null); if (!cpl_errorstate_is_equal(prestate)) cpl_error_set_where(fid); return data; } /** * @brief * Read a value from a string array. * * @param array Array to be accessed. * @param indx Position of element to be read. * * @return Character string read. In case of an invalid array element, * or in case of error, a @c NULL pointer is returned. * * Read a value from an array of type @c CPL_TYPE_STRING. If @em array is a * @c NULL pointer a @c CPL_ERROR_NULL_INPUT is set. If the array is not * of the expected type, a @c CPL_ERROR_TYPE_MISMATCH is set. If @em indx * is outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is set. * Indexes are counted starting from 0. If the input array has length zero, * the @c CPL_ERROR_ACCESS_OUT_OF_RANGE is always set. * * @note * The returned string is a pointer to an array element, not its * copy. Its manipulation will directly affect that array element, * while changing that array element using @c cpl_array_set_string() * will turn it into garbage. Therefore, if a real copy of a string * array element is required, this function should be called as an * argument of the function @c strdup(). */ const char *cpl_array_get_string(const cpl_array *array, int indx) { const char *data; if (array == 0x0) { cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT); return NULL; } data = cpl_column_get_string_const(array->column, indx); if (data == NULL) cpl_error_set_where(cpl_func); return data; } /** * @brief * Write a value to a numerical array element. * * @param array Array to be accessed. * @param indx Position where to write value. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of numerical * type, a @c CPL_ERROR_INVALID_TYPE is returned. If @em indx is outside * the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is returned. If * the input array has length zero, the @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is always returned. * * Write a value to a numerical array element. The value is cast to the * accessed array type. The written value is automatically flagged as * valid. To invalidate an array value use @c cpl_array_set_invalid(). * Array elements are counted starting from 0. */ cpl_error_code cpl_array_set(cpl_array *array, int indx, double value) { const char *fid = "cpl_array_set"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_set(array->column, indx, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write a value to an @em integer array element. * * @param array Array to be accessed. * @param indx Position where to write value. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of the * expected type, a @c CPL_ERROR_TYPE_MISMATCH is set. If @em indx is * outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is returned. * If the input array has length 0, the @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is always returned. * * Write a value to an @em integer array element. The written value * is automatically flagged as valid. To invalidate an array value use * @c cpl_array_set_invalid(). Array elements are counted starting * from 0. */ cpl_error_code cpl_array_set_int(cpl_array *array, int indx, int value) { const char *fid = "cpl_array_set_int"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_set_int(array->column, indx, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write a value to a @em float array element. * * @param array Array to be accessed. * @param indx Position where to write value. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of the * expected type, a @c CPL_ERROR_TYPE_MISMATCH is set. If @em indx is * outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is returned. * If the input array has length 0, the @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is always returned. * * Write a value to a @em float array element. The written value * is automatically flagged as valid. To invalidate an array value use * @c cpl_array_set_invalid(). Array elements are counted starting * from 0. */ cpl_error_code cpl_array_set_float(cpl_array *array, int indx, float value) { const char *fid = "cpl_array_set_float"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_set_float(array->column, indx, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write a value to a @em double array element. * * @param array Array to be accessed. * @param indx Position where to write value. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of the * expected type, a @c CPL_ERROR_TYPE_MISMATCH is set. If @em indx is * outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is returned. * If the input array has length 0, the @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is always returned. * * Write a value to a @em double array element. The written value * is automatically flagged as valid. To invalidate an array value use * @c cpl_array_set_invalid(). Array elements are counted starting * from 0. */ cpl_error_code cpl_array_set_double(cpl_array *array, int indx, double value) { const char *fid = "cpl_array_set_double"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_set_double(array->column, indx, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write a character string to a string array element. * * @param array Array to be accessed. * @param indx Position where to write character string. * @param string Character string to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of the * expected type, a @c CPL_ERROR_TYPE_MISMATCH is returned. If @em indx is * outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is returned. * If the input array has length 0, the @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is always returned. * * Copy a character string to a @em string array element. The written * value can also be a @c NULL pointer. Note that the input character * string is copied, therefore the original can be modified without * affecting the column content. To "plug" a character string directly * into an array element, use the function @c cpl_array_get_data_string(). * Array elements are counted starting from zero. */ cpl_error_code cpl_array_set_string(cpl_array *array, int indx, const char *string) { const char *fid = "cpl_array_set_string"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_set_string(array->column, indx, string); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Invalidate an array element * * @param array Array to be accessed * @param indx Position of element to invalidate * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If @em indx is outside the * array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is set. If the input * array has length 0, the @c CPL_ERROR_ACCESS_OUT_OF_RANGE is always set. * * In the case of a string array, the string is set free and its * pointer is set to @c NULL; for other data types, the corresponding * element of the null flags buffer is flagged. Array elements are * counted starting from zero. */ cpl_error_code cpl_array_set_invalid(cpl_array *array, int indx) { const char *fid = "cpl_array_set_invalid"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_set_invalid(array->column, indx); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write the same value within a numerical array segment. * * @param array Array to be accessed. * @param start Position where to begin write value. * @param count Number of values to write. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of numerical * type, a @c CPL_ERROR_INVALID_TYPE is returned. If @em start is outside * the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is returned. If * the input array has length zero, the @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is always returned. * * Write the same value to a numerical array segment. The value is cast to * the accessed array type. The written values are automatically flagged as * valid. To invalidate an array interval use @c cpl_array_fill_window_invalid(). */ cpl_error_code cpl_array_fill_window(cpl_array *array, int start, int count, double value) { const char *fid = "cpl_array_fill_window"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_fill(array->column, start, count, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write the same value within an @em integer array segment. * * @param array Array to be accessed. * @param start Position where to begin write value. * @param count Number of values to write. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of the * expected type, a @c CPL_ERROR_TYPE_MISMATCH is returned. If @em start * is outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is returned. If the input array has length zero, the error * @c CPL_ERROR_ACCESS_OUT_OF_RANGE is always returned. If @em count * is negative, a @c CPL_ERROR_ILLEGAL_INPUT is returned. * * Write the same value to an @em integer array segment. The written * values are automatically flagged as valid. To invalidate an array * interval use @c cpl_array_fill_window_invalid(). The @em count argument * can go beyond the array end, and in that case the specified @em value * will be written just up to the end of the array. If @em count is zero, * the array is not modified and no error is set. */ cpl_error_code cpl_array_fill_window_int(cpl_array *array, int start, int count, int value) { const char *fid = "cpl_array_fill_window_int"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_fill_int(array->column, start, count, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write the same value within a @em float array segment. * * @param array Array to be accessed. * @param start Position where to begin write value. * @param count Number of values to write. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of the * expected type, a @c CPL_ERROR_TYPE_MISMATCH is returned. If @em start * is outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is returned. If the input array has length zero, the error * @c CPL_ERROR_ACCESS_OUT_OF_RANGE is always returned. If @em count * is negative, a @c CPL_ERROR_ILLEGAL_INPUT is returned. * * Write the same value to a @em float array segment. The written * values are automatically flagged as valid. To invalidate an array * interval use @c cpl_array_fill_window_invalid(). The @em count argument * can go beyond the array end, and in that case the specified @em value * will be written just up to the end of the array. If @em count is zero, * the array is not modified and no error is set. */ cpl_error_code cpl_array_fill_window_float(cpl_array *array, int start, int count, float value) { const char *fid = "cpl_array_fill_window_float"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_fill_float(array->column, start, count, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write the same value within a @em double array segment. * * @param array Array to be accessed. * @param start Position where to begin write value. * @param count Number of values to write. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of the * expected type, a @c CPL_ERROR_TYPE_MISMATCH is returned. If @em start * is outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is returned. If the input array has length zero, the error * @c CPL_ERROR_ACCESS_OUT_OF_RANGE is always returned. If @em count * is negative, a @c CPL_ERROR_ILLEGAL_INPUT is returned. * * Write the same value to a @em double array segment. The written * values are automatically flagged as valid. To invalidate an array * interval use @c cpl_array_fill_window_invalid(). The @em count argument * can go beyond the array end, and in that case the specified @em value * will be written just up to the end of the array. If @em count is zero, * the array is not modified and no error is set. */ cpl_error_code cpl_array_fill_window_double(cpl_array *array, int start, int count, double value) { const char *fid = "cpl_array_fill_window_double"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_fill_double(array->column, start, count, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Write a string to a string array segment. * * @param array Array to be accessed. * @param start Position where to begin write value. * @param count Number of values to write. * @param value Value to write. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If the array is not of the * expected type, a @c CPL_ERROR_TYPE_MISMATCH is returned. If @em start * is outside the array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is returned. If the input array has length zero, the error * @c CPL_ERROR_ACCESS_OUT_OF_RANGE is always returned. If @em count * is negative, a @c CPL_ERROR_ILLEGAL_INPUT is returned. * * Copy the same string to a string array segment. If the input string * is not a @c NULL pointer, it is duplicated for each accessed array * element. If the input string is @c NULL, this call is equivalent to * @c cpl_array_fill_window_invalid(). The @em count argument can go beyond * the array end, and in that case the specified @em value will be * copied just up to the end of the array. If @em count is zero, * the array is not modified and no error is set. */ cpl_error_code cpl_array_fill_window_string(cpl_array *array, int start, int count, const char *value) { const char *fid = "cpl_array_fill_window_string"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_fill_string(array->column, start, count, value); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Set an array segment to NULL. * * @param array Array to be accessed. * @param start Position where to start writing NULLs. * @param count Number of column elements to set to NULL. * * @return @c CPL_ERROR_NONE on success. If @em array is a @c NULL pointer * a @c CPL_ERROR_NULL_INPUT is returned. If @em start is outside the * array range, a @c CPL_ERROR_ACCESS_OUT_OF_RANGE is returned. If the * input array has length zero, the error @c CPL_ERROR_ACCESS_OUT_OF_RANGE * is always returned. If @em count is negative, a @c CPL_ERROR_ILLEGAL_INPUT * is returned. * * Invalidate values contained in an array segment. The @em count argument * can go beyond the array end, and in that case the values will be * invalidated up to the end of the array. If @em count is zero, the * array is not modified and no error is set. In the case of a @em string * array, the invalidated strings are set free and their pointers are set * to @c NULL; for other data types, the corresponding elements are flagged * as invalid. */ cpl_error_code cpl_array_fill_window_invalid(cpl_array *array, int start, int count) { const char *fid = "cpl_array_fill_window_invalid"; cpl_error_code error = CPL_ERROR_NONE; if (array == 0x0) return cpl_error_set(fid, CPL_ERROR_NULL_INPUT); error = cpl_column_fill_invalid(array->column, start, count); if (error) cpl_error_set_where(fid); return error; } /** * @brief * Make a copy of an array. * * @param array Array to be duplicated. * * @return Pointer to the new array, or @c NULL in case of error. * * If the input @em array is a @c NULL pointer, a @c CPL_ERROR_NULL_INPUT * is returned. Copy is "in depth": in the case of a @em string array, * also the string elements are duplicated. */ cpl_array *cpl_array_duplicate(const cpl_array *array) { const char *fid = "cpl_array_duplicate"; cpl_column *column = NULL; cpl_array *new_array; if (array == 0x0) { cpl_error_set(fid, CPL_ERROR_NULL_INPUT); return NULL; } if (array->column) column = cpl_column_duplicate(array->column); new_array = cpl_array_new(cpl_array_get_size(array), cpl_array_get_type(array)); cpl_column_delete(new_array->column); new_array->column = column; return new_array; } /**@}*/