/* @(#)tcr.c 17.1.1.1 (ES0-DMD) 01/25/02 17:36:45 */ /*=========================================================================== 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 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding 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 tcr.c .LANGUAGE C .AUTHOR IPG-ESO Garching .CATEGORY table interface (old table system) .COMMENTS \begin{TeX} This module contains the routines to handle table rows. Access to elements is done by column and row numbers. Elements in the table can be integer, float, double precision and character string data types, as defined during the creation of the columns. Implicit conversion of the element value is done automatically if the input/output is done with a routine not corresponding to the data type. The functions provided by this module are: \begin{itemize} \item Delete several elements in a row (TCRDEL), \item Read several row elements from the table (TCRRDx), \item Write several row elements into the table (TCRWRx). \end{itemize} Main arguments used by the routines are: \begin{description} \item[column] sequential column number. Integer array defining the set of columns to be considered. \item[null] null flag. It is an array with a value TRUE if the corresponding element is undefined, FALSE otherwise. \item[row] sequential row number. It is an integer defining the row number in the table or the symbols LAST, FIRST, NEXT and PREVIOUS defined in the system file 'midas\_def.h' in the directory 'MID\_INCLUDE'. The sequence number is the physical sequence number (by default) or the sequence corresponding to the index of the reference column. \item[tid] table identifier. It is an integer number provided by the system when the table is created or opened. \item[value] row values. The type depends on the routine name. Implicit conversion is done if this type does not correspond to the column data type. \end{description} \end{TeX} .VERSION 1.0 25-Mar-1987 Implementation J.D. Ponz .VERSION 1.1 21-Oct-1987 Modification of the calling sequence .VERSION 1.2 11-Apr-1988 Modification of the calling sequence .VERSION 1.3 11-Jan-1989 Include record file organization .VERSION 1.4 16-Oct-1989 indexing (ifirst-1) .VERSION 3.0 01-Jul-1990 New Version with Arrays / Elementary IO Added Routine TCRSEL .VERSION 3.1 27-Sep-1990 Added TCRMAP TCRUMP .VERSION 3.2 18-Dec-1990: Take into account the number of selected rows. .VERSION 3.3 02-May-1991 read null values as 0 in order to be compatible with old application code MP 30-Oct-1991 correct bug in TCRRDC (oscopy...)MP feb1992 modif of TCRRDC for DANET MP 20-mAr-1992 correct bug in TCRRDC 07-Oct-1992 Correct again a bug in TCRRDC ------------------------------------------------------------*/ #include /* ANSI-C Prototyping */ #include /* Table System parameters */ #include /* Symbols used for Tables */ #include /* List of Table Errors */ #include /* Character classification */ #include /* Classical macros */ #include /* System Library */ static int zero = 0; static char col_sep = ' '; /* Column separator for ASCII */ #define CheckOverflow(tp,row) (row <= tp->arows ? ERR_NORMAL : \ TBL_ALLOROW(tid, row + row/5)) /*=================================================================== * Private Routines *===================================================================*/ #ifdef __STDC__ static int strloc(char *str, char c) #else static int strloc(str, c) /*+++++++ .PURPOSE Locate the first occurence of character `c' .RETURNS Index of `c' in str; length of str if `c' not found. ---------*/ char *str; /* IN: string to scan */ char c; /* IN: char to locate */ #endif { register char *p; for (p=str; *p && (*p != c); p++) ; return(p-str); } #ifdef __STDC__ static int check_cols(TABLE *tp, int nc, int *column) #else static int check_cols(tp, nc, column) /*+++++++ .PURPOSE Check if row / colums are OK .RETURNS Status ---------*/ TABLE *tp /* IN : table ptr */; int nc /* IN : number of cols. */; int column[] /* IN : column numbers */; #endif { int status, i, icol; for (i = 0, status = ERR_NORMAL; (status == ERR_NORMAL) && (i < nc); i++) { icol = column[i]; if ((icol<=0) || (icol>tp->cols)) status = TBL_errf(ERR_TBLCOL, "bad column number #array[%d]=%d, table: %s", i+1, icol, tp->phname); } return(status); } /*======================================================================= * Public Routines *=======================================================================*/ TCRDEL(tid, row) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Deletes all element in the row. .ALGORITHM uses TCEDEL. .RETURNS Status -------------------------------------------------------------*/ int tid /* IN : table id */; int row /* IN : row number */; { TABLE *tp; int status; int i; /* checks arguments */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckRow(tp, row)) return(TBL_errs(tid, status, row)); /* Loop on TCEDEL (Delete Element) */ for (i = 1; (status == ERR_NORMAL) && (i <= tp->cols); i++) status = TCEDEL(tid, row, i); /* Delete the Selection Column */ return (status); } TCRRDC(tid, row, nc, column, value, null) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads table row as a character string. .ALGORITHM Access each single row element with implicit type conversion. .RETURNS status -------------------------------------------------------------*/ int tid /* IN : table id */; int row /* IN : row number */; int nc /* IN : number of cols. */; int column[] /* IN : column numbers */; char value[] /* OUT: actual value */; int null[] /* OUT: null flag */; { TABLE *tp; int status, items, mylen; int ic, icol, icol1, nbytes, dtype, i, j, k, len, dummy, len0; char *p, *x, form[10], form0[10], ws[4]; /* checks arguments */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (row < 1) return(TBL_errs(tid, ERR_TBLROW, row)); mylen = strlen(value); for (i = 0; itp->cols)) { status = ERR_TBLCOL; TBL_errf(status, "bad column number #array[%d]=%d, table: %s", i+1, icol, tp->phname); continue; } if (! (*ColumnFormat(tp, icol))) status = TCFGET (tid, icol, form, &dummy, &dummy); } if (status) return(status); /* Execute Edition for types */ p = value; for (i = 0; (status == ERR_NORMAL) && (i < nc); p += len, i++) { *(p++) = col_sep; icol = column[i]; if (icol == 0) { len = len0; dummy = row; TBL_ed (p, form0, (TBL_D_I4<bytes[icol1]; dtype = tp->dtypes[icol1]; items = TBL_Items(dtype); if ((dtype & (~TBL_D_MASK)) == 0) { GetLabel(tp,icol,39,3,ws); ws[3] = '\0'; items = atoi(ws); if (items == 0) items = 1; nbytes = nbytes/items; } len = tp->abytes[icol1]; if (dtype & (~TBL_D_MASK)) len = (len+1)*items - 1; ic = TBL_offset(tp, row, icol); if (row > tp->rows) { null[i] = 1; oscfill (p, len, ' '); continue; } if_not(x = TBL_RD (tp, ic, nbytes)) { status = TBL_RDst(); continue; } null[i] = TBL_isNULL(dtype, (int *)x); /* oscfill (p, len, ' '); if (dtype & (~TBL_D_MASK)) p[len-1] = '*'; continue; } */ if ((dtype & (~TBL_D_MASK)) == 0) { /* Byte String. Copy */ for (j=1; j<=items; j++) { if (len <= nbytes) oscopy(p, x, len); else oscopy(p, x, nbytes); if (items > 1 && j != items) { x += nbytes; k = 0; /*while (k++ < MIN(len,nbytes) && *p) p++;*/ TBL_s1(p,len); p += MIN(len,nbytes); (*p++) = ','; } else TBL_s1(p,len); } continue; } /* Convert bin -> ascii */ TBL_ed (p, tp->format + icol1*(1+TBL_FORLEN), dtype, x); } *p = '\0'; return (status); } TCRRDD(tid, row, nc, column, value, null) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads table row as a double precision array. .ALGORITHM Access each single row element with implicit type conversion. .RETURNS status -------------------------------------------------------------*/ int tid /* IN : table id */; int row /* IN : row number */; int nc /* IN : number of cols. */; int column[] /* IN : column numbers */; double value[] /* OUT: actual value */; int null[] /* OUT: null flag */; { TABLE *tp; int status; int ic, icol, icol1, nbytes, dtype, i; char *x; /* checks arguments */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (row < 1) return(TBL_errs(tid, ERR_TBLROW, row)); if (status = check_cols(tp, nc, column)) return(status); /* Execute Edition for types */ for (i = 0; (status == ERR_NORMAL) && (i < nc); i++) { icol = column[i]; icol1 = icol - 1; nbytes= tp->bytes[icol1]; if (row > tp->rows) { null[i] = 1; /* TBL_toNULL ((TBL_D_R8<dtypes[icol1]; if_not (x = TBL_RD (tp, ic, nbytes)) { status = TBL_RDst(); continue;} if (null[i] = TBL_isNULL(dtype, (int *)x)) { /* TBL_toNULL ((TBL_D_R8<bytes[icol1]; if (row > tp->rows) { null[i] = 1; /* TBL_toNULL ((TBL_D_I4<dtypes[icol1]; ic = TBL_offset(tp, row, icol); if_not(x = TBL_RD (tp, ic, nbytes)) { status = TBL_RDst(); continue; } if (null[i] = TBL_isNULL(dtype, (int *)x)) { /* TBL_toNULL ((TBL_D_I4<bytes[icol1]; if (row > tp->rows) { null[i] = 1; /* TBL_toNULL ((TBL_D_R4<dtypes[icol1]; if_not(x = TBL_RD (tp, ic, nbytes)) { status = TBL_RDst(); continue; } if (null[i] = TBL_isNULL(dtype, (int *)x)) { /* TBL_toNULL ((TBL_D_R4< tp->arows)) status = TBL_errf(ERR_TBLROW, "bad row selection @%s outside range [1..%d], table: %s", pa, tp->arows, tp->phname); */ if (b) { p += ib; ic -= ib; *p = b; if ((p[0] = '.') && (p[1] == '.')) { p += 2; ic -= 2; i = atoi(p); if (i == 0) i = tp->rows; upper_bounds[j] = i; /* if ((i < 1) || (i > tp->arows)) status = TBL_errf(ERR_TBLROW, "bad row selection @%s outside range [1..%d], table: %s", pa, tp->arows, tp->phname); */ if (i < lower_bounds[j]) upper_bounds[j] = lower_bounds[j], lower_bounds[j] = i; } else status = TBL_errf(ERR_TBLROW, "bad punctuation in @%s, table: %s", pa, tp->phname); } p += ic; *p = c; if (c) p++; } *found_ranges = j; return (status); } TCRWRC(tid, row, nc, column, value) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes table row .ALGORITHM Access each row element with implicit type conversion. .RETURNS status -------------------------------------------------------------*/ int tid /* IN : table id */; int row /* IN : row number */; int nc /* IN : number of cols. */; int column[] /* IN : column numbers */; char value[] /* IN : values to write */; { TABLE *tp; int status; int ic, icol, icol1, nbytes, dtype, i, len, dummy; char *p, *x, form[10]; /* checks arguments */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (row < 1) return(TBL_errs(tid, ERR_TBLROW, row)); /* Don't use local check, col#0 valid */ for (i = 0; (status == ERR_NORMAL) && (i < nc); i++) { icol = column[i]; if ((icol<=0) || (icol>tp->cols)) status = TBL_errf(ERR_TBLCOL, "bad column number #array[%d]=%d, table: %s", i+1, icol, tp->phname); if (! (*ColumnFormat(tp, icol))) status = TCFGET (tid, icol, form, &dummy, &dummy); } if (status) return(status); /* check if row overflow */ if (status = CheckOverflow(tp,row)) return(status); tp = TBL_ptr(tid); if (row > tp->rows) tp->selected = row, tp->rows = row; /* read value with intrinsic type */ p = value; for (i = 0; (status == ERR_NORMAL) && (i < nc); i++) { icol = column[i]; status = TCFGET (tid, icol, form, &dummy, &dummy); icol1 = icol - 1; nbytes= tp->bytes[icol1]; len = tp->abytes[icol1]; dtype = tp->dtypes[icol1]; ic = TBL_offset(tp, row, icol); if_not( x = TBL_RDF (tp, ic, nbytes, 1)) { status = TBL_RDst(); continue; } dummy = p[len]; p[len] = '\0'; status = TBL_cv(p, form, dtype, x); p += len; *p = dummy; } return (status); } TCRWRD(tid, row, nc, column, value) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes table row from a double precision array. .ALGORITHM Access each row element with implicit type conversion. .RETURNS status -------------------------------------------------------------*/ int tid /* IN : table id */; int row /* IN : row number */; int nc /* IN : number of cols. */; int column[] /* IN : column numbers */; double value[] /* IN : array with values */; { TABLE *tp; int status; int ic, icol, icol1, nbytes, dtype, i; char *x; char form[9], edited[32]; /* checks arguments */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (row < 1) return(TBL_errs(tid, ERR_TBLROW, row)); if (status = check_cols(tp, nc, column)) return(status); /* check if row overflow */ if (status = CheckOverflow(tp,row)) return(status); tp = TBL_ptr(tid); /* Might be changed by overflow */ if (row > tp->rows) tp->selected = row, tp->rows = row; /* read value with intrinsic type */ for (i = 0; (status == ERR_NORMAL) && (i < nc); i++) { icol = column[i]; icol1 = icol - 1; nbytes= tp->bytes[icol1]; dtype = tp->dtypes[icol1]; ic = TBL_offset(tp, row, icol); if_not(x = TBL_RDF (tp, ic, nbytes, 1)) { status = TBL_RDst(); continue; } switch (TBL_ElementType(dtype)) { case TBL_D_A1: /* character string */ form[0] = '%'; if (nbytes < 7) form[1] = 'f', form[2] = '\0'; else sprintf(form+1, "%d.%de", MIN(22,nbytes), MIN(15, nbytes-7)); sprintf(edited, form, value[i]); status = TCEWRC (tid, row, icol, edited); break; case TBL_D_I1: *x = NINT(value[i]); break; case TBL_D_A2: *(unsigned short *)x = NINT(value[i]); break; case TBL_D_I2: *(short *)x = NINT(value[i]); break; case TBL_D_A4: case TBL_D_I4: *(int *)x = NINT(value[i]); break; case TBL_D_R8: *(double *)x = value[i]; break; case TBL_D_R4: *(float *)x = value[i]; break; } } return (status); } TCRWRI(tid, row, nc, column, value) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes table row from an integer array of values. .ALGORITHM Access each row element with implicit type conversion. .RETURNS status -------------------------------------------------------------*/ int tid /* IN : table id */; int row /* IN : row number */; int nc /* IN : number of cols. */; int column[] /* IN : column numbers */; int value[] /* IN : data array */; { TABLE *tp; int status; int ic, icol, icol1, nbytes, dtype, i; char *x; char edited[16]; /* checks arguments */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (row < 1) return(TBL_errs(tid, ERR_TBLROW, row)); if (status = check_cols(tp, nc, column)) return(status); /* check if row overflow */ if (status = CheckOverflow(tp,row)) return(status); tp = TBL_ptr(tid); /* Might be changed by overflow */ if (row > tp->rows) tp->selected = row, tp->rows = row; /* read value with intrinsic type */ for (i = 0; (status == ERR_NORMAL) && (i < nc); i++) { icol = column[i]; icol1 = icol - 1; nbytes= tp->bytes[icol1]; dtype = tp->dtypes[icol1]; ic = TBL_offset(tp, row, icol); if_not( x = TBL_RDF (tp, ic, nbytes, 1)) { status = TBL_RDst(); continue; } switch (TBL_ElementType(dtype)) { case TBL_D_A1: /* character string */ sprintf(edited, "%d", value[i]); status = TCEWRC (tid, row, icol, edited); break; case TBL_D_I1: *x = value[i]; break; case TBL_D_A2: *(unsigned short *)x = value[i];break; case TBL_D_I2: *(short *)x = value[i]; break; case TBL_D_A4: case TBL_D_I4: *(int *)x = value[i]; break; case TBL_D_R8: *(double *)x = value[i]; break; case TBL_D_R4: *(float *)x = value[i]; break; } } return (status); } TCRWRR(tid, row, nc, column, value) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes table row from a floating point data array. .ALGORITHM Access each row element with implicit type conversion. .RETURNS status -------------------------------------------------------------*/ int tid /* IN : table id */; int row /* IN : row number */; int nc /* IN : number of cols. */; int column[] /* IN : column numbers */; float value[] /* IN : data array */; { TABLE *tp; int status; int ic, icol, icol1, nbytes, dtype, i; char *x; char form[9], edited[32]; /* checks arguments */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (row < 1) return(TBL_errs(tid, ERR_TBLROW, row)); if (status = check_cols(tp, nc, column)) return(status); /* check if row overflow */ if (status = CheckOverflow(tp,row)) return(status); tp = TBL_ptr(tid); /* Might be changed by overflow */ if (row > tp->rows) tp->selected = row, tp->rows = row; /* read value with intrinsic type */ for (i = 0; (status == ERR_NORMAL) && (i < nc); i++) { icol = column[i]; icol1 = icol - 1; nbytes= tp->bytes[icol1]; dtype = tp->dtypes[icol1]; ic = TBL_offset(tp, row, icol); if_not (x = TBL_RDF (tp, ic, nbytes, 1)) { status = TBL_RDst(); continue; } switch (TBL_ElementType(dtype)) { case TBL_D_A1: /* character string */ form[0] = '%'; if (nbytes < 7) form[1] = 'f', form[2] = '\0'; else sprintf(form+1, "%d.%de", MIN(22,nbytes), MIN(15, nbytes-7)); sprintf(edited, form, value[i]); status = TCEWRC (tid, row, icol, edited); break; case TBL_D_I1: *x = NINT(value[i]); break; case TBL_D_A2: *(unsigned short *)x = NINT(value[i]); break; case TBL_D_I2: *(short *)x = NINT(value[i]); break; case TBL_D_A4: *(unsigned int *)x = NINT(value[i]); break; case TBL_D_I4: *(int *)x = NINT(value[i]); break; case TBL_D_R8: *(double *)x = value[i]; break; case TBL_D_R4: *(float *)x = value[i]; break; } } return (status); }