/* @(#)tbacol.c 17.1.1.1 (ESO-DMD) 01/25/02 17:47:09 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. Correspondence concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME tbacol.c .LANGUAGE C .AUTHOR IPG-ESO Garching .CATEGORY table applications: Column operations .COMMENTS The soubroutines of this module are tools manipulating columns. .VERSION 1.0 25-Mar-1989 Definition J.D. Ponz .VERSION 3.0 05-Jul-1990 New version with column arrays F.O. .VERSION 3.1 10-Jun-1991: Copy Column use partial mapping when possible .VERSION 3.2 27-Jul-1992: correct bug when the reference column is character 010613 last modif ------------------------------------------------------------*/ #include #include #include #include /* General-purpose macros */ #include #define MAXCHAR 4096 /* Max available for conversion */ static int itype, otype; /* Column datatypes */ static int iitems, oitems; /* Column sizes */ static int ibytes, obytes; /* Column sizes */ static int check_status; /* Set by check routine */ /* We use here pointers to functions */ typedef int (*FUNCTION)(); int TCERDC(), TCARDD(), TCARDI(), TCARDR(); int TCEWRC(), TCAWRD(), TCAWRI(), TCAWRR(); static FUNCTION read_functions[] = {TCERDC, TCARDI, TCARDR, TCARDD }; static FUNCTION write_functions[] = {TCEWRC, TCAWRI, TCAWRR, TCAWRD }; static int datatype(dtype) /*++++++++++++++++++ .PURPOSE Convert datatype into an index for functions .RETURNS 0 = char ; 1 = int ; 2 = R*4 ; 3 = R*8 ------------------*/ int dtype; /* IN: Datatype to convert */ { switch (dtype) { case D_R8_FORMAT: return (3); case D_R4_FORMAT: return (2); case D_C_FORMAT: return (0); default : return (1); } } static int check(in, icol, out, ocol) /*++++++++++++++++++ .PURPOSE Check compatibility of Columns .RETURNS 0 : Compatible; >0 : can be column mapped; -1 : Error (check_status) ------------------*/ int in; /* IN: Input Table */ int icol; /* IN: Column in */ int out; /* IN: Output Table */ int ocol; /* IN: Column out */ { int alen, dummy, isto, osto; char form[1+TBL_FORLEN]; if (check_status = TCBGET (in, icol, &itype, &iitems, &ibytes)) return(-1); if (check_status = TCBGET (out,ocol, &otype, &oitems, &obytes)) return(-1); if (check_status = TCDGET (in, &isto)) return(-1); if (check_status = TCDGET (out,&osto)) return(-1); if ((itype == otype) && (iitems == oitems) && (isto == F_TRANS)) return (ibytes); if (itype == D_C_FORMAT) { if (iitems > MAXCHAR) { SCTPUT ("**** Input column too long"); check_status = ERR_TBLCOL; return (-1); } return (0); } if (otype == D_C_FORMAT) { /* Check large enough... */ TCFGET (in, icol, form, &alen, &dummy); if (alen >= obytes) { SCTPUT("**** Output column too small"); check_status = ERR_TBLCOL; return (-1); } else return (0); } /* if ( (iitems > 1) || (oitems > 1)) { SCTPUT("**** Copy Array Columns not available"); check_status = ERR_TBLIMP; return (-1); } */ return(0); } static int mod_rows(tid, rows) /*++++++++++++++++++ .PURPOSE Modify the number of rows (in connection with MAP facilities) .RETURNS Status ------------------*/ int tid; /* IN: The table concerned */ int rows; /* IN: Number of Rows */ { int ncol, nrow, narow, dummy; int status; if (status = TCIGET (tid, &ncol, &nrow, &dummy, &dummy, &narow)) return(status); nrow = MAX (nrow, rows); nrow = MIN (nrow, narow); status = TCIPUT (tid, ncol, nrow); return (status); } /*========================================================================= * Public Routines *=========================================================================*/ tbl_appcol(in, icol, out, ocol, type, nrow, nout) /*++++++++++++++++++ .PURPOSE Copy the selected values of an input column to an output column. \begin{TeX} When the same table is used for input and output, values are placed in the same row, i.e. values of {\em ocol} are replaced by the calues of {\em icol} for selected rows. When two different tables are used, the {\em icol} values of the selected rows of the {\em in} table are used to replace the values of {\em ocol} values for {\em consecutive} rows of the {\em out} table, starting at {\em row number } nout. \end{TeX} .RETURNS Status ------------------*/ int in /* IN : input table id */; int icol /* IN : input column */; int out /* IN : output table id */; int ocol /* IN : output column */; int type /* IN : column type (UNUSED) */; int nrow /* IN : total number of rows in input table */; int *nout /* MOD: starting row on input / last copied row on output */; { int irow; /* input row */ int orow; /* output row */ int *prow, status, nobytes,bytes,items,k,smbytes; int null, dummy, sel,*ival; char *ip,cval[256]; float *rval; double value[MAXCHAR/sizeof(double)],*dval; char form[TBL_FORLEN+1]; char *osmmget(); int is, id, *smapped, ms, md, mms, mmd ; char *dmapped; FUNCTION eread, ewrite; /* Check Compatibility of columns */ bytes = check (in, icol, out, ocol); /*if not compatible: */ if (bytes < 0) return (check_status); /* If a single table is used (i.e. in == out), the same row id always used. */ prow = (in == out ? &irow : &orow); orow = *nout; TCFGET(in, icol, form, &dummy, &dummy); /* read colum format */ /* reads binary storage characteristics of column*/ TCBGET(in,icol,&dummy,&items,&nobytes); if (toupper(form[0]) == 'T') /* Time Function. Convert */ TCFGET(out, ocol, form, &dummy, &dummy); if (toupper(form[0]) == 'T') status = 0; /* Force character */ else status = datatype(itype); eread = read_functions[status]; ewrite = write_functions[status]; status = ERR_NORMAL; /*columns are compatible:*/ if (bytes > 0 ) { smapped = (int *)0; dmapped = (char *)0; is = id = 0; switch (type) { case D_I1_FORMAT: ival = (int *) osmmget(sizeof(int)); break; case D_I2_FORMAT: ival = (int *) osmmget(sizeof(int)); break; case D_I4_FORMAT: ival = (int *) osmmget(items * sizeof(int)); break; case D_R4_FORMAT: rval = (float *)osmmget(items * sizeof(float)); break; case D_R8_FORMAT: dval = (double *)osmmget(items * sizeof(double)); break; } for (irow=1; (status == ERR_NORMAL) && (irow <= nrow); irow++, is--, id--, smapped ++, dmapped += nobytes) { if (is <= 0) { if (smapped) { while (ms-- > 0) smapped --; TCEUNM (in, (char *)smapped); } status = TCCPAM(in, 0, irow, 0, &is, &smapped); ms = is; mms = 0; if (status != ERR_NORMAL) continue; } if (id <= 0) { if (dmapped) { while (md-- >0) dmapped -= nobytes; TCEUNM (in,dmapped); } status = TCCPAM(in, icol, irow, 0, &id, &dmapped); md = id; mmd = 0; if (status != ERR_NORMAL) continue; } if (!( *smapped)) continue; orow += 1; mms++; mmd++; switch (type) { case D_I1_FORMAT: for (k=0; k 255)) TCADEL(out,*prow,ocol,k+1,1); else TCAWRI(out,*prow,ocol,k+1,1,ival); } break; case D_I2_FORMAT: for (k=0; k 0xffff)) TCADEL(out,*prow,ocol,k+1,1); else TCAWRI(out,*prow,ocol,k+1,1,ival); } break; case D_I4_FORMAT: for (k=0; k 0) smapped --; TCEUNM (in, (char *)smapped); while (mmd-- >0) dmapped -= nobytes; TCEUNM (in, dmapped); mod_rows (out, orow); *nout = orow; return (status); } /* This part only executed if bytes == 0 */ status = ERR_NORMAL; /*MP 220291 */ for (irow = 1; (status == ERR_NORMAL) && (irow <= nrow); irow++) { if (status = TCSGET (in, irow, &sel)) continue; if (!sel) continue; orow += 1; if (status = (*eread)(in, irow, icol, 1, 1,value, &null)) continue; status = (*ewrite)(out, *prow, ocol,1,1, value); } mod_rows (out, orow); *nout = orow; return (status); } tbl_copycol(in, icol, out, ocol, type, nrow, nout) /*++++++++++++++++++ .PURPOSE Copy the selected values of an input column to an output column. \begin{TeX} Routine similar to {\em tbl\_appcol}, but the replacement always starts from the {\em first} row ot the output table. \end{TeX} .RETURNS Status ------------------*/ int in /* IN : input table id */; int icol /* IN : input column */; int out /* IN : output table id */; int ocol /* IN : output column */; int type /* IN : column type (UNUSED) */; int nrow /* IN : total number of rows in input table */; int *nout /* OUT: actual numberof rows copied */; { *nout = 0; return ( tbl_appcol(in, icol, out, ocol, type, nrow, nout)); } tbl_copyref(in,icol,iref,out,ocol,oref,type, nrow, nout) /*++++++++++++++++++ .PURPOSE Copy Column from one table to another by reference; NULL values are not copied. .RETURNS Status ------------------*/ int in /* IN : input table id */; int icol /* IN : input column */; int iref /* IN : input reference column */; int out /* IN : output table id */; int ocol /* IN : output column */; int oref /* IN : output reference column */; int type /* IN : column type (UNUSED) */; int nrow /* IN : total number of rows in input table */; int *nout /* OUT: actual number of rows copied */; { int irow, orow, j, status, bytes; int null, sel, rtype, rbytes, dummy,nelem; char *ip, *op; double rval, value[MAXCHAR/sizeof(double)], sval; FUNCTION sread, eread, ewrite; *nout = 0; /* Check Compatibility */ bytes = check (in, icol, out, ocol); if (bytes < 0) return (check_status); status = ERR_NORMAL; /*MP 110491*/ /* What's Selection ? */ TCBGET (in, iref, &rtype, &nelem, &rbytes); if (nelem > 1 && rtype != D_C_FORMAT) { SCTPUT ("**** Bad reference Column..."); return (ERR_TBLCOL); } switch (rtype) { case D_R4_FORMAT: case D_R8_FORMAT: sread = TCERDD; break; case D_C_FORMAT: sread = TCERDC; break; default: sread = TCERDI; break; } for (irow=1; (status == ERR_NORMAL) && (irow <= nrow); irow++) { if (status = (*sread)(in, irow, iref, &sval, &null)) continue; if (null) continue; TCSGET (in, irow, &sel); if (!sel) continue; if (sread == TCERDI) status = TCESRI(out, oref, *(int *)&sval, 0, 1, &orow); else if (sread == TCERDD) status = TCESRD(out, oref, sval, 0.0e0, 1, &orow); else status = TCESRC(out, oref, (char *)&sval, 1, rbytes, 1, &orow); if (status) continue; if (orow <= 0) continue; *nout += 1; if (bytes) { /* Straight Copy. Use TCEMAP */ if (status = TCEMAP (in, irow, icol, &ip, &null)) continue; if (status = TCEMAP (out,orow, ocol, &op, &null)) continue; oscopy (op, ip, bytes); TCEUNM(in,ip); TCEUNM(out,op); } else { if (status = TCERDD(in, irow, icol, value, &null)) continue; if (null) status = TCEDEL (out, orow, ocol); else status = TCEWRD(out, orow, ocol, value); } } return (status); }