/***********************************************************************//** * @brief Save table column into FITS file * * @exception GException::fits_hdu_not_found * Specified HDU not found in FITS file. * @exception GException::fits_error * Error occured during writing of the column data. * * Save Bit (vector) column into FITS file by writing 8 Bits at once. ***************************************************************************/ void GFitsTableBitCol::save_column(void) { // Continue only if a FITS file is connected and data have been loaded if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && m_data != NULL) { // Set any pending Bit set_pending(); // Move to the HDU int status = 0; status = __ffmahd(FPTR(m_fitsfile), (FPTR(m_fitsfile)->HDUposition)+1, NULL, &status); if (status != 0) { throw GException::fits_hdu_not_found(G_SAVE_COLUMN, (FPTR(m_fitsfile)->HDUposition)+1, status); } // Save data 8 Bits at once status = __ffpcn(FPTR(m_fitsfile), __TBYTE, m_colnum, 1, 1, m_size, m_data, m_nulval, &status); if (status != 0) { throw GException::fits_error(G_SAVE_COLUMN, status); } } // endif: FITS file was connected // Return return; }
/***********************************************************************//** * @brief Save table column into FITS file * * @exception GException::fits_hdu_not_found * Specified HDU not found in FITS file. * @exception GException::fits_error * Error occured during writing of the column data. * * The table column is only saved if it is linked to a FITS file and if the * data are indeed present in the class instance. This avoids saving of data * that have not been modified. * * The method make use of the virtual methods * GFitsTableCol::ptr_data and * GFitsTableCol::ptr_nulval. * These methods are implemented by the derived column classes which * implement a specific storage class (i.e. float, double, short, ...). ***************************************************************************/ void GFitsTableCol::save_column_fixed(void) { // Continue only if a FITS file is connected and data have been loaded if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && ptr_data() != NULL) { // Move to the HDU int status = 0; status = __ffmahd(FPTR(m_fitsfile), (FPTR(m_fitsfile)->HDUposition)+1, NULL, &status); if (status != 0) { throw GException::fits_hdu_not_found(G_SAVE_COLUMN_FIXED, (FPTR(m_fitsfile)->HDUposition)+1, status); } // Save the column data status = __ffpcn(FPTR(m_fitsfile), m_type, m_colnum, 1, 1, m_size, ptr_data(), ptr_nulval(), &status); if (status != 0) { std::string msg = "Unable to save column '"+name()+"' to" " FITS file."; throw GException::fits_error(G_SAVE_COLUMN_FIXED, status, msg); } } // endif: FITS file was connected // Return return; }
/***********************************************************************//** * @brief Load fixed-length column from FITS file * * @exception GException::fits_hdu_not_found * Specified HDU not found in FITS file. * @exception GException::fits_error * An error occured while loading column data from FITS file. * * If a FITS file is attached to the column the data are loaded into memory * from the FITS file. If no FITS file is attached, memory is allocated * to hold the column data and all cells are set to 0. * * The method makes use of the virtual methods * GFitsTableCol::alloc_data, * GFitsTableCol::init_data, * GFitsTableCol::ptr_data, and * GFitsTableCol::ptr_nulval. * These methods are implemented by the derived column classes which * implement a specific storage class (i.e. float, double, short, ...). ***************************************************************************/ void GFitsTableCol::load_column_fixed(void) { // Calculate size of memory m_size = m_number * m_length; // Load only if the column has a positive size if (m_size > 0) { // Allocate and initialise fresh memory alloc_data(); init_data(); // If a FITS file is attached then try loading column data from the // FITS file. This may fail in case that no data has yet been written // to the FITS file. In that case we just skip loading and return // the initalised column ... if (FPTR(m_fitsfile)->Fptr != NULL) { // Move to the HDU int status = 0; status = __ffmahd(FPTR(m_fitsfile), (FPTR(m_fitsfile)->HDUposition)+1, NULL, &status); // If this failed because: // - the primary HDU was not found (status 252) // - we moved past the file (status 107) // we assume that no data have yet been written to the file and // we skip the loading. if (status != 252 && status != 107) { // Break on any other cfitsio error if (status != 0) { throw GException::fits_hdu_not_found(G_LOAD_COLUMN_FIXED, (FPTR(m_fitsfile)->HDUposition)+1, status); } // Load data status = __ffgcv(FPTR(m_fitsfile), m_type, m_colnum, 1, 1, m_size, ptr_nulval(), ptr_data(), &m_anynul, &status); if (status != 0) { throw GException::fits_error(G_LOAD_COLUMN_FIXED, status, "for column '"+m_name+"'."); } } // endif: no primary HDU found } // endif: there was a FITS file attached } // endif: column has a positive size // Return return; }
int main() { short *p; p = calloc(SIZE, sizeof(fptr) + sizeof(short) + sizeof(void*)); FPTR(p)[0] = free; VOID(&FPTR(p)[1])[0] = p; FPTR(p)[0]( VOID(&FPTR(p)[1])[0] ); free(p); return 0; }
/***********************************************************************//** * @brief Load table column from FITS file * * @exception GException::fits_hdu_not_found * Specified HDU not found in FITS file. * @exception GException::fits_error * An error occured while loading column data from FITS file. * * Load Bit (vector) column into memory by reading 8 Bits at once. ***************************************************************************/ void GFitsTableBitCol::load_column(void) { // Compute total number of Bits in column m_bits = m_number * m_length; // Compute number of Bytes and Bits per row m_bytes_per_row = (m_number > 0) ? ((m_number-1) / 8) + 1 : 0; m_bits_per_row = m_bytes_per_row * 8; // Compute length of memory array m_size = m_bytes_per_row * m_length; // Load only if the column has a positive size if (m_size > 0) { // Allocate and initialise fresh memory alloc_data(); init_data(); // If a FITS file is attached then load column data from the FITS // file if (FPTR(m_fitsfile)->Fptr != NULL) { // Move to the HDU int status = 0; status = __ffmahd(FPTR(m_fitsfile), (FPTR(m_fitsfile)->HDUposition)+1, NULL, &status); if (status != 0) { throw GException::fits_hdu_not_found(G_LOAD_COLUMN, (FPTR(m_fitsfile)->HDUposition)+1, status); } // Load data 8 Bits at once status = __ffgcv(FPTR(m_fitsfile), __TBYTE, m_colnum, 1, 1, m_size, m_nulval, m_data, &m_anynul, &status); if (status != 0) { throw GException::fits_error(G_LOAD_COLUMN, status, "for column \""+m_name+"\"."); } } } // endif: column has a positive size // Return return; }
/***********************************************************************//** * @brief Load FITS image * * @param[in] datatype Datatype of pixels to be saved. * @param[in] pixels Pixel array to be saved. * @param[in] nulval Pointer to pixel nul value. * @param[out] anynul Number of nul values encountered during loading. * * @exception GException::fits_error * FITS error. * * Load image pixels from FITS file. ***************************************************************************/ void GFitsImage::load_image(int datatype, const void* pixels, const void* nulval, int* anynul) { // Move to HDU move_to_hdu(); // Load the image pixels (if there are some ...) if (m_naxis > 0) { long* fpixel = new long[m_naxis]; long* lpixel = new long[m_naxis]; long* inc = new long[m_naxis]; for (int i = 0; i < m_naxis; ++i) { fpixel[i] = 1; lpixel[i] = m_naxes[i]; inc[i] = 1; } int status = 0; status = __ffgsv(FPTR(m_fitsfile), datatype, fpixel, lpixel, inc, (void*)nulval, (void*)pixels, anynul, &status); delete [] fpixel; delete [] lpixel; delete [] inc; if (status != 0) { throw GException::fits_error(G_LOAD_IMAGE, status); } } // Return return; }
/***********************************************************************//** * @brief Save table column into FITS file * * @exception GException::fits_hdu_not_found * Specified HDU not found in FITS file. * @exception GException::fits_error * Error occured during writing of the column data. * * The table column is only saved if it is linked to a FITS file and if the * data are indeed present in the class instance. This avoids saving of data * that have not been modified. * * The method make use of the virtual methods * GFitsTableCol::ptr_data and * GFitsTableCol::ptr_nulval. * These methods are implemented by the derived column classes which * implement a specific storage class (i.e. float, double, short, ...). ***************************************************************************/ void GFitsTableCol::save_column_variable(void) { // Continue only if a FITS file is connected and data have been loaded if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && ptr_data() != NULL) { // Move to the HDU int status = 0; status = __ffmahd(FPTR(m_fitsfile), (FPTR(m_fitsfile)->HDUposition)+1, NULL, &status); if (status != 0) { throw GException::fits_hdu_not_found(G_SAVE_COLUMN_VARIABLE, (FPTR(m_fitsfile)->HDUposition)+1, status); } // Save the column data row-by-row for (int row = 0; row < m_length; ++row) { // Save row data status = __ffpcn(FPTR(m_fitsfile), std::abs(m_type), m_colnum, row+1, 1, elements(row), ptr_data(m_rowstart[row]), ptr_nulval(), &status); if (status != 0) { std::string msg = "Unable to save row "+gammalib::str(row+1)+"" " of column '"+name()+"' to FITS file."; throw GException::fits_error(G_SAVE_COLUMN_VARIABLE, status, msg); } } // endfor: looped over rows } // endif: FITS file was connected // Return return; }
/***********************************************************************//** * @brief Open Image * * @param[in] vptr FITS file void pointer. * * @exception GException::fits_error * FITS error. * * Open FITS image in FITS file. Opening means connecting the FITS file * pointer to the image and reading the image and axes dimensions. ***************************************************************************/ void GFitsImage::open_image(void* vptr) { // Move to HDU gammalib::fits_move_to_hdu(G_OPEN_IMAGE, vptr); // Save the FITS file pointer and the HDU number FPTR_COPY(m_fitsfile, vptr); m_hdunum = FPTR(vptr)->HDUposition; // Get the image dimensions int status = 0; status = __ffgidm(FPTR(m_fitsfile), &m_naxis, &status); if (status != 0) { throw GException::fits_error(G_OPEN_IMAGE, status); } // Reset number of image pixels m_num_pixels = 0; // Get the axes dimensions if (m_naxis > 0) { // Allocate memory for axes dimensions if (m_naxes != NULL) delete [] m_naxes; m_naxes = new long[m_naxis]; // Get the axes dimensions status = __ffgisz(FPTR(m_fitsfile), m_naxis, m_naxes, &status); if (status != 0) { throw GException::fits_error(G_OPEN_IMAGE, status); } // Calculate number of image pixels m_num_pixels = 1; for (int i = 0; i < m_naxis; ++i) { m_num_pixels *= m_naxes[i]; } } // endif: there is an image // Return return; }
void ui_menu_select_rw::handle() { // process the menu const ui_menu_event *event = process(0); if (event != NULL && event->iptkey == IPT_UI_SELECT) { *m_result = int(FPTR(event->itemref)); ui_menu::stack_pop(machine()); } }
/***********************************************************************//** * @brief Initialise class members ***************************************************************************/ void GFitsTableCol::init_members(void) { // Optionally print call graph #if defined(G_CALL_GRAPH) printf("GFitsTableCol::init_members\n"); #endif // Allocate FITS file pointer m_fitsfile = new __fitsfile; FPTR(m_fitsfile)->HDUposition = 0; FPTR(m_fitsfile)->Fptr = NULL; // Initialise members m_name.clear(); m_unit.clear(); m_dim.clear(); m_rowstart.clear(); m_colnum = 0; m_type = 0; m_repeat = 0; m_width = 0; m_number = 0; m_length = 0; m_variable = false; m_varlen = 0; m_size = 0; m_anynul = 0; // Optionally print call graph #if defined(G_CALL_GRAPH) printf("exit GFitsTableCol::init_members\n"); #endif // Return return; }
/***********************************************************************//** * @brief Fetch image pixels * * Fetch the image pixels. This function is in general called if pixel * values should be read or written yet no pixel array is allocated. In case * that pixels existed already before they will be deleted before fetching * new ones. * There are two possibilities to fetch the pixels: * (1) In case that a FITS file is attached to the image, the pixel array * will be loaded from the FITS file using the load_image() method. * (2) In case that no FITS file is attached, a new pixel array will be * allocated that is initalised to zero. ***************************************************************************/ void GFitsImage::fetch_data(void) { // Fetch only if there are pixels in image if (m_num_pixels > 0) { // Allocate and initialise fresh memory alloc_data(); init_data(); // If a FITS file is attached then load pixels from FITS file. if (FPTR(m_fitsfile)->Fptr != NULL) { load_image(type(), ptr_data(), ptr_nulval(), &m_anynul); } } // endif: there were pixels available // Return return; }
/***********************************************************************//** * @brief Delete class members ***************************************************************************/ void GFitsTableCol::free_members(void) { // Optionally print call graph #if defined(G_CALL_GRAPH) printf("GFitsTableCol::free_members\n"); #endif // Free memory if (m_fitsfile != NULL) delete FPTR(m_fitsfile); // Mark memory as free m_fitsfile = NULL; // Optionally print call graph #if defined(G_CALL_GRAPH) printf("exit GFitsTableCol::free_members\n"); #endif // Return return; }
/***********************************************************************//** * @brief Load variable-length column from FITS file * * @exception GException::fits_hdu_not_found * Specified HDU not found in FITS file. * @exception GException::fits_error * An error occured while loading column data from FITS file. * * If a FITS file is attached to the column the data are loaded into memory * from the FITS file. If no FITS file is attached, memory is allocated * to hold the column data and all cells are set to 0. * * The method makes use of the virtual methods * GFitsTableCol::alloc_data, * GFitsTableCol::init_data, * GFitsTableCol::ptr_data, and * GFitsTableCol::ptr_nulval. * These methods are implemented by the derived column classes which * implement a specific storage class (i.e. float, double, short, ...). ***************************************************************************/ void GFitsTableCol::load_column_variable(void) { // If a FITS file is attached then try loading column data from the // FITS file. This may fail in case that no data has yet been written // to the FITS file. In that case we just skip loading and return // the initalised column ... if (FPTR(m_fitsfile)->Fptr != NULL) { // Move to the HDU int status = 0; status = __ffmahd(FPTR(m_fitsfile), (FPTR(m_fitsfile)->HDUposition)+1, NULL, &status); // If this failed because: // - the primary HDU was not found (status 252) // - we moved past the file (status 107) // we assume that no data have yet been written to the file and // we skip the loading. if (status != 252 && status != 107) { // Break on any other cfitsio error if (status != 0) { throw GException::fits_hdu_not_found(G_LOAD_COLUMN_VARIABLE, (FPTR(m_fitsfile)->HDUposition)+1, status); } // Allocate rowstart array m_rowstart.assign(m_length+1, 0); // Determine the column length for each row by looping over // all rows and derive the total memory requirement m_size = 0; m_varlen = 0; m_rowstart[0] = 0; for (int row = 0; row < m_length; ++row) { // Initialise offset and repeat long offset(0); long repeat(0); // Get variable-length of row in repeat status = __ffgdes(FPTR(m_fitsfile), m_colnum, row+1, &repeat, &offset, &status); if (status != 0) { std::string msg = "Unable to get descriptor of row "+ gammalib::str(row+1)+" of column '"+ name()+"' from FITS file."; throw GException::fits_error(G_LOAD_COLUMN_VARIABLE, status, msg); } // Store start of next row m_rowstart[row+1] = m_rowstart[row] + repeat; m_size += repeat; if (repeat > m_varlen) { m_varlen = repeat; } } // endfor: looped over all rows // Allocate and initialise fresh memory alloc_data(); init_data(); // Load data for each row for (int row = 0; row < m_length; ++row) { // Initialise anynul int anynul(0); // Load data status = __ffgcv(FPTR(m_fitsfile), std::abs(m_type), m_colnum, row+1, 1, elements(row), ptr_nulval(), ptr_data(m_rowstart[row]), &anynul, &status); if (status != 0) { std::string msg = "Unable to load row "+gammalib::str(row+1)+"" " of column '"+name()+"' from FITS file."; throw GException::fits_error(G_LOAD_COLUMN_VARIABLE, status, msg); } // Increment anynul m_anynul += anynul; } // endfor: looped over all rows } // endif: no primary HDU found } // endif: there was a FITS file attached // Return return; }
void *osd_malloc_array(size_t size) { #ifndef MALLOC_DEBUG return malloc(size); #else // add in space for the size and offset size += MAX_ALIGNMENT + sizeof(size_t) + 2; size &= ~size_t(1); // round the size up to a page boundary size_t const rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; // reserve that much memory, plus two guard pages void *page_base = VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS); if (page_base == NULL) return NULL; // now allow access to everything but the first and last pages page_base = VirtualAlloc(reinterpret_cast<UINT8 *>(page_base) + PAGE_SIZE, rounded_size, MEM_COMMIT, PAGE_READWRITE); if (page_base == NULL) return NULL; // work backwards from the page base to get to the block base UINT8 *const block = GUARD_ALIGN_START ? reinterpret_cast<UINT8 *>(page_base) : (reinterpret_cast<UINT8 *>(page_base) + rounded_size - size); UINT8 *const result = reinterpret_cast<UINT8 *>(reinterpret_cast<FPTR>(block + sizeof(size_t) + MAX_ALIGNMENT) & ~(FPTR(MAX_ALIGNMENT) - 1)); // store the size at the start with a flag indicating it has a guard page *reinterpret_cast<size_t *>(block) = size | 1; *(result - 1) = result - block; return result; #endif }
/***********************************************************************//** * @brief Save FITS image * * @param[in] datatype Datatype of pixels to be saved * @param[in] pixels Pixel array to be saved * * @exception GException::fits_file_not_open * No FITS file has been opened. * @exception GException::fits_error * FITS error. * * Save image pixels into FITS file. In case that the HDU does not exist it * is created. In case that the pixel array is empty no data are saved; all * image pixels will be empty in this case. ***************************************************************************/ void GFitsImage::save_image(int datatype, const void* pixels) { // Throw an exception if FITS file is not open if (FPTR(m_fitsfile)->Fptr == NULL) { throw GException::fits_file_not_open(G_SAVE_IMAGE, "Open file before saving the image."); } // Move to HDU. We use here an explicit cfitsio moveto function since we // want to recover the error code ... int status = 0; int type = 0; status = __ffmahd(FPTR(m_fitsfile), m_hdunum+1, &type, &status); // If move was successful but HDU type in file differs from HDU type // of object then replace the HDU in the file if (status == 0 && type != exttype()) { status = __ffdhdu(FPTR(m_fitsfile), NULL, &status); if (status != 0) { throw GException::fits_error(G_SAVE_IMAGE, status); } status = __ffiimg(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status); //status = __ffiimgll(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status); if (status != 0) { throw GException::fits_error(G_SAVE_IMAGE, status); } } // If HDU does not yet exist in file then create it now if (status == 107) { status = 0; status = __ffcrim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status); if (status != 0) { throw GException::fits_error(G_SAVE_IMAGE, status); } } else if (status != 0) { throw GException::fits_error(G_SAVE_IMAGE, status); } // If HDU seems to be empty then create it now. This is only needed for the // primary HDU, since __ffmahd gives no error if the primary HDU is empty. // By checking the number of keywords in the HDU we detect an empty HDU ... int num = 0; status = __ffghsp(FPTR(m_fitsfile), &num, NULL, &status); if (status != 0) { throw GException::fits_error(G_SAVE_IMAGE, status); } if (num == 0) { status = __ffcrim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status); if (status != 0) { throw GException::fits_error(G_SAVE_IMAGE, status); } } // Make sure that the image on disk has the right size by resizing it status = __ffrsim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status); if (status != 0) { throw GException::fits_error(G_SAVE_IMAGE, status); } // Save the image pixels (if there are some ...) if (m_naxis > 0 && pixels != NULL) { long* fpixel = new long[m_naxis]; long* lpixel = new long[m_naxis]; for (int i = 0; i < m_naxis; ++i) { fpixel[i] = 1; lpixel[i] = m_naxes[i]; } status = __ffpss(FPTR(m_fitsfile), datatype, fpixel, lpixel, (void*)pixels, &status); delete [] fpixel; delete [] lpixel; if (status != 0) { throw GException::fits_error(G_SAVE_IMAGE, status); } } // Return return; }
void menu_software_list::handle() { const entry_info *selected_entry = nullptr; int bestmatch = 0; // process the menu const event *event = process(0); if (event && event->itemref) { if ((FPTR)event->itemref == 1 && event->iptkey == IPT_UI_SELECT) { m_ordered_by_shortname = !m_ordered_by_shortname; // reset the char buffer if we change ordering criterion m_filename_buffer.clear(); // reload the menu with the new order reset(reset_options::REMEMBER_REF); machine().popmessage(_("Switched Order: entries now ordered by %s"), m_ordered_by_shortname ? _("shortname") : _("description")); } // handle selections else if (event->iptkey == IPT_UI_SELECT) { entry_info *info = (entry_info *) event->itemref; m_result = info->short_name; stack_pop(); } else if (event->iptkey == IPT_SPECIAL) { if (input_character(m_filename_buffer, event->unichar, &is_valid_softlist_part_char)) { // display the popup ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer); // identify the selected entry entry_info const *const cur_selected = (FPTR(event->itemref) != 1) ? reinterpret_cast<entry_info const *>(get_selection_ref()) : nullptr; // loop through all entries for (auto &entry : m_entrylist) { // is this entry the selected entry? if (cur_selected != &entry) { auto &compare_name = m_ordered_by_shortname ? entry.short_name : entry.long_name; int match = 0; for (int i = 0; i < m_filename_buffer.length(); i++) { if (core_strnicmp(compare_name.c_str(), m_filename_buffer.c_str(), i) == 0) match = i; } if (match > bestmatch) { bestmatch = match; selected_entry = &entry; } } } if (selected_entry != nullptr && selected_entry != cur_selected) { set_selection((void *)selected_entry); centre_selection(); } } } else if (event->iptkey == IPT_UI_CANCEL) { // reset the char buffer also in this case m_filename_buffer.clear(); m_result = m_filename_buffer; stack_pop(); } } }
/***********************************************************************//** * @brief Save table into FITS file * * @exception GException::fits_error * A CFITSIO error occured in this method. * @exception GException::fits_bad_col_length * Table columns have inconsistent lengths. * * This method saves a table into a FITS file. * * In case that no table HDU exists it will be created by appending a new * HDU to the existing file. The definition of this HDU will be based on the * table definition in the class instance. * * The method also verifies the consistency of all table columns. Table * columns need to have identical lengths to be saved into a FITS table. * All columns with a length of zero will be excluded from saving, and if * they exist in the FITS file, they will be removed from the file. * * @todo This method should also update the header. Even easier, this method * should save the header into the file using the m_header.save() * method. * Only this assures coherence between the files !!!! Once this has * been implemented (also in the GFitsImage method) we should delete * the m_header.save() call in GFitsHDU::save. ***************************************************************************/ void GFitsTable::data_save(void) { // Debug definition: Dump method entry #if defined(G_DEBUG_SAVE) std::cout << "GFitsTable::save: entry" << std::endl; #endif // Make sure that column lengths are consistent with table length. // Columns with zero length will not be considered (why?) for (int i = 0; i < m_cols; ++i) { if (m_columns[i] != NULL && m_columns[i]->length() > 0) { if (m_columns[i]->length() != m_rows) { throw GException::fits_bad_col_length(G_DATA_SAVE, m_columns[i]->length(), m_rows); } } } // Move to HDU int status = 0; status = __ffmahd(FPTR(m_fitsfile), m_hdunum+1, NULL, &status); // If HDU does not exist in file then create it now if (status == 107) { // Reset status status = 0; // Initialise number of fields int tfields = 0; // Setup cfitsio column definition arrays char** ttype = NULL; char** tform = NULL; char** tunit = NULL; if (m_cols > 0) { ttype = new char*[m_cols]; tform = new char*[m_cols]; tunit = new char*[m_cols]; for (int i = 0; i < m_cols; ++i) { ttype[i] = NULL; tform[i] = NULL; tunit[i] = NULL; } for (int i = 0; i < m_cols; ++i) { ttype[tfields] = get_ttype(i); tform[tfields] = get_tform(i); tunit[tfields] = get_tunit(i); if (ttype[tfields] != NULL && tform[tfields] != NULL && tunit[tfields] != NULL) tfields++; } } // Create FITS table status = __ffcrtb(FPTR(m_fitsfile), m_type, m_rows, tfields, ttype, tform, tunit, NULL, &status); if (status != 0) throw GException::fits_error(G_DATA_SAVE, status); // De-allocate column definition arrays if (m_cols > 0) { for (int i = 0; i < m_cols; ++i) { if (ttype[i] != NULL) delete [] ttype[i]; if (tform[i] != NULL) delete [] tform[i]; if (tunit[i] != NULL) delete [] tunit[i]; } if (ttype != NULL) delete [] ttype; if (ttype != NULL) delete [] tform; if (ttype != NULL) delete [] tunit; } // Connect all existing columns to FITS table if (m_columns != NULL) { for (int i = 0; i < m_cols; ++i) { if (m_columns[i] != NULL) { FPTR_COPY(m_columns[i]->m_fitsfile, m_fitsfile); m_columns[i]->m_colnum = i+1; } } } // Debug option: Signal table creation #if defined(G_DEBUG_SAVE) std::cout << "GFitsTable::save: created new table" << std::endl; #endif } // ... otherwise we signal a FITS error else if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } // Determine number of columns in table int num_cols = 0; status = __ffgncl(FPTR(m_fitsfile), &num_cols, &status); if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } // Debug option: Log number of columns in FITS table #if defined(G_DEBUG_SAVE) std::cout << "GFitsTable::save: FITS table contains "; std::cout << num_cols << " columns." << std::endl; #endif // If we have no columns in the table then delete all columns from // FITS table if (m_columns == NULL && num_cols > 0) { for (int i = 0; i < num_cols; ++i) { status = __ffdcol(FPTR(m_fitsfile), i, &status); if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } } } // ... otherwise update the FITS table else { // Determine number of rows in table long num_rows = 0; status = __ffgnrw(FPTR(m_fitsfile), &num_rows, &status); if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } // Debug option: Log number of rows in FITS table #if defined(G_DEBUG_SAVE) std::cout << "GFitsTable::save: FITS table contains "; std::cout << num_rows << " rows." << std::endl; #endif // If the table length differs from number of rows in the FITS file // then readjust FITS table length. We do this by adding or // deleting rows at the end of the table as we anyways rewrite the // entire table later if (m_rows > num_rows) { // Insert rows at the end of the table long long firstrow = num_rows; long long nrows = m_rows - num_rows; status = __ffirow(FPTR(m_fitsfile), firstrow, nrows, &status); if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } // Debug option: Log row adding #if defined(G_DEBUG_SAVE) std::cout << "GFitsTable::save: Added " << nrows; std::cout << " rows to FITS table." << std::endl; #endif } else if (m_rows < num_rows) { // Delete rows at the end of the table long long firstrow = num_rows; long long nrows = num_rows - m_rows; status = __ffdrow(FPTR(m_fitsfile), firstrow, nrows, &status); if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } // Debug option: Log row adding #if defined(G_DEBUG_SAVE) std::cout << "GFitsTable::save: Deleted " << nrows; std::cout << " rows from FITS table." << std::endl; #endif } // Update all columns. The 'm_colnum' field specifies where in the // FITS file the column resides. If 'm_colnum=0' then we have a new // column that does not yet exist. In this case we append a new column // to the FITS file. for (int i = 0; i < m_cols; ++i) { // Only consider valid columns if (m_columns[i] != NULL) { // If column has no correspondance than add new column in // FITS table and link column to table. if (m_columns[i]->m_colnum == 0) { // Increment number of columns in FITS file num_cols++; // Append column to FITS file status = __fficol(FPTR(m_fitsfile), num_cols, get_ttype(i), get_tform(i), &status); if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } // Connect all column to FITS table by copying over the // FITS file pointer. FPTR_COPY(m_columns[i]->m_fitsfile, m_fitsfile); m_columns[i]->m_colnum = num_cols; } // endif: column appended to FITS file // Now write column into FITS file (only if length is positive) if (m_columns[i]->length() > 0) { m_columns[i]->save(); } } // endif: column was valid } // endfor: looped over all table columns // Delete all unused columns from FITS file. We do this from last to // first so that the column numbers remain valid. Also note that // FITS column counting starts from 1. for (int colnum = num_cols; colnum > 0; --colnum) { // Get column name from FITS file char keyname[10]; char value[80]; sprintf(keyname, "TTYPE%d", colnum); status = __ffgkey(FPTR(m_fitsfile), keyname, value, NULL, &status); if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } value[strlen(value)-1] = '\0'; std::string colname = strip_whitespace(&(value[1])); // Check if this column is actually in our list of columns bool used = false; for (int i = 0; i < m_cols; ++i) { if (m_columns[i] != NULL && m_columns[i]->length() > 0 && m_columns[i]->name() == colname) { used = true; break; } } // If column is not used then delete it now from FITS table if (!used) { // Delete column status = __ffdcol(FPTR(m_fitsfile), colnum, &status); if (status != 0) { throw GException::fits_error(G_DATA_SAVE, status); } // Debug option: Log column deletion #if defined(G_DEBUG_SAVE) std::cout << "GFitsTable::save: Deleted obsolete column "; std::cout << value << " from FITS table." << std::endl; #endif } // endif: deleted column } // endfor: Looped over all FITS columns } // endelse: FITS table has been updated // Now update the header for all columns (unit and TDIM information) for (int i = 0; i < m_cols; ++i) { // Only consider valid columns if (m_columns[i] != NULL) { // Get column number int colnum = m_columns[i]->m_colnum; // Update column units if available if (m_columns[i]->unit().length() > 0) { // Build keyname std::string keyname = "TUNIT"+str(colnum); // Update header card card(keyname, m_columns[i]->unit(), "physical unit of field"); } // Write TDIM keyword if available if (m_columns[i]->dim().size() > 0) { // Build keyname std::string keyname = "TDIM"+str(colnum); // Build value string std::string value = "("+str(m_columns[i]->dim()[0]); for (int k = 1; k < m_columns[i]->dim().size(); ++k) { value += ","+str(m_columns[i]->dim()[k]); } value += ")"; // Update header card card(keyname, value, "dimensions of field"); } // endif: wrote TDIM keyword } // endif: column was valid } // endfor: looped over all columns // Debug definition: Dump method exit #if defined(G_DEBUG_SAVE) std::cout << "GFitsTable::save: exit" << std::endl; #endif // Return return; }
/***********************************************************************//** * @brief Open Table * * @param[in] vptr FITS file pointer. * * @exception GException::fits_hdu_not_found * Specified HDU not found in FITS file. * @exception GException::fits_error * A CFITSIO error occured during loading the table. * @exception GException::fits_unknown_coltype * FITS column of unsupported type has been found in the FITS file. * @exception GException::fits_inconsistent_tdim * The TDIM information provided in the header is inconsistent * with the size of the column. * * This method loads a description of the table into memory. Column data are * not loaded at this point to save memory. They will be loaded on request * later. ***************************************************************************/ void GFitsTable::data_open(void* vptr) { // Move to HDU int status = 0; status = __ffmahd(FPTR(vptr), (FPTR(vptr)->HDUposition)+1, NULL, &status); if (status != 0) throw GException::fits_hdu_not_found(G_DATA_OPEN, (FPTR(vptr)->HDUposition)+1, status); // Save FITS file pointer FPTR_COPY(m_fitsfile, vptr); // Determine number of rows in table long nrows = 0; status = __ffgnrw(FPTR(m_fitsfile), &nrows, &status); if (status != 0) throw GException::fits_error(G_DATA_OPEN, status); else m_rows = (int)nrows; // Determine number of columns in table status = __ffgncl(FPTR(m_fitsfile), &m_cols, &status); if (status != 0) throw GException::fits_error(G_DATA_OPEN, status); // Allocate and initialise memory for column pointers. Note that this // initialisation is needed to allow for a clean free_members() call // in case of any exception. if (m_columns != NULL) delete [] m_columns; m_columns = new GFitsTableCol*[m_cols]; for (int i = 0; i < m_cols; ++i) m_columns[i] = NULL; // Get table column information int typecode = 0; long repeat = 0; long width = 0; for (int i = 0; i < m_cols; ++i) { // Get column name char keyname[10]; char value[80]; sprintf(keyname, "TTYPE%d", i+1); status = __ffgkey(FPTR(m_fitsfile), keyname, value, NULL, &status); if (status != 0) throw GException::fits_error(G_DATA_OPEN, status); value[strlen(value)-1] = '\0'; // Get column definition status = __ffgtcl(FPTR(m_fitsfile), i+1, &typecode, &repeat, &width, &status); if (status != 0) throw GException::fits_error(G_DATA_OPEN, status); // Check for unsigned columns unsigned long offset = 0; sprintf(keyname, "TZERO%d", i+1); status = __ffgky(FPTR(m_fitsfile), __TULONG, keyname, &offset, NULL, &status); if (status == 0) { if (typecode == __TSHORT && offset == 32768u) typecode = __TUSHORT; else if (typecode == __TLONG && offset == 2147483648u) typecode = __TULONG; else if (typecode == __TINT && offset == 2147483648u) typecode = __TUINT; else { std::ostringstream message; message << ", but column " << value << " has typecode " << typecode << " and unexpected associated TZERO=" << offset << "."; throw GException::fits_error(G_DATA_OPEN, 0, message.str()); } } else status = 0; // Get column unit (optional, leave blank if not found) char unit[80]; sprintf(keyname, "TUNIT%d", i+1); status = __ffgkey(FPTR(m_fitsfile), keyname, unit, NULL, &status); if (status != 0) { status = 0; unit[0] = '\0'; unit[1] = '\0'; } else unit[strlen(unit)-1] = '\0'; // Get column dimension (optional, leave blank if not found) char dim[80]; sprintf(keyname, "TDIM%d", i+1); status = __ffgkey(FPTR(m_fitsfile), keyname, dim, NULL, &status); if (status != 0) { status = 0; dim[0] = '\0'; dim[1] = '\0'; } else { dim[strlen(dim)-1] = '\0'; } // If found, extract column dimension into vector array of integers std::vector<int> vdim; std::string sdim = strip_chars(strip_whitespace(&(dim[1])),"()"); if (sdim.length() > 0) { std::vector<std::string> elements = split(sdim, ","); for (int k = 0; k < elements.size(); ++k) { vdim.push_back(toint(elements[k])); } } // Allocate column m_columns[i] = alloc_column(typecode); if (m_columns[i] == NULL) { std::ostringstream colname; colname << value; throw GException::fits_unknown_coltype(G_DATA_OPEN, colname.str(), typecode); } // Store column definition m_columns[i]->name(strip_whitespace(&(value[1]))); m_columns[i]->unit(strip_whitespace(&(unit[1]))); m_columns[i]->dim(vdim); m_columns[i]->m_colnum = i+1; m_columns[i]->m_type = typecode; m_columns[i]->m_repeat = repeat; m_columns[i]->m_width = width; m_columns[i]->m_length = m_rows; m_columns[i]->connect(FPTR(m_fitsfile)); // Extract column vector size if (m_columns[i]->m_repeat == 1) { // ASCII tables m_columns[i]->m_number = 1; } else { // Binary tables if (typecode == __TSTRING) { m_columns[i]->m_number = m_columns[i]->m_repeat / m_columns[i]->m_width; } else { m_columns[i]->m_number = m_columns[i]->m_repeat; } } // If TDIM information was set then check its consistency if (!vdim.empty()) { // Compute expectation int num = vdim[0]; for (int k = 1; k < vdim.size(); ++k) { num *= vdim[k]; } // Compare with real size if (num != m_columns[i]->m_number) { throw GException::fits_inconsistent_tdim(G_DATA_OPEN, vdim, m_columns[i]->m_number); } } // endif: Valid TDIM information was found } // endfor: looped over all columns // Return return; }
static void invoke_callback(JNIEnv* env, callback *cb, ffi_cif* cif, void *resp, void **cbargs) { jobject self; void *oldresp = resp; self = (*env)->NewLocalRef(env, cb->object); // Avoid calling back to a GC'd object if ((*env)->IsSameObject(env, self, NULL)) { fprintf(stderr, "JNA: callback object has been garbage collected\n"); if (cif->rtype->type != FFI_TYPE_VOID) { memset(resp, 0, cif->rtype->size); } } else if (cb->direct) { unsigned int i; void **args = alloca((cif->nargs + 3) * sizeof(void *)); args[0] = (void *)&env; args[1] = &self; args[2] = &cb->methodID; memcpy(&args[3], cbargs, cif->nargs * sizeof(void *)); // Note that there is no support for CVT_TYPE_MAPPER here if (cb->conversion_flags) { for (i=0;i < cif->nargs;i++) { switch(cb->conversion_flags[i]) { case CVT_INTEGER_TYPE: case CVT_POINTER_TYPE: case CVT_NATIVE_MAPPED: case CVT_NATIVE_MAPPED_STRING: case CVT_NATIVE_MAPPED_WSTRING: // Make sure we have space enough for the new argument args[i+3] = alloca(sizeof(void *)); *((void **)args[i+3]) = fromNativeCallbackParam(env, cb->arg_classes[i], cif->arg_types[i], cbargs[i], JNI_FALSE, cb->encoding); break; case CVT_POINTER: *((void **)args[i+3]) = newJavaPointer(env, *(void **)cbargs[i]); break; case CVT_STRING: *((void **)args[i+3]) = newJavaString(env, *(void **)cbargs[i], cb->encoding); break; case CVT_WSTRING: *((void **)args[i+3]) = newJavaWString(env, *(void **)cbargs[i]); break; case CVT_STRUCTURE: *((void **)args[i+3]) = newJavaStructure(env, *(void **)cbargs[i], cb->arg_classes[i]); break; case CVT_STRUCTURE_BYVAL: args[i+3] = alloca(sizeof(void *)); *((void **)args[i+3]) = newJavaStructure(env, cbargs[i], cb->arg_classes[i]); break; case CVT_CALLBACK: *((void **)args[i+3]) = newJavaCallback(env, *(void **)cbargs[i], cb->arg_classes[i]); break; case CVT_FLOAT: args[i+3] = alloca(sizeof(double)); *((double *)args[i+3]) = *(float*)cbargs[i]; break; case CVT_DEFAULT: break; default: fprintf(stderr, "JNA: Unhandled arg conversion type %d\n", cb->conversion_flags[i]); break; } } } if (cb->rflag == CVT_STRUCTURE_BYVAL) { resp = alloca(sizeof(jobject)); } else if (cb->cif.rtype->size > cif->rtype->size) { resp = alloca(cb->cif.rtype->size); } #define FPTR(ENV,OFFSET) (*(void **)((char *)(*(ENV)) + OFFSET)) #define JNI_FN(X) ((void (*)(void))(X)) ffi_call(&cb->java_cif, JNI_FN(FPTR(env, cb->fptr_offset)), resp, args); if ((*env)->ExceptionCheck(env)) { jthrowable throwable = (*env)->ExceptionOccurred(env); (*env)->ExceptionClear(env); if (!handle_exception(env, self, throwable)) { fprintf(stderr, "JNA: error handling callback exception, continuing\n"); } if (cif->rtype->type != FFI_TYPE_VOID) { memset(oldresp, 0, cif->rtype->size); } } else switch(cb->rflag) { case CVT_INTEGER_TYPE: if (cb->cif.rtype->size > sizeof(ffi_arg)) { *(jlong *)oldresp = getIntegerTypeValue(env, *(void **)resp); } else { *(ffi_arg *)oldresp = (ffi_arg)getIntegerTypeValue(env, *(void **)resp); } break; case CVT_POINTER_TYPE: *(void **)resp = getPointerTypeAddress(env, *(void **)resp); break; case CVT_NATIVE_MAPPED: toNative(env, *(void **)resp, oldresp, cb->cif.rtype->size, JNI_TRUE, cb->encoding); break; case CVT_NATIVE_MAPPED_STRING: case CVT_NATIVE_MAPPED_WSTRING: // TODO: getNativeString rather than allocated memory fprintf(stderr, "JNA: Likely memory leak here\n"); toNative(env, *(void **)resp, oldresp, cb->cif.rtype->size, JNI_TRUE, cb->encoding); break; case CVT_POINTER: *(void **)resp = getNativeAddress(env, *(void **)resp); break; case CVT_STRING: *(void **)resp = getNativeString(env, *(void **)resp, JNI_FALSE); break; case CVT_WSTRING: *(void **)resp = getNativeString(env, *(void **)resp, JNI_TRUE); break; case CVT_STRUCTURE: writeStructure(env, *(void **)resp); *(void **)resp = getStructureAddress(env, *(void **)resp); break; case CVT_STRUCTURE_BYVAL: writeStructure(env, *(void **)resp); memcpy(oldresp, getStructureAddress(env, *(void **)resp), cb->cif.rtype->size); break; case CVT_CALLBACK: *(void **)resp = getCallbackAddress(env, *(void **)resp); break; case CVT_DEFAULT: break; default: fprintf(stderr, "JNA: Unhandled result conversion: %d\n", cb->rflag); break; } if (cb->conversion_flags) { for (i=0;i < cif->nargs;i++) { if (cb->conversion_flags[i] == CVT_STRUCTURE) { writeStructure(env, *(void **)cbargs[i]); } } } } else { jobject result; jobjectArray params = (*env)->NewObjectArray(env, cif->nargs, classObject, NULL); unsigned int i; for (i=0;i < cif->nargs;i++) { jobject arg = new_object(env, cb->arg_jtypes[i], cbargs[i], JNI_FALSE, cb->encoding); (*env)->SetObjectArrayElement(env, params, i, arg); } result = (*env)->CallObjectMethod(env, self, cb->methodID, params); if ((*env)->ExceptionCheck(env)) { jthrowable throwable = (*env)->ExceptionOccurred(env); (*env)->ExceptionClear(env); if (!handle_exception(env, self, throwable)) { fprintf(stderr, "JNA: error while handling callback exception, continuing\n"); } if (cif->rtype->type != FFI_TYPE_VOID) memset(resp, 0, cif->rtype->size); } else { extract_value(env, result, resp, cif->rtype->size, JNI_TRUE, cb->encoding); } } }
void *osd_malloc(size_t size) { #ifndef MALLOC_DEBUG return malloc(size); #else // add in space for the size and offset size += MAX_ALIGNMENT + sizeof(size_t) + 2; size &= ~size_t(1); // basic objects just come from the heap UINT8 *const block = reinterpret_cast<UINT8 *>(HeapAlloc(GetProcessHeap(), 0, size)); if (block == NULL) return NULL; UINT8 *const result = reinterpret_cast<UINT8 *>(reinterpret_cast<FPTR>(block + sizeof(size_t) + MAX_ALIGNMENT) & ~(FPTR(MAX_ALIGNMENT) - 1)); // store the size and return and pointer to the data afterward *reinterpret_cast<size_t *>(block) = size; *(result - 1) = result - block; return result; #endif }