From 48f8b64ae495b64d404c91c8dbb86355e6771505 Mon Sep 17 00:00:00 2001 From: Jürgen Knödlseder Date: Fri, 22 Nov 2013 17:07:49 +0100 Subject: [PATCH] Implement resize_data() method for all classes (except for Bit columns) and implement elements() method for defining variable-length column. --- include/GFitsTableBitCol.hpp | 1 + include/GFitsTableBoolCol.hpp | 1 + include/GFitsTableByteCol.hpp | 1 + include/GFitsTableCDoubleCol.hpp | 1 + include/GFitsTableCFloatCol.hpp | 1 + include/GFitsTableCol.hpp | 2 +- include/GFitsTableDoubleCol.hpp | 1 + include/GFitsTableFloatCol.hpp | 1 + include/GFitsTableLongCol.hpp | 1 + include/GFitsTableLongLongCol.hpp | 1 + include/GFitsTableStringCol.hpp | 1 + include/GFitsTableULongCol.hpp | 1 + include/GFitsTableUShortCol.hpp | 1 + src/fits/GFitsTableBitCol.cpp | 22 ++++++++++++++++++++++ src/fits/GFitsTableBoolCol.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- src/fits/GFitsTableByteCol.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fits/GFitsTableCDoubleCol.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fits/GFitsTableCFloatCol.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fits/GFitsTableDoubleCol.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fits/GFitsTableFloatCol.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fits/GFitsTableLongCol.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fits/GFitsTableLongLongCol.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fits/GFitsTableStringCol.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/fits/GFitsTableULongCol.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fits/GFitsTableUShortCol.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/test_GFits.cpp | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------- 26 files changed, 898 insertions(+), 37 deletions(-) diff --git a/include/GFitsTableBitCol.hpp b/include/GFitsTableBitCol.hpp index 0b0a86f..7449118 100644 --- a/include/GFitsTableBitCol.hpp +++ b/include/GFitsTableBitCol.hpp @@ -84,6 +84,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableBoolCol.hpp b/include/GFitsTableBoolCol.hpp index 3059eca..f5f9917 100644 --- a/include/GFitsTableBoolCol.hpp +++ b/include/GFitsTableBoolCol.hpp @@ -85,6 +85,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableByteCol.hpp b/include/GFitsTableByteCol.hpp index 5cc717d..0401792 100644 --- a/include/GFitsTableByteCol.hpp +++ b/include/GFitsTableByteCol.hpp @@ -80,6 +80,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableCDoubleCol.hpp b/include/GFitsTableCDoubleCol.hpp index efaa4c7..57455fd 100644 --- a/include/GFitsTableCDoubleCol.hpp +++ b/include/GFitsTableCDoubleCol.hpp @@ -81,6 +81,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableCFloatCol.hpp b/include/GFitsTableCFloatCol.hpp index 0b66950..4b2b2e8 100644 --- a/include/GFitsTableCFloatCol.hpp +++ b/include/GFitsTableCFloatCol.hpp @@ -81,6 +81,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableCol.hpp b/include/GFitsTableCol.hpp index 88228e0..5229c44 100644 --- a/include/GFitsTableCol.hpp +++ b/include/GFitsTableCol.hpp @@ -108,7 +108,7 @@ protected: virtual void alloc_data(void) = 0; virtual void init_data(void) = 0; virtual void fetch_data(void) const = 0; - virtual void resize_data(const int& index, const int& number) {} + virtual void resize_data(const int& index, const int& number) = 0; virtual void release_data(void) = 0; virtual void* ptr_data(const int& index = 0) = 0; virtual void* ptr_nulval(void) = 0; diff --git a/include/GFitsTableDoubleCol.hpp b/include/GFitsTableDoubleCol.hpp index e55fce5..3e4a741 100644 --- a/include/GFitsTableDoubleCol.hpp +++ b/include/GFitsTableDoubleCol.hpp @@ -80,6 +80,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableFloatCol.hpp b/include/GFitsTableFloatCol.hpp index 68dbf40..3949920 100644 --- a/include/GFitsTableFloatCol.hpp +++ b/include/GFitsTableFloatCol.hpp @@ -80,6 +80,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableLongCol.hpp b/include/GFitsTableLongCol.hpp index f6925e1..0cbdbe7 100644 --- a/include/GFitsTableLongCol.hpp +++ b/include/GFitsTableLongCol.hpp @@ -80,6 +80,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableLongLongCol.hpp b/include/GFitsTableLongLongCol.hpp index 3dd66db..19a762c 100644 --- a/include/GFitsTableLongLongCol.hpp +++ b/include/GFitsTableLongLongCol.hpp @@ -80,6 +80,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableStringCol.hpp b/include/GFitsTableStringCol.hpp index a44aef0..356fc08 100644 --- a/include/GFitsTableStringCol.hpp +++ b/include/GFitsTableStringCol.hpp @@ -82,6 +82,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableULongCol.hpp b/include/GFitsTableULongCol.hpp index 6ab9011..4fbcb09 100644 --- a/include/GFitsTableULongCol.hpp +++ b/include/GFitsTableULongCol.hpp @@ -80,6 +80,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/include/GFitsTableUShortCol.hpp b/include/GFitsTableUShortCol.hpp index 6804739..1318b29 100644 --- a/include/GFitsTableUShortCol.hpp +++ b/include/GFitsTableUShortCol.hpp @@ -80,6 +80,7 @@ private: virtual void alloc_data(void); virtual void init_data(void); virtual void fetch_data(void) const; + virtual void resize_data(const int& index, const int& number); virtual void release_data(void); virtual void* ptr_data(const int& index = 0); virtual void* ptr_nulval(void); diff --git a/src/fits/GFitsTableBitCol.cpp b/src/fits/GFitsTableBitCol.cpp index 5feb2e1..2a6c585 100644 --- a/src/fits/GFitsTableBitCol.cpp +++ b/src/fits/GFitsTableBitCol.cpp @@ -723,6 +723,28 @@ void GFitsTableBitCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + * + * @todo Needs to be implemented + ***************************************************************************/ +void GFitsTableBitCol::resize_data(const int& index, const int& number) +{ + //TODO + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableBitCol::release_data(void) diff --git a/src/fits/GFitsTableBoolCol.cpp b/src/fits/GFitsTableBoolCol.cpp index 177dd93..c35cc95 100644 --- a/src/fits/GFitsTableBoolCol.cpp +++ b/src/fits/GFitsTableBoolCol.cpp @@ -531,7 +531,8 @@ void GFitsTableBoolCol::copy_members(const GFitsTableBoolCol& column) // Copy column data if (column.m_data != NULL && m_size > 0) { - alloc_data(); + if (m_data != NULL) delete [] m_data; + m_data = new bool[m_size]; for (int i = 0; i < m_size; ++i) { m_data[i] = column.m_data[i]; } @@ -644,6 +645,10 @@ void GFitsTableBoolCol::alloc_data(void) m_data = new bool[m_size]; } + // Allocate also buffer + free_buffer(); + alloc_buffer(); + // Return return; } @@ -660,16 +665,7 @@ void GFitsTableBoolCol::alloc_data(void) ***************************************************************************/ void GFitsTableBoolCol::fetch_data(void) const { - // Calculate size of memory - m_size = m_number * m_length; - - // Free old buffer memory - free_buffer(); - - // Allocate buffer memory - alloc_buffer(); - - // Save column + // Load column const_cast(this)->load_column(); // Extract values from buffer @@ -686,6 +682,73 @@ void GFitsTableBoolCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableBoolCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + if (m_data != NULL) { + int left = index - number; + bool* dst = m_data + index; + bool* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + bool* new_data = new bool[m_size]; + bool* dst = new_data; + bool* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = false; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableBoolCol::release_data(void) diff --git a/src/fits/GFitsTableByteCol.cpp b/src/fits/GFitsTableByteCol.cpp index 8ddc43d..c885aaf 100644 --- a/src/fits/GFitsTableByteCol.cpp +++ b/src/fits/GFitsTableByteCol.cpp @@ -620,6 +620,71 @@ void GFitsTableByteCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableByteCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + unsigned char* dst = m_data + index; + unsigned char* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + unsigned char* new_data = new unsigned char[m_size]; + unsigned char* dst = new_data; + unsigned char* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = 0; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableByteCol::release_data(void) diff --git a/src/fits/GFitsTableCDoubleCol.cpp b/src/fits/GFitsTableCDoubleCol.cpp index 9c48bc3..41d8002 100644 --- a/src/fits/GFitsTableCDoubleCol.cpp +++ b/src/fits/GFitsTableCDoubleCol.cpp @@ -630,6 +630,73 @@ void GFitsTableCDoubleCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableCDoubleCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + GFits::cdouble* dst = m_data + index; + GFits::cdouble* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + GFits::cdouble* new_data = new GFits::cdouble[m_size]; + GFits::cdouble* dst = new_data; + GFits::cdouble* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + dst->re = 0.0; + dst->im = 0.0; + dst++; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableCDoubleCol::release_data(void) diff --git a/src/fits/GFitsTableCFloatCol.cpp b/src/fits/GFitsTableCFloatCol.cpp index 5dcb43d..f4de3c2 100644 --- a/src/fits/GFitsTableCFloatCol.cpp +++ b/src/fits/GFitsTableCFloatCol.cpp @@ -630,6 +630,73 @@ void GFitsTableCFloatCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableCFloatCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + GFits::cfloat* dst = m_data + index; + GFits::cfloat* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + GFits::cfloat* new_data = new GFits::cfloat[m_size]; + GFits::cfloat* dst = new_data; + GFits::cfloat* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + dst->re = 0.0; + dst->im = 0.0; + dst++; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableCFloatCol::release_data(void) diff --git a/src/fits/GFitsTableDoubleCol.cpp b/src/fits/GFitsTableDoubleCol.cpp index 6dbd92f..1aabf60 100644 --- a/src/fits/GFitsTableDoubleCol.cpp +++ b/src/fits/GFitsTableDoubleCol.cpp @@ -623,6 +623,71 @@ void GFitsTableDoubleCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableDoubleCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + double* dst = m_data + index; + double* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + double* new_data = new double[m_size]; + double* dst = new_data; + double* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = 0.0; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableDoubleCol::release_data(void) diff --git a/src/fits/GFitsTableFloatCol.cpp b/src/fits/GFitsTableFloatCol.cpp index f1d85dc..9054005 100644 --- a/src/fits/GFitsTableFloatCol.cpp +++ b/src/fits/GFitsTableFloatCol.cpp @@ -623,6 +623,71 @@ void GFitsTableFloatCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableFloatCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + float* dst = m_data + index; + float* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + float* new_data = new float[m_size]; + float* dst = new_data; + float* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = 0.0; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableFloatCol::release_data(void) diff --git a/src/fits/GFitsTableLongCol.cpp b/src/fits/GFitsTableLongCol.cpp index 624e4f1..184d316 100644 --- a/src/fits/GFitsTableLongCol.cpp +++ b/src/fits/GFitsTableLongCol.cpp @@ -623,6 +623,71 @@ void GFitsTableLongCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableLongCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + long* dst = m_data + index; + long* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + long* new_data = new long[m_size]; + long* dst = new_data; + long* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = 0; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableLongCol::release_data(void) diff --git a/src/fits/GFitsTableLongLongCol.cpp b/src/fits/GFitsTableLongLongCol.cpp index a07cf5e..90cc90f 100644 --- a/src/fits/GFitsTableLongLongCol.cpp +++ b/src/fits/GFitsTableLongLongCol.cpp @@ -623,6 +623,71 @@ void GFitsTableLongLongCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableLongLongCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + long long* dst = m_data + index; + long long* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + long long* new_data = new long long[m_size]; + long long* dst = new_data; + long long* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = 0; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableLongLongCol::release_data(void) diff --git a/src/fits/GFitsTableStringCol.cpp b/src/fits/GFitsTableStringCol.cpp index 9a9b06a..c52d233 100644 --- a/src/fits/GFitsTableStringCol.cpp +++ b/src/fits/GFitsTableStringCol.cpp @@ -539,7 +539,8 @@ void GFitsTableStringCol::copy_members(const GFitsTableStringCol& column) // Copy column data if (column.m_data != NULL && m_size > 0) { - alloc_data(); + if (m_data != NULL) delete [] m_data; + m_data = new std::string[m_size]; for (int i = 0; i < m_size; ++i) { m_data[i] = column.m_data[i]; } @@ -662,6 +663,10 @@ void GFitsTableStringCol::alloc_data(void) m_data = new std::string[m_size]; } + // Allocate also buffer + free_buffer(); + alloc_buffer(); + // Return return; } @@ -679,13 +684,13 @@ void GFitsTableStringCol::alloc_data(void) void GFitsTableStringCol::fetch_data(void) const { // Calculate size of memory - m_size = m_number * m_length; + //m_size = m_number * m_length; // Free old buffer memory - free_buffer(); + //free_buffer(); // Allocate buffer memory - alloc_buffer(); + //alloc_buffer(); // Load column const_cast(this)->load_column(); @@ -706,6 +711,71 @@ void GFitsTableStringCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableStringCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + std::string* dst = m_data + index; + std::string* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + std::string* new_data = new std::string[m_size]; + std::string* dst = new_data; + std::string* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = ""; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableStringCol::release_data(void) diff --git a/src/fits/GFitsTableULongCol.cpp b/src/fits/GFitsTableULongCol.cpp index b3dcb43..bcf51fe 100644 --- a/src/fits/GFitsTableULongCol.cpp +++ b/src/fits/GFitsTableULongCol.cpp @@ -619,6 +619,71 @@ void GFitsTableULongCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableULongCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + unsigned long* dst = m_data + index; + unsigned long* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + unsigned long* new_data = new unsigned long[m_size]; + unsigned long* dst = new_data; + unsigned long* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = 0; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableULongCol::release_data(void) diff --git a/src/fits/GFitsTableUShortCol.cpp b/src/fits/GFitsTableUShortCol.cpp index 3c8c8b0..4ae4ecd 100644 --- a/src/fits/GFitsTableUShortCol.cpp +++ b/src/fits/GFitsTableUShortCol.cpp @@ -619,6 +619,71 @@ void GFitsTableUShortCol::fetch_data(void) const /***********************************************************************//** + * @brief Resize column data + * + * @param[in] index Start index. + * @param[in] number Number of elements to add/remove. + * + * Adds or removes elements from specified index on. Adding is done if + * @p number is a positive number, removing if @p number is negative. + * Note that the method does not change the validity of the arguments. + * This needs to be done by the client. + ***************************************************************************/ +void GFitsTableUShortCol::resize_data(const int& index, const int& number) +{ + // Continue only if number of elements is not zero + if (number != 0) { + + // If data are not available then load them now + if (m_data == NULL) fetch_data(); + + // If elements should be removed then do not allocate new memory + // but just move elements forward and change the logical size of + // memory. Only if all elements should be removed the memory is + // released. + if (number < 0) { + int left = index - number; + unsigned short* dst = m_data + index; + unsigned short* src = m_data + left; + int num = m_size - left; + for (int i = 0; i < num; ++i) { + *dst++ = *src++; + } + m_size += number; + if (m_size < 1) { + release_data(); + } + } + + // If elements should be added then allocate new memory, copy over + // the old data and initialise the new elements + else { + int left = m_size - index; + m_size += number; + unsigned short* new_data = new unsigned short[m_size]; + unsigned short* dst = new_data; + unsigned short* src = m_data; + for (int i = 0; i < index; ++i) { + *dst++ = *src++; + } + for (int i = 0; i < number; ++i) { + *dst++ = 0; + } + for (int i = 0; i < left; ++i) { + *dst++ = *src++; + } + if (m_data != NULL) delete [] m_data; + m_data = new_data; + } + + } // endif: number was non-zero + + // Return + return; +} + + +/***********************************************************************//** * @brief Release column data ***************************************************************************/ void GFitsTableUShortCol::release_data(void) diff --git a/test/test_GFits.cpp b/test/test_GFits.cpp index e3b4106..e0c255d 100644 --- a/test/test_GFits.cpp +++ b/test/test_GFits.cpp @@ -208,6 +208,71 @@ col2.string(i,j)+" is not "+gammalib::str(val)); \ } \ } +#define TEST_TABLE2_BOOL \ + for (int i = 0; i < nrows; ++i) { \ + for (int j = 0; j < nvec; ++j) { \ + col2(i,j) = (i % 2) * (j % 2); \ + } \ + } \ + for (int i = 0; i < nrows; ++i) { \ + for (int j = 0; j < nvec; ++j) { \ + int ival = ((i % 2) * (j % 2)); \ + std::string sval = ((i % 2) * (j % 2)) ? "T" : "F"; \ + test_assert((col2(i,j) == ival), \ + "Test access operator row "+gammalib::str(i)+" and element "+gammalib::str(j), \ + gammalib::str(col2(i,j))+" is not "+gammalib::str(ival)); \ + test_assert((col2.real(i,j) == double(ival)), \ + "Test real() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ + gammalib::str(col2.real(i,j))+" is not "+gammalib::str(double(ival))); \ + test_assert((col2.integer(i,j) == int(ival)), \ + "Test integer() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ + gammalib::str(col2.integer(i,j))+" is not "+gammalib::str(int(ival))); \ + test_assert((col2.string(i,j) == gammalib::str(ival) || col2.string(i,j) == sval), \ + "Test string() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ + col2.string(i,j)+" is not "+gammalib::str(ival)+" or "+sval); \ + } \ + } +#define TEST_TABLE2_STRING \ + for (int i = 0; i < nrows; ++i) { \ + for (int j = 0; j < nvec; ++j) { \ + col2(i,j) = gammalib::str(double(i)*2.3 + double(j)*11.7 + 0.95); \ + } \ + } \ + for (int i = 0; i < nrows; ++i) { \ + for (int j = 0; j < nvec; ++j) { \ + double val = double(i)*2.3 + double(j)*11.7 + 0.95; \ + test_value(gammalib::todouble(col2(i,j)), val, 1e-6, \ + "Test access operator row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ + test_value(col2.real(i,j), val, 1e-6, \ + "Test real() method for row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ + test_value(col2.integer(i,j), int(val), 1e-6, \ + "Test integer() method for row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ + test_assert((col2.string(i,j) == gammalib::str(val)), \ + "Test string() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ + col2.string(i,j)+" is not "+gammalib::str(val)); \ + } \ + } +#define TEST_VARTABLE \ + for (int i = 0; i < nrows; ++i) { \ + col3.elements(i,i+1); \ + for (int j = 0; j < i+1; ++j) { \ + col3(i,j) = double(i)*2.3 + double(j)*11.7 + 0.95; \ + } \ + } \ + for (int i = 0; i < nrows; ++i) { \ + for (int j = 0; j < i+1; ++j) { \ + double val = double(i)*2.3 + double(j)*11.7 + 0.95; \ + test_value(col3(i,j), val, 1e-6, \ + "Test access operator row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ + test_value(col3.real(i,j), val, 1e-6, \ + "Test real() method for row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ + test_value(col3.integer(i,j), int(val), 1e-6, \ + "Test integer() method for row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ + test_assert((col3.string(i,j) == gammalib::str(val)), \ + "Test string() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ + col3.string(i,j)+" is not "+gammalib::str(val)); \ + } \ + } #define TEST_VARTABLE_INT \ for (int i = 0; i < nrows; ++i) { \ col3.elements(i,i+1); \ @@ -232,48 +297,50 @@ col3.string(i,j)+" is not "+gammalib::str(val)); \ } \ } -#define TEST_TABLE2_BOOL \ +#define TEST_VARTABLE_BOOL \ for (int i = 0; i < nrows; ++i) { \ - for (int j = 0; j < nvec; ++j) { \ - col2(i,j) = (i % 2) * (j % 2); \ + col3.elements(i,i+1); \ + for (int j = 0; j < i+1; ++j) { \ + col3(i,j) = (i % 2) * (j % 2); \ } \ } \ for (int i = 0; i < nrows; ++i) { \ - for (int j = 0; j < nvec; ++j) { \ + for (int j = 0; j < i+1; ++j) { \ int ival = ((i % 2) * (j % 2)); \ std::string sval = ((i % 2) * (j % 2)) ? "T" : "F"; \ - test_assert((col2(i,j) == ival), \ + test_assert((col3(i,j) == ival), \ "Test access operator row "+gammalib::str(i)+" and element "+gammalib::str(j), \ - gammalib::str(col2(i,j))+" is not "+gammalib::str(ival)); \ - test_assert((col2.real(i,j) == double(ival)), \ + gammalib::str(col3(i,j))+" is not "+gammalib::str(ival)); \ + test_assert((col3.real(i,j) == double(ival)), \ "Test real() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ - gammalib::str(col2.real(i,j))+" is not "+gammalib::str(double(ival))); \ - test_assert((col2.integer(i,j) == int(ival)), \ + gammalib::str(col3.real(i,j))+" is not "+gammalib::str(double(ival))); \ + test_assert((col3.integer(i,j) == int(ival)), \ "Test integer() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ - gammalib::str(col2.integer(i,j))+" is not "+gammalib::str(int(ival))); \ - test_assert((col2.string(i,j) == gammalib::str(ival) || col2.string(i,j) == sval), \ + gammalib::str(col3.integer(i,j))+" is not "+gammalib::str(int(ival))); \ + test_assert((col3.string(i,j) == gammalib::str(ival) || col3.string(i,j) == sval), \ "Test string() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ - col2.string(i,j)+" is not "+gammalib::str(ival)+" or "+sval); \ + col3.string(i,j)+" is not "+gammalib::str(ival)+" or "+sval); \ } \ } -#define TEST_TABLE2_STRING \ +#define TEST_VARTABLE_STRING \ for (int i = 0; i < nrows; ++i) { \ - for (int j = 0; j < nvec; ++j) { \ - col2(i,j) = gammalib::str(double(i)*2.3 + double(j)*11.7 + 0.95); \ + col3.elements(i,i+1); \ + for (int j = 0; j < i+1; ++j) { \ + col3(i,j) = gammalib::str(double(i)*2.3 + double(j)*11.7 + 0.95); \ } \ } \ for (int i = 0; i < nrows; ++i) { \ - for (int j = 0; j < nvec; ++j) { \ + for (int j = 0; j < i+1; ++j) { \ double val = double(i)*2.3 + double(j)*11.7 + 0.95; \ - test_value(gammalib::todouble(col2(i,j)), val, 1e-6, \ + test_value(gammalib::todouble(col3(i,j)), val, 1e-6, \ "Test access operator row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ - test_value(col2.real(i,j), val, 1e-6, \ + test_value(col3.real(i,j), val, 1e-6, \ "Test real() method for row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ - test_value(col2.integer(i,j), int(val), 1e-6, \ + test_value(col3.integer(i,j), int(val), 1e-6, \ "Test integer() method for row "+gammalib::str(i)+" and element "+gammalib::str(j)); \ - test_assert((col2.string(i,j) == gammalib::str(val)), \ + test_assert((col3.string(i,j) == gammalib::str(val)), \ "Test string() method for row "+gammalib::str(i)+" and element "+gammalib::str(j), \ - col2.string(i,j)+" is not "+gammalib::str(val)); \ + col3.string(i,j)+" is not "+gammalib::str(val)); \ } \ } #define TEST_WRITE_TABLES \ @@ -284,6 +351,7 @@ GFitsBinTable table = GFitsBinTable(nrows); \ table.append_column(col1); \ table.insert_column(1, col2); \ + table.append_column(col3); \ fits.append(table); \ fits.save(); \ fits.close(); \ @@ -945,6 +1013,10 @@ void TestGFits::test_bintable_double(void) GFitsTableDoubleCol col2("DOUBLE10", nrows, nvec); TEST_TABLE2; + // Test variable-length column table + GFitsTableDoubleCol col3("DOUBLEVAR", nrows, -1); + TEST_VARTABLE; + // Write tables TEST_WRITE_TABLES; @@ -995,6 +1067,10 @@ void TestGFits::test_bintable_float(void) GFitsTableFloatCol col2("FLOAT10", nrows, nvec); TEST_TABLE2; + // Test variable-length column table + GFitsTableFloatCol col3("FLOATVAR", nrows, -1); + TEST_VARTABLE; + // Write tables TEST_WRITE_TABLES; @@ -1101,6 +1177,10 @@ void TestGFits::test_bintable_short(void) GFitsTableUShortCol col2("USHORT10", nrows, nvec); TEST_TABLE2_INT; + // Test variable-length column table + GFitsTableUShortCol col3("USHORTVAR", nrows, -1); + TEST_VARTABLE_INT; + // Write tables TEST_WRITE_TABLES; @@ -1152,6 +1232,10 @@ void TestGFits::test_bintable_long(void) GFitsTableLongCol col2("LONG10", nrows, nvec); TEST_TABLE2_INT; + // Test variable-length column table + GFitsTableLongCol col3("LONGVAR", nrows, -1); + TEST_VARTABLE_INT; + // Write tables TEST_WRITE_TABLES; @@ -1203,6 +1287,10 @@ void TestGFits::test_bintable_longlong(void) GFitsTableLongLongCol col2("LONGLONG10", nrows, nvec); TEST_TABLE2_INT; + // Test variable-length column table + GFitsTableLongLongCol col3("LONGLONGVAR", nrows, -1); + TEST_VARTABLE_INT; + // Write tables TEST_WRITE_TABLES; @@ -1254,6 +1342,10 @@ void TestGFits::test_bintable_ulong(void) GFitsTableULongCol col2("ULONG10", nrows, nvec); TEST_TABLE2_INT; + // Test variable-length column table + GFitsTableULongCol col3("ULONGVAR", nrows, -1); + TEST_VARTABLE_INT; + // Write tables TEST_WRITE_TABLES; @@ -1305,6 +1397,11 @@ void TestGFits::test_bintable_string(void) GFitsTableStringCol col2("STRING10", nrows, 20, nvec); TEST_TABLE2_STRING; + // Test variable-length column table + GFitsTableStringCol col3("STRINGVAR", nrows, 1); + //GFitsTableStringCol col3("STRINGVAR", nrows, -1); + //TEST_VARTABLE_STRING; + // Write tables TEST_WRITE_TABLES; @@ -1356,6 +1453,10 @@ void TestGFits::test_bintable_logical(void) GFitsTableBoolCol col2("LOGICAL10", nrows, nvec); TEST_TABLE2_BOOL; + // Test variable-length column table + GFitsTableBoolCol col3("LOGICALVAR", nrows, -1); + TEST_VARTABLE_BOOL; + // Write tables TEST_WRITE_TABLES; @@ -1407,6 +1508,10 @@ void TestGFits::test_bintable_bit(void) GFitsTableBitCol col2("BIT10", nrows, nvec); TEST_TABLE2_BOOL; + // Test variable-length column table + GFitsTableBitCol col3("BITVAR", nrows, -1); + //TEST_VARTABLE_BOOL; + // Write tables TEST_WRITE_TABLES; -- libgit2 0.21.4