Bug Summary

File:src/fits/GFitsTableBitCol.cpp
Location:line 379, column 26
Description:Dereference of null pointer

Annotated Source Code

1/***************************************************************************
2 * GFitsTableBitCol.cpp - FITS table Bit column class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2008-2013 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- *
6 * *
7 * This program is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GFitsTableBitCol.cpp
23 * @brief FITS table bit column class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H1
29#include <config.h>
30#endif
31#include <string>
32#include "GException.hpp"
33#include "GTools.hpp"
34#include "GFitsCfitsio.hpp"
35#include "GFitsTableBitCol.hpp"
36
37/* __ Method name definitions ____________________________________________ */
38#define G_INSERT"GFitsTableBitCol::insert(int&, int&)" "GFitsTableBitCol::insert(int&, int&)"
39#define G_REMOVE"GFitsTableBitCol::remove(int&, int&)" "GFitsTableBitCol::remove(int&, int&)"
40#define G_LOAD_COLUMN"GFitsTableBitCol::load_column()" "GFitsTableBitCol::load_column()"
41#define G_SAVE_COLUMN"GFitsTableBitCol::save_column()" "GFitsTableBitCol::save_column()"
42#define G_GET_BIT"GFitsTableBitCol::get_bit(int&,int&)" "GFitsTableBitCol::get_bit(int&,int&)"
43
44/* __ Macros _____________________________________________________________ */
45
46/* __ Coding definitions _________________________________________________ */
47
48/* __ Debug definitions __________________________________________________ */
49//#define G_CALL_GRAPH //!< Dump call graph in console
50
51
52/*==========================================================================
53 = =
54 = Constructors/destructors =
55 = =
56 ==========================================================================*/
57
58/***********************************************************************//**
59 * @brief Constructor
60 ***************************************************************************/
61GFitsTableBitCol::GFitsTableBitCol(void) : GFitsTableCol()
62{
63 // Initialise class members for clean destruction
64 init_members();
65
66 // Return
67 return;
68}
69
70
71/***********************************************************************//**
72 * @brief Constructor
73 *
74 * @param[in] name Name of column.
75 * @param[in] length Length of column.
76 * @param[in] size Vector size of column.
77 ***************************************************************************/
78GFitsTableBitCol::GFitsTableBitCol(const std::string& name,
79 const int& length,
80 const int& size) :
81 GFitsTableCol(name, length, size, 1)
82{
83 // Initialise class members for clean destruction
84 init_members();
85
86 // Return
87 return;
88}
89
90
91/***********************************************************************//**
92 * @brief Copy constructor
93 *
94 * @param[in] column Table column.
95 ***************************************************************************/
96GFitsTableBitCol::GFitsTableBitCol(const GFitsTableBitCol& column) :
97 GFitsTableCol(column)
98{
99 // Initialise class members for clean destruction
100 init_members();
101
102 // Copy members
103 copy_members(column);
104
105 // Return
106 return;
107}
108
109
110/***********************************************************************//**
111 * @brief Destructor
112 ***************************************************************************/
113GFitsTableBitCol::~GFitsTableBitCol(void)
114{
115 // Free members
116 free_members();
117
118 // Return
119 return;
120}
121
122
123/*==========================================================================
124 = =
125 = Operators =
126 = =
127 ==========================================================================*/
128
129/***********************************************************************//**
130 * @brief Assignment operator
131 *
132 * @param[in] column Table column.
133 * @return Table column.
134 ***************************************************************************/
135GFitsTableBitCol& GFitsTableBitCol::operator=(const GFitsTableBitCol& column)
136{
137 // Execute only if object is not identical
138 if (this != &column) {
139
140 // Copy base class members
141 this->GFitsTableCol::operator=(column);
142
143 // Free members
144 free_members();
145
146 // Initialise private members for clean destruction
147 init_members();
148
149 // Copy members
150 copy_members(column);
151
152 } // endif: object was not identical
153
154 // Return this object
155 return *this;
156}
157
158
159/***********************************************************************//**
160 * @brief Column data access operator
161 *
162 * @param[in] row Row of column to access.
163 * @param[in] inx Vector index in column row to access.
164 *
165 * Provides access to data in a column.
166 ***************************************************************************/
167bool& GFitsTableBitCol::operator()(const int& row, const int& inx)
168{
169 // If data are not available then load them now
170 if (m_data == NULL__null) this->fetch_data();
171
172 // Set any pending Bit
173 set_pending();
174
175 // Get Bit
176 get_bit(row, inx);
177
178 // Signal that a Bit is pending. We need this here since the non-const
179 // operator allows changing the Bit after exiting the method, hence
180 // we have to signal that the actual value of 'm_bit_value' could have
181 // been modified and needs to be written back into the data array.
182 m_bit_pending = true;
183
184 // Return Bit
185 return m_bit_value;
186}
187
188
189/***********************************************************************//**
190 * @brief Column data access operator (const variant)
191 *
192 * @param[in] row Row of column to access.
193 * @param[in] inx Vector index in column row to access
194 *
195 * Provides access to data in a column.
196 ***************************************************************************/
197const bool& GFitsTableBitCol::operator()(const int& row, const int& inx) const
198{
199 // Circumvent const correctness
200 GFitsTableBitCol* ptr = const_cast<GFitsTableBitCol*>(this);
201
202 // If data are not available then load them now
203 if (m_data == NULL__null) ptr->fetch_data();
204
205 // Set any pending Bit
206 ptr->set_pending();
207
208 // Get Bit
209 ptr->get_bit(row, inx);
210
211 // Return data bin
212 return m_bit_value;
213}
214
215
216/*==========================================================================
217 = =
218 = Public methods =
219 = =
220 ==========================================================================*/
221
222/***********************************************************************//**
223 * @brief Clear instance
224 *
225 * This method properly resets the object to an initial state.
226 ***************************************************************************/
227void GFitsTableBitCol::clear(void)
228{
229 // Free class members (base and derived classes, derived class first)
230 free_members();
231 this->GFitsTableCol::free_members();
232
233 // Initialise members
234 this->GFitsTableCol::init_members();
235 init_members();
236
237 // Return
238 return;
239}
240
241
242/***********************************************************************//**
243 * @brief Clone column
244 ***************************************************************************/
245GFitsTableBitCol* GFitsTableBitCol::clone(void) const
246{
247 return new GFitsTableBitCol(*this);
248}
249
250
251/***********************************************************************//**
252 * @brief Get string value
253 *
254 * @param[in] row Table row.
255 * @param[in] inx Table column vector index.
256 *
257 * Returns value of specified row and vector index as string.
258 ***************************************************************************/
259std::string GFitsTableBitCol::string(const int& row, const int& inx) const
260{
261 // Get Bit value
262 bool bit = (*this)(row, inx);
263
264 // Convert bit into string
265 std::string result = (bit) ? "T" : "F";
266
267 // Return result
268 return result;
269}
270
271
272/***********************************************************************//**
273 * @brief Get double precision value
274 *
275 * @param[in] row Table row.
276 * @param[in] inx Table column vector index.
277 *
278 * Returns value of specified row and vector index as double precision.
279 ***************************************************************************/
280double GFitsTableBitCol::real(const int& row, const int& inx) const
281{
282 // Get Bit value
283 bool bit = (*this)(row, inx);
284
285 // Convert bit into double
286 double result = (bit) ? 1.0 : 0.0;
287
288 // Return result
289 return result;
290}
291
292
293/***********************************************************************//**
294 * @brief Get integer value
295 *
296 * @param[in] row Table row.
297 * @param[in] inx Table column vector index.
298 *
299 * Returns value of specified row and vector index as integer.
300 ***************************************************************************/
301int GFitsTableBitCol::integer(const int& row, const int& inx) const
302{
303 // Get Bit value
304 bool bit = (*this)(row, inx);
305
306 // Convert bit into double
307 int result = (bit) ? 1 : 0;
308
309 // Return result
310 return result;
311}
312
313
314/***********************************************************************//**
315 * @brief Insert rows in column
316 *
317 * @param[in] row Row after which rows should be inserted (0=first row).
318 * @param[in] nrows Number of rows to be inserted.
319 *
320 * @exception GException::fits_invalid_row
321 * Specified row is invalid.
322 *
323 * This method inserts rows into a FITS table. This implies that the column
324 * will be loaded into memory.
325 ***************************************************************************/
326void GFitsTableBitCol::insert(const int& row, const int& nrows)
327{
328 // Make sure that row is valid
329 if (row < 0 || row > m_length) {
1
Assuming 'row' is >= 0
2
Taking false branch
330 throw GException::fits_invalid_row(G_INSERT"GFitsTableBitCol::insert(int&, int&)", row, m_length);
331 }
332
333 // Continue only if there are rows to be inserted
334 if (nrows > 0) {
3
Assuming 'nrows' is > 0
4
Taking true branch
335
336 // If we have no rows yet then simply set the length to the
337 // number of rows to be inserted
338 if (m_length == 0) {
5
Taking false branch
339 m_length = nrows;
340 }
341
342 // ... otherwise fetch data, allocate new data and copy over
343 // the existing items
344 else {
345
346 // If data are not available then load them now
347 if (m_data == NULL__null) fetch_data();
6
Taking true branch
348
349 // Set any pending Bit
350 set_pending();
351
352 // Compute new column length
353 int length = m_length + nrows;
354
355 // Compute total number of Bits in column
356 m_bits = m_number * length;
357
358 // Compute number of Bytes and Bits per row
359 m_bytes_per_row = (m_number > 0) ? ((m_number-1) / 8) + 1 : 0;
7
'?' condition is true
360 m_bits_per_row = m_bytes_per_row * 8;
361
362 // Compute length of memory array
363 m_size = m_bytes_per_row * length;
364
365 // Allocate new data to hold the column
366 unsigned char* new_data = new unsigned char[m_size];
367
368 // Compute the number of elements before the insertion point,
369 // the number of elements that get inserted, and the total
370 // number of elements after the insertion point
371 int n_before = m_bytes_per_row * row;
372 int n_insert = m_bytes_per_row * nrows;
373 int n_after = m_bytes_per_row * (m_length - row);
374
375 // Copy and initialise data
376 unsigned char* src = m_data;
377 unsigned char* dst = new_data;
378 for (int i = 0; i < n_before; ++i) {
8
Assuming 'i' is < 'n_before'
9
Loop condition is true. Entering loop body
379 *dst++ = *src++;
10
Dereference of null pointer
380 }
381 for (int i = 0; i < n_insert; ++i) {
382 *dst++ = 0;
383 }
384 for (int i = 0; i < n_after; ++i) {
385 *dst++ = *src++;
386 }
387
388 // Free old data
389 if (m_data != NULL__null) delete [] m_data;
390
391 // Set pointer to new data and store length
392 m_data = new_data;
393 m_length = length;
394
395 } // endelse: there were already data
396
397 } // endfor: there were rows to be inserted
398
399 // Return
400 return;
401}
402
403
404/***********************************************************************//**
405 * @brief Remove rows from column
406 *
407 * @param[in] row Row after which rows should be removed (0=first row).
408 * @param[in] nrows Number of rows to be removed.
409 *
410 * @exception GException::fits_invalid_row
411 * Specified row is invalid.
412 * @exception GException::fits_invalid_nrows
413 * Invalid number of rows specified.
414 *
415 * This method removes rows from a FITS table. This implies that the column
416 * will be loaded into memory.
417 ***************************************************************************/
418void GFitsTableBitCol::remove(const int& row, const int& nrows)
419{
420 // Make sure that row is valid
421 if (row < 0 || row >= m_length) {
422 throw GException::fits_invalid_row(G_REMOVE"GFitsTableBitCol::remove(int&, int&)", row, m_length-1);
423 }
424
425 // Make sure that we don't remove beyond the limit
426 if (nrows < 0 || nrows > m_length-row) {
427 throw GException::fits_invalid_nrows(G_REMOVE"GFitsTableBitCol::remove(int&, int&)", nrows, m_length-row);
428 }
429
430 // Continue only if there are rows to be removed
431 if (nrows > 0) {
432
433 // If data are not available then load them now
434 if (m_data == NULL__null) fetch_data();
435
436 // Set any pending Bit
437 set_pending();
438
439 // Compute new column length
440 int length = m_length - nrows;
441
442 // Compute total number of Bits in column
443 m_bits = m_number * length;
444
445 // Compute number of Bytes and Bits per row
446 m_bytes_per_row = (m_number > 0) ? ((m_number-1) / 8) + 1 : 0;
447 m_bits_per_row = m_bytes_per_row * 8;
448
449 // Compute length of memory array
450 m_size = m_bytes_per_row * length;
451
452 // If we have rows remaining then allocate new data to hold
453 // the column
454 if (m_size > 0) {
455
456 // Allocate new data to hold the column
457 unsigned char* new_data = new unsigned char[m_size];
458
459 // Compute the number of elements before the removal point,
460 // the number of elements that get removed, and the total
461 // number of elements after the removal point
462 int n_before = m_bytes_per_row * row;
463 int n_remove = m_bytes_per_row * nrows;
464 int n_after = m_bytes_per_row * (length - row);
465
466 // Copy data
467 unsigned char* src = m_data;
468 unsigned char* dst = new_data;
469 for (int i = 0; i < n_before; ++i) {
470 *dst++ = *src++;
471 }
472 src += n_remove;
473 for (int i = 0; i < n_after; ++i) {
474 *dst++ = *src++;
475 }
476
477 // Free old data
478 if (m_data != NULL__null) delete [] m_data;
479
480 // Set pointer to new data and store length
481 m_data = new_data;
482 m_length = length;
483
484 } // endif: there are still elements after removal
485
486 // ... otherwise just remove all data
487 else {
488
489 // Free old data
490 if (m_data != NULL__null) delete [] m_data;
491
492 // Set pointer to new data and store length
493 m_data = NULL__null;
494 m_length = length;
495 }
496
497 } // endfor: there were rows to be removed
498
499 // Return
500 return;
501}
502
503
504/***********************************************************************//**
505 * @brief Set nul value
506 *
507 * @param[in] value Nul value.
508 *
509 * @todo To correctly reflect the nul value in the data, the column should
510 * be reloaded. However, the column may have been changed, so in principle
511 * saving is needed. However, we may not want to store the data, hence saving
512 * is also not desired. We thus have to develop a method to update the
513 * column information for a new nul value in place ...
514 ***************************************************************************/
515void GFitsTableBitCol::nulval(const unsigned char* value)
516{
517 // Allocate nul value
518 alloc_nulval(value);
519
520 // Update column
521// if (m_data != NULL) {
522// save();
523// load();
524// }
525
526 // Return
527 return;
528}
529
530
531/*==========================================================================
532 = =
533 = Private methods =
534 = =
535 ==========================================================================*/
536
537/***********************************************************************//**
538 * @brief Initialise class members
539 ***************************************************************************/
540void GFitsTableBitCol::init_members(void)
541{
542 // Optionally print call graph
543 #if defined(G_CALL_GRAPH)
544 printf("GFitsTableBitCol::init_members\n");
545 #endif
546
547 // Initialise members
548 m_type = __TBIT1;
549 m_bits = 0;
550 m_bytes_per_row = 0;
551 m_bits_per_row = 0;
552 m_data = NULL__null;
553 m_nulval = NULL__null;
554 m_bit_pending = false;
555 m_bit_value = false;
556 m_bit_byte = 0;
557 m_bit_mask = 0;
558
559 // Optionally print call graph
560 #if defined(G_CALL_GRAPH)
561 printf("exit GFitsTableBitCol::init_members\n");
562 #endif
563
564 // Return
565 return;
566}
567
568
569/***********************************************************************//**
570 * @brief Copy class members
571 *
572 * @param[in] column Column.
573 *
574 * Sets the content of the vector column by copying from another column.
575 * If the code is compiled with the small memory option, and if the source
576 * column has not yet been loaded, then we only load the column temporarily
577 * for copying purposes and release it again once copying is finished.
578 ***************************************************************************/
579void GFitsTableBitCol::copy_members(const GFitsTableBitCol& column)
580{
581 // Fetch data if necessary
582 bool not_loaded = (!column.isloaded());
583 if (not_loaded) {
584 column.fetch_data();
585 }
586
587 // Copy attributes
588 m_type = column.m_type;
589 m_size = column.m_size;
590 m_varlen = column.m_varlen;
591 m_rowstart = column.m_rowstart;
592 m_bits = column.m_bits;
593 m_bytes_per_row = column.m_bytes_per_row;
594 m_bits_per_row = column.m_bits_per_row;
595 m_bit_pending = column.m_bit_pending;
596 m_bit_value = column.m_bit_value;
597 m_bit_byte = column.m_bit_byte;
598 m_bit_mask = column.m_bit_mask;
599
600 // Copy column data
601 if (column.m_data != NULL__null && m_size > 0) {
602 alloc_data();
603 for (int i = 0; i < m_size; ++i)
604 m_data[i] = column.m_data[i];
605 }
606
607 // Copy NULL value
608 alloc_nulval(column.m_nulval);
609
610 // Small memory option: release column if it was fetch above
611 #if defined(G_SMALL_MEMORY1)
612 if (not_loaded) {
613 const_cast<GFitsTableBitCol*>(&column)->release_data();
614 }
615 #endif
616
617 // Return
618 return;
619}
620
621
622/***********************************************************************//**
623 * @brief Delete class members
624 ***************************************************************************/
625void GFitsTableBitCol::free_members(void)
626{
627 // Optionally print call graph
628 #if defined(G_CALL_GRAPH)
629 printf("GFitsTableBitCol::free_members\n");
630 #endif
631
632 // Free memory
633 if (m_data != NULL__null) delete [] m_data;
634 if (m_nulval != NULL__null) delete m_nulval;
635
636 // Mark memory as freed
637 m_data = NULL__null;
638 m_nulval = NULL__null;
639
640 // Reset load flag
641 m_size = 0;
642
643 // Optionally print call graph
644 #if defined(G_CALL_GRAPH)
645 printf("exit GFitsTableBitCol::free_members\n");
646 #endif
647
648 // Return
649 return;
650}
651
652
653/***********************************************************************//**
654 * @brief Returns format string of ASCII table
655 ***************************************************************************/
656std::string GFitsTableBitCol::ascii_format(void) const
657{
658 // Initialize format string
659 std::string format;
660
661 // Set type code
662 format.append("I");
663
664 // Set width
665 format.append(gammalib::str(m_width));
666
667 // Return format
668 return format;
669}
670
671
672/***********************************************************************//**
673 * @brief Allocates column data
674 ***************************************************************************/
675void GFitsTableBitCol::alloc_data(void)
676{
677 // Optionally print call graph
678 #if defined(G_CALL_GRAPH)
679 printf("GFitsTableBitCol::alloc_data(%d)\n", m_size);
680 #endif
681
682 // Free any existing memory
683 if (m_data != NULL__null) delete [] m_data;
684
685 // Mark pointer as free
686 m_data = NULL__null;
687
688 // Allocate new data
689 if (m_size > 0) {
690 m_data = new unsigned char[m_size];
691 }
692
693 // Optionally print call graph
694 #if defined(G_CALL_GRAPH)
695 printf("exit GFitsTableBitCol::alloc_data(m_data=%x)\n", m_data);
696 #endif
697
698 // Return
699 return;
700}
701
702
703/***********************************************************************//**
704 * @brief Fetch column data
705 *
706 * This method fetches column data when needed. It is declared const, so
707 * that const data access methods can be implemented.
708 *
709 * If a FITS file is attached to the column the data are loaded into memory
710 * from the FITS file. If no FITS file is attached, memory is allocated
711 * to hold the column data and all cells are initialised.
712 *
713 * This method calls GFitsTableCol::load_column to do the job.
714 ***************************************************************************/
715void GFitsTableBitCol::fetch_data(void) const
716{
717 // Load column (circumvent const correctness)
718 const_cast<GFitsTableBitCol*>(this)->load_column();
719
720 // Return
721 return;
722}
723
724
725/***********************************************************************//**
726 * @brief Resize column data
727 *
728 * @param[in] index Start index.
729 * @param[in] number Number of elements to add/remove.
730 *
731 * Adds or removes elements from specified index on. Adding is done if
732 * @p number is a positive number, removing if @p number is negative.
733 * Note that the method does not change the validity of the arguments.
734 * This needs to be done by the client.
735 *
736 * @todo Needs to be implemented
737 ***************************************************************************/
738void GFitsTableBitCol::resize_data(const int& index, const int& number)
739{
740 //TODO
741
742 // Return
743 return;
744}
745
746
747/***********************************************************************//**
748 * @brief Release column data
749 ***************************************************************************/
750void GFitsTableBitCol::release_data(void)
751{
752 // Free any existing memory
753 if (m_data != NULL__null) delete [] m_data;
754
755 // Mark pointer as free and reset loaded vector size
756 m_data = NULL__null;
757 m_size = 0;
758
759 // Return
760 return;
761}
762
763
764/***********************************************************************//**
765 * @brief Allocates null value
766 ***************************************************************************/
767void GFitsTableBitCol::alloc_nulval(const unsigned char* value)
768{
769 // Free any existing memory
770 if (m_nulval != NULL__null) delete m_nulval;
771
772 // Mark pointer as free
773 m_nulval = NULL__null;
774
775 // If we have valid value, allocate and set nul value
776 if (value != NULL__null) {
777 m_nulval = new unsigned char;
778 *m_nulval = *value;
779 }
780
781 // Return
782 return;
783}
784
785
786/***********************************************************************//**
787 * @brief Initialise column data
788 ***************************************************************************/
789void GFitsTableBitCol::init_data(void)
790{
791 // Initialise data if they exist
792 if (m_data != NULL__null) {
793 for (int i = 0; i < m_size; ++i) {
794 m_data[i] = 0;
795 }
796 }
797
798 // Return
799 return;
800}
801
802
803/***********************************************************************//**
804 * @brief Load table column from FITS file
805 *
806 * @exception GException::fits_hdu_not_found
807 * Specified HDU not found in FITS file.
808 * @exception GException::fits_error
809 * An error occured while loading column data from FITS file.
810 *
811 * Load Bit (vector) column into memory by reading 8 Bits at once.
812 ***************************************************************************/
813void GFitsTableBitCol::load_column(void)
814{
815 // Compute total number of Bits in column
816 m_bits = m_number * m_length;
817
818 // Compute number of Bytes and Bits per row
819 m_bytes_per_row = (m_number > 0) ? ((m_number-1) / 8) + 1 : 0;
820 m_bits_per_row = m_bytes_per_row * 8;
821
822 // Compute length of memory array
823 m_size = m_bytes_per_row * m_length;
824
825 // Load only if the column has a positive size
826 if (m_size > 0) {
827
828 // Allocate and initialise fresh memory
829 alloc_data();
830 init_data();
831
832 // If a FITS file is attached then load column data from the FITS
833 // file
834 if (FPTR(m_fitsfile)((__fitsfile*)m_fitsfile)->Fptr != NULL__null) {
835
836 // Move to the HDU
837 int status = 0;
838 status = __ffmahd(FPTR(m_fitsfile),ffmahd(((__fitsfile*)m_fitsfile), (((__fitsfile*)m_fitsfile)->
HDUposition)+1, __null, &status)
839 (FPTR(m_fitsfile)->HDUposition)+1,ffmahd(((__fitsfile*)m_fitsfile), (((__fitsfile*)m_fitsfile)->
HDUposition)+1, __null, &status)
840 NULL, &status)ffmahd(((__fitsfile*)m_fitsfile), (((__fitsfile*)m_fitsfile)->
HDUposition)+1, __null, &status)
;
841 if (status != 0) {
842 throw GException::fits_hdu_not_found(G_LOAD_COLUMN"GFitsTableBitCol::load_column()",
843 (FPTR(m_fitsfile)((__fitsfile*)m_fitsfile)->HDUposition)+1,
844 status);
845 }
846
847 // Load data 8 Bits at once
848 status = __ffgcv(FPTR(m_fitsfile), __TBYTE, m_colnum, 1, 1, m_size,ffgcv(((__fitsfile*)m_fitsfile), 11, m_colnum, 1, 1, m_size, m_nulval
, m_data, &m_anynul, &status)
849 m_nulval, m_data, &m_anynul, &status)ffgcv(((__fitsfile*)m_fitsfile), 11, m_colnum, 1, 1, m_size, m_nulval
, m_data, &m_anynul, &status)
;
850 if (status != 0) {
851 throw GException::fits_error(G_LOAD_COLUMN"GFitsTableBitCol::load_column()", status,
852 "for column \""+m_name+"\".");
853 }
854 }
855
856 } // endif: column has a positive size
857
858 // Return
859 return;
860}
861
862
863/***********************************************************************//**
864 * @brief Save table column into FITS file
865 *
866 * @exception GException::fits_hdu_not_found
867 * Specified HDU not found in FITS file.
868 * @exception GException::fits_error
869 * Error occured during writing of the column data.
870 *
871 * Save Bit (vector) column into FITS file by writing 8 Bits at once.
872 ***************************************************************************/
873void GFitsTableBitCol::save_column(void)
874{
875 // Continue only if a FITS file is connected and data have been loaded
876 if (FPTR(m_fitsfile)((__fitsfile*)m_fitsfile)->Fptr != NULL__null && m_colnum > 0 && m_data != NULL__null) {
877
878 // Set any pending Bit
879 set_pending();
880
881 // Move to the HDU
882 int status = 0;
883 status = __ffmahd(FPTR(m_fitsfile),ffmahd(((__fitsfile*)m_fitsfile), (((__fitsfile*)m_fitsfile)->
HDUposition)+1, __null, &status)
884 (FPTR(m_fitsfile)->HDUposition)+1, NULL,ffmahd(((__fitsfile*)m_fitsfile), (((__fitsfile*)m_fitsfile)->
HDUposition)+1, __null, &status)
885 &status)ffmahd(((__fitsfile*)m_fitsfile), (((__fitsfile*)m_fitsfile)->
HDUposition)+1, __null, &status)
;
886 if (status != 0) {
887 throw GException::fits_hdu_not_found(G_SAVE_COLUMN"GFitsTableBitCol::save_column()",
888 (FPTR(m_fitsfile)((__fitsfile*)m_fitsfile)->HDUposition)+1,
889 status);
890 }
891
892 // Save data 8 Bits at once
893 status = __ffpcn(FPTR(m_fitsfile), __TBYTE, m_colnum, 1, 1,ffpcn(((__fitsfile*)m_fitsfile), 11, m_colnum, 1, 1, m_size, m_data
, m_nulval, &status)
894 m_size, m_data, m_nulval, &status)ffpcn(((__fitsfile*)m_fitsfile), 11, m_colnum, 1, 1, m_size, m_data
, m_nulval, &status)
;
895 if (status != 0) {
896 throw GException::fits_error(G_SAVE_COLUMN"GFitsTableBitCol::save_column()", status);
897 }
898
899 } // endif: FITS file was connected
900
901 // Return
902 return;
903}
904
905
906/***********************************************************************//**
907 * @brief Get Bit for boolean access
908 *
909 * @param[in] row Row of column.
910 * @param[in] inx Vector index in column row.
911 *
912 * @exception GException::fits_invalid_row
913 * Table row out of valid range.
914 * @exception GException::out_of_range
915 * Table vector index out of valid range.
916 *
917 * Set the Bit for boolean data access. Note that this method assumes that
918 * the data have already been loaded.
919 ***************************************************************************/
920void GFitsTableBitCol::get_bit(const int& row, const int& inx)
921{
922 // Check row value
923 #if defined(G_RANGE_CHECK1)
924 if (row < 0 || row >= m_length) {
925 throw GException::fits_invalid_row(G_GET_BIT"GFitsTableBitCol::get_bit(int&,int&)", row, m_length-1);
926 }
927 #endif
928
929 // Check inx value
930 #if defined(G_RANGE_CHECK1)
931 if (inx < 0 || inx >= m_number) {
932 throw GException::out_of_range(G_GET_BIT"GFitsTableBitCol::get_bit(int&,int&)", inx, 0, m_number-1);
933 }
934 #endif
935
936 // Compute Byte and Bit mask
937 m_bit_byte = row * m_bytes_per_row + inx / 8;
938 m_bit_mask = 1 << (7 - (inx % 8));
939
940 // Set Bit value
941 m_bit_value = (m_data[m_bit_byte] & m_bit_mask);
942
943 // Return
944 return;
945}
946
947
948/***********************************************************************//**
949 * @brief Set pending Bit
950 *
951 * Write the pending Bit into the data. Note that this method assumes that
952 * the data have already been loaded.
953 ***************************************************************************/
954void GFitsTableBitCol::set_pending(void)
955{
956 // Continue only if we have a pending Bit
957 if (m_bit_pending) {
958
959 // Set or unset Bit
960 if (m_bit_value) {
961 m_data[m_bit_byte] = m_data[m_bit_byte] | m_bit_mask;
962 }
963 else {
964 m_data[m_bit_byte] = m_data[m_bit_byte] & ~m_bit_mask;
965 }
966
967 // Signal that no more Bit is pending
968 m_bit_pending = false;
969
970 }
971
972 // Return
973 return;
974}