aboutsummaryrefslogtreecommitdiff
path: root/vendor/cfitsio/drvrmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/cfitsio/drvrmem.c')
-rw-r--r--vendor/cfitsio/drvrmem.c1184
1 files changed, 1184 insertions, 0 deletions
diff --git a/vendor/cfitsio/drvrmem.c b/vendor/cfitsio/drvrmem.c
new file mode 100644
index 00000000..4ef23b70
--- /dev/null
+++ b/vendor/cfitsio/drvrmem.c
@@ -0,0 +1,1184 @@
+/* This file, drvrmem.c, contains driver routines for memory files. */
+
+/* The FITSIO software was written by William Pence at the High Energy */
+/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */
+/* Goddard Space Flight Center. */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h> /* apparently needed to define size_t */
+#include "fitsio2.h"
+
+/* prototype for .Z file uncompression function in zuncompress.c */
+int zuncompress2mem(char *filename,
+ FILE *diskfile,
+ char **buffptr,
+ size_t *buffsize,
+ void *(*mem_realloc)(void *p, size_t newsize),
+ size_t *filesize,
+ int *status);
+
+#define RECBUFLEN 1000
+
+static char stdin_outfile[FLEN_FILENAME];
+
+typedef struct /* structure containing mem file structure */
+{
+ char **memaddrptr; /* Pointer to memory address pointer; */
+ /* This may or may not point to memaddr. */
+ char *memaddr; /* Pointer to starting memory address; may */
+ /* not always be used, so use *memaddrptr instead */
+ size_t *memsizeptr; /* Pointer to the size of the memory allocation. */
+ /* This may or may not point to memsize. */
+ size_t memsize; /* Size of the memory allocation; this may not */
+ /* always be used, so use *memsizeptr instead. */
+ size_t deltasize; /* Suggested increment for reallocating memory */
+ void *(*mem_realloc)(void *p, size_t newsize); /* realloc function */
+ LONGLONG currentpos; /* current file position, relative to start */
+ LONGLONG fitsfilesize; /* size of the FITS file (always <= *memsizeptr) */
+ FILE *fileptr; /* pointer to compressed output disk file */
+} memdriver;
+
+static memdriver memTable[NMAXFILES]; /* allocate mem file handle tables */
+
+/*--------------------------------------------------------------------------*/
+int mem_init(void)
+{
+ int ii;
+
+ for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */
+ {
+ memTable[ii].memaddrptr = 0;
+ memTable[ii].memaddr = 0;
+ }
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_setoptions(int options)
+{
+ /* do something with the options argument, to stop compiler warning */
+ options = 0;
+ return(options);
+}
+/*--------------------------------------------------------------------------*/
+int mem_getoptions(int *options)
+{
+ *options = 0;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_getversion(int *version)
+{
+ *version = 10;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_shutdown(void)
+{
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_create(char *filename, int *handle)
+/*
+ Create a new empty memory file for subsequent writes.
+ The file name is ignored in this case.
+*/
+{
+ int status;
+
+ /* initially allocate 1 FITS block = 2880 bytes */
+ status = mem_createmem(2880L, handle);
+
+ if (status)
+ {
+ ffpmsg("failed to create empty memory file (mem_create)");
+ return(status);
+ }
+
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_create_comp(char *filename, int *handle)
+/*
+ Create a new empty memory file for subsequent writes.
+ Also create an empty compressed .gz file. The memory file
+ will be compressed and written to the disk file when the file is closed.
+*/
+{
+ FILE *diskfile;
+ char mode[4];
+ int status;
+
+ /* first, create disk file for the compressed output */
+
+
+ if ( !strcmp(filename, "-.gz") || !strcmp(filename, "stdout.gz") ||
+ !strcmp(filename, "STDOUT.gz") )
+ {
+ /* special case: create uncompressed FITS file in memory, then
+ compress it an write it out to 'stdout' when it is closed. */
+
+ diskfile = stdout;
+ }
+ else
+ {
+ /* normal case: create disk file for the compressed output */
+
+ strcpy(mode, "w+b"); /* create file with read-write */
+
+ diskfile = fopen(filename, "r"); /* does file already exist? */
+
+ if (diskfile)
+ {
+ fclose(diskfile); /* close file and exit with error */
+ return(FILE_NOT_CREATED);
+ }
+
+#if MACHINE == ALPHAVMS || MACHINE == VAXVMS
+ /* specify VMS record structure: fixed format, 2880 byte records */
+ /* but force stream mode access to enable random I/O access */
+ diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm");
+#else
+ diskfile = fopen(filename, mode);
+#endif
+
+ if (!(diskfile)) /* couldn't create file */
+ {
+ return(FILE_NOT_CREATED);
+ }
+ }
+
+ /* now create temporary memory file */
+
+ /* initially allocate 1 FITS block = 2880 bytes */
+ status = mem_createmem(2880L, handle);
+
+ if (status)
+ {
+ ffpmsg("failed to create empty memory file (mem_create_comp)");
+ return(status);
+ }
+
+ memTable[*handle].fileptr = diskfile;
+
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_openmem(void **buffptr, /* I - address of memory pointer */
+ size_t *buffsize, /* I - size of buffer, in bytes */
+ size_t deltasize, /* I - increment for future realloc's */
+ void *(*memrealloc)(void *p, size_t newsize), /* function */
+ int *handle)
+/*
+ lowest level routine to open a pre-existing memory file.
+*/
+{
+ int ii;
+
+ *handle = -1;
+ for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in handle table */
+ {
+ if (memTable[ii].memaddrptr == 0)
+ {
+ *handle = ii;
+ break;
+ }
+ }
+ if (*handle == -1)
+ return(TOO_MANY_FILES); /* too many files opened */
+
+ memTable[ii].memaddrptr = (char **) buffptr; /* pointer to start addres */
+ memTable[ii].memsizeptr = buffsize; /* allocated size of memory */
+ memTable[ii].deltasize = deltasize; /* suggested realloc increment */
+ memTable[ii].fitsfilesize = *buffsize; /* size of FITS file (upper limit) */
+ memTable[ii].currentpos = 0; /* at beginning of the file */
+ memTable[ii].mem_realloc = memrealloc; /* memory realloc function */
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_createmem(size_t msize, int *handle)
+/*
+ lowest level routine to allocate a memory file.
+*/
+{
+ int ii;
+
+ *handle = -1;
+ for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in handle table */
+ {
+ if (memTable[ii].memaddrptr == 0)
+ {
+ *handle = ii;
+ break;
+ }
+ }
+ if (*handle == -1)
+ return(TOO_MANY_FILES); /* too many files opened */
+
+ /* use the internally allocated memaddr and memsize variables */
+ memTable[ii].memaddrptr = &memTable[ii].memaddr;
+ memTable[ii].memsizeptr = &memTable[ii].memsize;
+
+ /* allocate initial block of memory for the file */
+ if (msize > 0)
+ {
+ memTable[ii].memaddr = (char *) malloc(msize);
+ if ( !(memTable[ii].memaddr) )
+ {
+ ffpmsg("malloc of initial memory failed (mem_createmem)");
+ return(FILE_NOT_OPENED);
+ }
+ }
+
+ /* set initial state of the file */
+ memTable[ii].memsize = msize;
+ memTable[ii].deltasize = 2880;
+ memTable[ii].fitsfilesize = 0;
+ memTable[ii].currentpos = 0;
+ memTable[ii].mem_realloc = realloc;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_truncate(int handle, LONGLONG filesize)
+/*
+ truncate the file to a new size
+*/
+{
+ char *ptr;
+
+ /* call the memory reallocation function, if defined */
+ if ( memTable[handle].mem_realloc )
+ { /* explicit LONGLONG->size_t cast */
+ ptr = (memTable[handle].mem_realloc)(
+ *(memTable[handle].memaddrptr),
+ (size_t) filesize);
+ if (!ptr)
+ {
+ ffpmsg("Failed to reallocate memory (mem_truncate)");
+ return(MEMORY_ALLOCATION);
+ }
+
+ /* if allocated more memory, initialize it to zero */
+ if ( filesize > *(memTable[handle].memsizeptr) )
+ {
+ memset(ptr + *(memTable[handle].memsizeptr),
+ 0,
+ ((size_t) filesize) - *(memTable[handle].memsizeptr) );
+ }
+
+ *(memTable[handle].memaddrptr) = ptr;
+ *(memTable[handle].memsizeptr) = (size_t) (filesize);
+ }
+
+ memTable[handle].currentpos = filesize;
+ memTable[handle].fitsfilesize = filesize;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int stdin_checkfile(char *urltype, char *infile, char *outfile)
+/*
+ do any special case checking when opening a file on the stdin stream
+*/
+{
+ if (strlen(outfile))
+ {
+ stdin_outfile[0] = '\0';
+ strncat(stdin_outfile,outfile,FLEN_FILENAME-1); /* an output file is specified */
+ strcpy(urltype,"stdinfile://");
+ }
+ else
+ *stdin_outfile = '\0'; /* no output file was specified */
+
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int stdin_open(char *filename, int rwmode, int *handle)
+/*
+ open a FITS file from the stdin file stream by copying it into memory
+ The file name is ignored in this case.
+*/
+{
+ int status;
+ char cbuff;
+
+ if (*stdin_outfile)
+ {
+ /* copy the stdin stream to the specified disk file then open the file */
+
+ /* Create the output file */
+ status = file_create(stdin_outfile,handle);
+
+ if (status)
+ {
+ ffpmsg("Unable to create output file to copy stdin (stdin_open):");
+ ffpmsg(stdin_outfile);
+ return(status);
+ }
+
+ /* copy the whole stdin stream to the file */
+ status = stdin2file(*handle);
+ file_close(*handle);
+
+ if (status)
+ {
+ ffpmsg("failed to copy stdin to file (stdin_open)");
+ ffpmsg(stdin_outfile);
+ return(status);
+ }
+
+ /* reopen file with proper rwmode attribute */
+ status = file_open(stdin_outfile, rwmode, handle);
+ }
+ else
+ {
+
+ /* get the first character, then put it back */
+ cbuff = fgetc(stdin);
+ ungetc(cbuff, stdin);
+
+ /* compressed files begin with 037 or 'P' */
+ if (cbuff == 31 || cbuff == 75)
+ {
+ /* looks like the input stream is compressed */
+ status = mem_compress_stdin_open(filename, rwmode, handle);
+
+ }
+ else
+ {
+ /* copy the stdin stream into memory then open file in memory */
+
+ if (rwmode != READONLY)
+ {
+ ffpmsg("cannot open stdin with WRITE access");
+ return(READONLY_FILE);
+ }
+
+ status = mem_createmem(2880L, handle);
+
+ if (status)
+ {
+ ffpmsg("failed to create empty memory file (stdin_open)");
+ return(status);
+ }
+
+ /* copy the whole stdin stream into memory */
+ status = stdin2mem(*handle);
+
+ if (status)
+ {
+ ffpmsg("failed to copy stdin into memory (stdin_open)");
+ free(memTable[*handle].memaddr);
+ }
+ }
+ }
+
+ return(status);
+}
+/*--------------------------------------------------------------------------*/
+int stdin2mem(int hd) /* handle number */
+/*
+ Copy the stdin stream into memory. Fill whatever amount of memory
+ has already been allocated, then realloc more memory if necessary.
+*/
+{
+ size_t nread, memsize, delta;
+ LONGLONG filesize;
+ char *memptr;
+ char simple[] = "SIMPLE";
+ int c, ii, jj;
+
+ memptr = *memTable[hd].memaddrptr;
+ memsize = *memTable[hd].memsizeptr;
+ delta = memTable[hd].deltasize;
+
+ filesize = 0;
+ ii = 0;
+
+ for(jj = 0; (c = fgetc(stdin)) != EOF && jj < 2000; jj++)
+ {
+ /* Skip over any garbage at the beginning of the stdin stream by */
+ /* reading 1 char at a time, looking for 'S', 'I', 'M', 'P', 'L', 'E' */
+ /* Give up if not found in the first 2000 characters */
+
+ if (c == simple[ii])
+ {
+ ii++;
+ if (ii == 6) /* found the complete string? */
+ {
+ memcpy(memptr, simple, 6); /* copy "SIMPLE" to buffer */
+ filesize = 6;
+ break;
+ }
+ }
+ else
+ ii = 0; /* reset search to beginning of the string */
+ }
+
+ if (filesize == 0)
+ {
+ ffpmsg("Couldn't find the string 'SIMPLE' in the stdin stream.");
+ ffpmsg("This does not look like a FITS file.");
+ return(FILE_NOT_OPENED);
+ }
+
+ /* fill up the remainder of the initial memory allocation */
+ nread = fread(memptr + 6, 1, memsize - 6, stdin);
+ nread += 6; /* add in the 6 characters in 'SIMPLE' */
+
+ if (nread < memsize) /* reached the end? */
+ {
+ memTable[hd].fitsfilesize = nread;
+ return(0);
+ }
+
+ filesize = nread;
+
+ while (1)
+ {
+ /* allocate memory for another FITS block */
+ memptr = realloc(memptr, memsize + delta);
+
+ if (!memptr)
+ {
+ ffpmsg("realloc failed while copying stdin (stdin2mem)");
+ return(MEMORY_ALLOCATION);
+ }
+ memsize += delta;
+
+ /* read another FITS block */
+ nread = fread(memptr + filesize, 1, delta, stdin);
+
+ filesize += nread;
+
+ if (nread < delta) /* reached the end? */
+ break;
+ }
+
+ memTable[hd].fitsfilesize = filesize;
+ *memTable[hd].memaddrptr = memptr;
+ *memTable[hd].memsizeptr = memsize;
+
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int stdin2file(int handle) /* handle number */
+/*
+ Copy the stdin stream to a file. .
+*/
+{
+ size_t nread;
+ char simple[] = "SIMPLE";
+ int c, ii, jj, status;
+ char recbuf[RECBUFLEN];
+
+ ii = 0;
+ for(jj = 0; (c = fgetc(stdin)) != EOF && jj < 2000; jj++)
+ {
+ /* Skip over any garbage at the beginning of the stdin stream by */
+ /* reading 1 char at a time, looking for 'S', 'I', 'M', 'P', 'L', 'E' */
+ /* Give up if not found in the first 2000 characters */
+
+ if (c == simple[ii])
+ {
+ ii++;
+ if (ii == 6) /* found the complete string? */
+ {
+ memcpy(recbuf, simple, 6); /* copy "SIMPLE" to buffer */
+ break;
+ }
+ }
+ else
+ ii = 0; /* reset search to beginning of the string */
+ }
+
+ if (ii != 6)
+ {
+ ffpmsg("Couldn't find the string 'SIMPLE' in the stdin stream");
+ return(FILE_NOT_OPENED);
+ }
+
+ /* fill up the remainder of the buffer */
+ nread = fread(recbuf + 6, 1, RECBUFLEN - 6, stdin);
+ nread += 6; /* add in the 6 characters in 'SIMPLE' */
+
+ status = file_write(handle, recbuf, nread);
+ if (status)
+ return(status);
+
+ /* copy the rest of stdin stream */
+ while(0 != (nread = fread(recbuf,1,RECBUFLEN, stdin)))
+ {
+ status = file_write(handle, recbuf, nread);
+ if (status)
+ return(status);
+ }
+
+ return(status);
+}
+/*--------------------------------------------------------------------------*/
+int stdout_close(int handle)
+/*
+ copy the memory file to stdout, then free the memory
+*/
+{
+ int status = 0;
+
+ /* copy from memory to standard out. explicit LONGLONG->size_t cast */
+ if(fwrite(memTable[handle].memaddr, 1,
+ ((size_t) memTable[handle].fitsfilesize), stdout) !=
+ (size_t) memTable[handle].fitsfilesize )
+ {
+ ffpmsg("failed to copy memory file to stdout (stdout_close)");
+ status = WRITE_ERROR;
+ }
+
+ free( memTable[handle].memaddr ); /* free the memory */
+ memTable[handle].memaddrptr = 0;
+ memTable[handle].memaddr = 0;
+ return(status);
+}
+/*--------------------------------------------------------------------------*/
+int mem_compress_openrw(char *filename, int rwmode, int *hdl)
+/*
+ This routine opens the compressed diskfile and creates an empty memory
+ buffer with an appropriate size, then calls mem_uncompress2mem. It allows
+ the memory 'file' to be opened with READWRITE access.
+*/
+{
+ return(mem_compress_open(filename, READONLY, hdl));
+}
+/*--------------------------------------------------------------------------*/
+int mem_compress_open(char *filename, int rwmode, int *hdl)
+/*
+ This routine opens the compressed diskfile and creates an empty memory
+ buffer with an appropriate size, then calls mem_uncompress2mem.
+*/
+{
+ FILE *diskfile;
+ int status, estimated = 1;
+ unsigned char buffer[4];
+ size_t finalsize;
+ char *ptr;
+
+ if (rwmode != READONLY)
+ {
+ ffpmsg(
+ "cannot open compressed file with WRITE access (mem_compress_open)");
+ ffpmsg(filename);
+ return(READONLY_FILE);
+ }
+
+ /* open the compressed disk file */
+ status = file_openfile(filename, READONLY, &diskfile);
+ if (status)
+ {
+ ffpmsg("failed to open compressed disk file (compress_open)");
+ ffpmsg(filename);
+ return(status);
+ }
+
+ if (fread(buffer, 1, 2, diskfile) != 2) /* read 2 bytes */
+ {
+ fclose(diskfile);
+ return(READ_ERROR);
+ }
+
+ if (memcmp(buffer, "\037\213", 2) == 0) /* GZIP */
+ {
+ /* the uncompressed file size is give at the end of the file */
+
+ fseek(diskfile, 0, 2); /* move to end of file */
+ fseek(diskfile, -4L, 1); /* move back 4 bytes */
+ fread(buffer, 1, 4L, diskfile); /* read 4 bytes */
+
+ /* have to worry about integer byte order */
+ finalsize = buffer[0];
+ finalsize |= buffer[1] << 8;
+ finalsize |= buffer[2] << 16;
+ finalsize |= buffer[3] << 24;
+
+ estimated = 0; /* file size is known, not estimated */
+ }
+ else if (memcmp(buffer, "\120\113", 2) == 0) /* PKZIP */
+ {
+ /* the uncompressed file size is give at byte 22 the file */
+
+ fseek(diskfile, 22L, 0); /* move to byte 22 */
+ fread(buffer, 1, 4L, diskfile); /* read 4 bytes */
+
+ /* have to worry about integer byte order */
+ finalsize = buffer[0];
+ finalsize |= buffer[1] << 8;
+ finalsize |= buffer[2] << 16;
+ finalsize |= buffer[3] << 24;
+
+ estimated = 0; /* file size is known, not estimated */
+ }
+ else if (memcmp(buffer, "\037\036", 2) == 0) /* PACK */
+ finalsize = 0; /* for most methods we can't determine final size */
+ else if (memcmp(buffer, "\037\235", 2) == 0) /* LZW */
+ finalsize = 0; /* for most methods we can't determine final size */
+ else if (memcmp(buffer, "\037\240", 2) == 0) /* LZH */
+ finalsize = 0; /* for most methods we can't determine final size */
+ else
+ {
+ /* not a compressed file; this should never happen */
+ fclose(diskfile);
+ return(1);
+ }
+
+ if (finalsize == 0) /* estimate uncompressed file size */
+ {
+ fseek(diskfile, 0, 2); /* move to end of the compressed file */
+ finalsize = ftell(diskfile); /* position = size of file */
+ finalsize = finalsize * 3; /* assume factor of 3 compression */
+ }
+
+ fseek(diskfile, 0, 0); /* move back to beginning of file */
+
+ /* create a memory file big enough (hopefully) for the uncompressed file */
+ status = mem_createmem(finalsize, hdl);
+
+ if (status && estimated)
+ {
+ /* memory allocation failed, so try a smaller estimated size */
+ finalsize = finalsize / 3;
+ status = mem_createmem(finalsize, hdl);
+ }
+
+ if (status)
+ {
+ fclose(diskfile);
+ ffpmsg("failed to create empty memory file (compress_open)");
+ return(status);
+ }
+
+ /* uncompress file into memory */
+ status = mem_uncompress2mem(filename, diskfile, *hdl);
+
+ fclose(diskfile);
+
+ if (status)
+ {
+ mem_close_free(*hdl); /* free up the memory */
+ ffpmsg("failed to uncompress file into memory (compress_open)");
+ return(status);
+ }
+
+ /* if we allocated too much memory initially, then free it */
+ if (*(memTable[*hdl].memsizeptr) >
+ (( (size_t) memTable[*hdl].fitsfilesize) + 256L) )
+ {
+ ptr = realloc(*(memTable[*hdl].memaddrptr),
+ ((size_t) memTable[*hdl].fitsfilesize) );
+ if (!ptr)
+ {
+ ffpmsg("Failed to reduce size of allocated memory (compress_open)");
+ return(MEMORY_ALLOCATION);
+ }
+
+ *(memTable[*hdl].memaddrptr) = ptr;
+ *(memTable[*hdl].memsizeptr) = (size_t) (memTable[*hdl].fitsfilesize);
+ }
+
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_compress_stdin_open(char *filename, int rwmode, int *hdl)
+/*
+ This routine reads the compressed input stream and creates an empty memory
+ buffer, then calls mem_uncompress2mem.
+*/
+{
+ int status;
+ char *ptr;
+
+ if (rwmode != READONLY)
+ {
+ ffpmsg(
+ "cannot open compressed input stream with WRITE access (mem_compress_stdin_open)");
+ return(READONLY_FILE);
+ }
+
+ /* create a memory file for the uncompressed file */
+ status = mem_createmem(28800, hdl);
+
+ if (status)
+ {
+ ffpmsg("failed to create empty memory file (compress_stdin_open)");
+ return(status);
+ }
+
+ /* uncompress file into memory */
+ status = mem_uncompress2mem(filename, stdin, *hdl);
+
+ if (status)
+ {
+ mem_close_free(*hdl); /* free up the memory */
+ ffpmsg("failed to uncompress stdin into memory (compress_stdin_open)");
+ return(status);
+ }
+
+ /* if we allocated too much memory initially, then free it */
+ if (*(memTable[*hdl].memsizeptr) >
+ (( (size_t) memTable[*hdl].fitsfilesize) + 256L) )
+ {
+ ptr = realloc(*(memTable[*hdl].memaddrptr),
+ ((size_t) memTable[*hdl].fitsfilesize) );
+ if (!ptr)
+ {
+ ffpmsg("Failed to reduce size of allocated memory (compress_stdin_open)");
+ return(MEMORY_ALLOCATION);
+ }
+
+ *(memTable[*hdl].memaddrptr) = ptr;
+ *(memTable[*hdl].memsizeptr) = (size_t) (memTable[*hdl].fitsfilesize);
+ }
+
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_iraf_open(char *filename, int rwmode, int *hdl)
+/*
+ This routine creates an empty memory buffer, then calls iraf2mem to
+ open the IRAF disk file and convert it to a FITS file in memeory.
+*/
+{
+ int status;
+ size_t filesize = 0;
+
+ /* create a memory file with size = 0 for the FITS converted IRAF file */
+ status = mem_createmem(filesize, hdl);
+ if (status)
+ {
+ ffpmsg("failed to create empty memory file (mem_iraf_open)");
+ return(status);
+ }
+
+ /* convert the iraf file into a FITS file in memory */
+ status = iraf2mem(filename, memTable[*hdl].memaddrptr,
+ memTable[*hdl].memsizeptr, &filesize, &status);
+
+ if (status)
+ {
+ mem_close_free(*hdl); /* free up the memory */
+ ffpmsg("failed to convert IRAF file into memory (mem_iraf_open)");
+ return(status);
+ }
+
+ memTable[*hdl].currentpos = 0; /* save starting position */
+ memTable[*hdl].fitsfilesize=filesize; /* and initial file size */
+
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_rawfile_open(char *filename, int rwmode, int *hdl)
+/*
+ This routine creates an empty memory buffer, writes a minimal
+ image header, then copies the image data from the raw file into
+ memory. It will byteswap the pixel values if the raw array
+ is in little endian byte order.
+*/
+{
+ FILE *diskfile;
+ fitsfile *fptr;
+ short *sptr;
+ int status, endian, datatype, bytePerPix, naxis;
+ long dim[5] = {1,1,1,1,1}, ii, nvals, offset = 0;
+ size_t filesize = 0, datasize;
+ char rootfile[FLEN_FILENAME], *cptr = 0, *cptr2 = 0;
+ void *ptr;
+
+ if (rwmode != READONLY)
+ {
+ ffpmsg(
+ "cannot open raw binary file with WRITE access (mem_rawfile_open)");
+ ffpmsg(filename);
+ return(READONLY_FILE);
+ }
+
+ cptr = strchr(filename, '['); /* search for opening bracket [ */
+
+ if (!cptr)
+ {
+ ffpmsg("binary file name missing '[' character (mem_rawfile_open)");
+ ffpmsg(filename);
+ return(URL_PARSE_ERROR);
+ }
+
+ *rootfile = '\0';
+ strncat(rootfile, filename, cptr - filename); /* store the rootname */
+
+ cptr++;
+
+ while (*cptr == ' ')
+ cptr++; /* skip leading blanks */
+
+ /* Get the Data Type of the Image */
+
+ if (*cptr == 'b' || *cptr == 'B')
+ {
+ datatype = BYTE_IMG;
+ bytePerPix = 1;
+ }
+ else if (*cptr == 'i' || *cptr == 'I')
+ {
+ datatype = SHORT_IMG;
+ bytePerPix = 2;
+ }
+ else if (*cptr == 'u' || *cptr == 'U')
+ {
+ datatype = USHORT_IMG;
+ bytePerPix = 2;
+
+ }
+ else if (*cptr == 'j' || *cptr == 'J')
+ {
+ datatype = LONG_IMG;
+ bytePerPix = 4;
+ }
+ else if (*cptr == 'r' || *cptr == 'R' || *cptr == 'f' || *cptr == 'F')
+ {
+ datatype = FLOAT_IMG;
+ bytePerPix = 4;
+ }
+ else if (*cptr == 'd' || *cptr == 'D')
+ {
+ datatype = DOUBLE_IMG;
+ bytePerPix = 8;
+ }
+ else
+ {
+ ffpmsg("error in raw binary file datatype (mem_rawfile_open)");
+ ffpmsg(filename);
+ return(URL_PARSE_ERROR);
+ }
+
+ cptr++;
+
+ /* get Endian: Big or Little; default is same as the local machine */
+
+ if (*cptr == 'b' || *cptr == 'B')
+ {
+ endian = 0;
+ cptr++;
+ }
+ else if (*cptr == 'l' || *cptr == 'L')
+ {
+ endian = 1;
+ cptr++;
+ }
+ else
+ endian = BYTESWAPPED; /* byteswapped machines are little endian */
+
+ /* read each dimension (up to 5) */
+
+ naxis = 1;
+ dim[0] = strtol(cptr, &cptr2, 10);
+
+ if (cptr2 && *cptr2 == ',')
+ {
+ naxis = 2;
+ dim[1] = strtol(cptr2+1, &cptr, 10);
+
+ if (cptr && *cptr == ',')
+ {
+ naxis = 3;
+ dim[2] = strtol(cptr+1, &cptr2, 10);
+
+ if (cptr2 && *cptr2 == ',')
+ {
+ naxis = 4;
+ dim[3] = strtol(cptr2+1, &cptr, 10);
+
+ if (cptr && *cptr == ',')
+ naxis = 5;
+ dim[4] = strtol(cptr+1, &cptr2, 10);
+ }
+ }
+ }
+
+ cptr = maxvalue(cptr, cptr2);
+
+ if (*cptr == ':') /* read starting offset value */
+ offset = strtol(cptr+1, 0, 10);
+
+ nvals = dim[0] * dim[1] * dim[2] * dim[3] * dim[4];
+ datasize = nvals * bytePerPix;
+ filesize = nvals * bytePerPix + 2880;
+ filesize = ((filesize - 1) / 2880 + 1) * 2880;
+
+ /* open the raw binary disk file */
+ status = file_openfile(rootfile, READONLY, &diskfile);
+ if (status)
+ {
+ ffpmsg("failed to open raw binary file (mem_rawfile_open)");
+ ffpmsg(rootfile);
+ return(status);
+ }
+
+ /* create a memory file with corrct size for the FITS converted raw file */
+ status = mem_createmem(filesize, hdl);
+ if (status)
+ {
+ ffpmsg("failed to create memory file (mem_rawfile_open)");
+ fclose(diskfile);
+ return(status);
+ }
+
+ /* open this piece of memory as a new FITS file */
+ ffimem(&fptr, (void **) memTable[*hdl].memaddrptr, &filesize, 0, 0, &status);
+
+ /* write the required header keywords */
+ ffcrim(fptr, datatype, naxis, dim, &status);
+
+ /* close the FITS file, but keep the memory allocated */
+ ffclos(fptr, &status);
+
+ if (status > 0)
+ {
+ ffpmsg("failed to write basic image header (mem_rawfile_open)");
+ fclose(diskfile);
+ mem_close_free(*hdl); /* free up the memory */
+ return(status);
+ }
+
+ if (offset > 0)
+ fseek(diskfile, offset, 0); /* offset to start of the data */
+
+ /* read the raw data into memory */
+ ptr = *memTable[*hdl].memaddrptr + 2880;
+
+ if (fread((char *) ptr, 1, datasize, diskfile) != datasize)
+ status = READ_ERROR;
+
+ fclose(diskfile); /* close the raw binary disk file */
+
+ if (status)
+ {
+ mem_close_free(*hdl); /* free up the memory */
+ ffpmsg("failed to copy raw file data into memory (mem_rawfile_open)");
+ return(status);
+ }
+
+ if (datatype == USHORT_IMG) /* have to subtract 32768 from each unsigned */
+ { /* value to conform to FITS convention. More */
+ /* efficient way to do this is to just flip */
+ /* the most significant bit. */
+
+ sptr = (short *) ptr;
+
+ if (endian == BYTESWAPPED) /* working with native format */
+ {
+ for (ii = 0; ii < nvals; ii++, sptr++)
+ {
+ *sptr = ( *sptr ) ^ 0x8000;
+ }
+ }
+ else /* pixels are byteswapped WRT the native format */
+ {
+ for (ii = 0; ii < nvals; ii++, sptr++)
+ {
+ *sptr = ( *sptr ) ^ 0x80;
+ }
+ }
+ }
+
+ if (endian) /* swap the bytes if array is in little endian byte order */
+ {
+ if (datatype == SHORT_IMG || datatype == USHORT_IMG)
+ {
+ ffswap2( (short *) ptr, nvals);
+ }
+ else if (datatype == LONG_IMG || datatype == FLOAT_IMG)
+ {
+ ffswap4( (INT32BIT *) ptr, nvals);
+ }
+
+ else if (datatype == DOUBLE_IMG)
+ {
+ ffswap8( (double *) ptr, nvals);
+ }
+ }
+
+ memTable[*hdl].currentpos = 0; /* save starting position */
+ memTable[*hdl].fitsfilesize=filesize; /* and initial file size */
+
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_uncompress2mem(char *filename, FILE *diskfile, int hdl)
+{
+/*
+ lower level routine to uncompress a file into memory. The file
+ has already been opened and the memory buffer has been allocated.
+*/
+
+ size_t finalsize;
+ int status;
+ /* uncompress file into memory */
+ status = 0;
+
+ if (strstr(filename, ".Z")) {
+ zuncompress2mem(filename, diskfile,
+ memTable[hdl].memaddrptr, /* pointer to memory address */
+ memTable[hdl].memsizeptr, /* pointer to size of memory */
+ realloc, /* reallocation function */
+ &finalsize, &status); /* returned file size nd status*/
+ } else {
+ uncompress2mem(filename, diskfile,
+ memTable[hdl].memaddrptr, /* pointer to memory address */
+ memTable[hdl].memsizeptr, /* pointer to size of memory */
+ realloc, /* reallocation function */
+ &finalsize, &status); /* returned file size nd status*/
+ }
+
+ memTable[hdl].currentpos = 0; /* save starting position */
+ memTable[hdl].fitsfilesize=finalsize; /* and initial file size */
+ return status;
+}
+/*--------------------------------------------------------------------------*/
+int mem_size(int handle, LONGLONG *filesize)
+/*
+ return the size of the file; only called when the file is first opened
+*/
+{
+ *filesize = memTable[handle].fitsfilesize;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_close_free(int handle)
+/*
+ close the file and free the memory.
+*/
+{
+ free( *(memTable[handle].memaddrptr) );
+
+ memTable[handle].memaddrptr = 0;
+ memTable[handle].memaddr = 0;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_close_keep(int handle)
+/*
+ close the memory file but do not free the memory.
+*/
+{
+ memTable[handle].memaddrptr = 0;
+ memTable[handle].memaddr = 0;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_close_comp(int handle)
+/*
+ compress the memory file, writing it out to the fileptr (which might
+ be stdout)
+*/
+{
+ int status = 0;
+ size_t compsize;
+
+ /* compress file in memory to a .gz disk file */
+
+ if(compress2file_from_mem(memTable[handle].memaddr,
+ (size_t) (memTable[handle].fitsfilesize),
+ memTable[handle].fileptr,
+ &compsize, &status ) )
+ {
+ ffpmsg("failed to copy memory file to file (mem_close_comp)");
+ status = WRITE_ERROR;
+ }
+
+ free( memTable[handle].memaddr ); /* free the memory */
+ memTable[handle].memaddrptr = 0;
+ memTable[handle].memaddr = 0;
+
+ /* close the compressed disk file (except if it is 'stdout' */
+ if (memTable[handle].fileptr != stdout)
+ fclose(memTable[handle].fileptr);
+
+ return(status);
+}
+/*--------------------------------------------------------------------------*/
+int mem_seek(int handle, LONGLONG offset)
+/*
+ seek to position relative to start of the file.
+*/
+{
+ if (offset > memTable[handle].fitsfilesize )
+ return(END_OF_FILE);
+
+ memTable[handle].currentpos = offset;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_read(int hdl, void *buffer, long nbytes)
+/*
+ read bytes from the current position in the file
+*/
+{
+ if (memTable[hdl].currentpos + nbytes > memTable[hdl].fitsfilesize)
+ return(END_OF_FILE);
+
+ memcpy(buffer,
+ *(memTable[hdl].memaddrptr) + memTable[hdl].currentpos,
+ nbytes);
+
+ memTable[hdl].currentpos += nbytes;
+ return(0);
+}
+/*--------------------------------------------------------------------------*/
+int mem_write(int hdl, void *buffer, long nbytes)
+/*
+ write bytes at the current position in the file
+*/
+{
+ size_t newsize;
+ char *ptr;
+
+ if ((size_t) (memTable[hdl].currentpos + nbytes) >
+ *(memTable[hdl].memsizeptr) )
+ {
+
+ if (!(memTable[hdl].mem_realloc))
+ {
+ ffpmsg("realloc function not defined (mem_write)");
+ return(WRITE_ERROR);
+ }
+
+ /*
+ Attempt to reallocate additional memory:
+ the memory buffer size is incremented by the larger of:
+ 1 FITS block (2880 bytes) or
+ the defined 'deltasize' parameter
+ */
+
+ newsize = maxvalue( (size_t)
+ (((memTable[hdl].currentpos + nbytes - 1) / 2880) + 1) * 2880,
+ *(memTable[hdl].memsizeptr) + memTable[hdl].deltasize);
+
+ /* call the realloc function */
+ ptr = (memTable[hdl].mem_realloc)(
+ *(memTable[hdl].memaddrptr),
+ newsize);
+ if (!ptr)
+ {
+ ffpmsg("Failed to reallocate memory (mem_write)");
+ return(MEMORY_ALLOCATION);
+ }
+
+ *(memTable[hdl].memaddrptr) = ptr;
+ *(memTable[hdl].memsizeptr) = newsize;
+ }
+
+ /* now copy the bytes from the buffer into memory */
+ memcpy( *(memTable[hdl].memaddrptr) + memTable[hdl].currentpos,
+ buffer,
+ nbytes);
+
+ memTable[hdl].currentpos += nbytes;
+ memTable[hdl].fitsfilesize =
+ maxvalue(memTable[hdl].fitsfilesize,
+ memTable[hdl].currentpos);
+ return(0);
+}