int fitstable_copy_rows_data(fitstable_t* intable, int* rows, int N, fitstable_t* outtable) { int R; char* buf = NULL; int i; // We need to endian-flip if we're going from FITS file <--> memory. anbool flip = need_endian_flip() && (in_memory(intable) != in_memory(outtable)); R = fitstable_row_size(intable); buf = malloc(R); for (i=0; i<N; i++) { if (fitstable_read_row_data(intable, rows ? rows[i] : i, buf)) { ERROR("Failed to read data from input table"); return -1; } // The in-memory side (input/output) does the flip. if (flip) { if (in_memory(intable)) fitstable_endian_flip_row_data(intable, buf); else if (in_memory(outtable)) fitstable_endian_flip_row_data(outtable, buf); } if (write_row_data(outtable, buf, R)) { ERROR("Failed to write data to output table"); return -1; } } free(buf); return 0; }
int fitstable_write_one_column(fitstable_t* table, int colnum, int rowoffset, int nrows, const void* src, int src_stride) { anbool flip = TRUE; off_t foffset = 0; off_t start = 0; int i; char* buf = NULL; fitscol_t* col; int off; off = offset_of_column(table, colnum); if (!in_memory(table)) { foffset = ftello(table->fid); // jump to row start... start = get_row_offset(table, rowoffset) + off; if (fseeko(table->fid, start, SEEK_SET)) { SYSERROR("Failed to fseeko() to the start of the file."); return -1; } } col = getcol(table, colnum); if (col->fitstype != col->ctype) { int sz = col->fitssize * col->arraysize * nrows; buf = malloc(sz); fits_convert_data(buf, col->fitssize * col->arraysize, col->fitstype, src, src_stride, col->ctype, col->arraysize, nrows); src = buf; src_stride = col->fitssize * col->arraysize; } if (in_memory(table)) { for (i=0; i<nrows; i++) { memcpy(((char*)bl_access(table->rows, rowoffset + i)) + off, src, col->fitssize * col->arraysize); src = ((const char*)src) + src_stride; } } else { for (i=0; i<nrows; i++) { if (fseeko(table->fid, start + i * table->table->tab_w, SEEK_SET) || fits_write_data_array(table->fid, src, col->fitstype, col->arraysize, flip)) { SYSERROR("Failed to write row %i of column %i", rowoffset+i, colnum); return -1; } src = ((const char*)src) + src_stride; } } free(buf); if (!in_memory(table)) { if (fseeko(table->fid, foffset, SEEK_SET)) { SYSERROR("Failed to restore file offset."); return -1; } } return 0; }
int fitstable_switch_to_reading(fitstable_t* table) { assert(in_memory(table)); // store the current extension. fitstable_next_extension(table); // This resets all the meta-data about the table, meaning a reader // can then re-add columns it is interested in. fitstable_clear_table(table); table->extension = 1; return fitstable_open_extension(table, table->extension); }
int fitstable_write_header(fitstable_t* t) { if (!t->header) { if (fitstable_new_table(t)) { return -1; } } if (in_memory(t)) return 0; return fitsfile_write_header(t->fid, t->header, &t->table_offset, &t->end_table_offset, t->extension, t->fn); }
int fitstable_fix_header(fitstable_t* t) { // update NAXIS2 to reflect the number of rows written. fits_header_mod_int(t->header, "NAXIS2", t->table->nr, NULL); if (in_memory(t)) return 0; if (fitsfile_fix_header(t->fid, t->header, &t->table_offset, &t->end_table_offset, t->extension, t->fn)) { return -1; } return 0; //fits_pad_file(t->fid); }
int main() { std::stringstream in_memory(std::ios::binary); { // reading whole file into memory std::ifstream ifs("input.exe", std::ios::in | std::ios::binary); in_memory << ifs.rdbuf(); } // optionally write it out return 0; }
int fitstable_open_extension(fitstable_t* tab, int ext) { if (in_memory(tab)) { fitsext_t* theext; if (ext > bl_size(tab->extensions)) { ERROR("Table has only %zu extensions, but you requested #%i", bl_size(tab->extensions), ext); return -1; } theext = bl_access(tab->extensions, ext-1); tab->table = theext->table; tab->header = theext->header; tab->rows = theext->rows; tab->extension = ext; } else { if (tab->table) { qfits_table_close(tab->table); tab->table = NULL; } assert(tab->anq); if (ext >= anqfits_n_ext(tab->anq)) { ERROR("Requested FITS extension %i in file %s, but there are only %i extensions.\n", ext, tab->fn, anqfits_n_ext(tab->anq)); return -1; } tab->table = anqfits_get_table(tab->anq, ext); if (!tab->table) { ERROR("FITS extension %i in file %s is not a table (or there was an error opening the file)", ext, tab->fn); return -1; } if (tab->header) { qfits_header_destroy(tab->header); } tab->header = anqfits_get_header(tab->anq, ext); if (!tab->header) { ERROR("Couldn't get header for FITS extension %i in file %s", ext, tab->fn); return -1; } tab->extension = ext; } return 0; }
static int write_row_data(fitstable_t* table, void* data, int R) { assert(table); assert(data); if (in_memory(table)) { ensure_row_list_exists(table); bl_append(table->rows, data); // ? table->table->nr++; return 0; } if (R == 0) R = fitstable_row_size(table); if (fwrite(data, 1, R, table->fid) != R) { SYSERROR("Failed to write a row to %s", table->fn); return -1; } assert(table->table); table->table->nr++; return 0; }
int fitstable_read_nrows_data(fitstable_t* table, int row0, int nrows, void* dest) { int R; off_t off; assert(table); assert(row0 >= 0); assert((row0 + nrows) <= fitstable_nrows(table)); assert(dest); R = fitstable_row_size(table); if (in_memory(table)) { int i; char* cdest = dest; for (i=0; i<nrows; i++) memcpy(cdest, bl_access(table->rows, row0 + i), R); return 0; } if (!table->readfid) { table->readfid = fopen(table->fn, "rb"); if (!table->readfid) { SYSERROR("Failed to open FITS table %s for reading", table->fn); return -1; } assert(table->anq); off_t start; start = anqfits_data_start(table->anq, table->extension); table->end_table_offset = start; } off = get_row_offset(table, row0); if (fseeko(table->readfid, off, SEEK_SET)) { SYSERROR("Failed to fseeko() to read a row"); return -1; } if (fread(dest, 1, R*nrows, table->readfid) != (R*nrows)) { SYSERROR("Failed to read %i rows starting from %i, from %s", nrows, row0, table->fn); return -1; } return 0; }
void fitstable_next_extension(fitstable_t* tab) { if (is_writing(tab)) fits_pad_file(tab->fid); if (in_memory(tab)) { fitsext_t ext; if (!tab->table) return; // update NAXIS2 fitstable_fix_header(tab); ext.table = tab->table; ext.header = tab->header; ext.rows = tab->rows; bl_append(tab->extensions, &ext); tab->rows = NULL; } else { qfits_table_close(tab->table); qfits_header_destroy(tab->header); } tab->extension++; tab->table = NULL; tab->header = NULL; }
/** If "inds" is non-NULL, it's a list of indices to read. */ static void* read_array_into(const fitstable_t* tab, const char* colname, tfits_type ctype, anbool array_ok, int offset, const int* inds, int Nread, void* dest, int deststride, int desired_arraysize, int* p_arraysize) { int colnum; qfits_col* col; int fitssize; int csize; int fitstype; int arraysize; char* tempdata = NULL; char* cdata; char* fitsdata; int cstride; int fitsstride; int N; colnum = fits_find_column(tab->table, colname); if (colnum == -1) { ERROR("Column \"%s\" not found in FITS table %s", colname, tab->fn); return NULL; } col = tab->table->col + colnum; if (!array_ok && (col->atom_nb != 1)) { ERROR("Column \"%s\" in FITS table %s is an array of size %i, not a scalar", colname, tab->fn, col->atom_nb); return NULL; } arraysize = col->atom_nb; if (p_arraysize) *p_arraysize = arraysize; if (desired_arraysize && arraysize != desired_arraysize) { ERROR("Column \"%s\" has array size %i but you wanted %i", colname, arraysize, desired_arraysize); return NULL; } fitstype = col->atom_type; fitssize = fits_get_atom_size(fitstype); csize = fits_get_atom_size(ctype); N = tab->table->nr; if (Nread == -1) Nread = N; if (offset == -1) offset = 0; if (dest) cdata = dest; else cdata = calloc(Nread * arraysize, csize); if (dest && deststride > 0) cstride = deststride; else cstride = csize * arraysize; fitsstride = fitssize * arraysize; if (csize < fitssize) { // Need to allocate a bigger temp array and down-convert the data. // HACK - could set data=tempdata and realloc after (if 'dest' is NULL) tempdata = calloc(Nread * arraysize, fitssize); fitsdata = tempdata; } else { // We'll read the data into the first fraction of the output array. fitsdata = cdata; } if (in_memory(tab)) { int i; int off; int sz; if (!tab->rows) { ERROR("No data has been written to this fitstable"); return NULL; } if (offset + Nread > bl_size(tab->rows)) { ERROR("Number of data items requested exceeds number of rows: offset %i, n %i, nrows %zu", offset, Nread, bl_size(tab->rows)); return NULL; } off = fits_offset_of_column(tab->table, colnum); sz = fitsstride; if (inds) { for (i=0; i<Nread; i++) memcpy(fitsdata + i * fitsstride, ((char*)bl_access(tab->rows, inds[i])) + off, sz); } else { for (i=0; i<Nread; i++) memcpy(fitsdata + i * fitsstride, ((char*)bl_access(tab->rows, offset+i)) + off, sz); } } else { int res; if (inds) { res = qfits_query_column_seq_to_array_inds(tab->table, colnum, inds, Nread, (unsigned char*)fitsdata, fitsstride); } else { res = qfits_query_column_seq_to_array(tab->table, colnum, offset, Nread, (unsigned char*)fitsdata, fitsstride); } if (res) { ERROR("Failed to read column from FITS file"); // MEMLEAK! return NULL; } } if (fitstype != ctype) { if (csize <= fitssize) { // work forward fits_convert_data(cdata, cstride, ctype, fitsdata, fitsstride, fitstype, arraysize, Nread); } else { // work backward from the end of the array fits_convert_data(cdata + (((off_t)Nread*(off_t)arraysize)-1) * (off_t)csize, -csize, ctype, fitsdata + (((off_t)Nread*(off_t)arraysize)-1) * (off_t)fitssize, -fitssize, fitstype, 1, Nread * arraysize); } } free(tempdata); return cdata; }
// One of "struc" or "ap" should be non-null. static int write_one(fitstable_t* table, const void* struc, anbool flip, va_list* ap) { int i; char* buf = NULL; int Nbuf = 0; int ret = 0; int nc = ncols(table); char* thisrow = NULL; int rowoff = 0; if (in_memory(table)) { ensure_row_list_exists(table); thisrow = calloc(1, bl_datasize(table->rows)); } for (i=0; i<nc; i++) { fitscol_t* col; const char* columndata; col = getcol(table, i); if (col->in_struct) { if (struc) columndata = struc + col->coffset; else columndata = NULL; } else { if (struc) columndata = NULL; else columndata = va_arg(*ap, void *); } // If "columndata" is NULL, fits_write_data_array // skips the required number of bytes. // This allows both structs and normal columns to coexist // (in theory -- is this ever used?) // (yes, by blind.c when writing rdls and correspondence files // with tag-along data...) if (columndata && col->fitstype != col->ctype) { int sz = MAX(256, MAX(col->csize, col->fitssize) * col->arraysize); if (sz > Nbuf) { free(buf); buf = malloc(sz); } fits_convert_data(buf, col->fitssize, col->fitstype, columndata, col->csize, col->ctype, col->arraysize, 1); columndata = buf; } if (in_memory(table)) { int nb = fitscolumn_get_size(col); memcpy(thisrow + rowoff, columndata, nb); rowoff += nb; } else { ret = fits_write_data_array(table->fid, columndata, col->fitstype, col->arraysize, flip); if (ret) break; } } free(buf); if (in_memory(table)) bl_append(table->rows, thisrow); free(thisrow); table->table->nr++; return ret; }
int fitstable_read_structs(fitstable_t* tab, void* struc, int strucstride, int offset, int N) { int i; void* tempdata = NULL; int highwater = 0; //printf("fitstable_read_structs: stride %i, offset %i, N %i\n",strucstride, offset, N); for (i=0; i<ncols(tab); i++) { void* dest; int stride; void* finaldest; int finalstride; fitscol_t* col = getcol(tab, i); if (col->col == -1) continue; if (!col->in_struct) continue; finaldest = ((char*)struc) + col->coffset; finalstride = strucstride; if (col->fitstype != col->ctype) { int NB = fitscolumn_get_size(col) * N; if (NB > highwater) { free(tempdata); tempdata = malloc(NB); highwater = NB; } dest = tempdata; stride = fitscolumn_get_size(col); } else { dest = finaldest; stride = finalstride; } if (in_memory(tab)) { int j; int off = offset_of_column(tab, i); int sz; if (!tab->rows) { ERROR("No data has been written to this fitstable"); return -1; } if (offset + N > bl_size(tab->rows)) { ERROR("Number of data items requested exceeds number of rows: offset %i, n %i, nrows %zu", offset, N, bl_size(tab->rows)); return -1; } //logverb("column %i: dest offset %i, stride %i, row offset %i, input offset %i, size %i (%ix%i)\n", i, (int)(dest - struc), stride, offset, off, fitscolumn_get_size(col), col->fitssize, col->arraysize); sz = fitscolumn_get_size(col); for (j=0; j<N; j++) memcpy(((char*)dest) + j * stride, ((char*)bl_access(tab->rows, offset+j)) + off, sz); } else { // Read from FITS file... qfits_query_column_seq_to_array(tab->table, col->col, offset, N, dest, stride); } if (col->fitstype != col->ctype) { fits_convert_data(finaldest, finalstride, col->ctype, dest, stride, col->fitstype, col->arraysize, N); } } free(tempdata); if (tab->postprocess_read_structs) return tab->postprocess_read_structs(tab, struc, strucstride, offset, N); return 0; }
int fitstable_fix_primary_header(fitstable_t* t) { if (in_memory(t)) return 0; return fitsfile_fix_primary_header(t->fid, t->primheader, &t->end_header_offset, t->fn); }