1 /*
2 *class++
3 *  Name:
4 *     Table
5 
6 *  Purpose:
7 *     A 2-dimensional table of values.
8 
9 *  Constructor Function:
10 c     astTable
11 f     AST_TABLE
12 
13 *  Description:
14 *     The Table class is a type of KeyMap that represents a two-dimensional
15 *     table of values. The
16 c     astMapGet... and astMapPut...
17 f     AST_MAPGET... and AST_MAPPUT...
18 *     methods provided by the KeyMap class should be used for storing and
19 *     retrieving values from individual cells within a Table. Each entry
20 *     in the KeyMap represents a single cell of the table and has an
21 *     associated key of the form "<COL>(i)" where "<COL>" is the
22 *     upper-case name of a table column and "i" is the row index (the
23 *     first row is row 1). Keys of this form should always be used when
24 *     using KeyMap methods to access entries within a Table.
25 *
26 *     Columns must be declared using the
27 c     astAddColumn
28 f     AST_ADDCOLUMN
29 *     method before values can be stored within them. This also fixes the
30 *     type and shape of the values that may be stored in any cell of the
31 *     column. Cells may contain scalar or vector values of any data type
32 *     supported by the KeyMap class. Multi-dimensional arrays may also be
33 *     stored, but these must be vectorised when storing and retrieving
34 *     them within a table cell. All cells within a single column must
35 *     have the same type and shape, as specified when the column is added
36 *     to the Table.
37 *
38 *     Tables may have parameters that describe global properties of the
39 *     entire table. These are stored as entries in the parent KeyMap and
40 *     can be access using the get and set method of the KeyMap class.
41 *     However, parameters must be declared using the
42 c     astAddParameter
43 f     AST_ADDPARAMETER
44 *     method before being accessed.
45 *
46 *     Note - since accessing entries within a KeyMap is a relatively slow
47 *     process, it is not recommended to use the Table class to store
48 *     very large tables.
49 
50 *  Inheritance:
51 *     The Table class inherits from the KeyMap class.
52 
53 *  Attributes:
54 *     In addition to those attributes common to all KeyMaps, every
55 *     Table also has the following attributes:
56 *
57 *     - ColumnLenC(column): The largest string length of any value in a column
58 *     - ColumnLength(column): The number of elements in each value in a column
59 *     - ColumnNdim(column): The number of axes spanned by each value in a column
60 *     - ColumnType(column): The data type of each value in a column
61 *     - ColumnUnit(column): The unit string describing each value in a column
62 *     - Ncolumn: The number of columns currently in the Table
63 *     - Nrow: The number of rows currently in the Table
64 *     - Nparameter: The number of global parameters currently in the Table
65 
66 *  Functions:
67 c     In addition to those functions applicable to all KeyMaps, the
68 c     following functions may also be applied to all Tables:
69 f     In addition to those routines applicable to all KeyMaps, the
70 f     following routines may also be applied to all Tables:
71 *
72 c     - astAddColumn: Add a new column definition to a Table
73 c     - astAddParameter: Add a new global parameter definition to a Table
74 c     - astColumnName: Return the name of the column with a given index
75 c     - astColumnShape: Return the shape of the values in a named column
76 c     - astHasColumn: Checks if a column exists in a Table
77 c     - astHasParameter: Checks if a global parameter exists in a Table
78 c     - astParameterName: Return the name of the parameter with a given index
79 c     - astPurgeRows: Remove all empty rows from a Table
80 c     - astRemoveColumn: Remove a column from a Table
81 c     - astRemoveParameter: Remove a global parameter from a Table
82 c     - astRemoveRow: Remove a row from a Table
83 f     - AST_ADDCOLUMN: Add a new column definition to a Table
84 f     - AST_ADDPARAMETER: Add a new global parameter definition to a Table
85 f     - AST_COLUMNNAME: Return the name of the column with a given index
86 f     - AST_COLUMNSHAPE: Return the shape of the values in a named column
87 f     - AST_HASCOLUMN: Checks if a column exists in a Table
88 f     - AST_HASPARAMETER: Checks if a global parameter exists in a Table
89 f     - AST_PARAMETERNAME: Return the name of the parameter with a given index
90 f     - AST_PURGEROWS: Remove all empty rows from a Table
91 f     - AST_REMOVECOLUMN: Remove a column from a Table
92 f     - AST_REMOVEPARAMETER: Remove a global parameter from a Table
93 f     - AST_REMOVEROW: Remove a row from a Table
94 
95 *  Copyright:
96 *     Copyright (C) 2010-2011 Science & Technology Facilities Council.
97 *     All Rights Reserved.
98 
99 *  Licence:
100 *     This program is free software: you can redistribute it and/or
101 *     modify it under the terms of the GNU Lesser General Public
102 *     License as published by the Free Software Foundation, either
103 *     version 3 of the License, or (at your option) any later
104 *     version.
105 *
106 *     This program is distributed in the hope that it will be useful,
107 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
108 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
109 *     GNU Lesser General Public License for more details.
110 *
111 *     You should have received a copy of the GNU Lesser General
112 *     License along with this program.  If not, see
113 *     <http://www.gnu.org/licenses/>.
114 
115 *  Authors:
116 *     DSB: David S. Berry (Starlink)
117 
118 *  History:
119 *     22-NOV-2010 (DSB):
120 *        Original version.
121 *     13-MAY-2011 (DSB):
122 *        Added support for table parameters.
123 *     16-NOV-2013 (DSB):
124 *        Fix bug in forming keys in GetColumnLenC.
125 *class--
126 */
127 
128 /* Module Macros. */
129 /* ============== */
130 /* Set the name of the class we are implementing. This indicates to
131    the header files that define class interfaces that they should make
132    "protected" symbols available. */
133 #define astCLASS Table
134 
135 /* Fixed KeyMap entry names */
136 #define LENGTH "Length"
137 #define NAME "Name"
138 #define NROW "Nrow"
139 #define SHAPE "Shape"
140 #define SIZE "Size"
141 #define TYPE "Type"
142 #define UNIT "Unit"
143 
144 /* A function macro that puts quotes around a value */
145 #define STRING(w) #w
146 
147 /* Include files. */
148 /* ============== */
149 /* Interface definitions. */
150 /* ---------------------- */
151 
152 #include "globals.h"             /* Thread-safe global data access */
153 #include "error.h"               /* Error reporting facilities */
154 #include "memory.h"              /* Memory allocation facilities */
155 #include "object.h"              /* Base Object class */
156 #include "keymap.h"              /* Coordinate keymaps (parent class) */
157 #include "channel.h"             /* I/O channels */
158 #include "table.h"               /* Interface definition for this class */
159 
160 
161 /* Error code definitions. */
162 /* ----------------------- */
163 #include "ast_err.h"             /* AST error codes */
164 
165 /* C header files. */
166 /* --------------- */
167 #include <ctype.h>
168 #include <stdarg.h>
169 #include <stddef.h>
170 #include <stdio.h>
171 #include <string.h>
172 
173 
174 /* Module Variables. */
175 /* ================= */
176 
177 /* Address of this static variable is used as a unique identifier for
178    member of this class. */
179 static int class_check;
180 
181 /* Pointers to parent class methods which are extended by this class. */
182 static const char *(* parent_getattrib)( AstObject *, const char *, int * );
183 static void (* parent_setkeycase)( AstKeyMap *, int, int * );
184 static void (* parent_clearkeycase)( AstKeyMap *, int * );
185 static int (* parent_equal)( AstObject *, AstObject *, int * );
186 static int (* parent_getobjsize)( AstObject *, int * );
187 static int (* parent_mapget0a)( AstKeyMap *, const char *, AstObject * *, int *);
188 static int (* parent_mapget0c)( AstKeyMap *, const char *, const char **, int *);
189 static int (* parent_mapget0d)( AstKeyMap *, const char *, double *, int *);
190 static int (* parent_mapget0f)( AstKeyMap *, const char *, float *, int *);
191 static int (* parent_mapget0i)( AstKeyMap *, const char *, int *, int *);
192 static int (* parent_mapget0p)( AstKeyMap *, const char *, void **, int *);
193 static int (* parent_mapget0b)( AstKeyMap *, const char *, unsigned char *, int *);
194 static int (* parent_mapget0s)( AstKeyMap *, const char *, short int *, int *);
195 static int (* parent_mapget1a)( AstKeyMap *, const char *, int, int *, AstObject **, int * );
196 static int (* parent_mapget1c)( AstKeyMap *, const char *, int, int, int *, char *, int * );
197 static int (* parent_mapget1d)( AstKeyMap *, const char *, int, int *, double *, int * );
198 static int (* parent_mapget1f)( AstKeyMap *, const char *, int, int *, float *, int * );
199 static int (* parent_mapget1i)( AstKeyMap *, const char *, int, int *, int *, int * );
200 static int (* parent_mapget1p)( AstKeyMap *, const char *, int, int *, void **, int * );
201 static int (* parent_mapget1s)( AstKeyMap *, const char *, int, int *, short int *, int * );
202 static int (* parent_mapget1b)( AstKeyMap *, const char *, int, int *, unsigned char *, int * );
203 static int (* parent_mapgetelema)( AstKeyMap *, const char *, int, AstObject **, int * );
204 static int (* parent_mapgetelemc)( AstKeyMap *, const char *, int, int, char *, int * );
205 static int (* parent_mapgetelemd)( AstKeyMap *, const char *, int, double *, int * );
206 static int (* parent_mapgetelemf)( AstKeyMap *, const char *, int, float *, int * );
207 static int (* parent_mapgetelemi)( AstKeyMap *, const char *, int, int *, int * );
208 static int (* parent_mapgetelemp)( AstKeyMap *, const char *, int, void **, int * );
209 static int (* parent_mapgetelems)( AstKeyMap *, const char *, int, short int *, int * );
210 static int (* parent_mapgetelemb)( AstKeyMap *, const char *, int, unsigned char *, int * );
211 static int (* parent_testattrib)( AstObject *, const char *, int * );
212 static void (* parent_clearattrib)( AstObject *, const char *, int * );
213 static void (* parent_mapput0a)( AstKeyMap *, const char *, AstObject *, const char *, int *);
214 static void (* parent_mapput0c)( AstKeyMap *, const char *, const char *, const char *, int *);
215 static void (* parent_mapput0d)( AstKeyMap *, const char *, double, const char *, int *);
216 static void (* parent_mapput0f)( AstKeyMap *, const char *, float, const char *, int *);
217 static void (* parent_mapput0i)( AstKeyMap *, const char *, int, const char *, int *);
218 static void (* parent_mapput0p)( AstKeyMap *, const char *, void *, const char *, int *);
219 static void (* parent_mapput0b)( AstKeyMap *, const char *, unsigned char, const char *, int *);
220 static void (* parent_mapput0s)( AstKeyMap *, const char *, short int, const char *, int *);
221 static void (* parent_mapput1a)( AstKeyMap *, const char *, int, AstObject *const [], const char *, int * );
222 static void (* parent_mapput1c)( AstKeyMap *, const char *, int, const char *const [], const char *, int * );
223 static void (* parent_mapput1d)( AstKeyMap *, const char *, int, const double *, const char *, int * );
224 static void (* parent_mapput1f)( AstKeyMap *, const char *, int, const float *, const char *, int * );
225 static void (* parent_mapput1i)( AstKeyMap *, const char *, int, const int *, const char *, int * );
226 static void (* parent_mapput1p)( AstKeyMap *, const char *, int, void *const [], const char *, int * );
227 static void (* parent_mapput1b)( AstKeyMap *, const char *, int, const unsigned char *, const char *, int * );
228 static void (* parent_mapput1s)( AstKeyMap *, const char *, int, const short int *, const char *, int * );
229 static void (* parent_mapputelema)( AstKeyMap *, const char *, int, AstObject *, int * );
230 static void (* parent_mapputelemc)( AstKeyMap *, const char *, int, const char *, int * );
231 static void (* parent_mapputelemd)( AstKeyMap *, const char *, int, double, int * );
232 static void (* parent_mapputelemf)( AstKeyMap *, const char *, int, float, int * );
233 static void (* parent_mapputelemi)( AstKeyMap *, const char *, int, int, int * );
234 static void (* parent_mapputelemp)( AstKeyMap *, const char *, int, void *, int * );
235 static void (* parent_mapputelemb)( AstKeyMap *, const char *, int, unsigned char, int * );
236 static void (* parent_mapputelems)( AstKeyMap *, const char *, int, short int, int * );
237 static void (* parent_mapremove)( AstKeyMap *, const char *, int * );
238 static void (* parent_setattrib)( AstObject *, const char *, int * );
239 static void (* parent_mapputu)( AstKeyMap *, const char *, const char *, int * );
240 
241 #if defined(THREAD_SAFE)
242 static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
243 #endif
244 
245 
246 /* Define macros for accessing each item of thread specific global data. */
247 #ifdef THREAD_SAFE
248 
249 /* Define how to initialise thread-specific globals. */
250 #define GLOBAL_inits \
251    globals->Class_Init = 0; \
252    globals->GetAttrib_Buff[ 0 ] = 0;
253 
254 /* Create the function that initialises global data for this module. */
255 astMAKE_INITGLOBALS(Table)
256 
257 /* Define macros for accessing each item of thread specific global data. */
258 #define class_init astGLOBAL(Table,Class_Init)
259 #define class_vtab astGLOBAL(Table,Class_Vtab)
260 #define getattrib_buff astGLOBAL(Table,GetAttrib_Buff)
261 
262 
263 
264 /* If thread safety is not needed, declare and initialise globals at static
265    variables. */
266 #else
267 
268 static char getattrib_buff[ 101 ];
269 
270 /* Define the class virtual function table and its initialisation flag
271    as static variables. */
272 static AstTableVtab class_vtab;   /* Virtual function table */
273 static int class_init = 0;       /* Virtual function table initialised? */
274 
275 #endif
276 
277 /* External Interface Function Prototypes. */
278 /* ======================================= */
279 /* The following functions have public prototypes only (i.e. no
280    protected prototypes), so we must provide local prototypes for use
281    within this module. */
282 AstTable *astTableId_( const char *, ... );
283 
284 /* Prototypes for Private Member Functions. */
285 /* ======================================== */
286 static AstKeyMap *ColumnProps( AstTable *, int * );
287 static AstKeyMap *ParameterProps( AstTable *, int * );
288 static const char *ColumnName( AstTable *, int index, int * );
289 static const char *ParameterName( AstTable *, int index, int * );
290 static const char *GetColumnUnit( AstTable *, const char *, int * );
291 static const char *TypeString( int );
292 static int Equal( AstObject *, AstObject *, int * );
293 static int GetColumnLenC( AstTable *, const char *, int * );
294 static int GetColumnLength( AstTable *, const char *, int * );
295 static int GetColumnNdim( AstTable *, const char *, int * );
296 static int GetColumnType( AstTable *, const char *, int * );
297 static int GetNcolumn( AstTable *, int * );
298 static int GetNparameter( AstTable *, int * );
299 static int GetObjSize( AstObject *, int * );
300 static int HasColumn( AstTable *, const char *, int *);
301 static int HasParameter( AstTable *, const char *, int *);
302 static int MapGet0A( AstKeyMap *, const char *, AstObject **, int * );
303 static int MapGet0B( AstKeyMap *, const char *, unsigned char *, int * );
304 static int MapGet0C( AstKeyMap *, const char *, const char **, int * );
305 static int MapGet0D( AstKeyMap *, const char *, double *, int * );
306 static int MapGet0F( AstKeyMap *, const char *, float *, int * );
307 static int MapGet0I( AstKeyMap *, const char *, int *, int * );
308 static int MapGet0P( AstKeyMap *, const char *, void **, int * );
309 static int MapGet0S( AstKeyMap *, const char *, short int *, int * );
310 static int MapGet1A( AstKeyMap *, const char *, int, int *, AstObject **, int * );
311 static int MapGet1B( AstKeyMap *, const char *, int, int *, unsigned char *, int * );
312 static int MapGet1C( AstKeyMap *, const char *, int, int, int *, char *, int * );
313 static int MapGet1D( AstKeyMap *, const char *, int, int *, double *, int * );
314 static int MapGet1F( AstKeyMap *, const char *, int, int *, float *, int * );
315 static int MapGet1I( AstKeyMap *, const char *, int, int *, int *, int * );
316 static int MapGet1P( AstKeyMap *, const char *, int, int *, void **, int * );
317 static int MapGet1S( AstKeyMap *, const char *, int, int *, short int *, int * );
318 static int MapGetElemA( AstKeyMap *, const char *, int, AstObject **, int * );
319 static int MapGetElemB( AstKeyMap *, const char *, int, unsigned char *, int * );
320 static int MapGetElemC( AstKeyMap *, const char *, int, int, char *, int * );
321 static int MapGetElemD( AstKeyMap *, const char *, int, double *, int * );
322 static int MapGetElemF( AstKeyMap *, const char *, int, float *, int * );
323 static int MapGetElemI( AstKeyMap *, const char *, int, int *, int * );
324 static int MapGetElemP( AstKeyMap *, const char *, int, void **, int * );
325 static int MapGetElemS( AstKeyMap *, const char *, int, short int *, int * );
326 static int ParseKey( AstTable *, const char *, int, char *, int *, AstKeyMap **, const char *, int * );
327 static void AddColumn( AstTable *, const char *, int, int, int *, const char *, int * );
328 static void AddParameter( AstTable *, const char *, int * );
329 static void ColumnShape( AstTable *, const char *, int, int *, int *, int *);
330 static void Copy( const AstObject *, AstObject *, int * );
331 static void Delete( AstObject *, int * );
332 static void Dump( AstObject *, AstChannel *, int * );
333 static void MapPut0A( AstKeyMap *, const char *, AstObject *, const char *, int * );
334 static void MapPut0B( AstKeyMap *, const char *, unsigned char, const char *, int * );
335 static void MapPut0C( AstKeyMap *, const char *, const char *, const char *, int * );
336 static void MapPut0D( AstKeyMap *, const char *, double, const char *, int * );
337 static void MapPut0F( AstKeyMap *, const char *, float, const char *, int * );
338 static void MapPut0I( AstKeyMap *, const char *, int, const char *, int * );
339 static void MapPut0P( AstKeyMap *, const char *, void *, const char *, int * );
340 static void MapPut0S( AstKeyMap *, const char *, short int, const char *, int * );
341 static void MapPut1A( AstKeyMap *, const char *, int, AstObject *const [], const char *, int * );
342 static void MapPut1B( AstKeyMap *, const char *, int, const unsigned char *, const char *, int * );
343 static void MapPut1C( AstKeyMap *, const char *, int, const char *const [], const char *, int * );
344 static void MapPut1D( AstKeyMap *, const char *, int, const double *, const char *, int * );
345 static void MapPut1F( AstKeyMap *, const char *, int, const float *, const char *, int * );
346 static void MapPut1I( AstKeyMap *, const char *, int, const int *, const char *, int * );
347 static void MapPut1P( AstKeyMap *, const char *, int, void *const [], const char *, int * );
348 static void MapPut1S( AstKeyMap *, const char *, int, const short int *, const char *, int * );
349 static void MapPutElemA( AstKeyMap *, const char *, int, AstObject *, int * );
350 static void MapPutElemB( AstKeyMap *, const char *, int, unsigned char, int * );
351 static void MapPutElemC( AstKeyMap *, const char *, int, const char *, int * );
352 static void MapPutElemD( AstKeyMap *, const char *, int, double, int * );
353 static void MapPutElemF( AstKeyMap *, const char *, int, float, int * );
354 static void MapPutElemI( AstKeyMap *, const char *, int, int, int * );
355 static void MapPutElemP( AstKeyMap *, const char *, int, void *, int * );
356 static void MapPutElemS( AstKeyMap *, const char *, int, short int, int * );
357 static void MapPutU( AstKeyMap *, const char *, const char *, int * );
358 static void PurgeRows( AstTable *, int * );
359 static void RemoveColumn( AstTable *, const char *, int * );
360 static void RemoveParameter( AstTable *, const char *, int * );
361 static void RemoveRow( AstTable *, int, int * );
362 static void SetKeyCase( AstKeyMap *, int, int * );
363 static void ClearKeyCase( AstKeyMap *, int * );
364 
365 #if defined(THREAD_SAFE)
366 static int ManageLock( AstObject *, int, int, AstObject **, int * );
367 #endif
368 
369 static const char *GetAttrib( AstObject *, const char *, int * );
370 static int TestAttrib( AstObject *, const char *, int * );
371 static void ClearAttrib( AstObject *, const char *, int * );
372 static void SetAttrib( AstObject *, const char *, int * );
373 
374 static int GetNrow( AstTable *, int * );
375 static void SetNrow( AstTable *, int, int * );
376 
377 static int GetNcolumn( AstTable *, int * );
378 static int GetNparameter( AstTable *, int * );
379 
380 
381 /* Member functions. */
382 /* ================= */
AddColumn(AstTable * this,const char * name,int type,int ndim,int * dims,const char * unit,int * status)383 static void AddColumn( AstTable *this, const char *name, int type,
384                        int ndim, int *dims, const char *unit, int *status ) {
385 /*
386 *++
387 *  Name:
388 c     astAddColumn
389 f     AST_ADDCOLUMN
390 
391 *  Purpose:
392 *     Add a new column definition to a table.
393 
394 *  Type:
395 *     Public virtual function.
396 
397 *  Synopsis:
398 c     #include "table.h"
399 c     void astAddColumn( AstTable *this, const char *name, int type, int ndim,
400 c                        int *dims, const char *unit )
401 f     CALL AST_ADDCOLUMN( THIS, NAME, TYPE, NDIM, DIMS, UNIT, STATUS )
402 
403 *  Class Membership:
404 *     Table method.
405 
406 *  Description:
407 *     Adds the definition of a new column to the supplied table. Initially,
408 *     the column is empty. Values may be added subsequently using the
409 *     methods of the KeyMap class.
410 
411 *  Parameters:
412 c     this
413 f     THIS = INTEGER (Given)
414 *        Pointer to the Table.
415 c     name
416 f     NAME = CHARACTER * ( * ) (Given)
417 *        The column name. Trailing spaces are ignored (all other spaces
418 *        are significant). The supplied string is converted to upper case.
419 c     type
420 f     TYPE = INTEGER (Given)
421 *        The data type associated with the column. See "Applicability:"
422 *        below.
423 c     ndim
424 f     NDIM = INTEGER (Given)
425 *        The number of dimensions spanned by the values stored in a single
426 *        cell of the column. Zero if the column holds scalar values.
427 c     dims
428 f     DIMS( NDIM ) = INTEGER (Given)
429 *        An array holding the the lengths of each of the axes spanned by
430 *        the values stored in a single cell of the column. Ignored if the
431 *        column holds scalara values.
432 c     unit
433 f     UNIT = CHARACTER * ( * ) (Given)
434 *        A string specifying the units of the column. Supply a blank
435 *        string if the column is unitless.
436 f     STATUS = INTEGER (Given and Returned)
437 f        The global status.
438 
439 *  Applicability:
440 *     Table
441 *        Tables can hold columns with any of the following data types -
442 *        AST__INTTYPE (for integer), AST__SINTTYPE (for
443 c        short int),
444 f        INTEGER*2),
445 *        AST__BYTETYPE (for
446 c        unsigned bytes - i.e. unsigned chars),
447 f        bytes),
448 *        AST__DOUBLETYPE (for double
449 *        precision floating point), AST__FLOATTYPE (for single
450 *        precision floating point), AST__STRINGTYPE (for character string),
451 *        AST__OBJECTTYPE (for AST Object pointer), AST__POINTERTYPE (for
452 *        arbitrary C pointer) or AST__UNDEFTYPE (for undefined values
453 *        created by
454 c        astMapPutU).
455 f        AST_MAPPUTU).
456 *     FitsTable
457 *        FitsTables can hold columns with any of the following data types -
458 *        AST__INTTYPE (for integer), AST__SINTTYPE (for
459 c        short int),
460 f        INTEGER*2),
461 *        AST__BYTETYPE (for
462 c        unsigned bytes - i.e. unsigned chars),
463 f        bytes),
464 *        AST__DOUBLETYPE (for double
465 *        precision floating point), AST__FLOATTYPE (for single
466 *        precision floating point), AST__STRINGTYPE (for character string).
467 
468 *  Notes:
469 *     - This
470 c     function
471 f     routine
472 *     returns without action if a column already exists in the Table
473 *     with the supplied name and properties. However an error is
474 *     reported if any of the properties differ.
475 
476 *--
477 */
478 
479 /* Local Variables: */
480    AstKeyMap *cols;      /* KeyMap holding all column details */
481    AstKeyMap *col_km;    /* KeyMap holding new column details */
482    const char *oldunit;  /* Pointer to the old coumn unit string */
483    int *olddims;         /* Shape of pre-existing column */
484    int idim;             /* Axis index */
485    int namlen;           /* Used length of "name" */
486    int nval;             /* Number of values returned */
487    int oldtype;          /* Data type of pre-existing column */
488 
489 /* Check the global error status. */
490    if ( !astOK ) return;
491 
492 /* Verify supplied values. */
493    namlen = astChrLen( name );
494    if( namlen == 0 ) {
495       astError( AST__BADKEY, "astAddColumn(%s): Illegal blank column name "
496                "supplied.", status, astGetClass( this ) );
497 
498    } else if( namlen > AST__MXCOLNAMLEN ) {
499       astError( AST__BADKEY, "astAddColumn(%s): Column name '%s' is too "
500                "long (must be no more than %d characters).", status,
501                astGetClass( this ), name, AST__MXCOLNAMLEN );
502 
503    } else if( ndim < 0 ) {
504       astError( AST__NAXIN, "astAddColumn(%s): No of axes (%d) for values in "
505                "new column %s is invalid.", status, astGetClass( this ),
506                ndim, name );
507 
508    } else if( TypeString( type ) == NULL ) {
509       astError( AST__NAXIN, "astAddColumn(%s): Bad data type supplied (%d) "
510                 "for new column %s.", status, astGetClass( this ), type,
511                 name );
512 
513    } else {
514       for( idim = 0; idim < ndim; idim++ ) {
515          if( dims[ idim ] < 1 ) {
516             astError( AST__DIMIN, "astAddColumn(%s): Length of axis %d (%d) "
517                       "for new column %s is invalid.", status,
518                       astGetClass( this ), idim + 1, dims[ idim ], name );
519             break;
520          }
521       }
522    }
523 
524 /* If there is already a column with the given name, check its properties
525    match the supplied properties. */
526    if( astOK ) {
527       cols = astColumnProps( this );
528       if( astMapGet0A( cols, name, &col_km ) ) {
529 
530          astMapGet0I( col_km, TYPE, &oldtype );
531          if( oldtype != type && astOK ) {
532             astError( AST__OLDCOL, "astAddColumn(%s): A column called "
533                       "%s already exists in the table with a different "
534                       "data type (%s).", status, astGetClass( this ),
535                       name, TypeString( oldtype ) );
536          }
537 
538          if( !astMapGet0C( col_km, UNIT, &oldunit ) ) oldunit = "";
539          if( strcmp( oldunit, unit ) && astOK ) {
540             astError( AST__OLDCOL, "astAddColumn(%s): A column called "
541                       "%s already exists in the table with a different "
542                       "unit string ('%s').", status, astGetClass( this ),
543                       name, oldunit );
544          }
545 
546          if( ndim != astMapLength( col_km, SHAPE ) && astOK ) {
547             astError( AST__OLDCOL, "astAddColumn(%s): A column called "
548                       "%s already exists in the table with a different "
549                       "number of axes (%d).", status, astGetClass( this ),
550                       name, astMapLength( col_km, SHAPE ) );
551          }
552 
553          if( ndim > 0 && astOK ) {
554             olddims = astMalloc( sizeof( int )*ndim );
555             (void) astMapGet1I( col_km, SHAPE, ndim, &nval, olddims );
556             for( idim = 0; idim < ndim && astOK; idim++ ) {
557                if( dims[ idim ] != olddims[ idim ] ) {
558                   astError( AST__OLDCOL, "astAddColumn(%s): A column called "
559                             "%s already exists in the table with a different "
560                             "shape.", status, astGetClass( this ), name );
561                }
562             }
563             olddims = astFree( olddims );
564          }
565 
566 /* Otherwise, add a new column to the table. */
567       } else {
568 
569 /* Add a suitable entry describing the column to the Columns KeyMap. */
570          col_km = astKeyMap( " ", status );
571          astMapPut0C( col_km, NAME, name, NULL );
572          astMapPut0I( col_km, TYPE, type, NULL );
573          if( ndim ) astMapPut1I( col_km, SHAPE, ndim, dims, NULL );
574          astMapPut0C( col_km, UNIT, unit, NULL );
575 
576 /* Put the column KeyMap into the KeyMap holding details of all columns.
577    Use the column name as the key. */
578          astMapPut0A( cols, name, col_km, NULL );
579       }
580 
581 /* Annul the local KeyMap pointers. */
582       col_km = astAnnul( col_km );
583       cols = astAnnul( cols );
584    }
585 }
586 
AddParameter(AstTable * this,const char * name,int * status)587 static void AddParameter( AstTable *this, const char *name, int *status ) {
588 /*
589 *++
590 *  Name:
591 c     astAddParameter
592 f     AST_ADDPARAMETER
593 
594 *  Purpose:
595 *     Add a new global parameter definition to a table.
596 
597 *  Type:
598 *     Public virtual function.
599 
600 *  Synopsis:
601 c     #include "table.h"
602 c     void astAddParameter( AstTable *this, const char *name )
603 f     CALL AST_ADDPARAMETER( THIS, NAME, STATUS )
604 
605 *  Class Membership:
606 *     Table method.
607 
608 *  Description:
609 *     Adds the definition of a new global parameter to the supplied
610 *     table. Note, this does not store a value for the parameter. To get
611 *     or set the parameter value, the methods of the paremt KeyMap class
612 *     should be used, using the name of the parameter as the key.
613 
614 *  Parameters:
615 c     this
616 f     THIS = INTEGER (Given)
617 *        Pointer to the Table.
618 c     name
619 f     NAME = CHARACTER * ( * ) (Given)
620 *        The parameter name. Trailing spaces are ignored (all other spaces
621 *        are significant). The supplied string is converted to upper case.
622 f     STATUS = INTEGER (Given and Returned)
623 f        The global status.
624 
625 *  Notes:
626 *     - Unlike columns, the definition of a parameter does not specify its type,
627 *     size or dimensionality.
628 
629 *--
630 */
631 
632 /* Local Variables: */
633    AstKeyMap *pars;      /* KeyMap holding all parameter details */
634    int namlen;           /* Used length of "name" */
635 
636 /* Check the global error status. */
637    if ( !astOK ) return;
638 
639 /* Verify supplied values. */
640    namlen = astChrLen( name );
641    if( namlen == 0 ) {
642       astError( AST__BADKEY, "astAddParameter(%s): Illegal blank parameter name "
643                "supplied.", status, astGetClass( this ) );
644 
645    } else if( namlen > AST__MXCOLNAMLEN ) {
646       astError( AST__BADKEY, "astAddParameter(%s): Parameter name '%s' is too "
647                "long (must be no more than %d characters).", status,
648                astGetClass( this ), name, AST__MXCOLNAMLEN );
649    }
650 
651 /* Do nothing if there is already a parameter with the given name. */
652    if( astOK ) {
653       pars = astParameterProps( this );
654       if( !astMapHasKey( pars, name ) ) {
655 
656 /* Add a suitable entry to the Parameters KeyMap. The value is arbitrary
657    and currently unused. */
658          astMapPut0I( pars, name, 1, NULL );
659       }
660 
661 /* Annul the local KeyMap pointer. */
662       pars = astAnnul( pars );
663    }
664 }
665 
ClearAttrib(AstObject * this_object,const char * attrib,int * status)666 static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) {
667 /*
668 *  Name:
669 *     ClearAttrib
670 
671 *  Purpose:
672 *     Clear an attribute value for a Table.
673 
674 *  Type:
675 *     Private function.
676 
677 *  Synopsis:
678 *     #include "table.h"
679 *     void ClearAttrib( AstObject *this, const char *attrib )
680 
681 *  Class Membership:
682 *     Table member function (over-rides the astClearAttrib protected
683 *     method inherited from the KeyMap class).
684 
685 *  Description:
686 *     This function clears the value of a specified attribute for a
687 *     Table, so that the default value will subsequently be used.
688 
689 *  Parameters:
690 *     this
691 *        Pointer to the Table.
692 *     attrib
693 *        Pointer to a null terminated string specifying the attribute
694 *        name.  This should be in lower case with no surrounding white
695 *        space.
696 */
697 
698 /* Local Variables: */
699    AstTable *this;
700    int nc;
701    int len;
702 
703 /* Check the global error status. */
704    if ( !astOK ) return;
705 
706 /* Obtain a pointer to the Table structure. */
707    this = (AstTable *) this_object;
708 
709 /* Get the length of the attribute string. */
710    len = strlen( attrib );
711 
712 /* Check the attribute name and clear the appropriate attribute. */
713    /* None yet */
714 
715 /* Define a macro to see if the attribute string matches any of the
716    read-only column attributes of this class. */
717 #define MATCH(attr) \
718         ( nc = 0, ( 0 == astSscanf( attrib, attr "(%*s)%n", &nc ) ) && \
719                   ( nc >= len ) )
720 
721 /* If the name was not recognised, test if it matches any of the
722    read-only attributes of this class. If it does, then report an
723    error. */
724    if ( !strcmp( attrib, "nrow" ) ||
725         !strcmp( attrib, "ncolumn" ) ||
726         !strcmp( attrib, "nparameter" ) ||
727         MATCH( "columnlenc" ) ||
728         MATCH( "columnlength" ) ||
729         MATCH( "columnndim" ) ||
730         MATCH( "columntype" ) ||
731         MATCH( "columnunit" ) ) {
732       astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" "
733                 "value for a %s.", status, attrib, astGetClass( this ) );
734       astError( AST__NOWRT, "This is a read-only attribute." , status);
735 
736 /* If the attribute is still not recognised, pass it on to the parent
737    method for further interpretation. */
738    } else {
739       (*parent_clearattrib)( this_object, attrib, status );
740    }
741 
742 #undef MATCH
743 
744 }
745 
ClearKeyCase(AstKeyMap * this,int * status)746 static void ClearKeyCase( AstKeyMap *this, int *status ) {
747 /*
748 *  Name:
749 *     ClearKeyCase
750 
751 *  Purpose:
752 *     Clear the KeyCase attribute value for a Table.
753 
754 *  Type:
755 *     Private function.
756 
757 *  Synopsis:
758 *     #include "keymape.h"
759 *     void ClearKeyCase( AstKeyMap *this, int *status )
760 
761 *  Class Membership:
762 *     Table member function (over-rides the astClearKeyCase protected
763 *     method inherited from the KeyMap class).
764 
765 *  Description:
766 *     This function clears the value of the KeyCase attribute for a
767 *     Table. For a Table, the KeyCase attribute cannot be changed so this
768 *     function exits without action.
769 
770 *  Parameters:
771 *     this
772 *        Pointer to the Table.
773 */
774 
775 }
776 
ColumnName(AstTable * this,int index,int * status)777 static const char *ColumnName( AstTable *this, int index, int *status ) {
778 /*
779 *++
780 *  Name:
781 c     astColumnName
782 f     AST_COLUMNNAME
783 
784 *  Purpose:
785 *     Get the name of the column at a given index within the Table.
786 
787 *  Type:
788 *     Public virtual function.
789 
790 *  Synopsis:
791 c     #include "table.h"
792 c     const char *astColumnName( AstTable *this, int index )
793 f     RESULT = AST_COLUMNNAME( THIS, INDEX, STATUS )
794 
795 *  Class Membership:
796 *     Table method.
797 
798 *  Description:
799 *     This function returns a string holding the name of the column with
800 *     the given index within the Table.
801 *
802 *     This function is intended primarily as a means of iterating round all
803 *     the columns in a Table. For this purpose, the number of columns in
804 *     the Table is given by the Ncolumn attribute of the Table. This function
805 *     could then be called in a loop, with the index value going from
806 c     zero to one less than Ncolumn.
807 f     one to Ncolumn.
808 *
809 *     Note, the index associated with a column decreases monotonically with
810 *     the age of the column: the oldest Column in the Table will have index
811 *     one, and the Column added most recently to the Table will have the
812 *     largest index.
813 
814 *  Parameters:
815 c     this
816 f     THIS = INTEGER (Given)
817 *        Pointer to the Table.
818 c     index
819 f     INDEX = INTEGER (Given)
820 *        The index into the list of columns. The first column has index
821 *        one, and the last has index "Ncolumn".
822 f     STATUS = INTEGER (Given and Returned)
823 f        The global status.
824 
825 *  Returned Value:
826 c     astColumnName()
827 c        A pointer to a null-terminated string containing the
828 f     AST_COLUMNNAME = CHARACTER * ( AST__SZCHR )
829 f        The
830 *        upper case column name.
831 
832 *  Notes:
833 c     - The returned pointer is guaranteed to remain valid and the
834 c     string to which it points will not be over-written for a total
835 c     of 50 successive invocations of this function. After this, the
836 c     memory containing the string may be re-used, so a copy of the
837 c     string should be made if it is needed for longer than this.
838 c     - A NULL pointer will be returned if this function is invoked
839 c     with the AST error status set, or if it should fail for any
840 c     reason.
841 f     - A blank string will be returned if this function is invoked
842 f     with STATUS set to an error value, or if it should fail for any
843 f     reason.
844 *--
845 */
846 
847 /* Local Variables: */
848    AstKeyMap *cols;        /* KeyMap holding column definitions */
849    const char *result;
850 
851 /* Check the global error status. */
852    if ( !astOK ) return NULL;
853 
854 /* Get apointer to the KeyMap holding all column definitions. */
855    cols = astColumnProps( this );
856 
857 /* Issue a more useful error message than that issued by astMapKey if the
858    index is invalid. */
859    if( index < 1 || index > astMapSize( cols ) ) {
860       astError( AST__MPIND, "astColumnName(%s): Cannot find column "
861                 "%d (zero-based) of the %s - invalid index.", status,
862                 astGetClass( this ), index, astGetClass( this ) );
863    }
864 
865 /* Get the column name. */
866    result = astMapKey( cols, index - 1 );
867 
868 /* Free resources. */
869    cols = astAnnul( cols );
870 
871 /* Return a pointer to the required column name. */
872    return result;
873 }
874 
ColumnProps(AstTable * this,int * status)875 static AstKeyMap *ColumnProps( AstTable *this, int *status ) {
876 /*
877 *+
878 *  Name:
879 *     astColumnProps
880 
881 *  Purpose:
882 *     Returns a pointer to the KeyMap holding column properties.
883 
884 *  Type:
885 *     Protected virtual function.
886 
887 *  Synopsis:
888 *     #include "table.h"
889 *     AstKeyMap *astColumnProps( AstTable *this )
890 
891 *  Class Membership:
892 *     Table method.
893 
894 *  Description:
895 *     This function returns a pointer to the KeyMap that holds
896 *     definitions of all the coumns added to the Table.
897 
898 *  Parameters:
899 *     this
900 *        Pointer to the Table.
901 
902 *  Returned Value:
903 *        A pointer to the KeyMap. It shpould be annulled using astAnnul
904 *        when no longer needed.
905 
906 *-
907 */
908 
909 /* Check the global error status. */
910    if ( !astOK ) return NULL;
911 
912 /* Return a cloned pointer to the required KeyMap. */
913    return astClone( this->columns );
914 }
915 
ColumnShape(AstTable * this,const char * column,int mxdim,int * ndim,int * dims,int * status)916 static void ColumnShape( AstTable *this, const char *column, int mxdim,
917                          int *ndim, int *dims, int *status ){
918 /*
919 *++
920 *  Name:
921 c     astColumnShape
922 f     AST_COLUMNSHAPE
923 
924 *  Purpose:
925 *     Returns the shape of the values in a named column.
926 
927 *  Type:
928 *     Public virtual function.
929 
930 *  Synopsis:
931 c     #include "table.h"
932 c     void astColumnShape( AstTable *this, const char *column, int mxdim,
933 c                          int *ndim, int *dims )
934 f     CALL AST_COLUMNSHAPE( THIS, COLUMN, MXDIM, NDIM, DIMS, STATUS )
935 
936 *  Class Membership:
937 *     Table method.
938 
939 *  Description:
940 c     This function
941 f     This routine
942 *     returns the number of dimensions spaned by each value in a named
943 *     column of a Table, together with the length of each dimension.
944 *     These are the values supplied when the column was created using
945 c     astAddColumn.
946 f     AST_ADDCOLUMN.
947 
948 *  Parameters:
949 c     this
950 f     THIS = INTEGER (Given)
951 *        Pointer to the Table.
952 c     column
953 f     COLUMN = CHARACTER * ( * ) (Given)
954 *        The character string holding the upper case name of the column. Trailing
955 *        spaces are ignored.
956 c     mxdim
957 f     MXDIM = INTEGER (Given)
958 *        The length of the
959 c        "dims" array.
960 f        DIMS array.
961 c     ndim
962 f     NDIM = INTEGER (Returned)
963 c        Pointer to an int in which to return the
964 f        The
965 *        number of dimensions spanned by values in the named column.
966 *        This will be zero if the column contains scalar values.
967 c     dims
968 f     DIMS( MXDIM ) = INTEGER (Returned)
969 c        Pointer to an
970 f        An
971 *        array in which to return the length of each dimension. Any
972 *        excess trailing elements will be filled with the value 1.
973 f     STATUS = INTEGER (Given and Returned)
974 f        The global status.
975 
976 *  Notes:
977 *     - No error is reported if the requested column cannot be found in the
978 *     given Table. A value of zero is returned for
979 c     "ndim" and the supplied values in "dims"
980 f     NDIM and the supplied values in DIMS
981 *     are left unchanged.
982 *     - A value of zero is returned for
983 c     "ndim"
984 f     NDIM
985 *     if an error occurs.
986 
987 *--
988 */
989 
990 /* Local Variables: */
991    AstKeyMap *cols;        /* Pointer to KeyMap holding all column info */
992    AstKeyMap *col_km;      /* Pointer to KeyMap holding requested column info */
993    int idim;               /* Axis index */
994 
995 /* Initialise */
996    *ndim = 0;
997 
998 /* Check the inherited status. */
999    if( !astOK ) return;
1000 
1001 
1002 /* Get the KeyMap holding information about the requested column. */
1003    cols = astColumnProps( this );
1004    if( astMapGet0A( cols, column, &col_km ) ) {
1005 
1006 /* Get the shape of the column values. */
1007       (void) astMapGet1I( col_km, SHAPE, mxdim, ndim, dims );
1008 
1009 /* Fill excess array elements with 1. */
1010       for( idim = *ndim; idim < mxdim; idim++ ) dims[ idim ] = 1;
1011 
1012 /* Free resources. */
1013       col_km = astAnnul( col_km );
1014    }
1015    cols = astAnnul( cols );
1016 
1017 /* If an error has occurred, set ndim to zero. */
1018    if( !astOK ) *ndim = 0;
1019 
1020 }
1021 
Equal(AstObject * this_object,AstObject * that_object,int * status)1022 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
1023 /*
1024 *  Name:
1025 *     Equal
1026 
1027 *  Purpose:
1028 *     Test if two Tables are equivalent.
1029 
1030 *  Type:
1031 *     Private function.
1032 
1033 *  Synopsis:
1034 *     #include "table.h"
1035 *     int Equal( AstObject *this, AstObject *that, int *status )
1036 
1037 *  Class Membership:
1038 *     Table member function (over-rides the astEqual protected
1039 *     method inherited from the astKeyMap class).
1040 
1041 *  Description:
1042 *     This function returns a boolean result (0 or 1) to indicate whether
1043 *     two Tables are equivalent.
1044 
1045 *  Parameters:
1046 *     this
1047 *        Pointer to the first Object (a Table).
1048 *     that
1049 *        Pointer to the second Object.
1050 *     status
1051 *        Pointer to the inherited status variable.
1052 
1053 *  Returned Value:
1054 *     One if the Tables are equivalent, zero otherwise.
1055 
1056 *  Notes:
1057 *     - A value of zero will be returned if this function is invoked
1058 *     with the global status set, or if it should fail for any reason.
1059 */
1060 
1061 /* Local Variables: */
1062    AstKeyMap *this_km;
1063    AstKeyMap *that_km;
1064    AstTable *that;
1065    AstTable *this;
1066    int result;
1067 
1068 /* Initialise. */
1069    result = 0;
1070 
1071 /* Check the global error status. */
1072    if ( !astOK ) return result;
1073 
1074 /* Obtain pointers to the two Table structures. */
1075    this = (AstTable *) this_object;
1076    that = (AstTable *) that_object;
1077 
1078 /* Check the second object is a Table. We know the first is a
1079    Table since we have arrived at this implementation of the virtual
1080    function. */
1081    if( astIsATable( that ) ) {
1082 
1083 /* Check the Tables are equal when compared as KeyMaps. */
1084       if( (*parent_equal)( this_object, that_object, status ) ) {
1085 
1086 /* Check the Columns KeyMaps are equal.  */
1087          this_km = astColumnProps( this );
1088          that_km = astColumnProps( that );
1089          result = astEqual( this_km, that_km );
1090          this_km = astAnnul( this_km );
1091          that_km = astAnnul( that_km );
1092 
1093 /* Check the Parameter KeyMaps are equal.  */
1094          this_km = astParameterProps( this );
1095          that_km = astParameterProps( that );
1096          result = astEqual( this_km, that_km );
1097          this_km = astAnnul( this_km );
1098          that_km = astAnnul( that_km );
1099       }
1100    }
1101 
1102 /* If an error occurred, clear the result value. */
1103    if ( !astOK ) result = 0;
1104 
1105 /* Return the result, */
1106    return result;
1107 }
1108 
GetAttrib(AstObject * this_object,const char * attrib,int * status)1109 static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) {
1110 /*
1111 *  Name:
1112 *     GetAttrib
1113 
1114 *  Purpose:
1115 *     Get the value of a specified attribute for a Table.
1116 
1117 *  Type:
1118 *     Private function.
1119 
1120 *  Synopsis:
1121 *     #include "table.h"
1122 *     const char *GetAttrib( AstObject *this, const char *attrib, int *status )
1123 
1124 *  Class Membership:
1125 *     Table member function (over-rides the protected astGetAttrib
1126 *     method inherited from the KeyMap class).
1127 
1128 *  Description:
1129 *     This function returns a pointer to the value of a specified
1130 *     attribute for a Table, formatted as a character string.
1131 
1132 *  Parameters:
1133 *     this
1134 *        Pointer to the Table.
1135 *     attrib
1136 *        Pointer to a null terminated string containing the name of
1137 *        the attribute whose value is required. This name should be in
1138 *        lower case, with all white space removed.
1139 *     status
1140 *        Pointer to the inherited status variable.
1141 
1142 *  Returned Value:
1143 *     - Pointer to a null terminated string containing the attribute
1144 *     value.
1145 
1146 *  Notes:
1147 *     - The returned string pointer may point at memory allocated
1148 *     within the Table, or at static memory. The contents of the
1149 *     string may be over-written or the pointer may become invalid
1150 *     following a further invocation of the same function or any
1151 *     modification of the Table. A copy of the string should
1152 *     therefore be made if necessary.
1153 *     - A NULL pointer will be returned if this function is invoked
1154 *     with the global error status set, or if it should fail for any
1155 *     reason.
1156 */
1157 
1158 /* Local Variables: */
1159    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
1160    char cname[ AST__MXCOLNAMLEN + 1 ]; /* Column name */
1161    AstTable *this;               /* Pointer to the Table structure */
1162    const char *result;           /* Pointer value to return */
1163    int ival;                     /* Int attribute value */
1164    int len;                      /* Length of attrib string */
1165    int nc;                       /* No. characters read by astSscanf */
1166 
1167 /* Initialise. */
1168    result = NULL;
1169 
1170 /* Check the global error status. */
1171    if ( !astOK ) return result;
1172 
1173 /* Get a pointer to the thread specific global data structure. */
1174    astGET_GLOBALS(this_object);
1175 
1176 /* Obtain a pointer to the Table structure. */
1177    this = (AstTable *) this_object;
1178 
1179 /* Obtain the length of the attrib string. */
1180    len = strlen( attrib );
1181 
1182 /* Compare "attrib" with each recognised attribute name in turn,
1183    obtaining the value of the required attribute. If necessary, write
1184    the value into "getattrib_buff" as a null terminated string in an
1185    appropriate format.  Set "result" to point at the result string. */
1186 
1187 /* Table properties */
1188 /* ================ */
1189 
1190 /* Ncolumn */
1191 /* ------- */
1192    if( !strcmp( attrib, "ncolumn" ) ) {
1193       ival = astGetNcolumn( this );
1194       if ( astOK ) {
1195          (void) sprintf( getattrib_buff, "%d", ival );
1196          result = getattrib_buff;
1197       }
1198 
1199 /* Nrow */
1200 /* ---- */
1201    } else if( !strcmp( attrib, "nrow" ) ) {
1202       ival = astGetNrow( this );
1203       if ( astOK ) {
1204          (void) sprintf( getattrib_buff, "%d", ival );
1205          result = getattrib_buff;
1206       }
1207 
1208 /* Nparameter */
1209 /* ---------- */
1210    } else if( !strcmp( attrib, "nparameter" ) ) {
1211       ival = astGetNparameter( this );
1212       if ( astOK ) {
1213          (void) sprintf( getattrib_buff, "%d", ival );
1214          result = getattrib_buff;
1215       }
1216 
1217 
1218 
1219 /* Column properties */
1220 /* ================= */
1221 
1222 /* A macro that gives the scannf pattern to test for a given column
1223    property. Needed since the buffer length is defined by a macro
1224    (AST__MXCOLNAMLEN). */
1225 #define PATTERN(cnam,blen) #cnam "(%" STRING(blen) "[^()])%n"
1226 
1227 /* ColumnNdim */
1228    } else if ( nc = 0,
1229              ( 1 == astSscanf( attrib, PATTERN(columnndim,AST__MXCOLNAMLEN),
1230                                cname, &nc ) ) && ( nc >= len ) ) {
1231       ival = astGetColumnNdim( this, cname );
1232       if ( astOK ) {
1233          (void) sprintf( getattrib_buff, "%d", ival );
1234          result = getattrib_buff;
1235       }
1236 
1237 /* ColumnLenC */
1238    } else if ( nc = 0,
1239              ( 1 == astSscanf( attrib, PATTERN(columnlenc,AST__MXCOLNAMLEN),
1240                                cname, &nc ) ) && ( nc >= len ) ) {
1241       ival = astGetColumnLenC( this, cname );
1242       if ( astOK ) {
1243          (void) sprintf( getattrib_buff, "%d", ival );
1244          result = getattrib_buff;
1245       }
1246 
1247 /* ColumnType */
1248    } else if ( nc = 0,
1249              ( 1 == astSscanf( attrib, PATTERN(columntype,AST__MXCOLNAMLEN),
1250                                cname, &nc ) ) && ( nc >= len ) ) {
1251       ival = astGetColumnType( this, cname );
1252       if ( astOK ) {
1253          (void) sprintf( getattrib_buff, "%d", ival );
1254          result = getattrib_buff;
1255       }
1256 
1257 /* ColumnLength */
1258    } else if ( nc = 0,
1259              ( 1 == astSscanf( attrib, PATTERN(columnlength,AST__MXCOLNAMLEN),
1260                                cname, &nc ) ) && ( nc >= len ) ) {
1261       ival = astGetColumnLength( this, cname );
1262       if ( astOK ) {
1263          (void) sprintf( getattrib_buff, "%d", ival );
1264          result = getattrib_buff;
1265       }
1266 
1267 /* ColumnUnit */
1268    } else if ( nc = 0,
1269              ( 1 == astSscanf( attrib, PATTERN(columnunit,AST__MXCOLNAMLEN),
1270                                cname, &nc ) ) && ( nc >= len ) ) {
1271       result = astGetColumnUnit( this, cname );
1272 
1273 #undef PATTERN
1274 
1275 
1276 /* Unknown attributes */
1277 /* ================== */
1278 
1279 /* If the attribute name was not recognised, pass it on to the parent
1280    method for further interpretation. */
1281    } else {
1282       result = (*parent_getattrib)( this_object, attrib, status );
1283    }
1284 
1285 /* Return the result. */
1286    return result;
1287 }
1288 
GetColumnLenC(AstTable * this,const char * column,int * status)1289 static int GetColumnLenC( AstTable *this, const char *column, int *status ) {
1290 /*
1291 *+
1292 *  Name:
1293 *     astGetColumnLenC
1294 
1295 *  Purpose:
1296 *     Get the maximum formatted length of any value in a column.
1297 
1298 *  Type:
1299 *     Protected virtual function.
1300 
1301 *  Synopsis:
1302 *     #include "table.h"
1303 *     int astGetColumnLenC( AstTable *this, const char *column )
1304 
1305 *  Class Membership:
1306 *     Table method.
1307 
1308 *  Description:
1309 *     This function returns the minimum length which a character variable
1310 *     must have in order to be able to store the longest value currently
1311 *     present (at any row) in a specified column of the supplied Table. If
1312 *     the named column holds vector values, then the returned value is
1313 *     the length of the longest element of the vector value.
1314 
1315 *  Parameters:
1316 *     this
1317 *        Pointer to the Table.
1318 *     column
1319 *        The character string holding the upper-case name of the column.
1320 *        Trailing spaces are ignored. An error is reported if the supplied
1321 *        column is not found in the Table.
1322 
1323 *  Returned Value:
1324 *     The length (i.e. number of characters) of the longest formatted
1325 *     value associated with the named column. This does not include the
1326 *     trailing null character.
1327 
1328 *  Notes:
1329 *     - Automatic data type conversion occurs if the named column holds
1330 *     numerical values.
1331 *     - An error will be reported if named column does not exist or cannot
1332 *     be formatted as a character
1333 *     string.
1334 *     - A function value of zero will be returned if an error has already
1335 *     occurred, or if this function should fail for any reason.
1336 
1337 *-
1338 */
1339 
1340 /* Local Variables: */
1341    AstKeyMap *cols;        /* KeyMap holding column definitions */
1342    char key[ AST__MXCOLKEYLEN ]; /* Current cell key string */
1343    int irow;               /* Current row index */
1344    int len;                /* Length needed to format current cell */
1345    int nrow;               /* Number of rows in table */
1346    int result;             /* Returned value */
1347 
1348 /* Initialise */
1349    result = 0;
1350 
1351 /* Check the global error status. */
1352    if ( !astOK ) return result;
1353 
1354 /* Get the KeyMap holding information about all columns. */
1355    cols = astColumnProps( this );
1356 
1357 /* Check the table contains the requested column. */
1358    if( astMapHasKey( cols, column ) ) {
1359 
1360 /* Loop round all rows in the table. */
1361       nrow = astGetNrow( this );
1362       for( irow = 1; irow <= nrow; irow++ ) {
1363 
1364 /* Format the cell name. */
1365          sprintf( key, "%.*s(%d)", (int) astChrLen(column), column, irow );
1366 
1367 /* Get the maximum length needed to format a string in the current
1368    row/column. */
1369          len = astMapLenC( this, key );
1370 
1371 /* Return the largest value found for any row. */
1372          if( len > result ) result = len;
1373       }
1374 
1375 /* Report an error if the column does not exist. */
1376    } else if( astOK ) {
1377       astError( AST__BADCOL, "astGetColumnLenC(%s): No column named '%s' "
1378                 "exists in the table.", status, astGetClass( this ), column );
1379    }
1380 
1381 /* Free resources */
1382    cols = astAnnul( cols );
1383 
1384 /* Return AST__BADTYPE if an error occurred. */
1385    if( !astOK ) result = 0;
1386 
1387 /* Return the result. */
1388    return result;
1389 }
1390 
GetColumnLength(AstTable * this,const char * column,int * status)1391 static int GetColumnLength( AstTable *this, const char *column, int *status ) {
1392 /*
1393 *+
1394 *  Name:
1395 *     astGetColumnLength
1396 
1397 *  Purpose:
1398 *     Get the number of elements in each value in a column.
1399 
1400 *  Type:
1401 *     Protected virtual function.
1402 
1403 *  Synopsis:
1404 *     #include "table.h"
1405 *     int astGetColumnLength( AstTable *this, const char *column )
1406 
1407 *  Class Membership:
1408 *     Table method.
1409 
1410 *  Description:
1411 *     This function returns the number of elements in each value stored
1412 *     in a named column. Each value can be a scalar (in which case the
1413 *     ColumnLength attribute has a value of 1), or a multi-dimensional
1414 *     array ( in which case the ColumnLength value is equal to the
1415 *     product of the array dimensions).
1416 
1417 *  Parameters:
1418 *     this
1419 *        Pointer to the Table.
1420 *     column
1421 *        The character string holding the upper-case name of the column.
1422 *        Trailing spaces are ignored. An error is reported if the supplied
1423 *        column is not found in the Table.
1424 
1425 *  Returned Value:
1426 *     The number of elements in each column value.
1427 
1428 *  Notes:
1429 *     - An error will be reported if named column does not exist or cannot
1430 *     be formatted as a character
1431 *     string.
1432 *     - A function value of zero will be returned if an error has already
1433 *     occurred, or if this function should fail for any reason.
1434 
1435 *-
1436 */
1437 
1438 /* Local Variables: */
1439    AstKeyMap *col_km;      /* KeyMap holding requested column definition */
1440    AstKeyMap *cols;        /* KeyMap holding all column definitions */
1441    int *dims;              /* Pointer to array holding dimensions */
1442    int idim;               /* Index of dimension */
1443    int ndim;               /* Number of dimensions */
1444    int result;             /* Returned value */
1445 
1446 /* Initialise */
1447    result = 0;
1448 
1449 /* Check the global error status. */
1450    if ( !astOK ) return result;
1451 
1452 /* Get the KeyMap holding information about all columns. */
1453    cols = astColumnProps( this );
1454 
1455 /* Get the KeyMap holding information about the requested column. */
1456    if( astMapGet0A( cols, column, &col_km ) ) {
1457 
1458 /* If the Column properties includes the length, return it. Otherwise,
1459    calculate the length and store it in the KeyMap as a column property. */
1460       if( ! astMapGet0I( col_km, LENGTH, &result ) ) {
1461 
1462 /* Get the number of axes spanned by each column value, and allocate an
1463    array big enough to hold the dimensions of these axes. */
1464          ndim = astMapLength( col_km, SHAPE );
1465          dims = astMalloc( sizeof( int )*ndim );
1466          if( astOK ) {
1467 
1468 /* Get the dimensions. */
1469             astMapGet1I( col_km, SHAPE, ndim, &ndim, dims );
1470 
1471 /* Find the number of elements. */
1472             result = 1;
1473             for( idim = 0; idim < ndim; idim++ ) {
1474                result *= dims[ idim ];
1475             }
1476 
1477 /* Store the result in the column KeyMap. */
1478             astMapPut0I( col_km, LENGTH, result, NULL );
1479          }
1480          dims = astFree( dims );
1481       }
1482 
1483 /* Free resources */
1484       col_km = astAnnul( col_km );
1485 
1486 /* Report an error if the column does not exist. */
1487    } else if( astOK ) {
1488       astError( AST__BADCOL, "astGetColumnLength(%s): No column named '%s' "
1489                 "exists in the table.", status, astGetClass( this ), column );
1490    }
1491 
1492 /* Free resources */
1493    cols = astAnnul( cols );
1494 
1495 /* Return AST__BADTYPE if an error occurred. */
1496    if( !astOK ) result = 0;
1497 
1498 /* Return the result. */
1499    return result;
1500 }
1501 
GetColumnNdim(AstTable * this,const char * column,int * status)1502 static int GetColumnNdim( AstTable *this, const char *column, int *status ) {
1503 /*
1504 *+
1505 *  Name:
1506 *     astGetColumnNdim
1507 
1508 *  Purpose:
1509 *     Get the number of dimensions for a column in a Table.
1510 
1511 *  Type:
1512 *     Protected virtual function.
1513 
1514 *  Synopsis:
1515 *     #include "table.h"
1516 *     int astGetColumnNdim( AstTable *this, const char *column )
1517 
1518 *  Class Membership:
1519 *     Table method.
1520 
1521 *  Description:
1522 *     This function attribute holds the number of axes spanned by each value
1523 *     in a column. If each cell in the column is a scalar, ColumnNdim will
1524 *     be zero. If each cell in the column is a 1D spectrum, ColumnNdim will
1525 *     be one. If each cell in the column is a 2D image, ColumnNdim will be
1526 *     two, etc.
1527 
1528 *  Parameters:
1529 *     this
1530 *        Pointer to the Table.
1531 *     column
1532 *        The character string holding the upper-case name of the column.
1533 *        Trailing spaces are ignored. An error is reported if the supplied
1534 *        column is not found in the Table.
1535 
1536 *  Returned Value:
1537 *     The number of dimensions - zero for a scalar.
1538 
1539 *  Notes:
1540 *     - A function value of zero will be returned if an error has
1541 *     already occurred, or if this function should fail for any reason.
1542 
1543 *-
1544 */
1545 
1546 /* Local Variables: */
1547    AstKeyMap *cols;        /* KeyMap holding column definitions */
1548    AstKeyMap *col_km;      /* Pointer to KeyMap holding column info */
1549    int result;             /* Returned value */
1550 
1551 /* Initialise */
1552    result = 0;
1553 
1554 /* Check the global error status. */
1555    if ( !astOK ) return result;
1556 
1557 /* Get the KeyMap holding information about all columns. */
1558    cols = astColumnProps( this );
1559 
1560 /* Get the KeyMap holding information about the requested column. */
1561    if( astMapGet0A( cols, column, &col_km ) ) {
1562 
1563 /* Get the number of dimensions. */
1564       result = astMapLength( col_km, SHAPE );
1565 
1566 /* Free resources */
1567       col_km = astAnnul( col_km );
1568 
1569 /* Report an error if the column does not exist. */
1570    } else if( astOK ) {
1571       astError( AST__BADCOL, "astGetColumnNdim(%s): No column named '%s' "
1572                 "exists in the table.", status, astGetClass( this ), column );
1573    }
1574    cols = astAnnul( cols );
1575 
1576 /* Return AST__BADTYPE if an error occurred. */
1577    if( !astOK ) result = 0;
1578 
1579 /* Return the result. */
1580    return result;
1581 }
1582 
GetColumnType(AstTable * this,const char * column,int * status)1583 static int GetColumnType( AstTable *this, const char *column, int *status ) {
1584 /*
1585 *+
1586 *  Name:
1587 *     astGetColumnType
1588 
1589 *  Purpose:
1590 *     Get the data type of a column in a Table.
1591 
1592 *  Type:
1593 *     Protected virtual function.
1594 
1595 *  Synopsis:
1596 *     #include "table.h"
1597 *     int astGetColumnType( AstTable *this, const char *column )
1598 
1599 *  Class Membership:
1600 *     Table method.
1601 
1602 *  Description:
1603 *     This function returns a value indicating the data type of a
1604 *     named column in a Table. This is the data type which was used
1605 *     when the column was added to the Table using astAddColumn.
1606 
1607 *  Parameters:
1608 *     this
1609 *        Pointer to the Table.
1610 *     column
1611 *        The character string holding the upper-case name of the column.
1612 *        Trailing spaces are ignored. An error is reported if the supplied
1613 *        column is not found in the Table.
1614 
1615 *  Returned Value:
1616 *     One of AST__INTTYPE (for integer), AST__SINTTYPE (for short int),
1617 *     AST__BYTETYPE (for unsigned bytes - i.e. unsigned chars),
1618 *     AST__DOUBLETYPE (for double precision floating point),
1619 *     AST__FLOATTYPE (for single precision floating point), AST__STRINGTYPE
1620 *     (for character string), AST__OBJECTTYPE (for AST Object pointer),
1621 *     AST__POINTERTYPE (for arbitrary C pointer) or AST__UNDEFTYPE (for
1622 *     undefined values created by astMapPutU).
1623 
1624 *  Notes:
1625 *     - A function value of AST__BADTYPE will be returned if an error has
1626 *     already occurred, or if this function should fail for any reason.
1627 
1628 *-
1629 */
1630 
1631 /* Local Variables: */
1632    AstKeyMap *cols;        /* Pointer to KeyMap holding all column info */
1633    AstKeyMap *col_km;      /* Pointer to KeyMap holding requested column info */
1634    int result;             /* Returned value */
1635 
1636 /* Initialise */
1637    result = AST__BADTYPE;
1638 
1639 /* Check the global error status. */
1640    if ( !astOK ) return result;
1641 
1642 /* Get the KeyMap holding information about the requested column. */
1643    cols = astColumnProps( this );
1644    if( astMapGet0A( cols, column, &col_km ) ) {
1645 
1646 /* Get the column data type. */
1647       (void) astMapGet0I( col_km, TYPE, &result );
1648 
1649 /* Annul the KeyMap pointer. */
1650       col_km = astAnnul( col_km );
1651 
1652 /* Report an error if the column does not exist. */
1653    } else if( astOK ) {
1654       astError( AST__BADCOL, "astGetColumnType(%s): No column named '%s' "
1655                 "exists in the table.", status, astGetClass( this ), column );
1656    }
1657    cols = astAnnul( cols );
1658 
1659 /* Return AST__BADTYPE if an error occurred. */
1660    if( !astOK ) result = AST__BADTYPE;
1661 
1662 /* Return the result. */
1663    return result;
1664 }
1665 
GetColumnUnit(AstTable * this,const char * column,int * status)1666 static const char *GetColumnUnit( AstTable *this, const char *column, int *status ) {
1667 /*
1668 *+
1669 *  Name:
1670 *     astGetColumnUnit
1671 
1672 *  Purpose:
1673 *     Get the unit string for a column in a Table.
1674 
1675 *  Type:
1676 *     Protected virtual function.
1677 
1678 *  Synopsis:
1679 *     #include "table.h"
1680 *     const char *astGetColumnUnit( AstTable *this, const char *column )
1681 
1682 *  Class Membership:
1683 *     Table method.
1684 
1685 *  Description:
1686 *     This function returns the unit string for a named column in a Table.
1687 *     This is the unit string that was provided when the column was added to
1688 *     the Table using astAddColumn.
1689 
1690 *  Parameters:
1691 *     this
1692 *        Pointer to the Table.
1693 *     column
1694 *        The character string holding the upper-case name of the column.
1695 *        Trailing spaces are ignored. An error is reported if the supplied
1696 *        column is not found in the Table.
1697 
1698 *  Returned Value:
1699 *     A pointer to a null-terminated string containing the column units.
1700 
1701 *-
1702 */
1703 
1704 /* Local Variables: */
1705    AstKeyMap *col_km;    /* Pointer to KeyMap holding requested column info */
1706    AstKeyMap *cols;      /* Pointer to KeyMap holding all column info */
1707    const char *result;   /* Returned value */
1708 
1709 /* Initialise */
1710    result = NULL;
1711 
1712 /* Check the global error status. */
1713    if ( !astOK ) return result;
1714 
1715 /* Get the KeyMap holding information about the requested column. */
1716    cols = astColumnProps( this );
1717    if( astMapGet0A( cols, column, &col_km ) ) {
1718 
1719 /* Get the column unit string. */
1720       (void) astMapGet0C( col_km, UNIT, &result );
1721 
1722 /* Annul the KeyMap pointer. */
1723       col_km = astAnnul( col_km );
1724 
1725 /* Report an error if the column does not exist. */
1726    } else if( astOK ) {
1727       astError( AST__BADCOL, "astGetColumnUnit(%s): No column named '%s' "
1728                 "exists in the table.", status, astGetClass( this ), column );
1729    }
1730    cols = astAnnul( cols );
1731 
1732 /* Return NULL if an error occurred. */
1733    if( !astOK ) result = NULL;
1734 
1735 /* Return the result. */
1736    return result;
1737 }
1738 
GetNcolumn(AstTable * this,int * status)1739 static int GetNcolumn( AstTable *this, int *status ) {
1740 /*
1741 *+
1742 *  Name:
1743 *     astGetNcolumn
1744 
1745 *  Purpose:
1746 *     Get the number of columns in a Table.
1747 
1748 *  Type:
1749 *     Protected virtual function.
1750 
1751 *  Synopsis:
1752 *     #include "table.h"
1753 *     int astGetNcolumn( AstTable *this )
1754 
1755 *  Class Membership:
1756 *     Table method.
1757 
1758 *  Description:
1759 *     This function returns the number of columns currently in the Table.
1760 
1761 *  Parameters:
1762 *     this
1763 *        Pointer to the Table.
1764 
1765 *  Returned Value:
1766 *     Number of columns.
1767 
1768 *  Notes:
1769 *     - A value of zero will be returned if this function is invoked
1770 *     with the global error status set, or if it should fail for any
1771 *     reason.
1772 *-
1773 */
1774 
1775 /* Local Variables: */
1776    AstKeyMap *cols;
1777    int result;
1778 
1779 /* Check the global error status. */
1780    if ( !astOK ) return 0;
1781 
1782 /* Get a pointer to the KeyMap holding the column definitions. */
1783    cols = astColumnProps( this );
1784 
1785 /* Get the number of column definitions in the KeyMap. */
1786    result = astMapSize( cols );
1787 
1788 /* Annul the KeyMap pointer. */
1789    cols = astAnnul( cols );
1790 
1791 /* Return the result. */
1792    return result;
1793 }
1794 
GetNparameter(AstTable * this,int * status)1795 static int GetNparameter( AstTable *this, int *status ) {
1796 /*
1797 *+
1798 *  Name:
1799 *     astGetNparameter
1800 
1801 *  Purpose:
1802 *     Get the number of global parameters in a Table.
1803 
1804 *  Type:
1805 *     Protected virtual function.
1806 
1807 *  Synopsis:
1808 *     #include "table.h"
1809 *     int astGetNparameter( AstTable *this )
1810 
1811 *  Class Membership:
1812 *     Table method.
1813 
1814 *  Description:
1815 *     This function returns the number of global parameters currently in the Table.
1816 
1817 *  Parameters:
1818 *     this
1819 *        Pointer to the Table.
1820 
1821 *  Returned Value:
1822 *     Number of parameters.
1823 
1824 *  Notes:
1825 *     - A value of zero will be returned if this function is invoked
1826 *     with the global error status set, or if it should fail for any
1827 *     reason.
1828 *-
1829 */
1830 
1831 /* Local Variables: */
1832    AstKeyMap *pars;
1833    int result;
1834 
1835 /* Check the global error status. */
1836    if ( !astOK ) return 0;
1837 
1838 /* Get a pointer to the KeyMap holding the parameter definitions. */
1839    pars = astParameterProps( this );
1840 
1841 /* Get the number of parameter definitions in the KeyMap. */
1842    result = astMapSize( pars );
1843 
1844 /* Annul the KeyMap pointer. */
1845    pars = astAnnul( pars );
1846 
1847 /* Return the result. */
1848    return result;
1849 }
1850 
GetObjSize(AstObject * this_object,int * status)1851 static int GetObjSize( AstObject *this_object, int *status ) {
1852 /*
1853 *  Name:
1854 *     GetObjSize
1855 
1856 *  Purpose:
1857 *     Return the in-memory size of an Object.
1858 
1859 *  Type:
1860 *     Private function.
1861 
1862 *  Synopsis:
1863 *     #include "table.h"
1864 *     int GetObjSize( AstObject *this, int *status )
1865 
1866 *  Class Membership:
1867 *     Table member function (over-rides the astGetObjSize protected
1868 *     method inherited from the parent class).
1869 
1870 *  Description:
1871 *     This function returns the in-memory size of the supplied Tables,
1872 *     in bytes.
1873 
1874 *  Parameters:
1875 *     this
1876 *        Pointer to the Table.
1877 *     status
1878 *        Pointer to the inherited status variable.
1879 
1880 *  Returned Value:
1881 *     The Table size, in bytes.
1882 
1883 *  Notes:
1884 *     - A value of zero will be returned if this function is invoked
1885 *     with the global status set, or if it should fail for any reason.
1886 */
1887 
1888 /* Local Variables: */
1889    AstKeyMap *km;             /* KeyMap holding column/parameter definitions */
1890    AstTable *this;            /* Pointer to Table structure */
1891    int result;                /* Result value to return */
1892 
1893 /* Initialise. */
1894    result = 0;
1895 
1896 /* Check the global error status. */
1897    if ( !astOK ) return result;
1898 
1899 /* Obtain a pointers to the Table structure. */
1900    this = (AstTable *) this_object;
1901 
1902 /* Invoke the GetObjSize method inherited from the parent KeyMap class, and
1903    then add on any components of the class structure defined by this class
1904    which are stored in dynamically allocated memory. */
1905    result = (*parent_getobjsize)( this_object, status );
1906 
1907    km = astColumnProps( this );
1908    result += astGetObjSize( km );
1909    km = astAnnul( km );
1910 
1911    km = astParameterProps( this );
1912    result += astGetObjSize( km );
1913    km = astAnnul( km );
1914 
1915 /* If an error occurred, clear the result value. */
1916    if ( !astOK ) result = 0;
1917 
1918 /* Return the result, */
1919    return result;
1920 }
1921 
HasColumn(AstTable * this,const char * column,int * status)1922 static int HasColumn( AstTable *this, const char *column, int *status ){
1923 /*
1924 *++
1925 *  Name:
1926 c     astHasColumn
1927 f     AST_HASCOLUMN
1928 
1929 *  Purpose:
1930 *     Returns a flag indicating if a column is present in a Table.
1931 
1932 *  Type:
1933 *     Public virtual function.
1934 
1935 *  Synopsis:
1936 c     #include "table.h"
1937 c     int astHasColumn( AstTable *this, const char *column )
1938 f     RESULT = AST_HASCOLUMN( THIS, COLUMN, STATUS )
1939 
1940 *  Class Membership:
1941 *     Table method.
1942 
1943 *  Description:
1944 c     This function
1945 f     This routine
1946 *     returns a flag indicating if a named column exists in a Table, for
1947 *     instance, by having been added to to the Table using
1948 c     astAddColumn.
1949 f     AST_ADDCOLUMN.
1950 
1951 *  Parameters:
1952 c     this
1953 f     THIS = INTEGER (Given)
1954 *        Pointer to the Table.
1955 c     column
1956 f     COLUMN = CHARACTER * ( * ) (Given)
1957 *        The character string holding the upper case name of the column. Trailing
1958 *        spaces are ignored.
1959 f     STATUS = INTEGER (Given and Returned)
1960 f        The global status.
1961 
1962 *  Notes:
1963 *     - A value of
1964 c     zero
1965 f     .FALSE.
1966 *     is returned for if an error occurs.
1967 
1968 *--
1969 */
1970 
1971 /* Local Variables: */
1972    AstKeyMap *cols;
1973    int result;
1974 
1975 /* Initialise */
1976    result = 0;
1977 
1978 /* Check the inherited status. */
1979    if( !astOK ) return result;
1980 
1981 /* Get the KeyMap holding information about all columns. */
1982    cols = astColumnProps( this );
1983 
1984 /* Seeif it contains an entry for the named column. */
1985    result = astMapHasKey( cols, column );
1986 
1987 /* Free resources. */
1988    cols = astAnnul( cols );
1989 
1990 /* If an error has occurred, return zero. */
1991    if( !astOK ) result = 0;
1992    return result;
1993 }
1994 
HasParameter(AstTable * this,const char * parameter,int * status)1995 static int HasParameter( AstTable *this, const char *parameter, int *status ){
1996 /*
1997 *++
1998 *  Name:
1999 c     astHasParameter
2000 f     AST_HASPARAMETER
2001 
2002 *  Purpose:
2003 *     Returns a flag indicating if a named global parameter is present in a Table.
2004 
2005 *  Type:
2006 *     Public virtual function.
2007 
2008 *  Synopsis:
2009 c     #include "table.h"
2010 c     int astHasParameter( AstTable *this, const char *parameter )
2011 f     RESULT = AST_HASPARAMETER( THIS, PARAMETER, STATUS )
2012 
2013 *  Class Membership:
2014 *     Table method.
2015 
2016 *  Description:
2017 c     This function
2018 f     This routine
2019 *     returns a flag indicating if a named parameter exists in a Table, for
2020 *     instance, by having been added to to the Table using
2021 c     astAddParameter.
2022 f     AST_ADDPARAMETER.
2023 
2024 *  Parameters:
2025 c     this
2026 f     THIS = INTEGER (Given)
2027 *        Pointer to the Table.
2028 c     parameter
2029 f     PARAMETER = CHARACTER * ( * ) (Given)
2030 *        The character string holding the upper case name of the parameter. Trailing
2031 *        spaces are ignored.
2032 f     STATUS = INTEGER (Given and Returned)
2033 f        The global status.
2034 
2035 *  Notes:
2036 *     - A value of
2037 c     zero
2038 f     .FALSE.
2039 *     is returned for if an error occurs.
2040 
2041 *--
2042 */
2043 
2044 /* Local Variables: */
2045    AstKeyMap *pars;
2046    int result;
2047 
2048 /* Initialise */
2049    result = 0;
2050 
2051 /* Check the inherited status. */
2052    if( !astOK ) return result;
2053 
2054 /* Get the KeyMap holding information about all parameters. */
2055    pars = astParameterProps( this );
2056 
2057 /* See if it contains an entry for the named parameter. */
2058    result = astMapHasKey( pars, parameter );
2059 
2060 /* Free resources. */
2061    pars = astAnnul( pars );
2062 
2063 /* If an error has occurred, return zero. */
2064    if( !astOK ) result = 0;
2065    return result;
2066 }
2067 
astInitTableVtab_(AstTableVtab * vtab,const char * name,int * status)2068 void astInitTableVtab_(  AstTableVtab *vtab, const char *name, int *status ) {
2069 /*
2070 *+
2071 *  Name:
2072 *     astInitTableVtab
2073 
2074 *  Purpose:
2075 *     Initialise a virtual function table for a Table.
2076 
2077 *  Type:
2078 *     Protected function.
2079 
2080 *  Synopsis:
2081 *     #include "table.h"
2082 *     void astInitTableVtab( AstTableVtab *vtab, const char *name )
2083 
2084 *  Class Membership:
2085 *     Table vtab initialiser.
2086 
2087 *  Description:
2088 *     This function initialises the component of a virtual function
2089 *     table which is used by the Table class.
2090 
2091 *  Parameters:
2092 *     vtab
2093 *        Pointer to the virtual function table. The components used by
2094 *        all ancestral classes will be initialised if they have not already
2095 *        been initialised.
2096 *     name
2097 *        Pointer to a constant null-terminated character string which contains
2098 *        the name of the class to which the virtual function table belongs (it
2099 *        is this pointer value that will subsequently be returned by the Object
2100 *        astClass function).
2101 *-
2102 */
2103 
2104 /* Local Variables: */
2105    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
2106    AstObjectVtab *object;        /* Pointer to Object component of Vtab */
2107    AstKeyMapVtab *keymap;        /* Pointer to KeyMap component of Vtab */
2108 
2109 /* Check the local error status. */
2110    if ( !astOK ) return;
2111 
2112 /* Get a pointer to the thread specific global data structure. */
2113    astGET_GLOBALS(NULL);
2114 
2115 /* Initialize the component of the virtual function table used by the
2116    parent class. */
2117    astInitKeyMapVtab( (AstKeyMapVtab *) vtab, name );
2118 
2119 /* Store a unique "magic" value in the virtual function table. This
2120    will be used (by astIsATable) to determine if an object belongs
2121    to this class.  We can conveniently use the address of the (static)
2122    class_check variable to generate this unique value. */
2123    vtab->id.check = &class_check;
2124    vtab->id.parent = &(((AstKeyMapVtab *) vtab)->id);
2125 
2126 /* Initialise member function pointers. */
2127 /* ------------------------------------ */
2128 /* Store pointers to the member functions (implemented here) that provide
2129    virtual methods for this class. */
2130    vtab->AddColumn = AddColumn;
2131    vtab->AddParameter = AddParameter;
2132    vtab->ColumnName = ColumnName;
2133    vtab->ParameterName = ParameterName;
2134    vtab->ColumnProps = ColumnProps;
2135    vtab->ColumnShape = ColumnShape;
2136    vtab->GetColumnLenC = GetColumnLenC;
2137    vtab->GetColumnLength = GetColumnLength;
2138    vtab->GetColumnNdim = GetColumnNdim;
2139    vtab->GetColumnType = GetColumnType;
2140    vtab->GetColumnUnit = GetColumnUnit;
2141    vtab->GetNcolumn = GetNcolumn;
2142    vtab->GetNparameter = GetNparameter;
2143    vtab->GetNrow = GetNrow;
2144    vtab->HasColumn = HasColumn;
2145    vtab->HasParameter = HasParameter;
2146    vtab->ParameterProps = ParameterProps;
2147    vtab->PurgeRows = PurgeRows;
2148    vtab->RemoveColumn = RemoveColumn;
2149    vtab->RemoveParameter = RemoveParameter;
2150    vtab->RemoveRow = RemoveRow;
2151    vtab->SetNrow = SetNrow;
2152 
2153 /* Save the inherited pointers to methods that will be extended, and
2154    replace them with pointers to the new member functions. */
2155    object = (AstObjectVtab *) vtab;
2156    keymap = (AstKeyMapVtab *) vtab;
2157 
2158    parent_equal = object->Equal;
2159    object->Equal = Equal;
2160 
2161    parent_getobjsize = object->GetObjSize;
2162    object->GetObjSize = GetObjSize;
2163 
2164    parent_clearattrib = object->ClearAttrib;
2165    object->ClearAttrib = ClearAttrib;
2166 
2167    parent_getattrib = object->GetAttrib;
2168    object->GetAttrib = GetAttrib;
2169 
2170    parent_setattrib = object->SetAttrib;
2171    object->SetAttrib = SetAttrib;
2172 
2173    parent_testattrib = object->TestAttrib;
2174    object->TestAttrib = TestAttrib;
2175 
2176 #if defined(THREAD_SAFE)
2177    parent_managelock = object->ManageLock;
2178    object->ManageLock = ManageLock;
2179 #endif
2180 
2181    parent_mapremove = keymap->MapRemove;
2182 
2183 /* Define convenience macros for overriding methods inherited from the
2184    parent KeyMap class using all data type supported by KeyMap. */
2185 #define OVERRIDE(method,code,methodlc,codelc) \
2186    parent_##methodlc##codelc = keymap->method##code; \
2187    keymap->method##code = method##code; \
2188 
2189 #define OVERRIDE_METHOD(method,methodlc) \
2190    OVERRIDE(method,A,methodlc,a) \
2191    OVERRIDE(method,P,methodlc,p) \
2192    OVERRIDE(method,C,methodlc,c) \
2193    OVERRIDE(method,D,methodlc,d) \
2194    OVERRIDE(method,F,methodlc,f) \
2195    OVERRIDE(method,I,methodlc,i) \
2196    OVERRIDE(method,S,methodlc,s) \
2197    OVERRIDE(method,B,methodlc,b)
2198 
2199 /* Use these macros to override the required methods. */
2200    OVERRIDE_METHOD(MapPut0,mapput0)
2201    OVERRIDE_METHOD(MapGet0,mapget0)
2202    OVERRIDE_METHOD(MapPut1,mapput1)
2203    OVERRIDE_METHOD(MapGet1,mapget1)
2204    OVERRIDE_METHOD(MapPutElem,mapputelem)
2205    OVERRIDE_METHOD(MapGetElem,mapgetelem)
2206    OVERRIDE(MapPut,U,mapput,u)
2207    OVERRIDE(SetKeyCase,,setkeycase,)
2208    OVERRIDE(ClearKeyCase,,clearkeycase,)
2209 
2210 /* Remove the macros. */
2211 #undef OVERRIDE_METHOD
2212 #undef OVERRIDE
2213 
2214 /* Store replacement pointers for methods which will be over-ridden by
2215    new member functions implemented here. */
2216 
2217 /* Declare the copy constructor, destructor and class dump function. */
2218    astSetCopy( vtab, Copy );
2219    astSetDelete( vtab, Delete );
2220    astSetDump( vtab, Dump, "Table", "Two-dimensional table of data values" );
2221 
2222 /* If we have just initialised the vtab for the current class, indicate
2223    that the vtab is now initialised, and store a pointer to the class
2224    identifier in the base "object" level of the vtab. */
2225    if( vtab == &class_vtab ) {
2226       class_init = 1;
2227       astSetVtabClassIdentifier( vtab, &(vtab->id) );
2228    }
2229 }
2230 
2231 #if defined(THREAD_SAFE)
ManageLock(AstObject * this_object,int mode,int extra,AstObject ** fail,int * status)2232 static int ManageLock( AstObject *this_object, int mode, int extra,
2233                        AstObject **fail, int *status ) {
2234 /*
2235 *  Name:
2236 *     ManageLock
2237 
2238 *  Purpose:
2239 *     Manage the thread lock on an Object.
2240 
2241 *  Type:
2242 *     Private function.
2243 
2244 *  Synopsis:
2245 *     #include "object.h"
2246 *     AstObject *ManageLock( AstObject *this, int mode, int extra,
2247 *                            AstObject **fail, int *status )
2248 
2249 *  Class Membership:
2250 *     Table member function (over-rides the astManageLock protected
2251 *     method inherited from the parent class).
2252 
2253 *  Description:
2254 *     This function manages the thread lock on the supplied Object. The
2255 *     lock can be locked, unlocked or checked by this function as
2256 *     deteremined by parameter "mode". See astLock for details of the way
2257 *     these locks are used.
2258 
2259 *  Parameters:
2260 *     this
2261 *        Pointer to the Object.
2262 *     mode
2263 *        An integer flag indicating what the function should do:
2264 *
2265 *        AST__LOCK: Lock the Object for exclusive use by the calling
2266 *        thread. The "extra" value indicates what should be done if the
2267 *        Object is already locked (wait or report an error - see astLock).
2268 *
2269 *        AST__UNLOCK: Unlock the Object for use by other threads.
2270 *
2271 *        AST__CHECKLOCK: Check that the object is locked for use by the
2272 *        calling thread (report an error if not).
2273 *     extra
2274 *        Extra mode-specific information.
2275 *     fail
2276 *        If a non-zero function value is returned, a pointer to the
2277 *        Object that caused the failure is returned at "*fail". This may
2278 *        be "this" or it may be an Object contained within "this". Note,
2279 *        the Object's reference count is not incremented, and so the
2280 *        returned pointer should not be annulled. A NULL pointer is
2281 *        returned if this function returns a value of zero.
2282 *     status
2283 *        Pointer to the inherited status variable.
2284 
2285 *  Returned Value:
2286 *    A local status value:
2287 *        0 - Success
2288 *        1 - Could not lock or unlock the object because it was already
2289 *            locked by another thread.
2290 *        2 - Failed to lock a POSIX mutex
2291 *        3 - Failed to unlock a POSIX mutex
2292 *        4 - Bad "mode" value supplied.
2293 
2294 *  Notes:
2295 *     - This function attempts to execute even if an error has already
2296 *     occurred.
2297 */
2298 
2299 /* Local Variables: */
2300    AstTable *this;         /* Pointer to Table structure */
2301    int result;             /* Returned status value */
2302 
2303 /* Initialise */
2304    result = 0;
2305 
2306 /* Check the supplied pointer is not NULL. */
2307    if( !this_object ) return result;
2308 
2309 /* Obtain a pointers to the Table structure. */
2310    this = (AstTable *) this_object;
2311 
2312 /* Invoke the ManageLock method inherited from the parent class. */
2313    if( !result ) result = (*parent_managelock)( this_object, mode, extra,
2314                                                 fail, status );
2315 
2316 /* Invoke the astManageLock method on any Objects contained within
2317    the supplied Object. */
2318    if( !result && this->columns ) result = astManageLock( this->columns, mode, extra,
2319                                                           fail );
2320 
2321    if( !result && this->parameters ) result = astManageLock( this->parameters, mode, extra,
2322                                                              fail );
2323 
2324 /* Return the result. */
2325    return result;
2326 }
2327 #endif
2328 
2329 /*
2330 *  Name:
2331 *     MapGet0<X>
2332 
2333 *  Purpose:
2334 *     Get a scalar value from a cell of a Table.
2335 
2336 *  Type:
2337 *     Private function.
2338 
2339 *  Synopsis:
2340 *     #include "table.h"
2341 *     int MapGet0<X>( AstKeyMap *this, const char *key, <X>type *value );
2342 
2343 *  Class Membership:
2344 *     Table member function (over-rides the astMapGet0<X> method inherited
2345 *     from the KeyMap class).
2346 
2347 *  Description:
2348 *     This is a set of functions for retrieving a scalar value from a
2349 *     cell of a Table. You should replace <X> in the generic function name
2350 *     MapGet0<X> by an appropriate 1-character type code (see the "Data
2351 *     Type Codes" section in the astMapGet0<X> docs). The stored value is
2352 *     converted to the data type indiced by <X> before being returned (an
2353 *     error is reported if it is not possible to convert the stored value
2354 *     to the requested data type).
2355 
2356 *  Parameters:
2357 *     this
2358 *        Pointer to the Table.
2359 *     key
2360 *        A character string identifying the cell from which the value is
2361 *        to be retrieved. It should have the form "COLNAME(irow)", where
2362 *        "COLNAME" is replaced by the name of a column that has been
2363 *        defined previously using the astAddColumn method, and "irow" is
2364 *        an integer row index (the first row is row 1).
2365 *     value
2366 *        A pointer to a buffer in which to return the requested value.
2367 *        If the requested cell is not found, or if it is found but has an
2368 *        undefined value (see astMapPutU), then the contents of the buffer
2369 *        on entry to this function will be unchanged on exit. For pointer
2370 *        types ("A" and "C"), the buffer should be a suitable pointer, and
2371 *        the address of this pointer should be supplied as the "value"
2372 *        parameter.
2373 *     status
2374 *        Pointer to inherited status value.
2375 
2376 *  Returned Value:
2377 *     A non-zero value is returned if the requested key name was found, and
2378 *     does not have an undefined value (see astMapPutU). Zero is returned
2379 *     otherwise.
2380 
2381 *  Notes:
2382 *     - No error is reported if the requested cell cannot be found in the
2383 *     given KeyMap, but a zero value will be returned as the function value.
2384 *     The supplied buffer will be returned unchanged.
2385 *     - Key names are case insensitive, and white space is considered
2386 *     significant.
2387 *     - If the stored value is a vector value, then the first value in
2388 *     the vector will be returned.
2389 *     - A string pointer returned by astMapGet0C is guaranteed to remain
2390 *     valid and the string to which it points will not be over-written for
2391 *     a total of 50 successive invocations of this function. After this,
2392 *     the memory containing the string may be re-used, so a copy of
2393 *     the string should be made if it is needed for longer than this.
2394 *     - If the returned value is an AST Object pointer, the Object's reference
2395 *     count is incremented by this call. Any subsequent changes made to
2396 *     the Object using the returned pointer will be reflected in any
2397 *     any other active pointers for the Object. The returned pointer
2398 *     should be annulled using astAnnul when it is no longer needed.
2399 */
2400 
2401 /* Define a macro to implement the function for a specific data type. */
2402 #define MAKE_MAPGET0(X,Xlc,Xtype,Itype) \
2403 static int MapGet0##X( AstKeyMap *this_keymap, const char *key, Xtype *value, \
2404                        int *status ) { \
2405 \
2406 /* Local Variables: */ \
2407    AstTable *this;     /* Pointer to Table structure */ \
2408    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */ \
2409    int irow;           /* Row index within key string */ \
2410    int result;         /* Returned flag */ \
2411 \
2412 /* Initialise */ \
2413    result = 0; \
2414 \
2415 /* Check the global error status. */ \
2416    if ( !astOK ) return result; \
2417 \
2418 /* Get a pointer to the Table structure. */ \
2419    this = (AstTable *) this_keymap; \
2420 \
2421 /* If the key is the name of a global table parameter, use the parent \
2422    method to get the value of hte parameter. */ \
2423    if( astHasParameter( this, key ) ) { \
2424       result = (*parent_mapget0##Xlc)( this_keymap, key, value, status ); \
2425 \
2426 /* Check the supplied key looks like a table cell key, and get the \
2427    the column name and the row number. Also checks that the table \
2428    contains a column with the specified name. */ \
2429    } else if( ParseKey( this, key, astGetKeyError( this ), colname, &irow, \
2430                         NULL, "astMapGet0" #X, status ) ) { \
2431 \
2432 /* If the row index is larger than the current number of rows in the \
2433    table, do nothing more. */ \
2434       if( irow <= astGetNrow( this ) ){ \
2435 \
2436 /* Use the astMapGet0<X> method in the parent keyMap class to get the \
2437    cell contents. */ \
2438          result = (*parent_mapget0##Xlc)( this_keymap, key, value, status ); \
2439       } \
2440    } \
2441 \
2442 /* If an error occurred, return zero. */ \
2443    if( !astOK ) result = 0; \
2444 \
2445 /* Return the result.*/ \
2446    return result; \
2447 }
2448 
2449 /* Expand the above macro to generate a function for each required
2450    data type. */
MAKE_MAPGET0(I,i,int,AST__INTTYPE)2451 MAKE_MAPGET0(I,i,int,AST__INTTYPE)
2452 MAKE_MAPGET0(D,d,double,AST__DOUBLETYPE)
2453 MAKE_MAPGET0(F,f,float,AST__FLOATTYPE)
2454 MAKE_MAPGET0(C,c,const char *,AST__STRINGTYPE)
2455 MAKE_MAPGET0(A,a,AstObject *,AST__OBJECTTYPE)
2456 MAKE_MAPGET0(P,p,void *,AST__POINTERTYPE)
2457 MAKE_MAPGET0(S,s,short int,AST__SINTTYPE)
2458 MAKE_MAPGET0(B,b,unsigned char,AST__BYTETYPE)
2459 
2460 /* Undefine the macro. */
2461 #undef MAKE_MAPGET0
2462 
2463 /*
2464 *  Name:
2465 *     MapGet1<X>
2466 
2467 *  Purpose:
2468 *     Get a vector value from a cell of a Table.
2469 
2470 *  Type:
2471 *     Private function.
2472 
2473 *  Synopsis:
2474 *     #include "table.h"
2475 *     int MapGet1<X>( AstKeyMap *this, const char *key, int mxval,
2476 *                     int *nval, <X>type *value )
2477 *     int MapGet1C( AstKeyMap *this, const char *key, int l, int mxval,
2478 *                   int *nval, const char *value )
2479 
2480 *  Class Membership:
2481 *     Table member function (over-rides the astMapGet1<X> method inherited
2482 *     from the KeyMap class).
2483 
2484 *  Description:
2485 *     This is a set of functions for retrieving a vector value from a
2486 *     cell of a Table. You should replace <X> in the generic function name
2487 *     MapGet1<X> by an appropriate 1-character type code (see the "Data
2488 *     Type Codes" section in the astMapGet1<X> docs). The stored value is
2489 *     converted to the data type indiced by <X> before being returned (an
2490 *     error is reported if it is not possible to convert the stored value
2491 *     to the requested data type).
2492 *
2493 *     Note, the MapGet1C function has an extra parameter "l" which
2494 *     specifies the maximum length of each string to be stored in the
2495 *     "value" buffer (see the "astMapGet1C" docs).
2496 
2497 *  Parameters:
2498 *     this
2499 *        Pointer to the Table.
2500 *     key
2501 *        A character string identifying the cell from which the value is
2502 *        to be retrieved. It should have the form "COLNAME(irow)", where
2503 *        "COLNAME" is replaced by the name of a column that has been
2504 *        defined previously using the astAddColumn method, and "irow" is
2505 *        an integer row index (the first row is row 1).
2506 *     mxval
2507 *        The number of elements in the "value" array.
2508 *     nval
2509 *        The address of an integer in which to put the number of elements
2510 *        stored in the "value" array. Any unused elements of the array are
2511 *        left unchanged.
2512 *     value
2513 *        A pointer to an array in which to return the requested values.
2514 *        If the requested cell is not found, or if it is found but has an
2515 *        undefined value (see astMapPutU), then the contents of the buffer
2516 *        on entry to this function will be unchanged on exit.
2517 *     status
2518 *        Pointer to inherited status value.
2519 
2520 *  Returned Value:
2521 *     A non-zero value is returned if the requested key name was found, and
2522 *     does not have an undefined value (see astMapPutU). Zero is returned
2523 *     otherwise.
2524 
2525 *  MapGet1C:
2526 *     The "value" buffer supplied to the MapGet1C function should be a
2527 *     pointer to a character array with "mxval*l" elements, where "l" is
2528 *     the maximum length of a string to be returned. The value of "l"
2529 *     should be supplied as an extra parameter following "key" when
2530 *     invoking MapGet1C, and should include space for a terminating
2531 *     null character.
2532 
2533 *  Notes:
2534 *     - No error is reported if the requested cell cannot be found in the
2535 *     given KeyMap, but a zero value will be returned as the function value.
2536 *     The supplied buffer will be returned unchanged.
2537 *     - Key names are case insensitive, and white space is considered
2538 *     significant.
2539 *     - If the stored value is a scalar value, then the value will be
2540 *     returned in the first element of the supplied array, and "nval"
2541 *     will be returned set to 1.
2542 */
2543 
2544 /* Define a macro to implement the function for a specific data type
2545    (excluding "C" since that needs an extra parameter). */
2546 #define MAKE_MAPGET1(X,Xlc,Xtype,Itype) \
2547 static int MapGet1##X( AstKeyMap *this_keymap, const char *key, int mxval, int *nval, \
2548                        Xtype *value, int *status ) { \
2549 \
2550 /* Local Variables: */ \
2551    AstTable *this;     /* Pointer to Table structure */ \
2552    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */ \
2553    int irow;           /* Row index within key string */ \
2554    int result;         /* Returned flag */ \
2555 \
2556 /* Initialise */ \
2557    result = 0; \
2558 \
2559 /* Check the global error status. */ \
2560    if ( !astOK ) return result; \
2561 \
2562 /* Get a pointer to the Table structure. */ \
2563    this = (AstTable *) this_keymap; \
2564 \
2565 /* If the key is the name of a global table parameter, use the parent \
2566    method to get the value of hte parameter. */ \
2567    if( astHasParameter( this, key ) ) { \
2568       result = (*parent_mapget1##Xlc)( this_keymap, key, mxval, nval, \
2569                 value, status ); \
2570 \
2571 /* Check the supplied key looks like a table cell key, and get the \
2572    the column name and the row number. Also checks that the table \
2573    contains a column with the specified name. */ \
2574    } else if( ParseKey( this, key, astGetKeyError( this ), colname, &irow, \
2575                  NULL, "astMapGet1" #X, status ) ) { \
2576 \
2577 /* If the row index is larger than the current number of rows in the \
2578    table, do nothing more. */ \
2579       if( irow <= astGetNrow( this ) ){ \
2580 \
2581 /* Use the astMapGet1<X> method in the parent keyMap class to get the \
2582    cell contents. */ \
2583          result = (*parent_mapget1##Xlc)( this_keymap, key, mxval, nval, \
2584                    value, status ); \
2585       } \
2586    } \
2587 \
2588 /* If an error occurred, return zero. */ \
2589    if( !astOK ) result = 0; \
2590 \
2591 /* Return the result.*/ \
2592    return result; \
2593 }
2594 
2595 /* Expand the above macro to generate a function for each required
2596    data type. */
2597 MAKE_MAPGET1(I,i,int,AST__INTTYPE)
2598 MAKE_MAPGET1(D,d,double,AST__DOUBLETYPE)
2599 MAKE_MAPGET1(F,f,float,AST__FLOATTYPE)
2600 MAKE_MAPGET1(A,a,AstObject *,AST__OBJECTTYPE)
2601 MAKE_MAPGET1(P,p,void *,AST__POINTERTYPE)
2602 MAKE_MAPGET1(S,s,short int,AST__SINTTYPE)
2603 MAKE_MAPGET1(B,b,unsigned char,AST__BYTETYPE)
2604 
2605 /* Undefine the macro. */
2606 #undef MAKE_MAPGET1
2607 
2608 
2609 static int MapGet1C( AstKeyMap *this_keymap, const char *key, int l, int mxval,
2610                      int *nval, char *value, int *status ) {
2611 /*
2612 *  Name:
2613 *     MapGet1C
2614 
2615 *  Purpose:
2616 *     Get a vector value from a cell of a Table.
2617 
2618 *  Type:
2619 *     Private function.
2620 
2621 *  Synopsis:
2622 *     #include "table.h"
2623 *     int MapGet1C( AstKeyMap *this, const char *key, int l, int mxval,
2624 *                   int *nval, const char *value )
2625 
2626 *  Class Membership:
2627 *     Table member function (over-rides the astMapGet1C method inherited
2628 *     from the KeyMap class).
2629 
2630 *  Description:
2631 *     This is the implementation of MapGet1<X> for <X> = "C". We
2632 *     cannot use the MAKE_MAPGET1 macro for this because the string
2633 *     version of this function has an extra parameter giving the maximum
2634 *     length of each string which can be stored in the supplied buffer.
2635 
2636 *  Parameters:
2637 *     (see MapGet1<X>)
2638 */
2639 
2640 /* Local Variables: */
2641    AstTable *this;     /* Pointer to Table structure */
2642    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */
2643    int irow;           /* Row index within key string */
2644    int result;         /* Returned flag */
2645 
2646 /* Initialise */
2647    result = 0;
2648 
2649 /* Check the global error status. */
2650    if ( !astOK ) return result;
2651 
2652 /* Get a pointer to the Table structure. */
2653    this = (AstTable *) this_keymap;
2654 
2655 /* If the key is the name of a global table parameter, use the parent
2656    method to get the value of hte parameter. */
2657    if( astHasParameter( this, key ) ) {
2658       result = (*parent_mapget1c)( this_keymap, key, l, mxval, nval,
2659                 value, status );
2660 
2661 /* Check the supplied key looks like a table cell key, and get the
2662    the column name and the row number. Also checks that the table
2663    contains a column with the specified name. */
2664    } else if( ParseKey( this, key, astGetKeyError( this ), colname, &irow,
2665                         NULL, "astMapGet1C", status ) ) {
2666 
2667 /* If the row index is larger than the current number of rows in the
2668    table, do nothing more. */
2669       if( irow <= astGetNrow( this ) ){
2670 
2671 /* Use the astMapGet1<X> method in the parent keyMap class to get the
2672    cell contents. */
2673          result = (*parent_mapget1c)( this_keymap, key, l, mxval, nval,
2674                    value, status );
2675       }
2676    }
2677 
2678 /* If an error occurred, return zero. */
2679    if( !astOK ) result = 0;
2680 
2681 /* Return the result.*/
2682    return result;
2683 }
2684 
2685 /*
2686 *  Name:
2687 *     MapGetElem<X>
2688 
2689 *  Purpose:
2690 *     Get a single element of a vector value from a cell of a Table.
2691 
2692 *  Type:
2693 *     Private function.
2694 
2695 *  Synopsis:
2696 *     #include "table.h"
2697 *     int MapGetElem<X>( AstKeyMap *this, const char *key, int elem,
2698 *                        <X>type *value, int *status )
2699 *     int MapGetElemC( AstKeyMap *this, const char *key, int l, int elem,
2700 *                      char *value, int *status )
2701 
2702 *  Class Membership:
2703 *     Table member function (over-rides the astMapGetElem<X> method inherited
2704 *     from the KeyMap class).
2705 
2706 *  Description:
2707 *     This is a set of functions for retrieving a single element of a vector
2708 *     value from a cell of a Table. You should replace <X> in the generic
2709 *     function name MapGetElem<X> by an appropriate 1-character type code
2710 *     (see the "Data Type Codes" section in the astMapGetElem<X> docs). The
2711 *     stored value is converted to the data type indiced by <X> before being
2712 *     returned (an error is reported if it is not possible to convert the
2713 *     stored value to the requested data type).
2714 *
2715 *     Note, the MapGetElemC function has an extra parameter "l" which
2716 *     specifies the maximum length of each string to be stored in the
2717 *     "value" buffer (see the "MapGetElemC" docs).
2718 
2719 *  Parameters:
2720 *     this
2721 *        Pointer to the Table.
2722 *     key
2723 *        A character string identifying the cell from which the value is
2724 *        to be retrieved. It should have the form "COLNAME(irow)", where
2725 *        "COLNAME" is replaced by the name of a column that has been
2726 *        defined previously using the astAddColumn method, and "irow" is
2727 *        an integer row index (the first row is row 1).
2728 *     elem
2729 *        The index of the vector element to modify, starting at zero.
2730 *        If the index is outside the range of the vector, an error will
2731 *        be reported.
2732 *     value
2733 *        A pointer to a buffer in which to return the requested values.
2734 *        If the requested cell is not found, or if it is found but has an
2735 *        undefined value (see astMapPutU), then the contents of the buffer
2736 *        on entry to this function will be unchanged on exit.
2737 *     status
2738 *        Pointer to inherited status value.
2739 
2740 *  Returned Value:
2741 *     A non-zero value is returned if the requested key name was found, and
2742 *     does not have an undefined value (see astMapPutU). Zero is returned
2743 *     otherwise.
2744 
2745 *  MapGetElemC:
2746 *     The "value" buffer supplied to the MapGetElemC function should be a
2747 *     pointer to a character array with "l" elements, where "l" is
2748 *     the maximum length of a string to be returned. The value of "l"
2749 *     should be supplied as an extra parameter following "key" when
2750 *     invoking MapGetElemC, and should include space for a terminating
2751 *     null character.
2752 
2753 *  Notes:
2754 *     - No error is reported if the requested cell cannot be found in the
2755 *     given KeyMap, but a zero value will be returned as the function value.
2756 *     The supplied buffer will be returned unchanged.
2757 *     - Key names are case insensitive, and white space is considered
2758 *     significant.
2759 *     - If the stored value is a scalar value, then the value will be
2760 *     returned in the first element of the supplied array, and "nval"
2761 *     will be returned set to 1.
2762 */
2763 
2764 /* Define a macro to implement the function for a specific data type
2765 (excluding "C" since that needs an extra parameter). */
2766 #define MAKE_MAPGETELEM(X,Xlc,Xtype,Itype) \
2767 static int MapGetElem##X( AstKeyMap *this_keymap, const char *key, int elem, \
2768                           Xtype *value, int *status ) { \
2769 \
2770 /* Local Variables: */ \
2771    AstTable *this;     /* Pointer to Table structure */ \
2772    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */ \
2773    int irow;           /* Row index within key string */ \
2774    int result;         /* Returned flag */ \
2775 \
2776 /* Initialise */ \
2777    result = 0; \
2778 \
2779 /* Check the global error status. */ \
2780    if ( !astOK ) return result; \
2781 \
2782 /* Get a pointer to the Table structure. */ \
2783    this = (AstTable *) this_keymap; \
2784 \
2785 /* If the key is the name of a global table parameter, use the parent \
2786    method to get the value of hte parameter. */ \
2787    if( astHasParameter( this, key ) ) { \
2788       result = (*parent_mapgetelem##Xlc)( this_keymap, key, elem, \
2789                                           value, status ); \
2790 \
2791 /* Check the supplied key looks like a table cell key, and get the \
2792    the column name and the row number. Also checks that the table \
2793    contains a column with the specified name. */ \
2794    } else if( ParseKey( this, key, astGetKeyError( this ), colname, &irow, \
2795                         NULL, "astMapGetElem" #X, status ) ) { \
2796 \
2797 /* If the row index is larger than the current number of rows in the \
2798    table, do nothing more. */ \
2799       if( irow <= astGetNrow( this ) ){ \
2800 \
2801 /* Use the astMapGetElem<X> method in the parent keyMap class to get the \
2802    cell contents. */ \
2803          result = (*parent_mapgetelem##Xlc)( this_keymap, key, elem, \
2804                                              value, status ); \
2805       } \
2806    } \
2807 \
2808 /* If an error occurred, return zero. */ \
2809    if( !astOK ) result = 0; \
2810 \
2811 /* Return the result.*/ \
2812    return result; \
2813 }
2814 
2815 /* Expand the above macro to generate a function for each required
2816    data type. */
MAKE_MAPGETELEM(I,i,int,AST__INTTYPE)2817 MAKE_MAPGETELEM(I,i,int,AST__INTTYPE)
2818 MAKE_MAPGETELEM(D,d,double,AST__DOUBLETYPE)
2819 MAKE_MAPGETELEM(F,f,float,AST__FLOATTYPE)
2820 MAKE_MAPGETELEM(A,a,AstObject *,AST__OBJECTTYPE)
2821 MAKE_MAPGETELEM(P,p,void *,AST__POINTERTYPE)
2822 MAKE_MAPGETELEM(S,s,short int,AST__SINTTYPE)
2823 MAKE_MAPGETELEM(B,b,unsigned char,AST__BYTETYPE)
2824 
2825 /* Undefine the macro. */
2826 #undef MAKE_MAPGETELEM
2827 
2828 static int MapGetElemC( AstKeyMap *this_keymap, const char *key, int l,
2829                         int elem, char *value, int *status ) {
2830 /*
2831 *  Name:
2832 *     MapGetElemC
2833 
2834 *  Purpose:
2835 *     Get a single element of a vector value from a cell of a Table.
2836 
2837 *  Type:
2838 *     Private function.
2839 
2840 *  Synopsis:
2841 *     #include "table.h"
2842 *     int MapGetElemC( AstKeyMap *this, const char *key, int l, int elem,
2843 *                      char *value, int *status )
2844 
2845 *  Class Membership:
2846 *     Table member function (over-rides the astMapGetElemC method inherited
2847 *     from the KeyMap class).
2848 
2849 *  Description:
2850 *     This is the implementation of MapGetElem<X> for <X> = "C". We
2851 *     cannot use the MAKE_MAPGETELEM macro for this because the string
2852 *     version of this function has an extra parameter giving the maximum
2853 *     length of each string which can be stored in the supplied buffer.
2854 
2855 *  Parameters:
2856 *     (see MapGetElem<X>)
2857 */
2858 
2859 /* Local Variables: */
2860    AstTable *this;     /* Pointer to Table structure */
2861    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */
2862    int irow;           /* Row index within key string */
2863    int result;         /* Returned flag */
2864 
2865 /* Initialise */
2866    result = 0;
2867 
2868 /* Check the global error status. */
2869    if ( !astOK ) return result;
2870 
2871 /* Get a pointer to the Table structure. */
2872    this = (AstTable *) this_keymap;
2873 
2874 /* If the key is the name of a global table parameter, use the parent
2875    method to get the value of hte parameter. */
2876    if( astHasParameter( this, key ) ) {
2877       result = (*parent_mapgetelemc)( this_keymap, key, l, elem,
2878                                       value, status );
2879 
2880 /* Check the supplied key looks like a table cell key, and get the
2881    the column name and the row number. Also checks that the table
2882    contains a column with the specified name. */
2883    } else if( ParseKey( this, key, astGetKeyError( this ), colname, &irow,
2884                         NULL, "astMapGetElemC", status ) ) {
2885 
2886 /* If the row index is larger than the current number of rows in the
2887    table, do nothing more. */
2888       if( irow <= astGetNrow( this ) ){
2889 
2890 /* Use the astMapGetElem<X> method in the parent keyMap class to get the
2891    cell contents. */
2892          result = (*parent_mapgetelemc)( this_keymap, key, l, elem,
2893                                          value, status );
2894       }
2895    }
2896 
2897 /* If an error occurred, return zero. */
2898    if( !astOK ) result = 0;
2899 
2900 /* Return the result.*/
2901    return result;
2902 }
2903 
2904 /*
2905 *  Name:
2906 *     MapPut0<X>
2907 
2908 *  Purpose:
2909 *     Stores a scalar value in a cell of a Table.
2910 
2911 *  Type:
2912 *     Private function.
2913 
2914 *  Synopsis:
2915 *     #include "table.h"
2916 *     void MapPut0<X>( AstKeyMap *this, const char *key, <X>type value,
2917 *                      const char *comment, int *status )
2918 
2919 *  Class Membership:
2920 *     Table member function (over-rides the astMapPut0<X> method inherited
2921 *     from the KeyMap class).
2922 
2923 *  Description:
2924 *     This is a set of functions for storing a scalar value in a cell of
2925 *     a Table. You should use a function which matches the data type of the
2926 *     data you wish to add to the Table by replacing <X> in the generic
2927 *     function name MapPut0<X> by an appropriate 1-character type code (see
2928 *     the "Data Type Codes" section in the astMapPut0<X> docs).
2929 
2930 *  Parameters:
2931 *     this
2932 *        Pointer to the Table in which to store the supplied value.
2933 *     key
2934 *        A character string identifying the cell in which the value is
2935 *        to be stored. It should have the form "COLNAME(irow)", where
2936 *        "COLNAME" is replaced by the name of a column that has been
2937 *        defined previously using the astAddColumn method, and "irow" is
2938 *        an integer row index (the first row is row 1).
2939 *     value
2940 *        The value to be stored. The data type of this value should match
2941 *        the 1-character type code appended to the function name (e.g. if
2942 *        you are using astMapPut0A, the type of this value should be "pointer
2943 *        to AstObject"). An error will be reported if this data type is
2944 *        different to the data type assigned to the column when it was
2945 *        created via astAddColumn.
2946 *     comment
2947 *        A pointer to a null-terminated comment string to be stored with the
2948 *        value. A NULL pointer may be supplied, in which case no comment is
2949 *        stored.
2950 *     status
2951 *        Pointer to inherited status value.
2952 
2953 *  Notes:
2954 *     - Key names are case insensitive, and white space is considered
2955 *     significant.
2956 *     - The new value will replace any old value already stored in the
2957 *     Table for the specified cell.
2958 *     - If the stored value is an AST Object pointer, the Object's reference
2959 *     count is incremented by this call. Any subsequent changes made to
2960 *     the Object using the returned pointer will be reflected in any
2961 *     any other active pointers for the Object, including any obtained
2962 *     later using astMapget0A. The reference count for the Object will be
2963 *     decremented when the KeyMap is destroyed, or the entry is removed or
2964 *     over-written with a different pointer.
2965 
2966 */
2967 /* Define a macro to implement the function for a specific data type. */
2968 #define MAKE_MAPPUT0(X,Xlc,Xtype,Itype,ValExp) \
2969 static void MapPut0##X( AstKeyMap *this_keymap, const char *key, Xtype value, \
2970                         const char *comment, int *status ) { \
2971 \
2972 /* Local Variables: */ \
2973    AstKeyMap *col_km;  /* KeyMap holding details of the requested column */ \
2974    AstTable *this;     /* Pointer to Table structure */ \
2975    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */ \
2976    int irow;           /* Row index within key string */ \
2977    int type;           /* Data type of the requested column */ \
2978 \
2979 /* Check the global error status. */ \
2980    if ( !astOK ) return; \
2981 \
2982 /* Get a pointer to the Table structure. */ \
2983    this = (AstTable *) this_keymap; \
2984 \
2985 /* If the key is the name of a global table parameter, use the parent \
2986    method to put the value of the parameter. */ \
2987    if( astHasParameter( this, key ) ) { \
2988       (*parent_mapput0##Xlc)( this_keymap, key, value, comment, status ); \
2989 \
2990 /* Check the supplied key looks like a table cell key, and get the \
2991    the column name and the row number. Also checks that the table \
2992    contains a column with the specified name. */ \
2993    } else if( ParseKey( this, key, 1, colname, &irow, &col_km, "astMapPut0" #X, \
2994                         status ) ) { \
2995 \
2996 /* Check the column holds scalar values of the type implied by the <X> \
2997    code in the function name. */ \
2998       (void) astMapGet0I( col_km, TYPE, &type ); \
2999       if( type != Itype && astOK ) { \
3000          astError( AST__BADTYP, "astMapPut0" #X "(%s): Failed to store a " \
3001                    #Xtype " value for cell \"%s\": column %s holds %s " \
3002                    "values.", status, astGetClass( this ), key, colname, \
3003                    TypeString( type ) ); \
3004       } \
3005 \
3006       if( astMapHasKey( col_km, SHAPE ) && astOK ) { \
3007          astError( AST__BADTYP, "astMapPut0" #X "(%s): Failed to store a " \
3008                    "scalar value for cell \"%s\": column %s holds vector " \
3009                    " values.", status, astGetClass( this ), key, colname ); \
3010       } \
3011 \
3012 /* If the row index is larger than the current number of rows in the \
3013    table, update the number of rows in the table. */ \
3014       if( irow > astGetNrow( this ) ) astSetNrow( this, irow ); \
3015 \
3016 /* Use the astMapPut0<X> method in the parent keyMap class to store the \
3017    new cell contents. */ \
3018       (*parent_mapput0##Xlc)( this_keymap, key, value, comment, status ); \
3019 \
3020 /* Free resources. */ \
3021       col_km = astAnnul( col_km ); \
3022    } \
3023 }
3024 
3025 /* Expand the above macro to generate a function for each required
3026    data type. */
MAKE_MAPPUT0(I,i,int,AST__INTTYPE,value)3027 MAKE_MAPPUT0(I,i,int,AST__INTTYPE,value)
3028 MAKE_MAPPUT0(D,d,double,AST__DOUBLETYPE,value)
3029 MAKE_MAPPUT0(F,f,float,AST__FLOATTYPE,value)
3030 MAKE_MAPPUT0(C,c,const char *,AST__STRINGTYPE,astStore(NULL,value,strlen(value)+1))
3031 MAKE_MAPPUT0(A,a,AstObject *,AST__OBJECTTYPE,(value?astClone(value):NULL))
3032 MAKE_MAPPUT0(P,p,void *,AST__POINTERTYPE,value)
3033 MAKE_MAPPUT0(S,s,short int,AST__SINTTYPE,value)
3034 MAKE_MAPPUT0(B,b,unsigned char,AST__BYTETYPE,value)
3035 
3036 /* Undefine the macro. */
3037 #undef MAKE_MAPPUT0
3038 
3039 /*
3040 *  Name:
3041 *     MapPut1<X>
3042 
3043 *  Purpose:
3044 *     Stores a vectorised value in a cell of a Table.
3045 
3046 *  Type:
3047 *     Private function.
3048 
3049 *  Synopsis:
3050 *     #include "table.h"
3051 *     void MapPut1<X>( AstKeyMap *this, const char *key, int size,
3052 *                      const <X>type value[], const char *comment,
3053 *                      int *status );
3054 
3055 *  Class Membership:
3056 *     Table member function (over-rides the astMapPut1<X> method inherited
3057 *     from the KeyMap class).
3058 
3059 *  Description:
3060 *     This is a set of functions for storing a vectorised value in a cell of
3061 *     a Table. You should use a function which matches the data type of the
3062 *     data you wish to add to the Table by replacing <X> in the generic
3063 *     function name MapPut1<X> by an appropriate 1-character type code (see
3064 *     the "Data Type Codes" section in the astMapPut1<X> docs).
3065 
3066 *  Parameters:
3067 *     this
3068 *        Pointer to the Table in which to store the supplied value.
3069 *     key
3070 *        A character string identifying the cell in which the value is
3071 *        to be stored. It should have the form "COLNAME(irow)", where
3072 *        "COLNAME" is replaced by the name of a column that has been
3073 *        defined previously using the astAddColumn method, and "irow" is
3074 *        an integer row index (the first row is row 1).
3075 *     size
3076 *        The number of elements in the supplied array of values.
3077 *     value
3078 *        The value to be stored. The data type of this value should match
3079 *        the 1-character type code appended to the function name (e.g. if
3080 *        you are using astMapPut0A, the type of this value should be "pointer
3081 *        to AstObject"). An error will be reported if this data type is
3082 *        different to the data type assigned to the column when it was
3083 *        created via astAddColumn.
3084 *     comment
3085 *        A pointer to a null-terminated comment string to be stored with the
3086 *        value. A NULL pointer may be supplied, in which case no comment is
3087 *        stored.
3088 *     status
3089 *        Pointer to inherited status value.
3090 
3091 *  Notes:
3092 *     - Key names are case insensitive, and white space is considered
3093 *     significant.
3094 *     - The new value will replace any old value already stored in the
3095 *     Table for the specified cell.
3096 
3097 */
3098 
3099 /* Define a macro to implement the function for a specific data type. */
3100 #define MAKE_MAPPUT1(X,Xlc,Xtype,Itype,ValExp) \
3101 static void MapPut1##X( AstKeyMap *this_keymap, const char *key, int size, \
3102                         Xtype value[], const char *comment, \
3103                         int *status ) { \
3104 \
3105 /* Local Variables: */ \
3106    AstTable *this;     /* Pointer to Table structure */ \
3107    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */ \
3108    int irow;           /* Row index within key string */ \
3109 \
3110 /* Check the global error status. */ \
3111    if ( !astOK ) return; \
3112 \
3113 /* Get a pointer to the Table structure. */ \
3114    this = (AstTable *) this_keymap; \
3115 \
3116 /* If the key is the name of a global table parameter, use the parent \
3117    method to put the value of the parameter. */ \
3118    if( astHasParameter( this, key ) ) { \
3119       (*parent_mapput1##Xlc)( this_keymap, key, size, value, \
3120                               comment, status ); \
3121 \
3122 /* Check the supplied key looks like a table cell key, and get the \
3123    the column name and the row number. Also checks that the table \
3124    contains a column with the specified name. */ \
3125    } else if( ParseKey( this, key, 1, colname, &irow, NULL, "astMapPut1" #X, \
3126                         status ) ) { \
3127 \
3128 /* Check the column holds vector values of the type implied by the <X> \
3129    code in the function name. */ \
3130       if(  astGetColumnType( this, colname ) != Itype && astOK ) { \
3131          astError( AST__BADTYP, "astMapPut1" #X "(%s): Failed to store " \
3132                    #Xtype " values for cell \"%s\": column %s holds %s values.", \
3133                    status, astGetClass( this ), key, colname, \
3134                    TypeString( astGetColumnType( this, colname ) ) ); \
3135       } \
3136 \
3137 /* Check the column holds vectors with length equal to the supplied vector. */ \
3138       if( astGetColumnLength( this, colname ) != size && astOK ) { \
3139          astError( AST__BADTYP, "astMapPut1" #X "(%s): Failed to " \
3140                    "store a vector value for cell \"%s\": column " \
3141                    "%s needs %d values per cell but %d were supplied.", \
3142                    status, astGetClass( this ), key, colname, \
3143                    astGetColumnLength( this, colname ), size ); \
3144       } \
3145 \
3146 /* If all is OK, update the number of rows in the table if required, and \
3147    store the vector in the parent KeyMap. */ \
3148       if( astOK ) { \
3149          if( irow > astGetNrow( this ) ) astSetNrow( this, irow ); \
3150          (*parent_mapput1##Xlc)( this_keymap, key, size, value, \
3151                                  comment, status ); \
3152       } \
3153 \
3154    } \
3155 }
3156 
3157 /* Expand the above macro to generate a function for each required
3158    data type. */
3159 MAKE_MAPPUT1(D,d,const double,AST__DOUBLETYPE,value[i])
3160 MAKE_MAPPUT1(F,f,const float,AST__FLOATTYPE,value[i])
3161 MAKE_MAPPUT1(I,i,const int,AST__INTTYPE,value[i])
3162 MAKE_MAPPUT1(C,c,const char *const,AST__STRINGTYPE,astStore(NULL,value[i],strlen(value[i])+1))
3163 MAKE_MAPPUT1(A,a,AstObject *const,AST__OBJECTTYPE,(value[i]?astClone(value[i]):NULL))
3164 MAKE_MAPPUT1(P,p,void *const,AST__POINTERTYPE,value[i])
3165 MAKE_MAPPUT1(S,s,const short int,AST__SINTTYPE,value[i])
3166 MAKE_MAPPUT1(B,b,const unsigned char,AST__BYTETYPE,value[i])
3167 
3168 /* Undefine the macro. */
3169 #undef MAKE_MAPPUT1
3170 
3171 /*
3172 *  Name:
3173 *     MapPutElem<X>
3174 
3175 *  Purpose:
3176 *     Put a value into an element of a vector value in a cell of a Table.
3177 
3178 *  Type:
3179 *     Private function.
3180 
3181 *  Synopsis:
3182 *     #include "table.h"
3183 *     void MapPutElem<X>( AstKeyMap *this, const char *key, int elem,
3184 *                         <X>type *value, int *status )
3185 
3186 *  Class Membership:
3187 *     Table member function (over-rides the astMapPutElem<X> method inherited
3188 *     from the KeyMap class).
3189 
3190 *  Description:
3191 *     This is a set of functions for storing a value in a single element
3192 *     of a vector value stored in a cell of a Table. You should use a
3193 *     function which matches the data type of the data you wish to add to
3194 *     the Table by replacing <X> in the generic function name MapPutElem<X>
3195 *     by an appropriate 1-character type code (see the "Data Type Codes"
3196 *     section in the astMapPutElem<X> docs).
3197 
3198 *  Parameters:
3199 *     this
3200 *        Pointer to the Table in which to store the supplied value.
3201 *     key
3202 *        A character string identifying the cell in which the value is
3203 *        to be stored. It should have the form "COLNAME(irow)", where
3204 *        "COLNAME" is replaced by the name of a column that has been
3205 *        defined previously using the astAddColumn method, and "irow" is
3206 *        an integer row index (the first row is row 1).
3207 *     elem
3208 *        The index of the vector element to modify, starting at zero.
3209 *        If the index is outside the range of the vector, an error will
3210 *        be reported.
3211 *     value
3212 *        The value to be stored. The data type of this value should match
3213 *        the 1-character type code appended to the function name (e.g. if
3214 *        you are using astMapPut0A, the type of this value should be "pointer
3215 *        to AstObject"). An error will be reported if this data type is
3216 *        different to the data type assigned to the column when it was
3217 *        created via astAddColumn.
3218 *     status
3219 *        Pointer to inherited status value.
3220 
3221 *  Notes:
3222 *     - Key names are case insensitive, and white space is considered
3223 *     significant.
3224 *     - The new value will replace any old value already stored in the
3225 *     Table for the specified cell.
3226 *     - If the stored value is an AST Object pointer, the Object's reference
3227 *     count is incremented by this call. Any subsequent changes made to
3228 *     the Object using the returned pointer will be reflected in any
3229 *     any other active pointers for the Object, including any obtained
3230 *     later using astMapget0A. The reference count for the Object will be
3231 *     decremented when the KeyMap is destroyed, or the entry is removed or
3232 *     over-written with a different pointer.
3233 
3234 */
3235 /* Define a macro to implement the function for a specific data type. */
3236 
3237 #define MAKE_MAPPUTELEM(X,Xlc,Xtype,Itype) \
3238 static void MapPutElem##X( AstKeyMap *this_keymap, const char *key, int elem, \
3239                            Xtype value, int *status ) { \
3240 \
3241 /* Local Variables: */ \
3242    AstTable *this;     /* Pointer to Table structure */ \
3243    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */ \
3244    int irow;           /* Row index within key string */ \
3245    int type;           /* Data type of the requested column */ \
3246 \
3247 /* Check the global error status. */ \
3248    if ( !astOK ) return; \
3249 \
3250 /* Get a pointer to the Table structure. */ \
3251    this = (AstTable *) this_keymap; \
3252 \
3253 /* If the key is the name of a global table parameter, use the parent \
3254    method to put the value of the parameter. */ \
3255    if( astHasParameter( this, key ) ) { \
3256       (*parent_mapputelem##Xlc)( this_keymap, key, elem, value, \
3257                                  status ); \
3258 \
3259 /* Check the supplied key looks like a table cell key, and get the \
3260    the column name and the row number. Also checks that the table \
3261    contains a column with the specified name. */ \
3262    } else if( ParseKey( this, key, 1, colname, &irow, NULL, "astMapPutElem" #X, \
3263                         status ) ) { \
3264 \
3265 /* Check the column holds vector values of the type implied by the <X> \
3266    code in the function name. */ \
3267       type = astGetColumnType( this, colname ); \
3268       if(  type != Itype && astOK ) { \
3269          astError( AST__BADTYP, "astMapPutElem" #X "(%s): Failed to store a " \
3270                    #Xtype " value in cell \"%s\": column %s holds %s values.", \
3271                    status, astGetClass( this ), key, colname, \
3272                    TypeString( type ) ); \
3273       } \
3274 \
3275 /* Check the column holds vectors with length equal to the supplied vector. */ \
3276       if( astGetColumnLength( this, colname ) <= elem && astOK ) { \
3277          astError( AST__BADTYP, "astMapPutElem" #X "(%s): Failed to " \
3278                    "store a value for element %d (zero-based) of " \
3279                    "cell \"%s\": column %s has only %d values per " \
3280                    "cell.", status, astGetClass( this ), elem, key, \
3281                    colname, astGetColumnLength( this, colname ) ); \
3282       } \
3283 \
3284 /* If all is OK, update the number of rows in the table if required, and \
3285    store the value in the parent KeyMap. */ \
3286       if( astOK ) { \
3287          if( irow > astGetNrow( this ) ) astSetNrow( this, irow ); \
3288          (*parent_mapputelem##Xlc)( this_keymap, key, elem, value, \
3289                                     status ); \
3290       } \
3291    } \
3292 }
3293 
3294 /* Expand the above macro to generate a function for each required
3295    data type. */
3296 MAKE_MAPPUTELEM(I,i,int,AST__INTTYPE)
3297 MAKE_MAPPUTELEM(D,d,double,AST__DOUBLETYPE)
3298 MAKE_MAPPUTELEM(F,f,float,AST__FLOATTYPE)
3299 MAKE_MAPPUTELEM(A,a,AstObject *,AST__OBJECTTYPE)
3300 MAKE_MAPPUTELEM(P,p,void *,AST__POINTERTYPE)
3301 MAKE_MAPPUTELEM(C,c,const char *,AST__STRINGTYPE)
3302 MAKE_MAPPUTELEM(S,s,short int,AST__SINTTYPE)
3303 MAKE_MAPPUTELEM(B,b,unsigned char,AST__BYTETYPE)
3304 
3305 /* Undefine the macro. */
3306 #undef MAKE_MAPPUTELEM
3307 
3308 static void MapPutU( AstKeyMap *this_keymap, const char *key, const char *comment,
3309                      int *status ) {
3310 /*
3311 *  Name:
3312 *     MapPutU
3313 
3314 *  Purpose:
3315 *     Stores a undefined value in a cell of a Table.
3316 
3317 *  Type:
3318 *     Private function.
3319 
3320 *  Synopsis:
3321 *     #include "table.h"
3322 *     void MapPutU( AstKeyMap *this, const char *key, const char *comment,
3323 *                   int *status )
3324 
3325 *  Class Membership:
3326 *     Table member function (over-rides the astMapPutU method inherited
3327 *     from the KeyMap class).
3328 
3329 *  Description:
3330 *     This function adds a new cell to a Table, but no value is stored with
3331 *     the cell. The cell therefore has a special data type represented by
3332 *     symbolic constant AST__UNDEFTYPE.
3333 *
3334 *     An example use is to add cells with undefined values to a Table
3335 *     prior to locking them with the MapLocked attribute. Such cells
3336 *     can act as placeholders for values that can be added to the KeyMap
3337 *     later.
3338 
3339 *  Parameters:
3340 *     this
3341 *        Pointer to the Table in which to store the supplied value.
3342 *     key
3343 *        A character string identifying the cell in which the value is
3344 *        to be stored. It should have the form "COLNAME(irow)", where
3345 *        "COLNAME" is replaced by the name of a column that has been
3346 *        defined previously using the astAddColumn method, and "irow" is
3347 *        an integer row index (the first row is row 1).
3348 *     comment
3349 *        A pointer to a null-terminated comment string to be stored with the
3350 *        value. A NULL pointer may be supplied, in which case no comment is
3351 *        stored.
3352 *     status
3353 *        Pointer to inherited status value.
3354 
3355 *  Notes:
3356 *     - Key names are case insensitive, and white space is considered
3357 *     significant.
3358 *     - The new undefined value will replace any old value already stored in
3359 *     the Table for the specified cell.
3360 
3361 */
3362 
3363 /* Local Variables: */
3364    AstTable *this;     /* Pointer to Table structure */
3365    char colname[ AST__MXCOLNAMLEN + 1 ]; /* Column name read from string */
3366    int irow;           /* Row index within key string */
3367 
3368 /* Check the global error status. */
3369    if ( !astOK ) return;
3370 
3371 /* Get a pointer to the Table structure. */
3372    this = (AstTable *) this_keymap;
3373 
3374 /* If the key is the name of a global table parameter, use the parent
3375    method to put the value of the parameter. */
3376    if( astHasParameter( this, key ) ) {
3377       (*parent_mapputu)( this_keymap, key, comment, status );
3378 
3379 /* Check the supplied key looks like a table cell key, and get the
3380    the column name and the row number. Also checks that the table
3381    contains a column with the specified name. */
3382    } else if( ParseKey( this, key, 1, colname, &irow, NULL, "astMapPutU",
3383                         status ) ) {
3384 
3385 /* If the row index is larger than the current number of rows in the
3386    table, update the number of rows in the table. */
3387       if( irow > astGetNrow( this ) ) astSetNrow( this, irow );
3388 
3389 /* Use the astMapPutU method in the parent keyMap class to store the
3390    new cell contents. */
3391       (*parent_mapputu)( this_keymap, key, comment, status );
3392    }
3393 }
3394 
ParameterName(AstTable * this,int index,int * status)3395 static const char *ParameterName( AstTable *this, int index, int *status ) {
3396 /*
3397 *++
3398 *  Name:
3399 c     astParameterName
3400 f     AST_PARAMETERNAME
3401 
3402 *  Purpose:
3403 *     Get the name of the global parameter at a given index within the Table.
3404 
3405 *  Type:
3406 *     Public virtual function.
3407 
3408 *  Synopsis:
3409 c     #include "table.h"
3410 c     const char *astParameterName( AstTable *this, int index )
3411 f     RESULT = AST_PARAMETERNAME( THIS, INDEX, STATUS )
3412 
3413 *  Class Membership:
3414 *     Table method.
3415 
3416 *  Description:
3417 *     This function returns a string holding the name of the global parameter with
3418 *     the given index within the Table.
3419 *
3420 *     This function is intended primarily as a means of iterating round all
3421 *     the parameters in a Table. For this purpose, the number of parameters in
3422 *     the Table is given by the Nparameter attribute of the Table. This function
3423 *     could then be called in a loop, with the index value going from
3424 c     zero to one less than Nparameter.
3425 f     one to Nparameter.
3426 *
3427 *     Note, the index associated with a parameter decreases monotonically with
3428 *     the age of the parameter: the oldest Parameter in the Table will have index
3429 *     one, and the Parameter added most recently to the Table will have the
3430 *     largest index.
3431 
3432 *  Parameters:
3433 c     this
3434 f     THIS = INTEGER (Given)
3435 *        Pointer to the Table.
3436 c     index
3437 f     INDEX = INTEGER (Given)
3438 *        The index into the list of parameters. The first parameter has index
3439 *        one, and the last has index "Nparameter".
3440 f     STATUS = INTEGER (Given and Returned)
3441 f        The global status.
3442 
3443 *  Returned Value:
3444 c     astParameterName()
3445 c        A pointer to a null-terminated string containing the
3446 f     AST_PARAMETERNAME = CHARACTER * ( AST__SZCHR )
3447 f        The
3448 *        upper case parameter name.
3449 
3450 *  Notes:
3451 c     - The returned pointer is guaranteed to remain valid and the
3452 c     string to which it points will not be over-written for a total
3453 c     of 50 successive invocations of this function. After this, the
3454 c     memory containing the string may be re-used, so a copy of the
3455 c     string should be made if it is needed for longer than this.
3456 c     - A NULL pointer will be returned if this function is invoked
3457 c     with the AST error status set, or if it should fail for any
3458 c     reason.
3459 f     - A blank string will be returned if this function is invoked
3460 f     with STATUS set to an error value, or if it should fail for any
3461 f     reason.
3462 *--
3463 */
3464 
3465 /* Local Variables: */
3466    AstKeyMap *pars;        /* KeyMap holding parameter definitions */
3467    const char *result;
3468 
3469 /* Check the global error status. */
3470    if ( !astOK ) return NULL;
3471 
3472 /* Get apointer to the KeyMap holding all parameter definitions. */
3473    pars = astParameterProps( this );
3474 
3475 /* Issue a more useful error message than that issued by astMapKey if the
3476    index is invalid. */
3477    if( index < 1 || index > astMapSize( pars ) ) {
3478       astError( AST__MPIND, "astParameterName(%s): Cannot find parameter "
3479                 "%d (zero-based) of the %s - invalid index.", status,
3480                 astGetClass( this ), index, astGetClass( this ) );
3481    }
3482 
3483 /* Get the parameter name. */
3484    result = astMapKey( pars, index - 1 );
3485 
3486 /* Free resources. */
3487    pars = astAnnul( pars );
3488 
3489 /* Return a pointer to the required parameter name. */
3490    return result;
3491 }
3492 
ParameterProps(AstTable * this,int * status)3493 static AstKeyMap *ParameterProps( AstTable *this, int *status ) {
3494 /*
3495 *+
3496 *  Name:
3497 *     astParameterProps
3498 
3499 *  Purpose:
3500 *     Returns a pointer to the KeyMap holding parameter properties.
3501 
3502 *  Type:
3503 *     Protected virtual function.
3504 
3505 *  Synopsis:
3506 *     #include "table.h"
3507 *     AstKeyMap *astParameterProps( AstTable *this )
3508 
3509 *  Class Membership:
3510 *     Table method.
3511 
3512 *  Description:
3513 *     This function returns a pointer to the KeyMap that holds
3514 *     definitions of all the parameters added to the Table.
3515 
3516 *  Parameters:
3517 *     this
3518 *        Pointer to the Table.
3519 
3520 *  Returned Value:
3521 *        A pointer to the KeyMap. It should be annulled using astAnnul
3522 *        when no longer needed.
3523 
3524 *-
3525 */
3526 
3527 /* Check the global error status. */
3528    if ( !astOK ) return NULL;
3529 
3530 /* Return a cloned pointer to the required KeyMap. */
3531    return astClone( this->parameters );
3532 }
3533 
ParseKey(AstTable * this,const char * key,int report,char colname[AST__MXCOLNAMLEN+1],int * irow,AstKeyMap ** col_km,const char * method,int * status)3534 static int ParseKey( AstTable *this, const char *key, int report,
3535                      char colname[ AST__MXCOLNAMLEN + 1 ], int *irow,
3536                      AstKeyMap **col_km, const char *method, int *status ){
3537 /*
3538 *  Name:
3539 *     ParseKey
3540 
3541 *  Purpose:
3542 *     Find the column name and row index in a KeyMap key.
3543 
3544 *  Type:
3545 *     Private function.
3546 
3547 *  Synopsis:
3548 *     #include "table.h"
3549 *     int ParseKey( AstTable *this, const char *key, int report,
3550 *                   char colname[ AST__MXCOLNAMLEN + 1 ], int *irow,
3551 *                   AstKeyMap **col_km, const char *method, int *status )
3552 
3553 *  Class Membership:
3554 *     Table member function
3555 
3556 *  Description:
3557 *     This function checks that the supplied KeyMap key conforms to the
3558 *     format expected for Table cells: i.e. "COLNAME(irow)", where
3559 *     "COLNAME" is the name of a column and "irow" is an integer row
3560 *     index (the first row is row 1), An error is reported if this is
3561 *     not the case.
3562 
3563 *  Parameters:
3564 *     this
3565 *        Pointer to the table.
3566 *     key
3567 *        The key string to test.
3568 *     report
3569 *        If non-zero, an error will be reported if the key does not
3570 *        correspond to a cell of an existing column. Otherwise, no
3571 *        error will be reported.
3572 *     colname
3573 *        A buffer in which to return the column name.
3574 *     irow
3575 *        Address of an int in which to return the row index.
3576 *     col_km
3577 *        Address of a KeyMap pointer in which to return a pointer to the
3578 *        KeyMap holding the information about the column. The returned
3579 *        KeyMap pointer should be annulled using astAnnul when no lngerr
3580 *        needed. If "col_km" is NULL, no KeyMap pointer is returned.
3581 *     method
3582 *        Pointer to a string holding the name of the method to include in
3583 *        any error message.
3584 *     status
3585 *        Address of the inherited status value.
3586 
3587 *  Returned Value:
3588 *     Zero is returned if the key is not a valid Table cell key, or if an
3589 *     error occurs.
3590 
3591 */
3592 
3593 /* Local Variables: */
3594    AstKeyMap *cols;    /* KeyMap holding column definitions */
3595    int result;         /* Returned flag */
3596    int collen;         /* Length of column name */
3597    int nctot;          /* Number of characters read */
3598 
3599 /* Initialise */
3600    result = 0;
3601 
3602 /* Check the global error status. */
3603    if ( !astOK ) return result;
3604 
3605 /* Check the supplied key looks like a table cell key, and extract the
3606    column name and row number. */
3607    nctot = 0;
3608    if( 1 == astSscanf( key, "%*[^(]%n(%d) %n", &collen, irow, &nctot )
3609        && ( nctot >= strlen( key ) ) ) {
3610 
3611 /* Check the column name is not too long. */
3612       if( collen > AST__MXCOLNAMLEN ) {
3613          if( report ) {
3614             astError( AST__BADKEY, "%s(%s): Failed to store a value for cell "
3615                       "\"%s\": column name is too long.", status, method,
3616                       astGetClass( this ), key );
3617          }
3618 
3619 /* Check the row index is positive. */
3620       } else if( *irow < 1 ) {
3621          if( report ) {
3622             astError( AST__BADKEY, "%s(%s): Failed to store a value for cell "
3623                       "\"%s\": row index %d is invalid.", status, method,
3624                       astGetClass( this ), key, *irow );
3625          }
3626 
3627 /* If the key looks OK so far... */
3628       } else {
3629 
3630 /* Convert the column name to upper case and store in the returned buffer. */
3631          astChrCase( key, colname, 1, collen + 1 );
3632          colname[ collen ] = 0;
3633 
3634 /* check that the column exists in the Table, returning a pointer to the
3635    column KeyMap is reequired. */
3636          cols = astColumnProps( this );
3637          if( col_km ) {
3638             result = astMapGet0A( cols, colname, col_km );
3639          } else {
3640             result = astMapHasKey( cols, colname );
3641          }
3642          cols = astAnnul( cols );
3643 
3644 /* Report an error if the table does not contain the specified column. */
3645          if( !result && astOK && report) {
3646             astError( AST__BADKEY, "%s(%s): Failed to store a value for "
3647                       "cell \"%s\": the table does not contain a column "
3648                       "called '%s'.", status, method, astGetClass( this ),
3649                       key, colname );
3650          }
3651       }
3652 
3653 /* Report an error if the cell key has the wrong format. */
3654    } else if( report ) {
3655       astError( AST__BADKEY, "%s(%s): Failed to store a value for cell "
3656                 "\"%s\": the cell name is invalid.", status, method,
3657                 astGetClass( this ), key );
3658    }
3659 
3660 /* Return the result.*/
3661    return result;
3662 }
3663 
PurgeRows(AstTable * this,int * status)3664 static void PurgeRows( AstTable *this, int *status ) {
3665 /*
3666 *++
3667 *  Name:
3668 c     astPurgeRows
3669 f     AST_PURGEROWS
3670 
3671 *  Purpose:
3672 *     Remove all empty rows from a table.
3673 
3674 *  Type:
3675 *     Public virtual function.
3676 
3677 *  Synopsis:
3678 c     #include "table.h"
3679 c     void astPurgeRows( AstTable *this )
3680 f     CALL AST_PURGEROWS( THIS, STATUS )
3681 
3682 *  Class Membership:
3683 *     Table method.
3684 
3685 *  Description:
3686 *     This function removes all empty rows from the Table, renaming
3687 *     the key associated with each table cell accordingly.
3688 
3689 *  Parameters:
3690 c     this
3691 f     THIS = INTEGER (Given)
3692 *        Pointer to the Table.
3693 f     STATUS = INTEGER (Given and Returned)
3694 f        The global status.
3695 
3696 *--
3697 */
3698 
3699 /* Local Variables: */
3700    char newkey[ AST__MXCOLKEYLEN + 1 ]; /* New cell key string */
3701    char oldkey[ AST__MXCOLKEYLEN + 1 ]; /* Old cell key string */
3702    const char *col;              /* Column name */
3703    const char *key;              /* Pointer to key string */
3704    const char *op;               /* Pointer to opening parenthesis */
3705    int *w1;                      /* Work space pointer */
3706    int icol;                     /* Column index */
3707    int inew;                     /* New row index */
3708    int iold;                     /* Old row index */
3709    int ncol;                     /* Number of columns in table */
3710    int nrow;                     /* Number of rows in table */
3711    int reset;                    /* Start a new pass through the KeyMap? */
3712 
3713 /* Check the global error status. */
3714    if ( !astOK ) return;
3715 
3716 /* Get the number of rows in the table. */
3717    nrow = astGetNrow( this );
3718 
3719 /* Create workspace to hold the number of defined values stored in each
3720    row. Initialise every row to have zero defined values. */
3721    w1 = astCalloc( nrow, sizeof( int ) );
3722    if( astOK ) {
3723 
3724 /* Iterate round all keys in the KeyMap. */
3725       reset = 1;
3726       while( ( key = astMapIterate( this, reset ) ) && astOK ) {
3727          reset = 0;
3728 
3729 /* Extract the row number from the key. */
3730          op = strchr( key, '(' );
3731          if( !op || astSscanf( op + 1, "%d", &iold ) != 1 ||
3732              iold > nrow ) {
3733             astError( AST__INTER, "astPurgeRows(%s): Illegal key '%s' "
3734                       "found in a %s (internal programming error).",
3735                       status, astGetClass( this ), key, astGetClass( this ) );
3736 
3737 /* Increment the number of values in this row. Note row indices are
3738    one-based. */
3739          } else {
3740             w1[ iold - 1 ]++;
3741          }
3742       }
3743 
3744 /* Loop round all columns in the Table. */
3745       ncol = astGetNcolumn( this );
3746       inew = nrow;
3747       for( icol = 1; icol <= ncol; icol++ ) {
3748 
3749 /* Get the column name */
3750          col = astColumnName( this, icol );
3751 
3752 /* Loop round all the old row numbers. Skip empty rows.*/
3753          inew = 0;
3754          for( iold = 0; iold < nrow; iold++ ) {
3755             if( w1[ iold ] > 0 ) {
3756 
3757 /* Increment the row number to use in place of the old row number. If the
3758    old and new row numbers are the same, we do not need to rename the cell. */
3759                if( iold != inew++ ) {
3760 
3761 /* For the old and new cell names */
3762                   sprintf( oldkey, "%s(%d)", col, iold + 1 );
3763                   sprintf( newkey, "%s(%d)", col, inew );
3764 
3765 /* Rename the KeyMap entry. */
3766                   astMapRename( this, oldkey, newkey );
3767                }
3768             }
3769          }
3770 
3771 /* If all rows were used, we do not need to check any more columns. */
3772          if( iold == inew ) break;
3773       }
3774 
3775 /* Store the new number of rows. */
3776       astSetNrow( this, inew );
3777    }
3778 
3779 /* Free resources. */
3780    w1 = astFree( w1 );
3781 
3782 }
3783 
RemoveColumn(AstTable * this,const char * name,int * status)3784 static void RemoveColumn( AstTable *this, const char *name, int *status ) {
3785 /*
3786 *++
3787 *  Name:
3788 c     astRemoveColumn
3789 f     AST_REMOVECOLUMN
3790 
3791 *  Purpose:
3792 *     Remove a column from a table.
3793 
3794 *  Type:
3795 *     Public virtual function.
3796 
3797 *  Synopsis:
3798 c     #include "table.h"
3799 c     void astRemoveColumn( AstTable *this, const char *name )
3800 f     CALL AST_REMOVECOLUMN( THIS, NAME, STATUS )
3801 
3802 *  Class Membership:
3803 *     Table method.
3804 
3805 *  Description:
3806 *     This function removes a specified column from the supplied table.
3807 *     The
3808 c     function
3809 f     routine
3810 *     returns without action if the named column does not exist in the
3811 *     Table (no error is reported).
3812 
3813 *  Parameters:
3814 c     this
3815 f     THIS = INTEGER (Given)
3816 *        Pointer to the Table.
3817 c     name
3818 f     NAME = CHARACTER * ( * ) (Given)
3819 *        The column name. Trailing spaces are ignored (all other spaces
3820 *        are significant). Case is significant.
3821 f     STATUS = INTEGER (Given and Returned)
3822 f        The global status.
3823 
3824 *--
3825 */
3826 
3827 /* Local Variables: */
3828    AstKeyMap *cols;      /* KeyMap holding column definitions */
3829    char key[ AST__MXCOLKEYLEN + 1 ]; /* Cell key string */
3830    int irow;             /* Row index */
3831    int namlen;           /* Used length of "name" */
3832    int nrow;             /* Number of rows in table */
3833 
3834 /* Check the global error status. */
3835    if ( !astOK ) return;
3836 
3837 /* Verify supplied values. */
3838    namlen = astChrLen( name );
3839    if( namlen == 0 ) {
3840       astError( AST__BADKEY, "astRemoveColumn(%s): Illegal blank column name "
3841                "supplied.", status, astGetClass( this ) );
3842    }
3843 
3844 /* Get the number of rows in the table. */
3845    nrow = astGetNrow( this );
3846 
3847 /* If there is no column with the given name in the Table, do nothing more. */
3848    cols = astColumnProps( this );
3849    if( astOK && astMapHasKey( cols, name ) ) {
3850 
3851 /* Remove the column description from the columns keymap. */
3852       astMapRemove( cols, name );
3853 
3854 /* Remove any column cells with defined values from the parent KeyMap. */
3855       for( irow = 1; irow <= nrow; irow++ ) {
3856          sprintf( key, "%.*s(%d)", namlen, name, irow );
3857          (*parent_mapremove)( (AstKeyMap *) this, key, status );
3858       }
3859    }
3860    cols = astAnnul( cols );
3861 }
3862 
RemoveParameter(AstTable * this,const char * name,int * status)3863 static void RemoveParameter( AstTable *this, const char *name, int *status ) {
3864 /*
3865 *++
3866 *  Name:
3867 c     astRemoveParameter
3868 f     AST_REMOVEPARAMETER
3869 
3870 *  Purpose:
3871 *     Remove a global parameter from a table.
3872 
3873 *  Type:
3874 *     Public virtual function.
3875 
3876 *  Synopsis:
3877 c     #include "table.h"
3878 c     void astRemoveParameter( AstTable *this, const char *name )
3879 f     CALL AST_REMOVEPARAMETER( THIS, NAME, STATUS )
3880 
3881 *  Class Membership:
3882 *     Table method.
3883 
3884 *  Description:
3885 *     This function removes a specified global parameter from the supplied table.
3886 *     The
3887 c     function
3888 f     routine
3889 *     returns without action if the named parameter does not exist in the
3890 *     Table (no error is reported).
3891 
3892 *  Parameters:
3893 c     this
3894 f     THIS = INTEGER (Given)
3895 *        Pointer to the Table.
3896 c     name
3897 f     NAME = CHARACTER * ( * ) (Given)
3898 *        The parameter name. Trailing spaces are ignored (all other spaces
3899 *        are significant). Case is significant.
3900 f     STATUS = INTEGER (Given and Returned)
3901 f        The global status.
3902 
3903 *--
3904 */
3905 
3906 /* Local Variables: */
3907    AstKeyMap *pars;      /* KeyMap holding parameter definitions */
3908 
3909 /* Check the global error status. */
3910    if ( !astOK ) return;
3911 
3912 /* Verify supplied values. */
3913    if( astChrLen( name ) == 0 ) {
3914       astError( AST__BADKEY, "astRemoveParameter(%s): Illegal blank parameter name "
3915                "supplied.", status, astGetClass( this ) );
3916    }
3917 
3918 /* If there is no parameter with the given name in the Table, do nothing more. */
3919    pars = astParameterProps( this );
3920    if( astOK && astMapHasKey( pars, name ) ) {
3921 
3922 /* Remove the parameter description from the parameters keymap. */
3923       astMapRemove( pars, name );
3924 
3925 /* Remove any entry holding the parameter value from the parent KeyMap. */
3926       (*parent_mapremove)( (AstKeyMap *) this, name, status );
3927    }
3928    pars = astAnnul( pars );
3929 }
3930 
RemoveRow(AstTable * this,int index,int * status)3931 static void RemoveRow( AstTable *this, int index, int *status ) {
3932 /*
3933 *++
3934 *  Name:
3935 c     astRemoveRow
3936 f     AST_REMOVEROW
3937 
3938 *  Purpose:
3939 *     Remove a row from a table.
3940 
3941 *  Type:
3942 *     Public virtual function.
3943 
3944 *  Synopsis:
3945 c     #include "table.h"
3946 c     void astRemoveRow( AstTable *this, int index )
3947 f     CALL AST_REMOVEROW( THIS, INDEX, STATUS )
3948 
3949 *  Class Membership:
3950 *     Table method.
3951 
3952 *  Description:
3953 *     This function removes a specified row from the supplied table.
3954 *     The
3955 c     function
3956 f     routine
3957 *     returns without action if the row does not exist in the
3958 *     Table (no error is reported).
3959 
3960 *  Parameters:
3961 c     this
3962 f     THIS = INTEGER (Given)
3963 *        Pointer to the Table.
3964 c     index
3965 f     INDEX = INTEGER (Given)
3966 *        The index of the row to be removed. The first row has index 1.
3967 f     STATUS = INTEGER (Given and Returned)
3968 f        The global status.
3969 
3970 *--
3971 */
3972 
3973 /* Local Variables: */
3974    AstKeyMap *cols;              /* KeyMap holding column definitions */
3975    char key[ AST__MXCOLKEYLEN + 1 ]; /* Cell key string */
3976    const char *col;              /* Column name */
3977    int icol;                     /* Column index */
3978    int ncol;                     /* Number of columns in table */
3979    int nrow;                     /* Number of rows in table */
3980 
3981 /* Check the global error status. */
3982    if ( !astOK ) return;
3983 
3984 /* Get the number of rows in the table. */
3985    nrow = astGetNrow( this );
3986 
3987 /* Do nothing if the specified row is out of bounds. */
3988    if( index > 0 && index <= nrow ) {
3989 
3990 /* Loop round all columns in the table. */
3991       cols = astColumnProps( this );
3992       ncol = astMapSize( cols );
3993       for( icol = 0; icol < ncol; icol++ ) {
3994          col = astMapKey( cols, icol );
3995 
3996 /* Remove the cell of the current column at the requested row. */
3997          sprintf( key, "%s(%d)", col, index );
3998          (*parent_mapremove)( (AstKeyMap *) this, key, status );
3999       }
4000       cols = astAnnul( cols );
4001 
4002 /* If the removed row was the last row, reduce the number of rows in the
4003    Table. */
4004       if( index == nrow ) astSetNrow( this, index - 1 );
4005    }
4006 }
4007 
SetAttrib(AstObject * this_object,const char * setting,int * status)4008 static void SetAttrib( AstObject *this_object, const char *setting, int *status ) {
4009 /*
4010 *  Name:
4011 *     SetAttrib
4012 
4013 *  Purpose:
4014 *     Set an attribute value for a Table.
4015 
4016 *  Type:
4017 *     Private function.
4018 
4019 *  Synopsis:
4020 *     #include "table.h"
4021 *     void SetAttrib( AstObject *this, const char *setting, int *status )
4022 
4023 *  Class Membership:
4024 *     Table member function (over-rides the astSetAttrib protected
4025 *     method inherited from the KeyMap class).
4026 
4027 *  Description:
4028 *     This function assigns an attribute value for a Table, the
4029 *     attribute and its value being specified by means of a string of
4030 *     the form:
4031 *
4032 *        "attribute= value "
4033 *
4034 *     Here, "attribute" specifies the attribute name and should be in
4035 *     lower case with no white space present. The value to the right
4036 *     of the "=" should be a suitable textual representation of the
4037 *     value to be assigned and this will be interpreted according to
4038 *     the attribute's data type.  White space surrounding the value is
4039 *     only significant for string attributes.
4040 
4041 *  Parameters:
4042 *     this
4043 *        Pointer to the Table.
4044 *     setting
4045 *        Pointer to a null terminated string specifying the new attribute
4046 *        value.
4047 *     status
4048 *        Pointer to the inherited status variable.
4049 */
4050 
4051 /* Local Variables: */
4052    AstTable *this;               /* Pointer to the Table structure */
4053    int len;                      /* Length of setting string */
4054    int nc;                       /* Number of characters read by astSscanf */
4055 
4056 /* Check the global error status. */
4057    if ( !astOK ) return;
4058 
4059 /* Obtain a pointer to the Table structure. */
4060    this = (AstTable *) this_object;
4061 
4062 /* Obtain the length of the setting string. */
4063    len = (int) strlen( setting );
4064 
4065 /* Test for each recognised attribute in turn, using "astSscanf" to parse
4066    the setting string and extract the attribute value (or an offset to
4067    it in the case of string values). In each case, use the value set
4068    in "nc" to check that the entire string was matched. Once a value
4069    has been obtained, use the appropriate method to set it. */
4070    /* None as yet */
4071 
4072 /* Define a macro to see if the setting string matches any of the
4073    read-only attributes of this class. */
4074 #define MATCH(attrib) \
4075         ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \
4076                   ( nc >= len ) )
4077 
4078 #define MATCH2(attrib) \
4079         ( nc = 0, ( 0 == astSscanf( setting, attrib "(%*s) =%*[^\n]%n", &nc ) ) && \
4080                   ( nc >= len ) )
4081 
4082 /* If the attribute was not recognised, use this macro to report an error
4083    if a read-only attribute has been specified. */
4084    if ( MATCH( "ncolumn" ) ||
4085         MATCH( "nparameter" ) ||
4086         MATCH( "nrow" ) ||
4087         MATCH2( "columnlenc" ) ||
4088         MATCH2( "columnlength" ) ||
4089         MATCH2( "columnndim" ) ||
4090         MATCH2( "columntype" ) ||
4091         MATCH2( "columnunit" ) ) {
4092       astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status,
4093                 setting, astGetClass( this ) );
4094       astError( AST__NOWRT, "This is a read-only attribute." , status);
4095 
4096 /* If the attribute is still not recognised, pass it on to the parent
4097    method for further interpretation. */
4098    } else {
4099       (*parent_setattrib)( this_object, setting, status );
4100    }
4101 
4102 /* Undefine macros local to this function. */
4103 #undef MATCH
4104 #undef MATCH2
4105 }
4106 
SetKeyCase(AstKeyMap * this,int keycase,int * status)4107 static void SetKeyCase( AstKeyMap *this, int keycase, int *status ) {
4108 /*
4109 *  Name:
4110 *     SetKeyCase
4111 
4112 *  Purpose:
4113 *     Set a value for the KeyCase attribute value for a Table.
4114 
4115 *  Type:
4116 *     Private function.
4117 
4118 *  Synopsis:
4119 *     #include "keymape.h"
4120 *     void SetKeyCase( AstKeyMap *this, int keycase, int *status )
4121 
4122 *  Class Membership:
4123 *     Table member function (over-rides the astSetKeyCase protected
4124 *     method inherited from the KeyMap class).
4125 
4126 *  Description:
4127 *     This function assigns a new valeu to the KeyCase attribute for a
4128 *     Table. For a Table, the KeyCase attribute cannot be changed so this
4129 *     function exits without action.
4130 
4131 *  Parameters:
4132 *     this
4133 *        Pointer to the Table.
4134 *     keycase
4135 *        The new value to set.
4136 */
4137 
4138 }
4139 
TestAttrib(AstObject * this_object,const char * attrib,int * status)4140 static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) {
4141 /*
4142 *  Name:
4143 *     TestAttrib
4144 
4145 *  Purpose:
4146 *     Test if a specified attribute value is set for a Table.
4147 
4148 *  Type:
4149 *     Private function.
4150 
4151 *  Synopsis:
4152 *     #include "table.h"
4153 *     int TestAttrib( AstObject *this, const char *attrib, int *status )
4154 
4155 *  Class Membership:
4156 *     Table member function (over-rides the astTestAttrib protected
4157 *     method inherited from the KeyMap class).
4158 
4159 *  Description:
4160 *     This function returns a boolean result (0 or 1) to indicate whether
4161 *     a value has been set for one of a Table's attributes.
4162 
4163 *  Parameters:
4164 *     this
4165 *        Pointer to the Table.
4166 *     attrib
4167 *        Pointer to a null terminated string specifying the attribute
4168 *        name.  This should be in lower case with no surrounding white
4169 *        space.
4170 *     status
4171 *        Pointer to the inherited status variable.
4172 
4173 *  Returned Value:
4174 *     One if a value has been set, otherwise zero.
4175 
4176 *  Notes:
4177 *     - A value of zero will be returned if this function is invoked
4178 *     with the global status set, or if it should fail for any reason.
4179 */
4180 
4181 /* Local Variables: */
4182    int len;                      /* Length of attribute string */
4183    int nc;                       /* Number of characters read by astSscanf */
4184    int result;                   /* Result value to return */
4185 
4186 /* Initialise. */
4187    result = 0;
4188 
4189 /* Check the global error status. */
4190    if ( !astOK ) return result;
4191 
4192 /* Get the length of the attribute string. */
4193    len = strlen( attrib );
4194 
4195 /* Check the attribute name and test the appropriate attribute. */
4196    /* None as yet */
4197 
4198 /* Define a macro to see if the attribute string matches any of the
4199    read-only column attributes of this class. */
4200 #define MATCH(attr) \
4201         ( nc = 0, ( 0 == astSscanf( attrib, attr "(%*s)%n", &nc ) ) && \
4202                   ( nc >= len ) )
4203 
4204 /* If the name is not recognised, test if it matches any of the
4205    read-only attributes of this class. If it does, then return
4206    zero. */
4207    if ( !strcmp( attrib, "ncolumn" ) ||
4208         !strcmp( attrib, "nparameter" ) ||
4209         !strcmp( attrib, "nrow" ) ||
4210         MATCH( "columnlenc" ) ||
4211         MATCH( "columnlength" ) ||
4212         MATCH( "columnndim" ) ||
4213         MATCH( "columntype" ) ||
4214         MATCH( "columnunit" ) ) {
4215       result = 0;
4216 
4217 /* If the attribute is still not recognised, pass it on to the parent
4218    method for further interpretation. */
4219    } else {
4220       result = (*parent_testattrib)( this_object, attrib, status );
4221    }
4222 
4223 /* Return the result, */
4224    return result;
4225 
4226 #undef MATCH
4227 }
4228 
TypeString(int type)4229 static const char *TypeString( int type ) {
4230 /*
4231 *  Name:
4232 *     TypeString
4233 
4234 *  Purpose:
4235 *     Return a pointer to a string describing a data type.
4236 
4237 *  Type:
4238 *     Private function.
4239 
4240 *  Synopsis:
4241 *      const char *TypeString( int type );
4242 
4243 *  Description:
4244 *     This function returns a pointer to a string describing a data type.
4245 
4246 *  Parameters:
4247 *     type
4248 *        The integer data type code.
4249 
4250 *  Returned Value:
4251 *     Pointer to a a string descirbing the data type (typically the C
4252 *     data type).
4253 
4254 */
4255 
4256 /* Local Variables: */
4257    const char *result;
4258 
4259 /* Compare the supplied type code against each supported value. */
4260    if( type == AST__INTTYPE ) {
4261       result = "int";
4262 
4263    } else if( type == AST__BYTETYPE ) {
4264       result = "byte";
4265 
4266    } else if( type == AST__DOUBLETYPE ) {
4267       result = "double";
4268 
4269    } else if( type == AST__STRINGTYPE ) {
4270       result = "string";
4271 
4272    } else if( type == AST__OBJECTTYPE ) {
4273       result = "Object";
4274 
4275    } else if( type == AST__FLOATTYPE ) {
4276       result = "float";
4277 
4278    } else if( type == AST__POINTERTYPE ) {
4279       result = "pointer";
4280 
4281    } else if( type == AST__SINTTYPE ) {
4282       result = "short int";
4283 
4284    } else if( type == AST__UNDEFTYPE ) {
4285       result = "undefined";
4286 
4287    } else {
4288       result = NULL;
4289    }
4290 
4291 /* Return the result. */
4292    return result;
4293 }
4294 
4295 
4296 /* Functions which access class attributes. */
4297 /* ---------------------------------------- */
4298 /* Implement member functions to access the attributes associated with
4299    this class using the macros defined for this purpose in the
4300    "object.h" file. For a description of each attribute, see the class
4301    interface (in the associated .h file). */
4302 
4303 /*
4304 *att++
4305 *  Name:
4306 *     ColumnLenC(column)
4307 
4308 *  Purpose:
4309 *     The largest string length of any value in a column
4310 
4311 *  Type:
4312 *     Public attribute.
4313 
4314 *  Synopsis:
4315 *     Integer, read-only.
4316 
4317 *  Description:
4318 *     This attribute holds the minimum length which a character variable
4319 *     must have in order to be able to store the longest value currently
4320 *     present (at any row) in a specified column of the supplied Table.
4321 c     This does not include room for a trailing null character.
4322 *     The required column name should be placed inside the parentheses in
4323 *     the attribute name. If the named column holds vector values, then
4324 *     the attribute value is the length of the longest element of the
4325 *     vector value.
4326 
4327 *  Applicability:
4328 *     Table
4329 *        All Tables have this attribute.
4330 
4331 *  Notes:
4332 *     - If the named column holds numerical values, the length returned
4333 *     is the length of the largest string that would be generated if the
4334 *     column values were accessed as strings.
4335 
4336 *att--
4337 */
4338 
4339 /*
4340 *att++
4341 *  Name:
4342 *     ColumnLength(column)
4343 
4344 *  Purpose:
4345 *     The number of elements in each value in a column
4346 
4347 *  Type:
4348 *     Public attribute.
4349 
4350 *  Synopsis:
4351 *     Integer, read-only.
4352 
4353 *  Description:
4354 *     This attribute holds the number of elements in each value stored
4355 *     in a named column. Each value can be a scalar (in which case the
4356 *     ColumnLength attribute has a value of 1), or a multi-dimensional
4357 *     array ( in which case the ColumnLength value is equal to the
4358 *     product of the array dimensions).
4359 
4360 *  Applicability:
4361 *     Table
4362 *        All Tables have this attribute.
4363 
4364 *att--
4365 */
4366 
4367 /*
4368 *att++
4369 *  Name:
4370 *     ColumnNdim(column)
4371 
4372 *  Purpose:
4373 *     The number of axes spanned by each value in a column
4374 
4375 *  Type:
4376 *     Public attribute.
4377 
4378 *  Synopsis:
4379 *     Integer, read-only.
4380 
4381 *  Description:
4382 *     This attribute holds the number of axes spanned by each value in a
4383 *     column. If each cell in the column is a scalar, ColumnNdim will be
4384 *     zero. If each cell in the column is a 1D spectrum, ColumnNdim will
4385 *     be one. If each cell in the column is a 2D image, ColumnNdim will be
4386 *     two, etc. The required column name should be placed inside the
4387 *     parentheses in the attribute name.
4388 
4389 *  Applicability:
4390 *     Table
4391 *        All Tables have this attribute.
4392 
4393 *att--
4394 */
4395 
4396 /*
4397 *att++
4398 *  Name:
4399 *     ColumnType(column)
4400 
4401 *  Purpose:
4402 *     The data type of each value in a column
4403 
4404 *  Type:
4405 *     Public attribute.
4406 
4407 *  Synopsis:
4408 *     Integer, read-only.
4409 
4410 *  Description:
4411 *     This attribute holds a integer value indicating the data type of
4412 *     a named column in a Table. This is the data type which was used
4413 *     when the column was added to the Table using astAddColumn. The
4414 *     required column name should be placed inside the parentheses in
4415 *     the attribute name.
4416 *
4417 *     The attribute value will be one of AST__INTTYPE (for integer),
4418 *     AST__SINTTYPE (for
4419 c     short int),
4420 f     INTEGER*2),
4421 *     AST__BYTETYPE (for
4422 c     unsigned bytes - i.e. unsigned chars),
4423 f     bytes),
4424 *     AST__DOUBLETYPE (for double
4425 *     precision floating point), AST__FLOATTYPE (for single
4426 *     precision floating point), AST__STRINGTYPE (for character string),
4427 *     AST__OBJECTTYPE (for AST Object pointer), AST__POINTERTYPE (for
4428 *     arbitrary C pointer) or AST__UNDEFTYPE (for undefined values
4429 *     created by
4430 c     astMapPutU).
4431 f     AST_MAPPUTU).
4432 
4433 *  Applicability:
4434 *     Table
4435 *        All Tables have this attribute.
4436 
4437 *att--
4438 */
4439 
4440 /*
4441 *att++
4442 *  Name:
4443 *     Ncolumn
4444 
4445 *  Purpose:
4446 *     The number of columns in the table.
4447 
4448 *  Type:
4449 *     Public attribute.
4450 
4451 *  Synopsis:
4452 *     Integer, read-only.
4453 
4454 *  Description:
4455 *     This attribute holds the number of columns currently in the table. Columns
4456 *     are added and removed using the
4457 c     astAddColumn and astRemoveColumn
4458 f     AST_ADDCOLUMN and AST_REMOVECOLUMN
4459 *     functions.
4460 
4461 *  Applicability:
4462 *     Table
4463 *        All Tables have this attribute.
4464 
4465 *att--
4466 */
4467 
4468 /*
4469 *att++
4470 *  Name:
4471 *     Nparameter
4472 
4473 *  Purpose:
4474 *     The number of global parameters in the table.
4475 
4476 *  Type:
4477 *     Public attribute.
4478 
4479 *  Synopsis:
4480 *     Integer, read-only.
4481 
4482 *  Description:
4483 *     This attribute holds the number of global parameters currently in the table.
4484 *     Parameters are added and removed using the
4485 c     astAddParameter and astRemoveParameter
4486 f     AST_ADDPARAMETER and AST_REMOVEPARAMETER
4487 *     functions.
4488 
4489 *  Applicability:
4490 *     Table
4491 *        All Tables have this attribute.
4492 
4493 *att--
4494 */
4495 
4496 /*
4497 *att++
4498 *  Name:
4499 *     Nrow
4500 
4501 *  Purpose:
4502 *     The number of rows in the table.
4503 
4504 *  Type:
4505 *     Public attribute.
4506 
4507 *  Synopsis:
4508 *     Integer, read-only.
4509 
4510 *  Description:
4511 *     This attribute holds the index of the last row to which any
4512 *     contents have been added using any of the
4513 *     astMapPut...
4514 *     AST_MAPPUT...
4515 *     functions. The first row has index 1.
4516 
4517 *  Applicability:
4518 *     Table
4519 *        All Tables have this attribute.
4520 
4521 *att--
4522 */
4523 astMAKE_GET(Table,Nrow,int,0,this->nrow)
astMAKE_SET(Table,Nrow,int,nrow,value)4524 astMAKE_SET(Table,Nrow,int,nrow,value)
4525 
4526 
4527 
4528 /* Copy constructor. */
4529 /* ----------------- */
4530 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
4531 /*
4532 *  Name:
4533 *     Copy
4534 
4535 *  Purpose:
4536 *     Copy constructor for Table objects.
4537 
4538 *  Type:
4539 *     Private function.
4540 
4541 *  Synopsis:
4542 *     void Copy( const AstObject *objin, AstObject *objout, int *status )
4543 
4544 *  Description:
4545 *     This function implements the copy constructor for Table objects.
4546 
4547 *  Parameters:
4548 *     objin
4549 *        Pointer to the object to be copied.
4550 *     objout
4551 *        Pointer to the object being constructed.
4552 *     status
4553 *        Pointer to the inherited status variable.
4554 
4555 *  Returned Value:
4556 *     void
4557 
4558 *  Notes:
4559 *     -  This constructor makes a deep copy, including a copy of the component
4560 *     Mappings within the Table.
4561 */
4562 
4563 /* Local Variables: */
4564    AstTable *in;                /* Pointer to input Table */
4565    AstTable *out;               /* Pointer to output Table */
4566 
4567 /* Check the global error status. */
4568    if ( !astOK ) return;
4569 
4570 /* Obtain pointers to the input and output Tables. */
4571    in = (AstTable *) objin;
4572    out = (AstTable *) objout;
4573 
4574 /* Make copies of the component KeyMaps and store pointers to them in the
4575    output Table structure. */
4576    out->columns = in->columns ? astCopy( in->columns ) : NULL;
4577    out->parameters = in->parameters ? astCopy( in->parameters ) : NULL;
4578 }
4579 
4580 
4581 /* Destructor. */
4582 /* ----------- */
Delete(AstObject * obj,int * status)4583 static void Delete( AstObject *obj, int *status ) {
4584 /*
4585 *  Name:
4586 *     Delete
4587 
4588 *  Purpose:
4589 *     Destructor for Table objects.
4590 
4591 *  Type:
4592 *     Private function.
4593 
4594 *  Synopsis:
4595 *     void Delete( AstObject *obj, int *status )
4596 
4597 *  Description:
4598 *     This function implements the destructor for Table objects.
4599 
4600 *  Parameters:
4601 *     obj
4602 *        Pointer to the object to be deleted.
4603 *     status
4604 *        Pointer to the inherited status variable.
4605 
4606 *  Returned Value:
4607 *     void
4608 
4609 *  Notes:
4610 *     This function attempts to execute even if the global error status is
4611 *     set.
4612 */
4613 
4614 /* Local Variables: */
4615    AstTable *this;              /* Pointer to Table */
4616 
4617 /* Obtain a pointer to the Table structure. */
4618    this = (AstTable *) obj;
4619 
4620 /* Annul the pointers to the component KeyMaps. */
4621    if( this->columns ) this->columns = astAnnul( this->columns );
4622    if( this->parameters ) this->parameters = astAnnul( this->parameters );
4623 
4624 }
4625 
4626 
4627 /* Dump function. */
4628 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)4629 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
4630 /*
4631 *  Name:
4632 *     Dump
4633 
4634 *  Purpose:
4635 *     Dump function for Table objects.
4636 
4637 *  Type:
4638 *     Private function.
4639 
4640 *  Synopsis:
4641 *     void Dump( AstObject *this, AstChannel *channel, int *status )
4642 
4643 *  Description:
4644 *     This function implements the Dump function which writes out data
4645 *     for the Table class to an output Channel.
4646 
4647 *  Parameters:
4648 *     this
4649 *        Pointer to the Table whose data are being written.
4650 *     channel
4651 *        Pointer to the Channel to which the data are being written.
4652 *     status
4653 *        Pointer to the inherited status variable.
4654 */
4655 
4656 /* Local Variables: */
4657    AstTable *this;             /* Pointer to the Table structure */
4658 
4659 /* Check the global error status. */
4660    if ( !astOK ) return;
4661 
4662 /* Obtain a pointer to the Table structure. */
4663    this = (AstTable *) this_object;
4664 
4665 /* Write out values representing the instance variables for the Table
4666    class.  Note, the primitive data in the Table will be written out
4667    by the parent KeyMap Dump function. This function deals just with the
4668    extra information held in the Table structure. */
4669 
4670 /* Write out the number of rows in the table. */
4671    astWriteInt( channel, "Nrow", 1, 1, astGetNrow( this ),
4672                 "Number of rows in table" );
4673 
4674 /* Write out the KeyMap holding definitions of each column. */
4675    if( this->columns ) {
4676       astWriteObject( channel, "Columns", 1, 0, this->columns, "KeyMap holding "
4677                       "column definitions" );
4678    }
4679 
4680 /* Write out the KeyMap holding definitions of each global parameter. */
4681    if( this->parameters ) {
4682       astWriteObject( channel, "Params", 1, 0, this->parameters, "KeyMap holding "
4683                       "parameter definitions" );
4684    }
4685 }
4686 
4687 
4688 
4689 
4690 
4691 
4692 /* Standard class functions. */
4693 /* ========================= */
4694 /* Implement the astIsATable and astCheckTable functions using the macros
4695    defined for this purpose in the "object.h" header file. */
astMAKE_ISA(Table,KeyMap)4696 astMAKE_ISA(Table,KeyMap)
4697 astMAKE_CHECK(Table)
4698 
4699 AstTable *astTable_( const char *options, int *status, ...) {
4700 /*
4701 *++
4702 *  Name:
4703 c     astTable
4704 f     AST_TABLE
4705 
4706 *  Purpose:
4707 *     Create a Table.
4708 
4709 *  Type:
4710 *     Public function.
4711 
4712 *  Synopsis:
4713 c     #include "table.h"
4714 c     AstTable *astTable( const char *options, ... )
4715 f     RESULT = AST_TABLE( OPTIONS, STATUS )
4716 
4717 *  Class Membership:
4718 *     Table constructor.
4719 
4720 *  Description:
4721 *     This function creates a new empty Table and optionally initialises
4722 *     its attributes.
4723 *
4724 *     The Table class is a type of KeyMap that represents a two-dimensional
4725 *     table of values. The
4726 c     astMapGet... and astMapPut...
4727 f     AST_MAPGET... and AST_MAPPUT...
4728 *     methods provided by the KeyMap class should be used for storing and
4729 *     retrieving values from individual cells within a Table. Each entry
4730 *     in the KeyMap represents a single cell of the table and has an
4731 *     associated key of the form "<COL>(i)" where "<COL>" is the name of a
4732 *     table column and "i" is the row index (the first row is row 1). Keys
4733 *     of this form should always be used when using KeyMap methods to access
4734 *     entries within a Table.
4735 *
4736 *     Columns must be declared using the
4737 c     astAddColumn
4738 f     AST_ADDCOLUMN
4739 *     method before values can be stored within them. This also fixes the
4740 *     type and shape of the values that may be stored in any cell of the
4741 *     column. Cells may contain scalar or vector values of any data type
4742 *     supported by the KeyMap class. Multi-dimensional arrays may also be
4743 *     stored, but these must be vectorised when storing and retrieving
4744 *     them within a table cell. All cells within a single column must
4745 *     have the same type and shape (specified when the column is declared).
4746 *
4747 *     Tables may have parameters that describe global properties of the
4748 *     entire table. These are stored as entries in the parent KeyMap and
4749 *     can be access using the get and set method of the KeyMap class.
4750 *     However, parameters must be declared using the
4751 c     astAddParameter
4752 f     AST_ADDPARAMETER
4753 *     method before being accessed.
4754 *
4755 *     Note - since accessing entries within a KeyMap is a relatively slow
4756 *     process, it is not recommended to use the Table class to store
4757 *     very large tables.
4758 
4759 *  Parameters:
4760 c     options
4761 f     OPTIONS = CHARACTER * ( * ) (Given)
4762 c        Pointer to a null-terminated string containing an optional
4763 c        comma-separated list of attribute assignments to be used for
4764 c        initialising the new Table. The syntax used is identical to
4765 c        that for the astSet function and may include "printf" format
4766 c        specifiers identified by "%" symbols in the normal way.
4767 f        A character string containing an optional comma-separated
4768 f        list of attribute assignments to be used for initialising the
4769 f        new Table. The syntax used is identical to that for the
4770 f        AST_SET routine.
4771 c     ...
4772 c        If the "options" string contains "%" format specifiers, then
4773 c        an optional list of additional arguments may follow it in
4774 c        order to supply values to be substituted for these
4775 c        specifiers. The rules for supplying these are identical to
4776 c        those for the astSet function (and for the C "printf"
4777 c        function).
4778 f     STATUS = INTEGER (Given and Returned)
4779 f        The global status.
4780 
4781 *  Returned Value:
4782 c     astTable()
4783 f     AST_TABLE = INTEGER
4784 *        A pointer to the new Table.
4785 
4786 *  Notes:
4787 *     - A null Object pointer (AST__NULL) will be returned if this
4788 c     function is invoked with the AST error status set, or if it
4789 f     function is invoked with STATUS set to an error value, or if it
4790 *     should fail for any reason.
4791 
4792 *  Status Handling:
4793 *     The protected interface to this function includes an extra
4794 *     parameter at the end of the parameter list described above. This
4795 *     parameter is a pointer to the integer inherited status
4796 *     variable: "int *status".
4797 
4798 *--
4799 */
4800 
4801 /* Local Variables: */
4802    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
4803    AstTable *new;              /* Pointer to new Table */
4804    va_list args;                 /* Variable argument list */
4805 
4806 /* Get a pointer to the thread specific global data structure. */
4807    astGET_GLOBALS(NULL);
4808 
4809 /* Check the global status. */
4810    if ( !astOK ) return NULL;
4811 
4812 /* Initialise the Table, allocating memory and initialising the
4813    virtual function table as well if necessary. */
4814    new = astInitTable( NULL, sizeof( AstTable ), !class_init, &class_vtab,
4815                        "Table" );
4816 
4817 /* If successful, note that the virtual function table has been
4818    initialised. */
4819    if ( astOK ) {
4820       class_init = 1;
4821 
4822 /* Obtain the variable argument list and pass it along with the options string
4823    to the astVSet method to initialise the new Table's attributes. */
4824       va_start( args, status );
4825       astVSet( new, options, NULL, args );
4826       va_end( args );
4827 
4828 /* If an error occurred, clean up by deleting the new object. */
4829       if ( !astOK ) new = astDelete( new );
4830    }
4831 
4832 /* Return a pointer to the new Table. */
4833    return new;
4834 }
4835 
astTableId_(const char * options,...)4836 AstTable *astTableId_( const char *options, ... ) {
4837 /*
4838 *  Name:
4839 *     astTableId_
4840 
4841 *  Purpose:
4842 *     Create a Table.
4843 
4844 *  Type:
4845 *     Private function.
4846 
4847 *  Synopsis:
4848 *     #include "table.h"
4849 *     AstTable *astTableId_( const char *options, ... )
4850 
4851 *  Class Membership:
4852 *     Table constructor.
4853 
4854 *  Description:
4855 *     This function implements the external (public) interface to the
4856 *     astTable constructor function. It returns an ID value (instead
4857 *     of a true C pointer) to external users, and must be provided
4858 *     because astTable_ has a variable argument list which cannot be
4859 *     encapsulated in a macro (where this conversion would otherwise
4860 *     occur).
4861 *
4862 *     The variable argument list also prevents this function from
4863 *     invoking astTable_ directly, so it must be a re-implementation
4864 *     of it in all respects, except for the final conversion of the
4865 *     result to an ID value.
4866 
4867 *  Parameters:
4868 *     As for astTable_.
4869 
4870 *  Returned Value:
4871 *     The ID value associated with the new Table.
4872 */
4873 
4874 /* Local Variables: */
4875    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
4876    AstTable *new;                /* Pointer to new Table */
4877    va_list args;                 /* Variable argument list */
4878 
4879    int *status;                  /* Pointer to inherited status value */
4880 
4881 /* Get a pointer to the inherited status value. */
4882    status = astGetStatusPtr;
4883 
4884 /* Get a pointer to the thread specific global data structure. */
4885    astGET_GLOBALS(NULL);
4886 
4887 /* Check the global status. */
4888    if ( !astOK ) return NULL;
4889 
4890 /* Initialise the Table, allocating memory and initialising the
4891    virtual function table as well if necessary. */
4892    new = astInitTable( NULL, sizeof( AstTable ), !class_init, &class_vtab,
4893                          "Table" );
4894 
4895 /* If successful, note that the virtual function table has been
4896    initialised. */
4897    if ( astOK ) {
4898       class_init = 1;
4899 
4900 /* Obtain the variable argument list and pass it along with the options string
4901    to the astVSet method to initialise the new Table's attributes. */
4902       va_start( args, options );
4903       astVSet( new, options, NULL, args );
4904       va_end( args );
4905 
4906 /* If an error occurred, clean up by deleting the new object. */
4907       if ( !astOK ) new = astDelete( new );
4908    }
4909 
4910 /* Return an ID value for the new Table. */
4911    return astMakeId( new );
4912 }
4913 
astInitTable_(void * mem,size_t size,int init,AstTableVtab * vtab,const char * name,int * status)4914 AstTable *astInitTable_( void *mem, size_t size, int init,
4915                          AstTableVtab *vtab, const char *name, int *status ) {
4916 /*
4917 *+
4918 *  Name:
4919 *     astInitTable
4920 
4921 *  Purpose:
4922 *     Initialise a Table.
4923 
4924 *  Type:
4925 *     Protected function.
4926 
4927 *  Synopsis:
4928 *     #include "table.h"
4929 *     AstTable *astInitTable( void *mem, size_t size, int init,
4930 *                                 AstTableVtab *vtab, const char *name )
4931 
4932 *  Class Membership:
4933 *     Table initialiser.
4934 
4935 *  Description:
4936 *     This function is provided for use by class implementations to initialise
4937 *     a new Table object. It allocates memory (if necessary) to accommodate
4938 *     the Table plus any additional data associated with the derived class.
4939 *     It then initialises a Table structure at the start of this memory. If
4940 *     the "init" flag is set, it also initialises the contents of a virtual
4941 *     function table for a Table at the start of the memory passed via the
4942 *     "vtab" parameter.
4943 
4944 *  Parameters:
4945 *     mem
4946 *        A pointer to the memory in which the Table is to be initialised.
4947 *        This must be of sufficient size to accommodate the Table data
4948 *        (sizeof(Table)) plus any data used by the derived class. If a value
4949 *        of NULL is given, this function will allocate the memory itself using
4950 *        the "size" parameter to determine its size.
4951 *     size
4952 *        The amount of memory used by the Table (plus derived class data).
4953 *        This will be used to allocate memory if a value of NULL is given for
4954 *        the "mem" parameter. This value is also stored in the Table
4955 *        structure, so a valid value must be supplied even if not required for
4956 *        allocating memory.
4957 *     init
4958 *        A logical flag indicating if the Table's virtual function table is
4959 *        to be initialised. If this value is non-zero, the virtual function
4960 *        table will be initialised by this function.
4961 *     vtab
4962 *        Pointer to the start of the virtual function table to be associated
4963 *        with the new Table.
4964 *     name
4965 *        Pointer to a constant null-terminated character string which contains
4966 *        the name of the class to which the new object belongs (it is this
4967 *        pointer value that will subsequently be returned by the astGetClass
4968 *        method).
4969 
4970 *  Returned Value:
4971 *     A pointer to the new Table.
4972 
4973 *  Notes:
4974 *     -  A null pointer will be returned if this function is invoked with the
4975 *     global error status set, or if it should fail for any reason.
4976 *-
4977 */
4978 
4979 /* Local Variables: */
4980    AstTable *new;              /* Pointer to new Table */
4981 
4982 /* Check the global status. */
4983    if ( !astOK ) return NULL;
4984 
4985 /* If necessary, initialise the virtual function table. */
4986    if ( init ) astInitTableVtab( vtab, name );
4987 
4988 /* Initialise. */
4989    new = NULL;
4990 
4991 /* Initialise a KeyMap structure (the parent class) as the first component
4992    within the Table structure, allocating memory if necessary. Specify that
4993    the KeyMap should be defined in both the forward and inverse directions. */
4994    new = (AstTable *) astInitKeyMap( mem, size, 0, (AstKeyMapVtab *) vtab,
4995                                      name );
4996    if ( astOK ) {
4997 
4998 /* Initialise the Table data. */
4999 /* ---------------------------- */
5000       new->nrow = 0;
5001       new->columns = astKeyMap( "KeyCase=0,Sortby=AgeDown", status );
5002       new->parameters = astKeyMap( "KeyCase=0,Sortby=AgeDown", status );
5003 
5004 /* Tables require the KeyCase attribute to be zero. */
5005       (*parent_setkeycase)( (AstKeyMap *) new, 0, status );
5006 
5007 /* If an error occurred, clean up by deleting the new Table. */
5008       if ( !astOK ) new = astDelete( new );
5009    }
5010 
5011 /* Return a pointer to the new Table. */
5012    return new;
5013 }
5014 
astLoadTable_(void * mem,size_t size,AstTableVtab * vtab,const char * name,AstChannel * channel,int * status)5015 AstTable *astLoadTable_( void *mem, size_t size, AstTableVtab *vtab,
5016                          const char *name, AstChannel *channel, int *status ) {
5017 /*
5018 *+
5019 *  Name:
5020 *     astLoadTable
5021 
5022 *  Purpose:
5023 *     Load a Table.
5024 
5025 *  Type:
5026 *     Protected function.
5027 
5028 *  Synopsis:
5029 *     #include "table.h"
5030 *     AstTable *astLoadTable( void *mem, size_t size, AstTableVtab *vtab,
5031 *                             const char *name, AstChannel *channel )
5032 
5033 *  Class Membership:
5034 *     Table loader.
5035 
5036 *  Description:
5037 *     This function is provided to load a new Table using data read
5038 *     from a Channel. It first loads the data used by the parent class
5039 *     (which allocates memory if necessary) and then initialises a
5040 *     Table structure in this memory, using data read from the input
5041 *     Channel.
5042 *
5043 *     If the "init" flag is set, it also initialises the contents of a
5044 *     virtual function table for a Table at the start of the memory
5045 *     passed via the "vtab" parameter.
5046 
5047 
5048 *  Parameters:
5049 *     mem
5050 *        A pointer to the memory into which the Table is to be
5051 *        loaded.  This must be of sufficient size to accommodate the
5052 *        Table data (sizeof(Table)) plus any data used by derived
5053 *        classes. If a value of NULL is given, this function will
5054 *        allocate the memory itself using the "size" parameter to
5055 *        determine its size.
5056 *     size
5057 *        The amount of memory used by the Table (plus derived class
5058 *        data).  This will be used to allocate memory if a value of
5059 *        NULL is given for the "mem" parameter. This value is also
5060 *        stored in the Table structure, so a valid value must be
5061 *        supplied even if not required for allocating memory.
5062 *
5063 *        If the "vtab" parameter is NULL, the "size" value is ignored
5064 *        and sizeof(AstTable) is used instead.
5065 *     vtab
5066 *        Pointer to the start of the virtual function table to be
5067 *        associated with the new Table. If this is NULL, a pointer
5068 *        to the (static) virtual function table for the Table class
5069 *        is used instead.
5070 *     name
5071 *        Pointer to a constant null-terminated character string which
5072 *        contains the name of the class to which the new object
5073 *        belongs (it is this pointer value that will subsequently be
5074 *        returned by the astGetClass method).
5075 *
5076 *        If the "vtab" parameter is NULL, the "name" value is ignored
5077 *        and a pointer to the string "Table" is used instead.
5078 
5079 *  Returned Value:
5080 *     A pointer to the new Table.
5081 
5082 *  Notes:
5083 *     - A null pointer will be returned if this function is invoked
5084 *     with the global error status set, or if it should fail for any
5085 *     reason.
5086 *-
5087 */
5088 
5089 /* Local Variables: */
5090    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
5091    AstTable *new;                /* Pointer to the new Table */
5092 
5093 /* Initialise. */
5094    new = NULL;
5095 
5096 /* Check the global error status. */
5097    if ( !astOK ) return new;
5098 
5099 /* Get a pointer to the thread specific global data structure. */
5100    astGET_GLOBALS(channel);
5101 
5102 /* If a NULL virtual function table has been supplied, then this is
5103    the first loader to be invoked for this Table. In this case the
5104    Table belongs to this class, so supply appropriate values to be
5105    passed to the parent class loader (and its parent, etc.). */
5106    if ( !vtab ) {
5107       size = sizeof( AstTable );
5108       vtab = &class_vtab;
5109       name = "Table";
5110 
5111 /* If required, initialise the virtual function table for this class. */
5112       if ( !class_init ) {
5113          astInitTableVtab( vtab, name );
5114          class_init = 1;
5115       }
5116    }
5117 
5118 /* Invoke the parent class loader to load data for all the ancestral
5119    classes of the current one, returning a pointer to the resulting
5120    partly-built Table. */
5121    new = astLoadKeyMap( mem, size, (AstKeyMapVtab *) vtab, name,
5122                          channel );
5123 
5124    if ( astOK ) {
5125 
5126 /* Read input data. */
5127 /* ================ */
5128 /* Request the input Channel to read all the input data appropriate to
5129    this class into the internal "values list". */
5130       astReadClassData( channel, "Table" );
5131 
5132 /* Now read each individual data item from this list and use it to
5133    initialise the appropriate instance variable(s) for this class. */
5134 
5135 /* The number of rows. */
5136       new->nrow = astReadInt( channel, "nrow", 0 );
5137 
5138 /* KeyMap holding columns definitions. */
5139       new->columns = astReadObject( channel, "columns", NULL );
5140 
5141 /* KeyMap holding parameter definitions. */
5142       new->parameters = astReadObject( channel, "params", NULL );
5143 
5144 /* If an error occurred, clean up by deleting the new Table. */
5145       if ( !astOK ) new = astDelete( new );
5146    }
5147 
5148 /* Return the new Table pointer. */
5149    return new;
5150 }
5151 
5152 /* Virtual function interfaces. */
5153 /* ============================ */
5154 /* These provide the external interface to the virtual functions defined by
5155    this class. Each simply checks the global error status and then locates and
5156    executes the appropriate member function, using the function pointer stored
5157    in the object's virtual function table (this pointer is located using the
5158    astMEMBER macro defined in "object.h").
5159 
5160    Note that the member function may not be the one defined here, as it may
5161    have been over-ridden by a derived class. However, it should still have the
5162    same interface. */
5163 
astAddColumn_(AstTable * this,const char * name,int type,int ndim,int * dims,const char * unit,int * status)5164 void astAddColumn_( AstTable *this, const char *name, int type,
5165                     int ndim, int *dims, const char *unit, int *status ) {
5166    if ( !astOK ) return;
5167    (**astMEMBER(this,Table,AddColumn))(this,name,type,ndim,dims,unit,status);
5168 }
astAddParameter_(AstTable * this,const char * name,int * status)5169 void astAddParameter_( AstTable *this, const char *name, int *status ) {
5170    if ( !astOK ) return;
5171    (**astMEMBER(this,Table,AddParameter))(this,name,status);
5172 }
astRemoveColumn_(AstTable * this,const char * name,int * status)5173 void astRemoveColumn_( AstTable *this, const char *name, int *status ){
5174    if ( !astOK ) return;
5175    (**astMEMBER(this,Table,RemoveColumn))(this,name,status);
5176 }
astRemoveParameter_(AstTable * this,const char * name,int * status)5177 void astRemoveParameter_( AstTable *this, const char *name, int *status ){
5178    if ( !astOK ) return;
5179    (**astMEMBER(this,Table,RemoveParameter))(this,name,status);
5180 }
astRemoveRow_(AstTable * this,int index,int * status)5181 void astRemoveRow_( AstTable *this, int index, int *status ){
5182    if ( !astOK ) return;
5183    (**astMEMBER(this,Table,RemoveRow))(this,index,status);
5184 }
astPurgeRows_(AstTable * this,int * status)5185 void astPurgeRows_( AstTable *this, int *status ){
5186    if ( !astOK ) return;
5187    (**astMEMBER(this,Table,PurgeRows))(this,status);
5188 }
astGetNcolumn_(AstTable * this,int * status)5189 int astGetNcolumn_( AstTable *this, int *status ) {
5190    if ( !astOK ) return 0;
5191    return (**astMEMBER(this,Table,GetNcolumn))( this, status );
5192 }
astGetNparameter_(AstTable * this,int * status)5193 int astGetNparameter_( AstTable *this, int *status ) {
5194    if ( !astOK ) return 0;
5195    return (**astMEMBER(this,Table,GetNparameter))( this, status );
5196 }
astColumnName_(AstTable * this,int index,int * status)5197 const char *astColumnName_( AstTable *this, int index, int *status ){
5198    if ( !astOK ) return NULL;
5199    return (**astMEMBER(this,Table,ColumnName))(this,index,status);
5200 }
astParameterName_(AstTable * this,int index,int * status)5201 const char *astParameterName_( AstTable *this, int index, int *status ){
5202    if ( !astOK ) return NULL;
5203    return (**astMEMBER(this,Table,ParameterName))(this,index,status);
5204 }
astGetColumnType_(AstTable * this,const char * column,int * status)5205 int astGetColumnType_( AstTable *this, const char *column, int *status ){
5206    if ( !astOK ) return 0;
5207    return (**astMEMBER(this,Table,GetColumnType))(this,column,status);
5208 }
astGetColumnUnit_(AstTable * this,const char * column,int * status)5209 const char *astGetColumnUnit_( AstTable *this, const char *column, int *status ){
5210    if ( !astOK ) return NULL;
5211    return (**astMEMBER(this,Table,GetColumnUnit))(this,column,status);
5212 }
astGetColumnLenC_(AstTable * this,const char * column,int * status)5213 int astGetColumnLenC_( AstTable *this, const char *column, int *status ){
5214    if ( !astOK ) return 0;
5215    return (**astMEMBER(this,Table,GetColumnLenC))(this,column,status);
5216 }
astGetColumnLength_(AstTable * this,const char * column,int * status)5217 int astGetColumnLength_( AstTable *this, const char *column, int *status ){
5218    if ( !astOK ) return 0;
5219    return (**astMEMBER(this,Table,GetColumnLength))(this,column,status);
5220 }
astGetColumnNdim_(AstTable * this,const char * column,int * status)5221 int astGetColumnNdim_( AstTable *this, const char *column, int *status ){
5222    if ( !astOK ) return 0;
5223    return (**astMEMBER(this,Table,GetColumnNdim))(this,column,status);
5224 }
astColumnShape_(AstTable * this,const char * column,int mxdim,int * ndim,int * dims,int * status)5225 void astColumnShape_( AstTable *this, const char *column, int mxdim,
5226                       int *ndim, int *dims, int *status ){
5227    if ( !astOK ) return;
5228    (**astMEMBER(this,Table,ColumnShape))( this, column, mxdim, ndim,
5229                                           dims, status );
5230 }
astColumnProps_(AstTable * this,int * status)5231 AstKeyMap *astColumnProps_( AstTable *this, int *status ){
5232    if ( !astOK ) return NULL;
5233    return (**astMEMBER(this,Table,ColumnProps))(this,status);
5234 }
astParameterProps_(AstTable * this,int * status)5235 AstKeyMap *astParameterProps_( AstTable *this, int *status ){
5236    if ( !astOK ) return NULL;
5237    return (**astMEMBER(this,Table,ParameterProps))(this,status);
5238 }
astHasColumn_(AstTable * this,const char * column,int * status)5239 int astHasColumn_( AstTable *this, const char *column, int *status ){
5240    if ( !astOK ) return 0;
5241    return (**astMEMBER(this,Table,HasColumn))(this,column,status);
5242 }
astHasParameter_(AstTable * this,const char * parameter,int * status)5243 int astHasParameter_( AstTable *this, const char *parameter, int *status ){
5244    if ( !astOK ) return 0;
5245    return (**astMEMBER(this,Table,HasParameter))(this,parameter,status);
5246 }
5247