diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 16:22:37 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 16:22:37 (GMT) |
commit | e9ad1f4c4c12164247d284f2d1824b75e35de23f (patch) | |
tree | 3c7ffeed177d1ed92ce83f6d9222aa6a08a2847d /ast/xmlchan.c | |
parent | 5492ad5105428df25cca70ab260229f757427278 (diff) | |
download | blt-e9ad1f4c4c12164247d284f2d1824b75e35de23f.zip blt-e9ad1f4c4c12164247d284f2d1824b75e35de23f.tar.gz blt-e9ad1f4c4c12164247d284f2d1824b75e35de23f.tar.bz2 |
upgrade ast 8.7.1
Diffstat (limited to 'ast/xmlchan.c')
-rw-r--r-- | ast/xmlchan.c | 14120 |
1 files changed, 0 insertions, 14120 deletions
diff --git a/ast/xmlchan.c b/ast/xmlchan.c deleted file mode 100644 index bf7aad9..0000000 --- a/ast/xmlchan.c +++ /dev/null @@ -1,14120 +0,0 @@ -/* -*class++ -* Name: -* XmlChan - -* Purpose: -* I/O Channel using XML to represent Objects. - -* Constructor Function: -c astXmlChan -f AST_XMLCHAN - -* Description: -* A XmlChan is a specialised form of Channel which supports XML I/O -* operations. Writing an Object to an XmlChan (using -c astWrite) will, if the Object is suitable, generate an -f AST_WRITE) will, if the Object is suitable, generate an -* XML description of that Object, and reading from an XmlChan will -* create a new Object from its XML description. -* -* Normally, when you use an XmlChan, you should provide "source" -c and "sink" functions which connect it to an external data store -c by reading and writing the resulting XML text. These functions -f and "sink" routines which connect it to an external data store -f by reading and writing the resulting XML text. These routines -* should perform any conversions needed between external character -c encodings and the internal ASCII encoding. If no such functions -f encodings and the internal ASCII encoding. If no such routines -* are supplied, a Channel will read from standard input and write -* to standard output. -* -* Alternatively, an XmlChan can be told to read or write from -* specific text files using the SinkFile and SourceFile attributes, -* in which case no sink or source function need be supplied. - -* Inheritance: -* The XmlChan class inherits from the Channel class. - -* Attributes: -* In addition to those attributes common to all Channels, every -* XmlChan also has the following attributes: -* -* - XmlFormat: System for formatting Objects as XML -* - XmlLength: Controls output buffer length -* - XmlPrefix: The namespace prefix to use when writing - -* Functions: -c The XmlChan class does not define any new functions beyond those -f The XmlChan class does not define any new routines beyond those -* which are applicable to all Mappings. - -* Copyright: -* Copyright (C) 1997-2006 Council for the Central Laboratory of the -* Research Councils -* Copyright (C) 2009 Science & Technology Facilities Council. -* All Rights Reserved. - -* Licence: -* This program is free software: you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation, either -* version 3 of the License, or (at your option) any later -* version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General -* License along with this program. If not, see -* <http://www.gnu.org/licenses/>. - -* Authors: -* DSB: David Berry (Starlink) - -* History: -* 10-OCT-2003 (DSB): -* Original version. -* 6-FEB-2004 (DSB): -* Added XmlPrefix and XmlFormat attributes. -* 10-FEB-2004 (DSB): -* - Added debug conditional code to keep track of memory leaks. -* - Fixed bug which prevented more than 1 object being read from -* an XmlChan. -* 7-DEC-2005 (DSB): -* Free memory allocated by calls to astReadString. -* 12-FEB-2010 (DSB): -* Represent AST__BAD externally using the string "<bad>". -*class-- - -* Further STC work: -* - Speed up general STC processing (a lot of time seems to be spent -* simplifying things) -* - Document (including a complete description of what is and is not -* supported in the reference docs for the XmlFormat attribute). -* - Produce a schema describing the format which can in fact be read by -* AST. -* - Look at Jonathan McDowell's mini-STC schema (also STC stuff in -* spectral data model) -* - Web services. Read only: test STCs for overlap, test points for -* inclusion/exclusion, plot a mask over an image, verification (can AST -* read it & does it generate warnings?). Read/Write: convert FITS to STC, -* transform STC into a new coord system. -* - Add support for writing as well as reading -* - Modify Stc... constructors to check that the supplied Frame is suitable. -* - What about multiple AstroCoordFrames and AstroCoordAreas in a STC? -* - Add support for generic CoordFrames -* - What should be done with pixel coords info within STC? -* - Extend coverage (e.g. to 3D space frames, etc) - -*/ - -/* Module Macros. */ -/* ============== */ -/* Set the name of the class we are implementing. This indicates to - the header files that define class interfaces that they should make - "protected" symbols available. */ -#define astCLASS XmlChan - -/* The XML element name used to store an AST attribute setting */ -#define ATTR "_attribute" - -/* The XML element name used for an AST "isa" element */ -#define ISA "_isa" - -/* The XML attribute name which holds the name of the AST class which - defines the item contained in the element. */ -#define DEFINEDBY "definedby" - -/* The XML attribute name which holds the name of the AST attribute */ -#define NAME "name" - -/* The XML attribute name which holds the value of the AST attribute */ -#define VALUE "value" - -/* The XML attribute name which indicates if the AST attribute value is a - default value. */ -#define DEFAULT "default" - -/* The XML attribute name which indicates if the AST attribute value was - originally a string value. */ -#define QUOTED "quoted" - -/* The XML attribute name which holds a description of the AST attribute. */ -#define DESC "desc" - -/* The XML attribute name which holds the label associated with an AST - Object (if any). */ -#define LABEL "label" - -/* A string used to indicate atrue attribute value */ -#define TRUE "true" - -/* Format identifiers and strings */ -#define UNKNOWN_FORMAT -1 -#define NATIVE_FORMAT 0 -#define QUOTED_FORMAT 1 -#define IVOA_FORMAT 2 -#define MAX_FORMAT 2 -#define UNKNOWN_STRING "UNKNOWN" -#define NATIVE_STRING "NATIVE" -#define QUOTED_STRING "QUOTED" -#define IVOA_STRING "IVOA" - -/* Values representing message severities. */ -#define WARNING 0 -#define FAILURE 1 -#define RESET 2 - -/* Known IVOA namespaces. When a new name is added, update the FindIVOAClass - function. */ -#define STC_URI "urn:nvo-stc" - -/* Known IVOA Classes and attributes. When a new name is added, it may be - necessary to update the FindIVOAClass function. */ -#define STC_RESOURCE_PROFILE "STCResourceProfile" -#define SEARCH_LOCATION "SearchLocation" -#define OBSERVATION_LOCATION "ObservationLocation" -#define OBSERVATORY_LOCATION "ObservatoryLocation" -#define CATALOG_ENTRY_LOCATION "CatalogEntryLocation" -#define OBS_DATA_LOCATION "ObsDataLocation" -#define ASTRO_COORD_SYSTEM "AstroCoordSystem" -#define ASTRO_COORD_AREA "AstroCoordArea" -#define ASTRO_COORDS "AstroCoords" -#define TIME_FRAME "TimeFrame" -#define SPACE_FRAME "SpaceFrame" -#define SPECTRAL_FRAME "SpectralFrame" -#define REDSHIFT_FRAME "RedshiftFrame" -#define DOPPLER_DEFINITION "DopplerDefinition" - -/* Returns string "an" or "a" depending on whether the first character of - the supplied string is a vowel or not. */ -#define ANA(t) (t?(strchr("AaEeIiOoUu",t[0])?"an":"a"):"") - -/* String used to represent AST__BAD externally. */ -#define BAD_STRING "<bad>" - -/* Include files. */ -/* ============== */ -/* Interface definitions. */ -/* ---------------------- */ - -#include "globals.h" /* Thread-safe global data access */ -#include "error.h" /* Error reporting facilities */ -#include "memory.h" /* Memory allocation facilities */ -#include "object.h" /* Base Object class */ -#include "frame.h" /* Coordinate Frames */ -#include "timeframe.h" /* Time coordinate Frames */ -#include "cmpframe.h" /* Coordinate Frames */ -#include "skyframe.h" /* Celestial coordinate Frames */ -#include "specframe.h" /* Spectral coordinate Frames */ -#include "region.h" /* Regions within coordinate Frames */ -#include "ellipse.h" /* Ellipses within coordinate Frames */ -#include "pointlist.h" /* Points within coordinate Frames */ -#include "polygon.h" /* Polygons within coordinate Frames */ -#include "circle.h" /* Circles within coordinate Frames */ -#include "keymap.h" /* Mapping of keys to values */ -#include "channel.h" /* Interface for parent class */ -#include "xmlchan.h" /* Interface definition for this class */ -#include "loader.h" /* Interface to the global loader */ -#include "object.h" /* Base Object class */ -#include "wcsmap.h" /* Angular conversion constants */ -#include "xml.h" /* AST XML facilities */ -#include "erfa.h" /* ERFA functions */ -#include "stcresourceprofile.h" /* IVOA StcResourceProfile class */ -#include "stcsearchlocation.h" /* IVOA SearchLocation class */ -#include "stccatalogentrylocation.h"/* IVOA CatalogEntryLocation class */ -#include "stcobsdatalocation.h" /* IVOA ObsDataLocation class */ -#include "nullregion.h" /* Null regions */ -#include "interval.h" /* Axis intervals */ -#include "box.h" /* Box regions */ -#include "cmpregion.h" /* Compound regions */ -#include "prism.h" /* Prism regions */ -#include "unitmap.h" /* Unit Mappings */ -#include "unit.h" /* Unit handling utilities */ -#include "pal.h" /* slalib functions */ -#include "globals.h" /* Thread-safe global data access */ - -/* Error code definitions. */ -/* ----------------------- */ -#include "ast_err.h" /* AST error codes */ - -/* C header files. */ -/* --------------- */ -#include <ctype.h> -#include <float.h> -#include <limits.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* Type Definitions */ -/* ================ */ - -/* A type for functions which read an IVOA element and return a - corresponding AST Object. */ -typedef AstObject *(*IVOAReader)( AstXmlChan *, AstXmlElement *, int * ); - -/* A structure to hold the result of scanning the content of an IVOA - element.*/ -typedef struct IVOAScan { - int n; /* Number of element names described by this structure */ - int *count; /* Array holding number of each element name found */ - AstXmlElement ***el; /* Array holding pointers to each element found */ -} IVOAScan; - -/* Module Variables. */ -/* ================= */ - -/* Address of this static variable is used as a unique identifier for - member of this class. */ -static int class_check; - -/* Pointers to parent class methods which are extended by this class. */ -static const char *(* parent_getattrib)( AstObject *, const char *, int * ); -static int (* parent_testattrib)( AstObject *, const char *, int * ); -static void (* parent_clearattrib)( AstObject *, const char *, int * ); -static void (* parent_setattrib)( AstObject *, const char *, int * ); -static int (* parent_getfull)( AstChannel *, int * ); -static int (* parent_getcomment)( AstChannel *, int * ); -static int (* parent_getindent)( AstChannel *, int * ); - -/* Text values used to represent XmlFormat values externally. These - should be in the order defined by the associated constants above. */ -static const char *xformat[3] = { NATIVE_STRING, QUOTED_STRING, IVOA_STRING }; - -/* Define macros for accessing each item of thread specific global data. */ -#ifdef THREAD_SAFE - -/* Define how to initialise thread-specific globals. */ -#define GLOBAL_inits \ - globals->Class_Init = 0; \ - globals->IsUsable_This = NULL; \ - globals->GetAttrib_Buff[ 0 ] = 0; \ - globals->GetNextChar_C = NULL; \ - globals->GetNextChar_Buf = NULL; - -/* Create the function that initialises global data for this module. */ -astMAKE_INITGLOBALS(XmlChan) - -/* Define macros for accessing each item of thread specific global data. */ -#define class_init astGLOBAL(XmlChan,Class_Init) -#define class_vtab astGLOBAL(XmlChan,Class_Vtab) -#define isusable_this astGLOBAL(XmlChan,IsUsable_This) -#define getattrib_buff astGLOBAL(XmlChan,GetAttrib_Buff) -#define getnextchar_c astGLOBAL(XmlChan,GetNextChar_C) -#define getnextchar_buf astGLOBAL(XmlChan,GetNextChar_Buf) - - - -/* If thread safety is not needed, declare and initialise globals at static - variables. */ -#else - -/* An XmlChan pointer use to communicate with the IsUsable function. */ -static AstXmlChan *isusable_this = NULL; - -/* Buffer returned by GetAttrib. */ -static char getattrib_buff[ 51 ]; - -/* Variables used in GetNextChar */ -static char *getnextchar_c = NULL; /* Pointer to next character to read */ -static char *getnextchar_buf = NULL; /* Pointer to previously read text */ - - -/* Define the class virtual function table and its initialisation flag - as static variables. */ -static AstXmlChanVtab class_vtab; /* Virtual function table */ -static int class_init = 0; /* Virtual function table initialised? */ - -#endif - - -/* External Interface Function Prototypes. */ -/* ======================================= */ -/* The following functions have public prototypes only (i.e. no - protected prototypes), so we must provide local prototypes for use - within this module. */ -AstXmlChan *astXmlChanForId_( const char *(*)( void ), - char *(*)( const char *(*)( void ), int * ), - void (*)( const char * ), - void (*)( void (*)( const char * ), const char *, int * ), - const char *, ... ); -AstXmlChan *astXmlChanId_( const char *(* source)( void ), - void (* sink)( const char * ), - const char *options, ... ); - -/* Prototypes for Private Member Functions. */ -/* ======================================== */ -static AstObject *AstroCoordSystemReader( AstXmlChan *, AstXmlElement *, int * ); -static AstObject *MakeAstFromXml( AstXmlChan *, AstXmlElement *, int * ); -static AstObject *ObsDataLocationReader( AstXmlChan *, AstXmlElement *, int * ); -static AstObject *Read( AstChannel *, int * ); -static AstObject *ReadObject( AstChannel *, const char *, AstObject *, int * ); -static AstObject *RedshiftFrameReader( AstXmlChan *, AstXmlElement *, int * ); -static AstObject *SpaceFrameReader( AstXmlChan *, AstXmlElement *, int * ); -static AstObject *SpectralFrameReader( AstXmlChan *, AstXmlElement *, int * ); -static AstObject *StcMetadataReader( AstXmlChan *, AstXmlElement *, int * ); -static AstObject *TimeFrameReader( AstXmlChan *, AstXmlElement *, int * ); -static AstPointList *ObservatoryLocationReader( AstXmlChan *, AstXmlElement *, AstStcObsDataLocation *, int * ); -static AstRegion *AllSkyReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *AstroCoordAreaReader( AstXmlChan *, AstXmlElement *, AstFrame *, AstRegion *[4], int, AstKeyMap **, int * ); -static AstRegion *BoxReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *CircleReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *ConstraintReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *ConvexReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *Coord2VecIntervalReader( AstXmlChan *, AstXmlElement *, const char *, AstFrame *, int * ); -static AstRegion *Coord3VecIntervalReader( AstXmlChan *, AstXmlElement *, const char *, AstFrame *, int * ); -static AstRegion *CoordScalarIntervalReader( AstXmlChan *, AstXmlElement *, const char *, AstFrame *, int * ); -static AstRegion *EllipseReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *IntersectionReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *NegationReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *PolygonReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *Position2DReader( AstXmlChan *, AstXmlElement *, AstFrame *, double *, AstKeyMap **, int * ); -static AstRegion *PositionIntervalReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *RedshiftIntervalReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *RedshiftReader( AstXmlChan *, AstXmlElement *, AstFrame *, AstKeyMap **, int * ); -static AstRegion *StcRegionReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *RegionReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *SpectralIntervalReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *SpectralReader( AstXmlChan *, AstXmlElement *, AstFrame *, double *, AstKeyMap **, int * ); -static AstRegion *SphereReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstRegion *TimeIntervalReader( AstXmlChan *, AstXmlElement *, AstTimeFrame *, int * ); -static AstRegion *TimeReader( AstXmlChan *, AstXmlElement *, AstTimeFrame *, double *, AstKeyMap **, int * ); -static AstRegion *UnionReader( AstXmlChan *, AstXmlElement *, AstFrame *, int * ); -static AstSystemType RedshiftSys( AstXmlChan *, AstXmlElement *, char **, int, int * ); -static AstSystemType SpecSys( AstXmlChan *, AstXmlElement *, const char *, int, int * ); -static AstXmlElement *FindAttribute( AstXmlChan *, const char *, int * ); -static AstXmlElement *FindElement( AstXmlChan *, AstXmlElement *, const char *, int * ); -static AstXmlElement *FindObject( AstXmlChan *, const char *, int * ); -static AstXmlElement *MakePos2D( AstXmlChan *, AstXmlElement *, int * ); -static AstXmlElement *ReadXmlText( AstXmlChan *, int * ); -static AstXmlElement *Remove( AstXmlChan *, AstXmlElement *, int * ); -static IVOAReader FindIVOAClass( AstXmlElement *, int *, int * ); -static IVOAScan *FreeIVOAScan( IVOAScan *, int * ); -static IVOAScan *ScanIVOAElement( AstXmlChan *, AstXmlElement *, int, const char *[], int[], int[], int * ); -static char *ReadString( AstChannel *, const char *, const char *, int * ); -static char *SourceWrap( const char *(*)( void ), int * ); -static char GetNextChar( void *, int * ); -static const char *FindNextIsA( AstXmlElement *, int, int * ); -static const char *GetAttrib( AstObject *, const char *, int * ); -static const char *GetTag( AstXmlObject *, int, int * ); -static double AstronTimeReader( AstXmlChan *, AstXmlElement *, AstTimeFrame *, int * ); -static double AttrValueD( AstXmlChan *, AstXmlElement *, const char *, double, int * ); -static double ElemValueD( AstXmlChan *, AstXmlElement *, double, int * ); -static double Error2PAReader( AstXmlChan *, AstXmlElement *, double *, int * ); -static double MakeMJD( AstTimeFrame *, double, int * ); -static double PosAngleReader( AstXmlChan *, AstXmlElement *, int * ); -static double ReadDouble( AstChannel *, const char *, double, int * ); -static int AstroCoordsReader( AstXmlChan *, AstXmlElement *, AstFrame *, AstRegion *[4], AstKeyMap **, int * ); -static int AttrValueB( AstXmlChan *, AstXmlElement *, const char *, int, int * ); -static int AttrValueI( AstXmlChan *, AstXmlElement *, const char *, int, int * ); -static int ElemListD( AstXmlChan *, AstXmlElement *, int, double *, int * ); -static int FindString( int, const char *[], const char *, const char *, const char *, const char *, int * ); -static int GetComment( AstChannel *, int * ); -static int GetFull( AstChannel *, int * ); -static int GetIndent( AstChannel *, int * ); -static int IsUsable( AstXmlElement *, int * ); -static int ReadInt( AstChannel *, const char *, int, int * ); -static int TestAttrib( AstObject *, const char *, int * ); -static int Use( AstXmlChan *, int, int, int * ); -static int Ustrcmp( const char *, const char *, int * ); -static int Ustrncmp( const char *, const char *, size_t, int * ); -static int VertexReader( AstXmlChan *, AstXmlElement *, double *, double *, int * ); -static void ClearAttrib( AstObject *, const char *, int * ); -static void Copy( const AstObject *, AstObject *, int * ); -static void Delete( AstObject *, int * ); -static void Dump( AstObject *, AstChannel *, int * ); -static void FillAndLims( AstXmlChan *, AstXmlElement *, AstRegion *, int * ); -static void OutputText( AstXmlChan *, const char *, int, int * ); -static void ReCentreAnc( AstRegion *, int, AstKeyMap **, int * ); -static void ReadClassData( AstChannel *, const char *, int * ); -static void Report( AstXmlChan *, AstXmlElement *, int, const char *, int * ); -static void SetAttrib( AstObject *, const char *, int * ); -static void SinkWrap( void (*)( const char * ), const char *, int * ); -static void WriteBegin( AstChannel *, const char *, const char *, int * ); -static void WriteDouble( AstChannel *, const char *, int, int, double, const char *, int * ); -static void WriteEnd( AstChannel *, const char *, int * ); -static void WriteInt( AstChannel *, const char *, int, int, int, const char *, int * ); -static void WriteIsA( AstChannel *, const char *, const char *, int * ); -static void WriteObject( AstChannel *, const char *, int, int, AstObject *, const char *, int * ); -static void WriteString( AstChannel *, const char *, int, int, const char *, const char *, int * ); -static AstTimeScaleType TimeScaleReader( AstXmlChan *, AstXmlElement *, int * ); - -static int TestXmlLength( AstXmlChan *, int * ); -static void ClearXmlLength( AstXmlChan *, int * ); -static void SetXmlLength( AstXmlChan *, int, int * ); -static int GetXmlLength( AstXmlChan *, int * ); - -static int TestXmlFormat( AstXmlChan *, int * ); -static void ClearXmlFormat( AstXmlChan *, int * ); -static void SetXmlFormat( AstXmlChan *, int, int * ); -static int GetXmlFormat( AstXmlChan *, int * ); - -static int TestXmlPrefix( AstXmlChan *, int * ); -static void ClearXmlPrefix( AstXmlChan *, int * ); -static void SetXmlPrefix( AstXmlChan *, const char *, int * ); -static const char * GetXmlPrefix( AstXmlChan *, int * ); - -/* Member functions. */ -/* ================= */ - -static AstRegion *AllSkyReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* AllSkyReader - -* Purpose: -* Make an AST Region from an IVOA AllSky element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *AllSkyReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* AllSky element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA AllSky element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Create a negated NullRegion (this is a boundless Region which includes - all points in the Frame). */ - new = (AstRegion *) astNullRegion( frm, NULL, "negated=1", status ); - -/* Get any fill factor from the element and assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstRegion *AstroCoordAreaReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, AstRegion *uncs[4], - int nanc, AstKeyMap **ancs, int *status ) { -/* -* Name: -* AstroCoordAreaReader - -* Purpose: -* Make an AST Region from an IVOA AstroCoordArea element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *AstroCoordAreaReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, AstRegion *uncs[4], -* int nanc, AstKeyMap **ancs, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* AstroCoordArea element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA AstroCoordArea element. May be NULL, in -* which case a NullRegion is returned. -* frm -* The Frame in which the returned Region is to be defined. If -* Units or reference values (Epoch, RestFreq, RefRA, etc) are not set -* for any axes, then they will be set by this function if possible. -* uncs -* Array holding pointers to the uncertainty Regions to be associated -* with each of the four STC domains (space, time, spectral, redshift). -* NULL should be suppied in any element for which no uncertainty is -* available. -* nanc -* Number of KeyMap pointers stored in "ancs" -* ancs -* Pointer to an array of "nanc" elements, each being a pointer to -* a KeyMap. Each one describes the ancilary information in an -* AstroCoords element associated with the AstroCoordsArea decribed -* by "region". Each KeyMap has elements with keys AST__STCERROR, -* AST__STCRES, AST__STCSIZE, AST__STCPIXSZ, AST__STCVALUE each of -* which holds a pointer to a Region. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. -*/ - -/* Local Variables: */ - AstRegion *r; - AstFrame *cfrm; - AstFrame *fr; - AstFrame *pfrm; - AstFrame *red_frame; - AstFrame *space_frame; - AstFrame *spec_frame; - AstFrameSet *fs; - AstMapping *map; - AstObject *o; - AstRegion **red_list; - AstRegion **spec_list; - AstRegion **space_list; - AstRegion **time_list; - AstRegion *new; - AstRegion *reg; - AstRegion *rred; - AstRegion *rspec; - AstRegion *rspace; - AstRegion *rtime; - AstRegion *sum; - AstRegion *tmp; - AstTimeFrame *time_frame; - IVOAScan *scan; - char *decset; - char *raset; - char buff[ AST__DBL_WIDTH + 30 ]; - char setting[ 100 ]; - const char *dom; - const char *id; - const char *names[4]; - const char *name; - const char *old_units; - const char *text; - double decref; - double lbnd[2]; - double raref; - double space_val[2]; - double spec_val; - double time_val; - double ubnd[2]; - int i; - int ianc; - int ired; - int ispace; - int ispec; - int itime; - int k; - int l; - int max[4]; - int min[4]; - int nax; - int nred; - int nspace; - int nspec; - int ntime; - int paxis; - - static const char *key[ 5 ] = { AST__STCERROR, - AST__STCRES, - AST__STCSIZE, - AST__STCPIXSZ, - AST__STCVALUE }; - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* If null AstroCoordArea element has been supplied, return a NullRegion. */ - if( !elem ) { - new = (AstRegion *) astNullRegion( frm, NULL, "", status ); - -/* Otherwise, create a Region of suitable class. */ - } else { - -/* First identify the individual Frames within the supplied Frame. Current - implementation for spatial axes is limited to celestial longitude and - latitude. */ - space_frame = NULL; - spec_frame = NULL; - red_frame = NULL; - time_frame = NULL; - - nax = astGetNaxes( frm ); - for( i = 0; i < nax; i++ ) { - astPrimaryFrame( frm, i, &pfrm, &paxis ); - dom = astGetDomain( pfrm ); - if( !strcmp( dom, "SKY" ) ) { - if( !space_frame ) { - space_frame = astClone( pfrm ); - } else if( pfrm != space_frame) { - Report( this, elem, FAILURE, "contains more than 2 spatial axes", status ); - } - - } else if( !strcmp( dom, "TIME" ) ) { - if( !time_frame ) { - if( astIsATimeFrame( pfrm ) ) { - time_frame = (AstTimeFrame *) astClone( pfrm ); - } else if( astOK ) { - astError( AST__INTER, "AstroCoordAreaReader(XmlChan): %s " - "supplied where TimeFrame expected (internal " - "AST programming error).", status, astGetClass( pfrm ) ); - } - } else { - Report( this, elem, FAILURE, "contains more than 1 time axis", status ); - } - - } else if( !strcmp( dom, "SPECTRUM" ) ) { - if( !spec_frame ) { - spec_frame = astClone( pfrm ); - } else { - Report( this, elem, FAILURE, "contains more than 1 spectral axis", status ); - } - - } else if( !strcmp( dom, "REDSHIFT" ) ) { - if( !red_frame ) { - red_frame = astClone( pfrm ); - } else { - Report( this, elem, FAILURE, "contains more than 1 redshift axis", status ); - } - - } else { - Report( this, elem, FAILURE, "contains axes for an unsupported domain", status ); - } - pfrm = astAnnul( pfrm ); - } - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Sphere|PositionInterval|Region"; - names[ 1 ] = "TimeInterval"; - names[ 2 ] = "SpectralInterval"; - names[ 3 ] = "RedshiftInterval"; - min[ 0 ] = 0; - min[ 1 ] = 0; - min[ 2 ] = 0; - min[ 3 ] = 0; - max[ 0 ] = INT_MAX; - max[ 1 ] = INT_MAX; - max[ 2 ] = INT_MAX; - max[ 3 ] = INT_MAX; - scan = ScanIVOAElement( this, elem, 4, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create Regions for all the SpatialIntervals found in the supplied element. */ - space_val[ 0 ] = AST__BAD; - space_val[ 1 ] = AST__BAD; - nspace = scan->count[ 0 ]; - space_list = astMalloc( sizeof(AstRegion *)*(size_t)nspace ); - if( space_list ) { - for( ispace = 0; ispace < nspace; ispace++ ) { - name = astXmlGetName( scan->el[ 0 ][ ispace ] ); - if( !strcmp( name, "Sphere" ) ) { - space_list[ ispace ] = SphereReader( this, - scan->el[ 0 ][ ispace ], - space_frame, status ); - } else if( !strcmp( name, "PositionInterval" ) ) { - space_list[ ispace ] = PositionIntervalReader( this, - scan->el[ 0 ][ ispace ], - space_frame, status ); - } else if( !strcmp( name, "Region" ) ) { - space_list[ ispace ] = StcRegionReader( this, - scan->el[ 0 ][ ispace ], - space_frame, status ); - } else if( astOK ) { - astError( AST__INTER, "AstroCoordAreaReader(XmlChan): " - "SpatialInterval type %s not yet supported " - "(AST internal programming error).", status, name ); - break; - } - -/* Store any uncertainty region.*/ - if( uncs[ 0 ] ) astSetUnc( space_list[ ispace ], uncs[ 0 ] ); - - } - -/* If the spatial region is a single point we will use the point as the - reference position for any SpecFrames which are created. If there is - just one spatial interval, and if it is bounded. and if the bounds are - equal on both axes, note the mean position. */ - if( nspace == 1 ){ - if( astGetBounded( space_list[ 0 ] ) ) { - astGetRegionBounds( space_list[ 0 ], lbnd, ubnd ); - if( astEQUAL( lbnd[ 0 ], ubnd[ 0 ] ) && - astEQUAL( lbnd[ 1 ], ubnd[ 1 ] ) ) { - space_val[ 0 ] = 0.5*( lbnd[ 0 ] + ubnd[ 0 ] ); - space_val[ 1 ] = 0.5*( lbnd[ 1 ] + ubnd[ 1 ] ); - } - } - } - } - -/* Create Regions for all the TimeIntervals found in the supplied element. */ - time_val = AST__BAD; - ntime = scan->count[ 1 ]; - time_list = astMalloc( sizeof(AstRegion *)*(size_t)ntime ); - if( time_list ) { - for( itime = 0; itime < ntime; itime++ ) { - time_list[ itime ] = TimeIntervalReader( this, - scan->el[ 1 ][ itime ], - time_frame, status ); - -/* Store any uncertainty region. Transfer the System and TimeOrigin - values from the time region to the time uncertainty, if set. */ - if( uncs[ 1 ] ) { - - if( astTestSystem( time_frame ) && - astTestTimeOrigin( time_frame ) ) { - - sprintf( setting, "System=%s", - astGetC( time_frame, "System" ) ); - astRegSetAttrib( uncs[ 1 ], setting, NULL ); - - - if( astTestUnit( time_frame, 0 ) ) { - old_units = astGetUnit( time_frame, 0 ); - old_units = astStore( NULL, old_units, - strlen( old_units ) + 1 ); - } else { - old_units = NULL; - } - - astSetUnit( time_frame, 0, astGetUnit( uncs[ 1 ], 0 ) ); - - sprintf( setting, "TimeOrigin=%s", - astGetC( time_frame, "TimeOrigin" ) ); - astRegSetAttrib( uncs[ 1 ], setting, NULL ); - - if( old_units ) { - astSetUnit( time_frame, 0, old_units ); - old_units = astFree( (void *) old_units ); - } else { - astClearUnit( time_frame, 0 ); - } - - } - - astSetUnc( time_list[ itime ], uncs[ 1 ] ); - } - } - -/* Use the mid point as the Epoch for all Frames which are created. If - either limit is not specified, use the specified limit. */ - if( ntime > 0 ){ - astGetRegionBounds( time_list[ 0 ], lbnd, ubnd ); - if( fabs( lbnd[ 0 ] ) != DBL_MAX && lbnd[ 0 ] != AST__BAD ){ - if( fabs( ubnd[ 0 ] ) != DBL_MAX && ubnd[ 0 ] != AST__BAD ){ - time_val = 0.5*( lbnd[ 0 ] + ubnd[ 0 ] ); - } else { - time_val = lbnd[ 0 ]; - } - } else if( fabs( ubnd[ 0 ] ) != DBL_MAX && ubnd[ 0 ] != AST__BAD ){ - time_val = ubnd[ 0 ]; - } - } - } - -/* Create Regions for all the SpectralIntervals found in the supplied element. */ - spec_val = AST__BAD; - nspec = scan->count[ 2 ]; - spec_list = astMalloc( sizeof(AstRegion *)*(size_t)nspec ); - if( spec_list ) { - for( ispec = 0; ispec < nspec; ispec++ ) { - spec_list[ ispec ] = SpectralIntervalReader( this, - scan->el[ 2 ][ ispec ], - spec_frame, status ); -/* Store any uncertainty region.*/ - if( uncs[ 2 ] ) astSetUnc( spec_list[ ispec ], uncs[ 2 ] ); - } - -/* If the spectral region is a single point we will use the point as the - rest frequency for all RedShift Frames which are created. If there is just - one spectral interval, and if it is bounded. and if the bounds are equal, - note the mean spectral value. */ - if( nspec == 1 ){ - if( astGetBounded( spec_list[ 0 ] ) ) { - astGetRegionBounds( spec_list[ 0 ], lbnd, ubnd ); - if( astEQUAL( lbnd[ 0 ], ubnd[ 0 ] ) ) { - spec_val = 0.5*( lbnd[ 0 ] + ubnd[ 0 ] ); - } - } - } - } - -/* Create Regions for all the RedshiftIntervals found in the supplied element. */ - nred = scan->count[ 3 ]; - red_list = astMalloc( sizeof(AstRegion *)*(size_t)nred ); - if( red_list ) { - for( ired = 0; ired < nred; ired++ ) { - red_list[ ired ] = RedshiftIntervalReader( this, - scan->el[ 3 ][ ired ], - red_frame, status ); -/* Store any uncertainty region.*/ - if( uncs[ 3 ] ) astSetUnc( red_list[ ired ], uncs[ 3 ] ); - } - } - -/* Free the can result structure.*/ - scan = FreeIVOAScan( scan, status ); - -/* If the spatial regions cover only a single point, convert it to FK5 - J2000 and use it as the reference position for any SpecFrames (spectral or - redshift) unless values were inherited from the supplied Frame. If the - supplied Frame did not contain set values for these attributes, set them - now. Use astRegSetAttrib which applies the attribute setting to both - base and current Frame of the Region's FrameSet, and avoids re-mapping - the current Frame. */ - if( astOK ) { - if( space_val[ 0 ] != AST__BAD && space_val[ 1 ] != AST__BAD ) { - -/* First need to convert to FK5 J2000 and format into a string for use with - astRegSetAttrib. Need to ensure that the Format and Digits attributes - are set to values which will result in no loss of precision in the - formatting and unformatting steps. */ - fr = astCopy( space_frame ); - astClear( fr, "Format(1),Format(2),Digits(1),Digits(2)" ); - astSet( fr, "digits=%d,system=FK5,equinox=J2000", status, AST__DBL_DIG); - fs = astConvert( space_frame, fr, "" ); - fr = astAnnul( fr ); - if( fs ) { - astTran2( fs, 1, space_val, space_val + 1, 1, &raref, &decref ); - - text = astFormat( fs, raref, 0 ); - l = text ? strlen( text ) : 0; - raset = astMalloc( l + 10 ); - if( raset ) sprintf( raset, "refra=%s", text ); - - text = astFormat( fs, decref, 1 ); - l = text ? strlen( text ) : 0; - decset = astMalloc( l + 10 ); - if( decset ) sprintf( decset, "refdec=%s", text ); - - fs = astAnnul( fs ); - -/* Now set the FK5 J2000 values in the required Frames and Regions. */ - if( !spec_frame || !astTestRefRA( spec_frame ) || - !astTestRefDec( spec_frame ) ) { - for( ispec = 0; ispec < nspec; ispec++ ) { - astRegSetAttrib( spec_list[ ispec ], raset, NULL ); - astRegSetAttrib( spec_list[ ispec ], decset, NULL ); - } - - if( spec_frame ) { - astSetRefRA( (AstSpecFrame *) spec_frame, raref ); - astSetRefDec( (AstSpecFrame *) spec_frame, decref ); - } - } - - if( !red_frame || !astTestRefRA( red_frame ) || - !astTestRefDec( red_frame ) ) { - for( ired = 0; ired < nred; ired++ ) { - astRegSetAttrib( red_list[ ired ], raset, NULL ); - astRegSetAttrib( red_list[ ired ], decset, NULL ); - } - - if( red_frame ) { - astSetRefRA( (AstSpecFrame *) red_frame, raref ); - astSetRefDec( (AstSpecFrame *) red_frame, decref ); - } - } - - for( ianc = 0; ianc < nanc; ianc++ ) { - for( k = 0; k < 5; k++ ) { - if( astMapGet0A( ancs[ ianc ], key[ k ], &o ) ) { - r = (AstRegion *) o; - astRegSetAttrib( r, raset, NULL ); - astRegSetAttrib( r, decset, NULL ); - r = astAnnul( r ); - } - } - } - -/* Free resources. */ - if( raset ) raset = astFree( raset ); - if( decset ) decset = astFree( decset ); - - } else if( astOK ) { - astError( AST__INTER, "AstroCoordAreaReader(XmlChan):" - " Cannot convert spatial position to FK5 J2000" , status); - } - } - -/* If a time region was specified, use a typical value as the epoch for - all Frames. Call MakeMJD to convert "time_val" from the system of the - TimeFrame to an MJD (as required by the Frame Epoch attribute). Set - the value in both the returned Region and the supplied Frame. */ - if( time_val != AST__BAD ) { - fr = astRegFrame( time_list[ 0 ] ); - if( astIsATimeFrame( fr ) ) { - time_val = MakeMJD( (AstTimeFrame *) fr, time_val, status ); - } else if( astOK ) { - astError( AST__INTER, "AstroCoordAreaReader(XmlChan): %s " - "supplied where TimeFrame expected (internal " - "AST programming error).", status, astGetClass( fr ) ); - } - fr = astAnnul( fr ); - - sprintf( buff, "epoch= MJD %.*g", AST__DBL_DIG, time_val ); - - if( !space_frame || !astTestEpoch( space_frame ) ) { - for( ispace = 0; ispace < nspace; ispace++ ) { - astRegSetAttrib( space_list[ ispace ], buff, NULL ); - } - if( space_frame ) astSetEpoch( space_frame, time_val ); - } - - if( !spec_frame || !astTestEpoch( spec_frame ) ) { - for( ispec = 0; ispec < nspec; ispec++ ) { - astRegSetAttrib( spec_list[ ispec ], buff, NULL ); - } - if( spec_frame ) astSetEpoch( spec_frame, time_val ); - } - - if( !red_frame || !astTestEpoch( red_frame ) ) { - for( ired = 0; ired < nred; ired++ ) { - astRegSetAttrib( red_list[ ired ], buff, NULL ); - } - if( red_frame ) astSetEpoch( red_frame, time_val ); - } - - for( ianc = 0; ianc < nanc; ianc++ ) { - for( k = 0; k < 5; k++ ) { - if( astMapGet0A( ancs[ ianc ], key[ k ], &o ) ) { - r = (AstRegion *) o; - astRegSetAttrib( r, buff, NULL ); - r = astAnnul( r ); - } - } - } - - } - -/* If the spectral regions cover only a single point, format it with its - units so that the astSetAttrib function can convert it to Hz and use - it as the rest frequency for any redshift Frames. */ - if( spec_val != AST__BAD && nred > 0 ) { - - text = astGetUnit( spec_frame, 0 ); - if( text ) sprintf( buff, "restfreq= %.*g %s", AST__DBL_DIG, - spec_val, text ); - - if( !red_frame || !astTestRestFreq( red_frame ) ) { - for( ired = 0; ired < nred; ired++ ) { - astRegSetAttrib( red_list[ ired ], buff, NULL ); - } - if( red_frame ) astSetAttrib( red_frame, buff ); - } - - for( ianc = 0; ianc < nanc; ianc++ ) { - for( k = 0; k < 5; k++ ) { - if( astMapGet0A( ancs[ ianc ], key[ k ], &o ) ) { - r = (AstRegion *) o; - astRegSetAttrib( r, buff, NULL ); - r = astAnnul( r ); - } - } - } - } - -/* Create Regions corresponding to every possible combination of interval - on each axis type, and assemble the union of these into a CmpRegion (if - there is more than one). */ - sum = NULL; - -/* Initialise indices of the sub-Frame intervals to use. */ - ispace = 0; - itime = 0; - ispec = 0; - ired = 0; - -/* Loop over all possible combinations of time+space+spec+red intervals. */ - while( 1 ) { - rspace = ( ispace < nspace ) ? space_list[ ispace ] : NULL; - rtime = ( itime < ntime ) ? time_list[ itime ] : NULL; - rspec = ( ispec < nspec ) ? spec_list[ ispec ] : NULL; - rred = ( ired < nred ) ? red_list[ ired ] : NULL; - -/* Prism Regions extrude a Region into higher dimensions, and the - extrusion is defined by an Interval. Spatial Regions are not - restricted to Intervals and so any spatial Region must be the first - Region to be included in the Prism (all the other axis types *are* - restricted to Intervals and so can be used to extrude the spatial - region). */ - reg = rspace ? astClone( rspace ) : NULL; - -/* Now extrude this region (if any) into the time axis. */ - if( rtime ) { - if( reg ) { - tmp = (AstRegion *) astPrism( reg, rtime, "", status ); - (void) astAnnul( reg ); - reg = tmp; - } else { - reg = astClone( rtime ); - } - } - -/* Now extrude this region (if any) into the spectral axis. */ - if( rspec ) { - if( reg ) { - tmp = (AstRegion *) astPrism( reg, rspec, "", status ); - (void) astAnnul( reg ); - reg = tmp; - } else { - reg = astClone( rspec ); - } - } - -/* Now extrude this region (if any) into the redshift axis. */ - if( rred ) { - if( reg ) { - tmp = (AstRegion *) astPrism( reg, rred, "", status ); - (void) astAnnul( reg ); - reg = tmp; - } else { - reg = astClone( rred ); - } - } - - -/* If a Prism was created, add it into the CmpRegion which holds the - running sum of the union of all Prisms created so far. */ - if( reg ) { - if( !sum ) { - sum = astClone( reg ); - } else { - tmp = (AstRegion *) astCmpRegion( sum, reg, AST__OR, "", status ); - (void) astAnnul( sum ); - sum = tmp; - } - reg = astAnnul( reg ); - } - -/* Increment the indices of the next set of sub-Frame Intervals to use. - Leave the while loop when all combinations have been done. */ - if( ++ired >= nred ) { - ired = 0; - if( ++ispec >= nspec ) { - ispec = 0; - if( ++itime >= ntime ) { - itime = 0; - if( ++ispace >= nspace ) break; - } - } - } - } - -/* Simplify the total sum Region. */ - tmp = astSimplify( sum ); - (void) astAnnul( sum ); - sum = tmp; - -/* The axes in this sum Region may not be in the correct order or units (i.e - in the order and units specified in the supplied Frame). So use - astConvert to get a Mapping from the Frame represented by the sum - Region to the supplied Frame. */ - fs = astConvert( sum, frm, "" ); - if( fs ) { - -/* Unless the Mapping is a UnitMap, remap the sum Region into the - supplied Frame using this Mapping. */ - map = astGetMapping( fs, AST__BASE, AST__CURRENT ); - if( !astIsAUnitMap( map ) ) { - new = astMapRegion( sum, map, frm ); - } else { - new = astClone( sum ); - } - - map = astAnnul( map ); - fs = astAnnul( fs ); - - } else if( astOK ) { - astError( AST__INTER, "AstroCoordAreaReader(%s): Cannot " - "convert from supplied Frame to internal Frame (AST " - "internal programming error).", status, astGetClass( this ) ); - } - -/* Transfer selected properties from the supplied Frame to the current Frame - of the returned Region. */ - cfrm = astRegFrame( new ); - if( astTestIdent( frm ) ) astSetIdent( cfrm, astGetIdent( frm ) ); - if( astTestTitle( frm ) ) astSetTitle( cfrm, astGetTitle( frm ) ); - -/* Ensure the Epoch is set correctly in the Region */ - if( time_val != AST__BAD ) { - sprintf( buff, "epoch= MJD %.*g", AST__DBL_DIG, time_val ); - astRegSetAttrib( new, buff, NULL ); - } - -/* Free resources. */ - cfrm = astAnnul( cfrm ); - sum = astAnnul( sum ); - } - - if( space_list ) { - for( i = 0; i < nspace; i++ ) space_list[ i ] = astAnnul( space_list[ i ] ); - space_list = astFree( space_list ); - } - - if( time_list ) { - for( i = 0; i < ntime; i++ ) time_list[ i ] = astAnnul( time_list[ i ] ); - time_list = astFree( time_list ); - } - - if( spec_list ) { - for( i = 0; i < nspec; i++ ) spec_list[ i ] = astAnnul( spec_list[ i ] ); - spec_list = astFree( spec_list ); - } - - if( red_list ) { - for( i = 0; i < nred; i++ ) red_list[ i ] = astAnnul( red_list[ i ] ); - red_list = astFree( red_list ); - } - - } - - if( space_frame ) space_frame = astAnnul( space_frame ); - if( time_frame ) time_frame = astAnnul( time_frame ); - if( spec_frame ) spec_frame = astAnnul( spec_frame ); - if( red_frame ) red_frame = astAnnul( red_frame ); - -/* Get the ID attribute from the AstroCoordArea element and store in the - returned Region. */ - id = astXmlGetAttributeValue( elem, "ID" ); - if( id ) astSetIdent( new, id ); - - } - -/* If an error has occurred,annul the returned pointer. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static int AstroCoordsReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, AstRegion *uncs[4], - AstKeyMap **anc, int *status ) { -/* -* Name: -* AstroCoordsReader - -* Purpose: -* Modify a Frame to take account of an IVOA AstroCoords element, and -* return an coordinate uncertainties. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int AstroCoordsReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, AstRegion *uncs[4], -* AstKeyMap **anc, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function modifies the supplied Frame object to incorporate the -* effects of the supplied AstroCoords element. It may also return -* Regions representing the bounds of the uncertainties in the four -* component coordinate Frames, depending on the contents of the -* AstroCoords element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA AstroCoords element. -* frm -* The Frame object to modify. -* uncs -* Array in which to return pointers to the uncertainty Regions to -* be associated with each of the four STC domains (space, time, -* spectral, redshift). NULL is returned in any element for which -* no uncertainty is specified within the supplied AstroCoords element. -* anc -* Address of a location at which to store the pointer to a newly -* created KeyMap holding ancillary information describing the -* AstroCoords element in the form required by constructors of AST -* Stc objects. A NULL pointer is returned if no usable ancillary -* information is found in the AstroCoords. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Non-zero if any non-NULL values have been returned in the "uncs" -* array. Zero otherwise. - -*/ - -/* Local Variables: */ - AstFrame *afrm; /* Pointer to axis Frame */ - AstFrame *gfrm; /* Pointer to generic Frame */ - AstFrame *pfrm; /* Pointer to position Frame */ - AstFrame *rfrm; /* Pointer to redshift Frame */ - AstFrame *sfrm; /* Pointer to spectral Frame */ - AstTimeFrame *tfrm; /* Pointer to time Frame */ - AstKeyMap *panc; /* KeyMap holding spatial ancillary data */ - AstKeyMap *ranc; /* KeyMap holding redshift ancillary data */ - AstKeyMap *sanc; /* KeyMap holding spectral ancillary data */ - AstKeyMap *tanc; /* KeyMap holding temporal ancillary data */ - AstObject *o; /* Pointer to object retrieved from KeyMap */ - AstRegion *r; /* Individual ancillary Region */ - AstRegion *t; /* Total extruded ancillary Region */ - AstRegion *tt; /* Temporary Region pointer */ - AstXmlElement *el; /* Pointer to Position2D element */ - IVOAScan *scan; /* Structure holding scan results */ - char **anames; /* Pointer to list of ancillary name pointers */ - const char *dom; /* Pointer to Domain attribute value */ - const char *nam; /* Pointer to ancillary Name string */ - const char *names[4]; /* Names of the subelements to be searched for */ - char buff[100]; /* Message buffer */ - double epoch; /* Epoch */ - double hi; /* High limit for zero-width interval */ - double lo; /* Low limit for zero-width interval */ - double pos[2]; /* Reference spatial position */ - double rf; /* Rest frequency */ - int axes[2]; /* Indices of position axes */ - int axis; /* Index of next axis to use */ - int empty; /* Is returned KeyMap empty? */ - int i; /* Loop count */ - int isearth; /* Does the SkyFrame represent terrestrial lon/lat? */ - int junk; /* Unused integer value */ - int max[4]; /* Max allowed occurrences of each name */ - int min[4]; /* Min allowed occurrences of each name */ - int nax; /* Number of axes in supplied Frame */ - int unc; /* Any uncertainty Regions found? */ - int use; /* Use ancillary information? */ - - static const char *key[ 5 ] = { AST__STCERROR, - AST__STCRES, - AST__STCSIZE, - AST__STCPIXSZ, - AST__STCVALUE }; -/* Initialise */ - unc = 0; - uncs[ 0 ] = NULL; - uncs[ 1 ] = NULL; - uncs[ 2 ] = NULL; - uncs[ 3 ] = NULL; - *anc = NULL; - -/* Check the global error status. */ - if ( !astOK ) return unc; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Position2D|Position3D"; - names[ 1 ] = "Time"; - names[ 2 ] = "Spectral"; - names[ 3 ] = "Redshift"; - min[ 0 ] = 0; - min[ 1 ] = 0; - min[ 2 ] = 0; - min[ 3 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - max[ 2 ] = 1; - max[ 3 ] = 1; - scan = ScanIVOAElement( this, elem, 4, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Initialise pointers to component Frames */ - pfrm = NULL; - tfrm = NULL; - sfrm = NULL; - rfrm = NULL; - -/* Initialise pointers to KeyMaps holding ancillary data. */ - panc = NULL; - tanc = NULL; - sanc = NULL; - ranc = NULL; - -/* Allocate storage for an array of pointers to strings holding the Name - value for each axis. Initialise them to a null string. */ - nax = astGetNaxes( frm ); - anames = astMalloc( sizeof( char * )*(size_t)nax ); - for( i = 0; i < nax; i++ ) anames[ i ] = NULL; - -/* Initialise the index of the next Frame axis to use. */ - axis = 0; - -/* Check to see if the next 2 axes describe positions on the sky or earth - (see SpaceFrameReader). */ - axes[ 0 ] = 0; - axes[ 1 ] = 1; - afrm = astPickAxes( frm, 2, axes, NULL ); - dom = astGetDomain( afrm ); - isearth = dom && ( !strcmp( dom, "GEO_D" ) || - !strcmp( dom, "GEO_C" ) ); - - if( isearth || ( dom && !strcmp( dom, "SKY" ) ) ){ - astPrimaryFrame( frm, axis, &pfrm, &junk ); - if( scan->count[ 0 ] ) { - -/* We currently also use SkyFrames to represent geographical long/lat used to - describe observatory positions. These may have 3D positions, in which - case we convert the 3D position to a 2D position by ignoring the 3rd axis - value (height). See SpaceFrameReader. */ - el = MakePos2D( this, scan->el[ 0 ][ 0 ], status ); - -/* Use the Position2D to create a Region describing the uncertainty in - the space axes of the Frame. Also create a KeyMap holding Regions - describing any ancillary information stored in the Position2D. */ - uncs[ 0 ] = Position2DReader( this, el, pfrm, pos, &panc, status ); - if( uncs[ 0 ] ) unc = 1; - el = astXmlDelete( el ); - -/* If ancillary information was returned, extract the Name element, and - store it twice (once for each axis) in the "names" array. */ - if( panc && astMapGet0C( panc, AST__STCNAME, &nam ) ) { - anames[ axis ] = astStore( NULL, nam, strlen( nam ) + 1 ); - anames[ axis + 1 ] = astStore( NULL, nam, strlen( nam ) + 1 ); - } - } - -/* Increment the axis index. */ - axis += 2; - -/* If the supplied Frame has no sky frame, but we found a Position2D, then - report a warning and ignore the Position2D. */ - } else if( scan->count[ 0 ] ) { - sprintf( buff, "contains a <%s> which is not being used.", - astXmlGetName( scan->el[ 0 ][ 0 ] ) ); - Report( this, elem, WARNING, buff, status ); - } - afrm = astAnnul( afrm ); - -/* Indicate we do not yet have an epoch to use. */ - epoch = AST__BAD; - -/* Check to see if the Frame contains a time frame. It will be the next - axis if it does. */ - afrm = astPickAxes( frm, 1, &axis, NULL ); - dom = astGetDomain( afrm ); - if( dom && !strcmp( dom, "TIME" ) ){ - astPrimaryFrame( frm, axis, &gfrm, &junk ); - -/* Report an error if it is not an AST TimeFrame. */ - if( !astIsATimeFrame( gfrm ) && astOK ) { - astError( AST__INTER, "AstroCoordAreaReader(XmlChan): %s " - "supplied where TimeFrame expected (internal " - "AST programming error).", status, astGetClass( pfrm ) ); - } else { - tfrm = (AstTimeFrame *) gfrm; - } - -/* Use any Time element to create a Region describing the uncertainty in the - time axis of the Frame. Also create a KeyMap holding Regions describing - any ancillary information stored in the Time element. */ - if( scan->count[ 1 ] ) { - uncs[ 1 ] = TimeReader( this, scan->el[ 1 ][ 0 ], tfrm, &epoch, - &tanc, status ); - if( uncs[ 1 ] ) unc = 1; - -/* If ancillary information was returned, extract the Name element, and - store it in the "names" array. */ - if( tanc && astMapGet0C( tanc, AST__STCNAME, &nam ) ) { - anames[ axis ] = astStore( NULL, nam, strlen( nam ) + 1 ); - } - } - -/* Increment the index of the next axis to use. */ - axis++; - -/* If the supplied Frame has no time frame, but we found a Time element, then - report a warning and ignore the Time element. */ - } else if( scan->count[ 1 ] ) { - Report( this, elem, WARNING, "contains a <Time> which is not needed", status ); - } - afrm = astAnnul( afrm ); - -/* Indicate we do not yet have a rest frequency to use with any redshift - axis. */ - rf = AST__BAD; - -/* Check to see if the Frame contains a spectral frame. It will be the next - axis if it does. */ - afrm = astPickAxes( frm, 1, &axis, NULL ); - dom = astGetDomain( afrm ); - if( dom && !strcmp( dom, "SPECTRUM" ) ){ - astPrimaryFrame( frm, axis, &sfrm, &junk ); - -/* Use any Spectral to create a Region describing the uncertainty in the - spectral axis of the Frame. If the Spectral contains a spectral value, the - first value will be returned so that it can be used as the rest frequency - for any Redshift axis. It will be in units of Hz and will be AST__BAD if - the Spectral did not contain any spectral values. Also create a KeyMap - holding Regions describing any ancillary information stored in the - Spectral element. */ - if( scan->count[ 2 ] ) { - uncs[ 2 ] = SpectralReader( this, scan->el[ 2 ][ 0 ], sfrm, &rf, - &sanc, status ); - if( uncs[ 2 ] ) unc = 1; - -/* If ancillary information was returned, extract the Name element, and - store it in the "names" array. */ - if( sanc && astMapGet0C( sanc, AST__STCNAME, &nam ) ) { - anames[ axis ] = astStore( NULL, nam, strlen( nam ) + 1 ); - } - } - -/* Increment the index of the next axis to use. */ - axis++; - -/* If the supplied Frame has no spectral frame, but we found a Spectral - element, then report a warning and ignore the Spectral element. */ - } else if( scan->count[ 2 ] ) { - Report( this, elem, WARNING, "contains a <Spectral> which is not needed", status ); - } - afrm = astAnnul( afrm ); - -/* Check to see if the Frame contains a redshift frame. It will be the next - axis if it does. */ - afrm = astPickAxes( frm, 1, &axis, NULL ); - dom = astGetDomain( afrm ); - if( dom && !strcmp( dom, "REDSHIFT" ) ){ - astPrimaryFrame( frm, axis, &rfrm, &junk ); - -/* Use any Redshift to create a Region describing the uncertainty in the - redshift axis of the Frame. Also create a KeyMap holding Regions describing - any ancillary information stored in the Redshift element. */ - if( scan->count[ 3 ] ) { - uncs[ 3 ] = RedshiftReader( this, scan->el[ 3 ][ 0 ], rfrm, - &ranc, status ); - if( uncs[ 3 ] ) unc = 1; - -/* If ancillary information was returned, extract the Name element, and - store it in the "names" array. */ - if( ranc && astMapGet0C( ranc, AST__STCNAME, &nam ) ) { - anames[ axis ] = astStore( NULL, nam, strlen( nam ) + 1 ); - } - } - -/* Increment the index of the next axis to use. */ - axis++; - -/* If the supplied Frame has no redshift frame, but we found a Redshift - element, then report a warning and ignore the Redshift element. */ - } else if( scan->count[ 3 ] ) { - Report( this, elem, WARNING, "contains a <Redshift> which is not needed", status ); - } - afrm = astAnnul( afrm ); - -/* Now assign fixed axis values (Epoch, RestFreq, etc) to the component - Frames of the supplied Frame. */ - if( epoch != AST__BAD ) { - if( pfrm ) astSetEpoch( pfrm, epoch ); - if( tfrm ) astSetEpoch( tfrm, epoch ); - if( sfrm ) astSetEpoch( sfrm, epoch ); - if( rfrm ) astSetEpoch( rfrm, epoch ); - astSetEpoch( frm, epoch ); - } - - if( sfrm && pfrm && astIsASpecFrame( sfrm ) && astIsASkyFrame( pfrm ) && - !isearth && pos[ 0 ] != AST__BAD && pos[ 1 ] != AST__BAD ) { - astSetRefPos( sfrm, pfrm, pos[ 0 ], pos[ 1 ] ); - } - - if( rfrm && astIsASpecFrame( rfrm ) && rf != AST__BAD ) { - astSetRestFreq( rfrm, rf ); - if( pfrm && astIsASkyFrame( pfrm ) && !isearth && - pos[ 0 ] != AST__BAD && pos[ 1 ] != AST__BAD ) { - astSetRefPos( rfrm, pfrm, pos[ 0 ], pos[ 1 ] ); - } - } - -/* Now combine ancillary data for each component Frame into the total - Frame. */ - *anc = astKeyMap( "", status ); - if( *anc ) { - empty = 1; - -/* Store the Names element if at least one axis has a Name item. */ - for( i = 0; i < nax; i++ ) { - if( !anames[ i ] ) anames[ i ] = astStore( NULL, "", 1 ); - } - - for( i = 0; i < nax; i++ ) { - if( empty && strlen( anames[ i ] ) > 0 ) { - astMapPut1C( *anc, AST__STCNAME, nax, (const char **) anames, NULL ); - empty = 0; - } - anames[ i ] = astFree( anames[ i ] ); - } - -/* Do each of the other items, all of which are described by a Region. */ - lo = 0.0; - hi = 0.0; - for( i = 0; i < 5; i++ ) { - -/* Initialise a flag indicating that we have not yet found any non-null - information to store for this item. */ - use = 0; - -/* Initialise a pointer to the Region describing the item extruded into - all axes. */ - t = NULL; - -/* If there is a positional Frame, determine the Region describing the - intersection of the total Region with the position Frame. If none is - supplied use a zero width Interval as a flag that no information is - available. */ - if( pfrm ) { - if( panc && astMapGet0A( panc, key[ i ], &o ) ) { - t = (AstRegion *) o; - use = 1; - } else { - t = (AstRegion *) astInterval( pfrm, &lo, &hi, NULL, "", status ); - } - } - -/* If there is a time Frame, determine the Region describing the intersection - of the total Region with the time Frame. If none is supplied use a zero - width Interval as a flag that no information is available. */ - if( tfrm ) { - if( tanc && astMapGet0A( tanc, key[ i ], &o ) ) { - r = (AstRegion *) o; - use = 1; - } else { - r = (AstRegion *) astInterval( tfrm, &lo, &hi, NULL, "", status ); - } - -/* If there were earlier axes, extrude the current total region into the - time axis, and use the extruded region as the new total region.*/ - if( t ) { - tt = (AstRegion *) astPrism( t, r, "", status ); - r = astAnnul( r ); - (void) astAnnul( t ); - t = tt; - -/* If this is the first axis, use the region determined for this axis as - the total Region.*/ - } else { - t = r; - } - } - -/* Do the same for any spectral axis. */ - if( sfrm ) { - if( sanc && astMapGet0A( sanc, key[ i ], &o ) ) { - r = (AstRegion *) o; - use = 1; - } else { - r = (AstRegion *) astInterval( sfrm, &lo, &hi, NULL, "", status ); - } - - if( t ) { - tt = (AstRegion *) astPrism( t, r, "", status ); - r = astAnnul( r ); - (void) astAnnul( t ); - t = tt; - } else { - t = r; - } - - } - -/* Do the same for any redshift axis. */ - if( rfrm ) { - if( ranc && astMapGet0A( ranc, key[ i ], &o ) ) { - r = (AstRegion *) o; - use = 1; - } else { - r = (AstRegion *) astInterval( rfrm, &lo, &hi, NULL, "", status ); - } - - if( t ) { - tt = (AstRegion *) astPrism( t, r, "", status ); - r = astAnnul( r ); - (void) astAnnul( t ); - t = tt; - } else { - t = r; - } - } - -/* If there is some non-null information for this item, replace the - stored Frame with the Frame which has set Epoch/RefLat/etc, simplify the - total Region and store it in the returned KeyMap. */ - if( use ) { - astSetRegFS( t, frm ); - tt = astSimplify( t ); - astMapPut0A( *anc, key[ i ], tt, NULL ); - tt = astAnnul( tt ); - empty = 0; - } - if( t ) t = astAnnul( t ); - } - -/* Return a NULL KeyMap pointer if the KeyMap is empty. */ - if( empty ) *anc = astAnnul( *anc ); - } - -/* Free resources. */ - if( panc ) panc = astAnnul( panc ); - if( tanc ) tanc = astAnnul( tanc ); - if( sanc ) sanc = astAnnul( sanc ); - if( ranc ) ranc = astAnnul( ranc ); - if( pfrm ) pfrm = astAnnul( pfrm ); - if( tfrm ) tfrm = astAnnul( tfrm ); - if( sfrm ) sfrm = astAnnul( sfrm ); - if( rfrm ) rfrm = astAnnul( rfrm ); - scan = FreeIVOAScan( scan, status ); - anames = astFree( anames ); - } - -/* Annull any returned Regions if an error occurred.*/ - if( !astOK ) { - uncs[ 0 ] = astAnnul( uncs[ 0 ] ); - uncs[ 1 ] = astAnnul( uncs[ 1 ] ); - uncs[ 2 ] = astAnnul( uncs[ 2 ] ); - uncs[ 3 ] = astAnnul( uncs[ 3 ] ); - unc = 0; - *anc = astAnnul( *anc ); - } - -/* Return the result. */ - return unc; -} - -static AstObject *AstroCoordSystemReader( AstXmlChan *this, - AstXmlElement *elem, int *status ) { -/* -* Name: -* AstroCoordSystemReader - -* Purpose: -* Make an AST Object from an IVOA AstroCoordSystem element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *AstroCoordSystemReader( AstXmlChan *this, -* AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Object from the supplied IVOA -* AstroCoordSystem element. This will be a Frame of some kind. -* If the AstroCoordSystem element contains only one sub-frame -* element, then the returned Frame will be of a suitable class -* to describe that sub-frame (SkyFrame, SpecFrame or TimeFrame). -* If the AstroCoordSystem element contains more than one sub-frame -* element, then the returned Frame will be a CmpFrame in which the -* component Frames are in the order SpaceFrame, TimeFrame, -* SpectralFrame, RedshiftFrame. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA AstroCoordSystem element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. - -* Notes: -* - GenericCoordFrame sub-elements are currently ignored since it is not -* clear how they relate to the other sub-elements. - -*/ - -/* Local Variables: */ - AstCmpFrame *tmp; /* Pointer to intermediate CmpFrame */ - AstFrame *comp[ 4 ]; /* Pointers to component Frames */ - AstObject *new; /* Pointer to returned Object */ - IVOAScan *scan; /* Structure holding scan results */ - const char *id; /* Pointer to ID attribute value */ - const char *names[4]; /* Names of the subelements to be searched for */ - int i; /* Index of current content item */ - int j; /* Index to store Frame pointer at */ - int max[4]; /* Max allowed occurrences of each name */ - int min[4]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = SPACE_FRAME; - names[ 1 ] = TIME_FRAME; - names[ 2 ] = SPECTRAL_FRAME; - names[ 3 ] = REDSHIFT_FRAME; - min[ 0 ] = 0; - min[ 1 ] = 0; - min[ 2 ] = 0; - min[ 3 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - max[ 2 ] = 1; - max[ 3 ] = 1; - scan = ScanIVOAElement( this, elem, 4, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create Frames from the found sub-elements */ - comp[ 0 ] = scan->count[0] ? (AstFrame *) SpaceFrameReader( this, - scan->el[ 0 ][ 0 ], status ) : NULL; - comp[ 1 ] = scan->count[1] ? (AstFrame *) TimeFrameReader( this, - scan->el[ 1 ][ 0 ], status ) : NULL; - comp[ 2 ] = scan->count[2] ? (AstFrame *) SpectralFrameReader( this, - scan->el[ 2 ][ 0 ], status ) : NULL; - comp[ 3 ] = scan->count[3] ? (AstFrame *) RedshiftFrameReader( this, - scan->el[ 3 ][ 0 ], status ) : NULL; - -/* If more than one frame was obtained combine them into a CmpFrame. If - present, the Frames are stored in the order SpaceFrame, TimeFrame, - SpectralFrame, RedshiftFrame. Shuffle the the higher elements of the - "comp" array down to fill any NULL elements. */ - j = 0; - for( i = 0; i < 4; i++ ) { - if( comp[ i ] ) { - comp[ j++ ] = comp[ i ]; - } - } - -/* Fill any unused elements at the end with NULL. */ - for( ; j < 4; j++ ) comp[ j ] = NULL; - -/* If no Frames were read issue a fatal error. */ - if( !comp[ 0 ] ) { - Report( this, elem, FAILURE, "contains no usable coordinate axes", status ); - -/* If only one Frame was read return a clone of its pointer. */ - } else if( !comp[ 1 ] ) { - new = astClone( comp[ 0 ] ); - -/* If two or more Frames were read, create a CmpFrame holding the Frames. */ - } else if( !comp[ 2 ] ) { - new = (AstObject *) astCmpFrame( comp[ 0 ], comp[ 1 ], "", status ); - - } else if( !comp[ 3 ] ) { - tmp = astCmpFrame( comp[ 0 ], comp[ 1 ], "", status ); - new = (AstObject *) astCmpFrame( tmp, comp[ 2 ], "", status ); - tmp = astAnnul( tmp ); - - } else { - tmp = astCmpFrame( comp[ 0 ], comp[ 1 ], "", status ); - (void) astAnnul( comp[ 0 ] ); - comp[ 0 ] = (AstFrame *) tmp; - tmp = astCmpFrame( comp[ 0 ], comp[ 2 ], "", status ); - new = (AstObject *) astCmpFrame( tmp, comp[ 3 ], "", status ); - tmp = astAnnul( tmp ); - } - -/* Get the ID attribute from the AstroCoordSystem element and store in the - returned Frame. */ - id = astXmlGetAttributeValue( elem, "ID" ); - if( id ) astSetIdent( new, id ); - -/* Free resources */ - for( i = 0; i < 4; i++ ) { - if( comp[ i ] ) comp[ i ] = astAnnul( comp[ i ] ); - } - scan = FreeIVOAScan( scan, status ); - - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Object. */ - return new; -} - -static double AstronTimeReader( AstXmlChan *this, AstXmlElement *elem, - AstTimeFrame *frm, int *status ){ -/* -* Name: -* AstronTimeReader - -* Purpose: -* Read a time value from an IVOA AstronTime element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* double AstronTimeReader( AstXmlChan *this, AstXmlElement *elem, -* AstTimeFrame *frm ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function returns a double representing the time specified by -* the supplied IVOA AstronTime element, converted into the system -* represented by the supplied Frame. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA AstronTime element. -* frm -* Pointer to the TimeFrame in which the returned value should be -* defined. Relevant attributes which are not set will be set by -* this function if possible. - -* Returned Value: -* The time value, in the system described by "frm". - -*/ - -/* Local Variables: */ - AstFrameSet *fs; /* FrameSet connecting two TimeFrames */ - AstTimeFrame *cfrm; /* TimeFrame describing XML time system */ - AstTimeScaleType ts; /* TimeScale */ - IVOAScan *scan; /* Structure holding scan results */ - char buff[ 200 ]; /* Message buffer */ - const char *iso; /* Pointer to ISO date string */ - const char *names[3]; /* Names of the subelements to be searched for */ - const char *time_type; /* Pointer to time type string */ - const char *unit; /* Pointer to Unit string */ - double fval; /* Value converted to supplied TimeFrame */ - double offset; /* Time offset */ - double result; /* Time offset converted to required TimeFrame */ - double val; /* Value read from element */ - int max[3]; /* Max allowed occurrences of each name */ - int min[3]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - offset = 0.0; - result = AST__BAD; - val = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return offset; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "JDTime|MJDTime|ISOTime"; - names[ 1 ] = "TimeOffset"; - names[ 2 ] = "TimeScale|Timescale"; - min[ 0 ] = 1; - min[ 1 ] = 0; - min[ 2 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - max[ 2 ] = 1; - scan = ScanIVOAElement( this, elem, 3, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* The supplied TimeFrame describes the system in which the caller wants - the time values to be returned. This may not be the same as the system - in which the value is stored in the XML. We create a TimeFrame - describing the XML system, and later transform time values from the XML - system to the system required by the caller. Any attributes of the XML - system which are not specified in the XML are assumed to be equal to - the values of the corresponding attributes in the supplied TimeFrame. - If the XML system specifies values for attributes which have not been - set in the supplied TimeFrame, then the values read fomr the XML are - assigned to the attributes of the supplied TimeFrame. */ - cfrm = astCopy( frm ); - - if( scan->count[2] ) { - ts = TimeScaleReader( this, scan->el[2][0], status ); - astSetTimeScale( cfrm, ts ); - if( !astTestTimeScale( frm ) ) astSetTimeScale( frm, ts ); - } - -/* If a JDTime element was found, get its value and set the TimeFrame System - values. */ - time_type = astXmlGetName( scan->el[0][0] ); - if( !strcmp( "JDTime", time_type ) ) { - val = ElemValueD( this, scan->el[0][0], 2400000.5, status ); - astSetSystem( cfrm, AST__JD ); - if( !astTestSystem( frm ) ) astSetSystem( frm, AST__JD ); - -/* If a ISOTime element was found, get its value and set the TimeFrame - System attribute to MJD (the choice of AST System for an ISOTime is - arbitrary - JD or JEPOCH could also have been used). */ - } else if( !strcmp( "ISOTime", time_type ) ) { - astSetSystem( cfrm, AST__MJD ); - if( !astTestSystem( frm ) ) astSetSystem( frm, AST__MJD ); - iso = astXmlGetValue( scan->el[0][0], 0 ); - astClearTimeOrigin( cfrm ); - if( iso && astUnformat( cfrm, 0, iso, &val ) != strlen( iso ) ) { - sprintf( buff, "contains unsupported ISO time format \"%s\"", - iso ); - Report( this, elem, FAILURE, buff, status ); - } - -/* If an MJDTime was found, get its value and set System attributes. */ - } else { - val = ElemValueD( this, scan->el[0][0], 2400000.5, status ); - astSetSystem( cfrm, AST__MJD ); - if( !astTestSystem( frm ) ) astSetSystem( frm, AST__MJD ); - } - -/* Use this value as the TimeFrame's TimeOrigin value. Use the public - astSetD rather than astSetTimeOrigin since the later requires the - value to be supplied in the default units for the TimeFrame's System. */ - astSetD( cfrm, "TimeOrigin", val ); - -/* If the supplied Frame has no set TimeOrigin, also use the value - obtained above as the TimeOrigin in "frm". Convert it into the supplied - TimeFrame, and set it. Note zero is used as the axis value in cfrm - because the relevant epoch is zero distance away from the cfrm - TimeOrigin (set above). */ - if( !astTestTimeOrigin( frm ) ) { - - fs = astConvert( cfrm, frm, "" ); - if( fs ){ - val = 0.0; - astTran1( fs, 1, &val, 1, &fval ); - astSetD( frm, "TimeOrigin", fval ); - fs = astAnnul( fs ); - } else if( astOK ) { - sprintf( buff, "contains inconsistent timescale (%s)", - astGetC( cfrm, "timescale" ) ); - Report( this, elem, FAILURE, buff, status ); - } - } - -/* If an TimeOffset element was found, get its value and the value of its - unit attribute (assume a default of days). Set the units in the - TimeFrames. */ - if( scan->count[1] ) { - offset = ElemValueD( this, scan->el[1][0], 0.0, status ); - unit = astXmlGetAttributeValue( scan->el[1][0], "unit" ); - if( !unit ) unit = "d"; - astSetUnit( cfrm, 0, unit ); - if( !astTestUnit( frm, 0 ) ) astSetUnit( frm, 0, unit ); - -/* If no offset was given, use zero. */ - } else { - offset = 0.0; - } - -/* Convert the offset from the system in which it is stored in the XML to - the system required by the caller. */ - fs = astConvert( cfrm, frm, "" ); - if( fs ){ - astTran1( fs, 1, &offset, 1, &result ); - fs = astAnnul( fs ); - } else if( astOK ) { - sprintf( buff, "contains inconsistent timescale (%s)", - astGetC( cfrm, "timescale" ) ); - Report( this, elem, FAILURE, buff, status ); - } - -/* Free resources. */ - cfrm = astAnnul( cfrm ); - scan = FreeIVOAScan( scan, status ); - } - -/* Return the time value. */ - return result; -} - -void astInitXmlChanVtab_( AstXmlChanVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitXmlChanVtab - -* Purpose: -* Initialise a virtual function table for an XmlChan. - -* Type: -* Protected function. - -* Synopsis: -* #include "xmlchan.h" -* void astInitXmlChanVtab( AstXmlChanVtab *vtab, const char *name ) - -* Class Membership: -* XmlChan vtab initialiser. - -* Description: -* This function initialises the component of a virtual function -* table which is used by the XmlChan class. - -* Parameters: -* vtab -* Pointer to the virtual function table. The components used by -* all ancestral classes will be initialised if they have not already -* been initialised. -* name -* Pointer to a constant null-terminated character string which contains -* the name of the class to which the virtual function table belongs (it -* is this pointer value that will subsequently be returned by the Object -* astClass function). -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstObjectVtab *object; /* Pointer to Object component of Vtab */ - AstChannelVtab *channel; /* Pointer to Channel component of Vtab */ - -/* Check the local error status. */ - if ( !astOK ) return; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Initialize the component of the virtual function table used by the - parent class. */ - astInitChannelVtab( (AstChannelVtab *) vtab, name ); - -/* Store a unique "magic" value in the virtual function table. This - will be used (by astIsAXmlChan) to determine if an object belongs - to this class. We can conveniently use the address of the (static) - class_check variable to generate this unique value. */ - vtab->id.check = &class_check; - vtab->id.parent = &(((AstChannelVtab *) vtab)->id); - -/* Initialise member function pointers. */ -/* ------------------------------------ */ -/* Store pointers to the member functions (implemented here) that provide - virtual methods for this class. */ - - vtab->SetXmlLength = SetXmlLength; - vtab->ClearXmlLength = ClearXmlLength; - vtab->TestXmlLength = TestXmlLength; - vtab->GetXmlLength = GetXmlLength; - - vtab->SetXmlFormat = SetXmlFormat; - vtab->ClearXmlFormat = ClearXmlFormat; - vtab->TestXmlFormat = TestXmlFormat; - vtab->GetXmlFormat = GetXmlFormat; - - vtab->SetXmlPrefix = SetXmlPrefix; - vtab->ClearXmlPrefix = ClearXmlPrefix; - vtab->TestXmlPrefix = TestXmlPrefix; - vtab->GetXmlPrefix = GetXmlPrefix; - -/* Save the inherited pointers to methods that will be extended, and - replace them with pointers to the new member functions. */ - object = (AstObjectVtab *) vtab; - channel = (AstChannelVtab *) vtab; - - channel->WriteBegin = WriteBegin; - channel->WriteIsA = WriteIsA; - channel->WriteEnd = WriteEnd; - channel->WriteInt = WriteInt; - channel->WriteDouble = WriteDouble; - channel->WriteString = WriteString; - channel->WriteObject = WriteObject; - - channel->Read = Read; - channel->ReadClassData = ReadClassData; - channel->ReadDouble = ReadDouble; - channel->ReadInt = ReadInt; - channel->ReadObject = ReadObject; - channel->ReadString = ReadString; - - parent_getindent = channel->GetIndent; - channel->GetIndent = GetIndent; - - parent_getfull = channel->GetFull; - channel->GetFull = GetFull; - - parent_getcomment = channel->GetComment; - channel->GetComment = GetComment; - - -/* Save the inherited pointers to methods that will be extended, and - replace them with pointers to the new member functions. */ - parent_clearattrib = object->ClearAttrib; - object->ClearAttrib = ClearAttrib; - parent_getattrib = object->GetAttrib; - object->GetAttrib = GetAttrib; - parent_setattrib = object->SetAttrib; - object->SetAttrib = SetAttrib; - parent_testattrib = object->TestAttrib; - object->TestAttrib = TestAttrib; - -/* Declare the class dump, copy and delete functions.*/ - astSetCopy( vtab, Copy ); - astSetDump( vtab, Dump, "XmlChan", "XML I/O channel" ); - astSetDelete( vtab, Delete ); - -/* If we have just initialised the vtab for the current class, indicate - that the vtab is now initialised, and store a pointer to the class - identifier in the base "object" level of the vtab. */ - if( vtab == &class_vtab ) { - class_init = 1; - astSetVtabClassIdentifier( vtab, &(vtab->id) ); - } -} - -static double AttrValueD( AstXmlChan *this, AstXmlElement *elem, - const char *name, double def, int *status ) { -/* -* Name: -* AttrValueD - -* Purpose: -* Read a floating point XML element attribute value. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* double AttrValueD( AstXmlChan *this, AstXmlElement *elem, -* const char *name, double def, int *status ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function returns the value of a named attribute of an XML -* element as a floating point value. A report is made if the -* attribute value is not floating point.The supplied default value is -* returned if the attribute is not present. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the XmlElement. -* name -* Pointer to a constant null-terminated character string -* containing the name of the required attribute value. -* def -* If the supplied element does not have the requried attribute, then -* this value will be returned instead. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The required attribute value, or the default if the value was not found. - -*/ - -/* Local Variables: */ - char buff[ 200 ]; /* Msg buffer */ - const char *value; /* Pointer to attribute value */ - double result; /* Value to be returned */ - int nc; /* Number of characters read by astSscanf */ - int nf; /* Number of matching fields */ - int len; /* Length of attribute string */ - -/* Initialise. */ - result = def; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get the attribute value as a string. */ - value = astXmlGetAttributeValue( elem, name ); - -/* If the attribute exists, attempt to decode the string to give a double - value, checking that the entire string is read. */ - if( value ) { - nc = 0; - nf = astSscanf( value, " %lf %n", &result, &nc ); - len = strlen( value ); - - if ( nf != 1 || nc < len ) { - sprintf( buff, "contains a bad <%s> value: \"%s\"", name, value ); - Report( this, elem, WARNING, buff, status ); - } - } - -/* Return the result. */ - return result; -} - -static int AttrValueI( AstXmlChan *this, AstXmlElement *elem, const char *name, - int def, int *status ) { -/* -* Name: -* AttrValueI - -* Purpose: -* Read an integer XML element attribute value. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int AttrValueI( AstXmlChan *this, AstXmlElement *elem, const char *name, -* int def ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function returns the value of a named attribute of an XML element -* as an integer value. A report is made if the attribute value is not -* integer. The supplied default value is returned if the attribute is not -* present. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the XmlElement. -* name -* Pointer to a constant null-terminated character string -* containing the name of the required attribute value. -* def -* If the supplied element does not have the requried attribute, then -* this value will be returned instead. - -* Returned Value: -* The required attribute value, or the default if the value was not found. - -*/ - -/* Local Variables: */ - char buff[ 200 ]; /* Msg buffer */ - const char *value; /* Pointer to attribute value */ - int result; /* Value to be returned */ - int nc; /* Number of characters read by astSscanf */ - int nf; /* Number of matching fields */ - int len; /* Length of attribute string */ - -/* Initialise. */ - result = def; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get the attribute value as a string. */ - value = astXmlGetAttributeValue( elem, name ); - -/* If the attribute exists, attempt to decode the string to give an integer - value, checking that the entire string is read. */ - if( value ) { - nc = 0; - nf = astSscanf( value, " %d %n", &result, &nc ); - len = strlen( value ); - - if ( nf != 1 || nc < len ) { - sprintf( buff, "contains a bad <%s> value: \"%s\"", name, value ); - Report( this, elem, WARNING, buff, status ); - } - } - -/* Return the result. */ - return result; -} - -static int AttrValueB( AstXmlChan *this, AstXmlElement *elem, const char *name, - int def, int *status ) { -/* -* Name: -* AttrValueB - -* Purpose: -* Read a boolean XML element attribute value. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int AttrValueB( AstXmlChan *this, AstXmlElement *elem, const char *name, -* int def, int *status ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function returns the value of a named attribute of an XML element -* as a boolean. A report is made if the attribute value is not -* boolean. The supplied default value is returned if the attribute is not -* present. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the XmlElement. -* name -* Pointer to a constant null-terminated character string -* containing the name of the required attribute value. -* def -* If the supplied element does not have the requried attribute, then -* this value will be returned instead. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The required attribute value, or the default if the value was not found. - -*/ - -/* Local Variables: */ - char buff[ 200 ]; /* Msg buffer */ - const char *value; /* Pointer to attribute value */ - int result; /* Value to be returned */ - int i; /* Loop count */ - -/* Define the recognised true and false strings. */ - const char *true[ 5 ] = { "true", "TRUE", "yes", "YES", "1" }; - const char *false[ 5 ] = { "false", "FALSE", "no", "NO", "0" }; - -/* Initialise. */ - result = def; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get the attribute value as a string. */ - value = astXmlGetAttributeValue( elem, name ); - -/* If the attribute exists, attempt to decode the string to give a boolean - value. */ - if( value ) { - -/* Indicate the result has not yet been determined. */ - result = -1; - -/* See if the attribute value is equal to (or an abbreviation of) any of - the true strings. */ - for( i = 0; i < 5; i++ ) { - if( strstr( true[ i ], value ) == true[ i ] ) { - result = 1; - break; - } - } - -/* If not, see if the attribute value is equal to (or an abbreviation of) any - of the false strings. */ - if( result == -1 ) { - for( i = 0; i < 5; i++ ) { - if( strstr( false[ i ], value ) == false[ i ] ) { - result = 0; - break; - } - } - } - -/* If not, report a warning and return the default. */ - if( result == -1 ) { - result = def; - sprintf( buff, "contains a bad <%s> value: \"%s\"", name, value ); - Report( this, elem, WARNING, buff, status ); - } - } - -/* Return the result. */ - return result; -} - -static AstRegion *BoxReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* BoxReader - -* Purpose: -* Make an AST Region from an IVOA Box element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *BoxReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Box element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Box element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstMapping *map; /* Mapping between units */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[2]; /* Names of the subelements to be searched for */ - const char *unit; /* Centre and radii unit string */ - double cen[2]; /* Centre */ - double size[2]; /* Axis sizes */ - double pos[8]; /* Polygon vertex axis values */ - double *x; /* Pointer to first vertex X axis value */ - double *y; /* Pointer to first vertex Y axis value */ - int i; /* Axis count */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Scan the supplied element for the required sub-elements */ - names[ 0 ] = "Center"; - names[ 1 ] = "Size"; - min[ 0 ] = 1; - min[ 1 ] = 1; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the centre. */ - cen[0] = 0.0; - cen[1] = 0.0; - ElemListD( this, scan->el[0][0], 2, cen, status ); - -/* Get the size. */ - size[0] = 0.0; - size[1] = 0.0; - ElemListD( this, scan->el[1][0], 2, size, status ); - -/* Get the units attribute from the supplied element. These are the units - of the centre and size values. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( !unit ) { - Report( this, elem, FAILURE, "contains no unit attribute", status ); - unit = ""; - } - -/* Since the SkyFrame class does not have active Units we must handle it - separately. */ - if( astIsASkyFrame( frm ) ) { - -/* Create the anti-clockwise list of (x,y) at the four corners of the box. */ - x = pos; - y = pos+ 4; - x[ 3 ] = cen[ 0 ] + 0.5*size[ 0 ]; - y[ 3 ] = cen[ 1 ] - 0.5*size[ 1 ]; - x[ 2 ] = cen[ 0 ] + 0.5*size[ 0 ]; - y[ 2 ] = cen[ 1 ] + 0.5*size[ 1 ]; - x[ 1 ] = cen[ 0 ] - 0.5*size[ 0 ]; - y[ 1 ] = cen[ 1 ] + 0.5*size[ 1 ]; - x[ 0 ] = cen[ 0 ] - 0.5*size[ 0 ]; - y[ 0 ] = cen[ 1 ] - 0.5*size[ 1 ]; - -/* Convert the axis values to radians. */ - map = astUnitMapper( unit, "rad", NULL, NULL ); - if( map ) { - astTran1( map, 8, pos, 1, pos ); - map = astAnnul( map ); - } else if( astOK ) { - Report( this, elem, FAILURE, "contains unusable units", status ); - } - -/* Create the Polygon. */ - new = (AstRegion *) astPolygon( frm, 4, 4, pos, NULL, "", status ); - -/* Now handles Frames other than SkyFrames. */ - } else { - -/* Create the anti-clockwise list of (x,y) at the four corners of the box. */ - x = pos; - y = pos+ 4; - x[ 0 ] = cen[ 0 ] + 0.5*size[ 0 ]; - y[ 0 ] = cen[ 1 ] - 0.5*size[ 1 ]; - x[ 1 ] = cen[ 0 ] + 0.5*size[ 0 ]; - y[ 1 ] = cen[ 1 ] + 0.5*size[ 1 ]; - x[ 2 ] = cen[ 0 ] - 0.5*size[ 0 ]; - y[ 2 ] = cen[ 1 ] + 0.5*size[ 1 ]; - x[ 3 ] = cen[ 0 ] - 0.5*size[ 0 ]; - y[ 3 ] = cen[ 1 ] - 0.5*size[ 1 ]; - -/* Take a copy of the supplied Frame and set its Units to the value - obtained from the supplied element. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - astSetUnit( cfrm, 1, unit ); - -/* Create a Polygon within this modified Frame. */ - new = (AstRegion *) astPolygon( frm, 4, 4, pos, NULL, "", status ); - -/* If the Unit of this Region differs from that of the supplied Frame, - set it to the Unit of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new Unit. If the supplied - Frame had no set Unit, set it to the units obtained from the supplied - element. */ - for( i = 0; i < 2; i++ ) { - if( astTestUnit( frm, i ) ) { - funit = astGetUnit( frm, i ); - if( strcmp( funit, unit ) ) astSetUnit( new, i, funit ); - } else { - astSetUnit( frm, i, unit ); - } - } - -/* Free resources */ - cfrm = astAnnul( cfrm ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstRegion *CircleReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* CircleReader - -* Purpose: -* Make an AST Region from an IVOA Circle element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *CircleReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Circle element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Circle element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstMapping *map; /* Mapping between units */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[2]; /* Names of the subelements to be searched for */ - const char *unit; /* Centre unit string from supplied element */ - double cen[2]; /* Centre */ - double rad; /* Radius */ - int i; /* Axis count */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Scan the supplied element for the required sub-elements */ - names[ 0 ] = "Radius"; - names[ 1 ] = "Center"; - min[ 0 ] = 1; - min[ 1 ] = 1; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the radius. */ - rad = ElemValueD( this, scan->el[0][0], 0.0, status ); - -/* Get the centre. */ - cen[0] = 0.0; - cen[1] = 0.0; - ElemListD( this, scan->el[1][0], 2, cen, status ); - -/* Get the units attribute from the supplied element. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( !unit ) { - Report( this, elem, FAILURE, "contains no unit attribute", status ); - unit = ""; - } - -/* Since the SkyFrame class does not have active Units we must handle it - separately. */ - if( astIsASkyFrame( frm ) ) { - -/* Convert the axis values and radius to radians. */ - map = astUnitMapper( unit, "rad", NULL, NULL ); - if( map ) { - astTran1( map, 2, cen, 1, cen ); - astTran1( map, 1, &rad, 1, &rad ); - map = astAnnul( map ); - } else if( astOK ) { - Report( this, elem, FAILURE, "contains unusable units", status ); - } - -/* Create the Circle. */ - new = (AstRegion *) astCircle( frm, 1, cen, &rad, NULL, "", status ); - -/* Now handles Frames other than SkyFrames. */ - } else { - -/* Take a copy of the supplied Frame and set its Units to the value - obtained from the supplied element. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - astSetUnit( cfrm, 1, unit ); - -/* Create a Circle within this modified Frame. */ - new = (AstRegion *) astCircle( cfrm, 1, cen, &rad, NULL, "", status ); - -/* If the Unit of this Region differs from that of the supplied Frame, - set it to the Unit of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new Unit. If the supplied - Frame had no set Unit, set it to the units obtained from the supplied - element. */ - for( i = 0; i < 2; i++ ) { - if( astTestUnit( frm, i ) ) { - funit = astGetUnit( frm, i ); - if( strcmp( funit, unit ) ) astSetUnit( new, i, funit ); - } else { - astSetUnit( frm, i, unit ); - } - } - -/* Free resources */ - cfrm = astAnnul( cfrm ); - - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* ClearAttrib - -* Purpose: -* Clear an attribute value for a XmlChan. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void ClearAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* Channel member function (over-rides the astClearAttrib protected -* method inherited from the Channel class). - -* Description: -* This function clears the value of a specified attribute for a -* XmlChan so that the default value will subsequently be used. - -* Parameters: -* this -* Pointer to the XmlChan. -* attrib -* Pointer to a null terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_object; - -/* Check the attribute name and clear the appropriate attribute. */ - -/* XmlLength */ -/* --------- */ - if ( !strcmp( attrib, "xmllength" ) ) { - astClearXmlLength( this ); - -/* XmlFormat */ -/* --------- */ - } else if ( !strcmp( attrib, "xmlformat" ) ) { - astClearXmlFormat( this ); - -/* XmlPrefix */ -/* --------- */ - } else if ( !strcmp( attrib, "xmlprefix" ) ) { - astClearXmlPrefix( this ); - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - (*parent_clearattrib)( this_object, attrib, status ); - } -} - -static AstRegion *ConstraintReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* ConstraintReader - -* Purpose: -* Make an AST Region from an IVOA Constraint element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *ConstraintReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Constraint element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Constraint element. -* frm -* Pointer to the Frame in which the returned Region should be -* defined. The Unit attribute is assumed to be set to "rad". -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[2]; /* Names of the subelements to be searched for */ - double cen[2]; /* Centre long/lat values */ - double vec[3]; /* Cartesian centre vector */ - double rad; /* Radius */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Scan the supplied element for the required sub-elements */ - names[ 0 ] = "Vector"; - names[ 1 ] = "Offset"; - min[ 0 ] = 1; - min[ 1 ] = 1; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the vector and convert from 3D cartesian to a 2D long/lat centre - position, in radians. */ - vec[0] = 1.0; - vec[1] = 0.0; - vec[2] = 0.0; - ElemListD( this, scan->el[0][0], 3, vec, status ); - palDcc2s( vec, cen, cen + 1 ); - -/* Get the offset, and convert to a radial distance in radians. */ - rad = acos( ElemValueD( this, scan->el[1][0], 1.0, status ) ); - -/* Create the Circle. */ - new = (AstRegion *) astCircle( frm, 1, cen, &rad, NULL, "", status ); - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstRegion *ConvexReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* ConvexReader - -* Purpose: -* Make an AST Region from an IVOA Convex element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *ConvexReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Convex element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Convex element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame to use when building Constraints */ - AstRegion *new; /* Pointer to returned Region */ - AstRegion *reg; /* Pointer to component Region */ - AstRegion *tmp; /* Pointer to new Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[1]; /* Names of the subelements to be searched for */ - const char *unit; /* Unit attribute in element tag */ - int i; /* Loop count */ - int issky; /* Is supplied Frame a SkyFrame? */ - int max[1]; /* Max allowed occurrences of each name */ - int min[1]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for a Region sub-element. */ - names[ 0 ] = "Constraint"; - min[ 0 ] = 1; - max[ 0 ] = INT_MAX; - scan = ScanIVOAElement( this, elem, 1, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Convex needs no units since all values are normalised to a unit sphere */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( unit ) { - Report( this, elem, WARNING, "contains unnecessary unit attribute", status ); - } - -/* Unless the supplied Frame is a SkyFrame (which handles the Unit - attribute unusually), take a copy of the supplied Frame and set its - units to radians. */ - issky = astIsASkyFrame( frm ); - if( issky ) { - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, "rad" ); - astSetUnit( cfrm, 1, "rad" ); - } else { - cfrm = astClone( frm ); - } - -/* Create Regions from all the component Constraint elements, and combine - them into nested CmpRegions, using the boolean AND operator to combine - them. */ - new = ConstraintReader( this, scan->el[0][0], cfrm, status ); - for( i = 1; i < scan->count[0]; i++ ) { - reg = ConstraintReader( this, scan->el[0][i], cfrm, status ); - tmp = (AstRegion *) astCmpRegion( new, reg, AST__AND, "", status ); - reg = astAnnul( reg ); - (void) astAnnul( new ); - new = tmp; - } - -/* If required, modify the units back to their original values This - will cause the axis values defining the returned Region to be re-mapped - into the new units. Do not do this if the supplied Frame is a SkyFrame. */ - if( !issky ) { - if( astTestUnit( frm, 0 ) ) astSetUnit( new, 0, astGetUnit( frm, 0 ) ); - if( astTestUnit( frm, 1 ) ) astSetUnit( new, 1, astGetUnit( frm, 1 ) ); - } - -/* Get any fill factor from the element and assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - cfrm = astAnnul( cfrm ); - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - - -static AstRegion *Coord2VecIntervalReader( AstXmlChan *this, AstXmlElement *elem, - const char *unit, AstFrame *frm, int *status ){ -/* -* Name: -* Coord2VecIntervalReader - -* Purpose: -* Make an AST Region from an IVOA Coord2VecInterval element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *Coord2VecIntervalReader( AstXmlChan *this, AstXmlElement *elem, -* const char *unit, AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Coord2VecInterval element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Coord2VecInterval element. -* unit -* A string holding the units in which the axis values are stored -* in the supplied element. -* frm -* Pointer to the Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstMapping *map; /* Mapping from supplied units to rads */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[2]; /* Names of the subelements to be searched for */ - double hilimit[2]; /* Upper limits */ - double lolimit[2]; /* Lower limits */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "LoLimit2Vec"; - names[ 1 ] = "HiLimit2Vec"; - min[ 0 ] = 0; - min[ 1 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the limits. */ - lolimit[0] = AST__BAD; - lolimit[1] = AST__BAD; - if( scan->count[0] ) ElemListD( this, scan->el[0][0], 2, lolimit, status ); - - hilimit[0] = AST__BAD; - hilimit[1] = AST__BAD; - if( scan->count[1] ) ElemListD( this, scan->el[1][0], 2, hilimit, status ); - -/* Since the SkyFrame class does not have active Units we must handle it - separately. */ - if( astIsASkyFrame( frm ) ) { - -/* Convert the limit values to radians. */ - map = astUnitMapper( unit, "rad", NULL, NULL ); - if( map ) { - astTran1( map, 2, lolimit, 1, lolimit ); - astTran1( map, 2, hilimit, 1, hilimit ); - map = astAnnul( map ); - } else if( astOK ) { - Report( this, elem, FAILURE, "contains unusable units", status ); - } - -/* If at least one limit was found, create an Interval within the supplied - Frame. Otherwise create a negated NullRegion. */ - if( lolimit[ 0 ] != AST__BAD || lolimit[ 1 ] != AST__BAD || - hilimit[ 0 ] != AST__BAD || hilimit[ 1 ] != AST__BAD ) { - new = (AstRegion *) astInterval( frm, lolimit, hilimit, NULL, "", status ); - } else { - new = (AstRegion *) astNullRegion( frm, NULL, "negated=1", status ); - } - -/* Now handles Frames other than SkyFrames. */ - } else { - -/* Take a copy of the supplied Frame and set its Unit attribute to the - supplied value. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - -/* If at least one limit was found, create an Interval within this - modified Frame. Otherwise create a negated NullRegion. */ - if( lolimit[ 0 ] != AST__BAD || lolimit[ 1 ] != AST__BAD || - hilimit[ 0 ] != AST__BAD || hilimit[ 1 ] != AST__BAD ) { - new = (AstRegion *) astInterval( cfrm, lolimit, hilimit, NULL, "", status ); - } else { - new = (AstRegion *) astNullRegion( cfrm, NULL, "negated=1", status ); - } - -/* If the supplied units differ from that of the supplied Frame, set the - units in the Region to those of the supplied Frame. This will cause the - encapsulated limits to be mapped into the required units. If the supplied - Frame had no set Units, set it to the supplied units. */ - if( astTestUnit( frm, 0 ) ) { - funit = astGetUnit( frm, 0 ); - if( strcmp( funit, unit ) ) astSetUnit( new, 0, funit ); - } else { - astSetUnit( frm, 0, unit ); - } - -/* Free resources */ - cfrm = astAnnul( cfrm ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstRegion *Coord3VecIntervalReader( AstXmlChan *this, AstXmlElement *elem, - const char *unit, AstFrame *frm, int *status ){ -/* -* Name: -* Coord3VecIntervalReader - -* Purpose: -* Make an AST Region from an IVOA Coord3VecInterval element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *Coord3VecIntervalReader( AstXmlChan *this, AstXmlElement *elem, -* const char *unit, AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Coord3VecInterval element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Coord3VecInterval element. -* unit -* A string holding the units in which the axis values are stored -* in the supplied element. -* frm -* Pointer to the Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[2]; /* Names of the subelements to be searched for */ - double hilimit[3]; /* Upper limits */ - double lolimit[3]; /* Lower limits */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "LoLimit3Vec"; - names[ 1 ] = "HiLimit3Vec"; - min[ 0 ] = 0; - min[ 1 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the limits. */ - lolimit[0] = AST__BAD; - lolimit[1] = AST__BAD; - lolimit[2] = AST__BAD; - if( scan->count[0] ) ElemListD( this, scan->el[0][0], 3, lolimit, status ); - - hilimit[0] = AST__BAD; - hilimit[1] = AST__BAD; - hilimit[2] = AST__BAD; - if( scan->count[1] ) ElemListD( this, scan->el[1][0], 3, hilimit, status ); - -/* Take a copy of the supplied Frame and set its Unit attribute to the - supplied value. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - -/* If at least one limit was found, create an Interval within this - modified Frame. Otherwise create a negated NullRegion. */ - if( lolimit[ 0 ] != AST__BAD || lolimit[ 1 ] != AST__BAD || - lolimit[ 2 ] != AST__BAD || - hilimit[ 0 ] != AST__BAD || hilimit[ 1 ] != AST__BAD || - hilimit[ 2 ] != AST__BAD ) { - new = (AstRegion *) astInterval( cfrm, lolimit, hilimit, NULL, "", status ); - } else { - new = (AstRegion *) astNullRegion( cfrm, NULL, "negated=1", status ); - } - -/* If the supplied units differ from that of the supplied Frame, set the - units in the Region to those of the supplied Frame. This will cause the - encapsulated limits to be mapped into the required units. If the supplied - Frame had no set Units, set it to the supplied units. */ - if( astTestUnit( frm, 0 ) ) { - funit = astGetUnit( frm, 0 ); - if( strcmp( funit, unit ) ) astSetUnit( new, 0, funit ); - } else { - astSetUnit( frm, 0, unit ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - cfrm = astAnnul( cfrm ); - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstRegion *CoordScalarIntervalReader( AstXmlChan *this, AstXmlElement *elem, - const char *unit, AstFrame *frm, int *status ){ -/* -* Name: -* CoordScalarIntervalReader - -* Purpose: -* Make an AST Region from an IVOA CoordScalarInterval element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *CoordScalarIntervalReader( AstXmlChan *this, AstXmlElement *elem, -* const char *unit, AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* CoordScalarInterval element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA CoordScalarInterval element. -* unit -* A string holding the units in which the axis values are stored -* in the supplied element. -* frm -* Pointer to the Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[2]; /* Names of the subelements to be searched for */ - double hilimit; /* Upper limit */ - double lolimit; /* Lower limit */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "LoLimit"; - names[ 1 ] = "HiLimit"; - min[ 0 ] = 0; - min[ 1 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the limits. */ - lolimit = scan->count[0] ? ElemValueD( this, scan->el[0][0], 0.0, status ) : AST__BAD; - hilimit = scan->count[1] ? ElemValueD( this, scan->el[1][0], 0.0, status ) : AST__BAD; - -/* Take a copy of the supplied Frame and set its Unit attribute to the - supplied value. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - -/* If at least one limit was found, create an Interval within this - modified Frame. Otherwise create a negated NullRegion. */ - if( lolimit != AST__BAD || hilimit != AST__BAD ) { - new = (AstRegion *) astInterval( cfrm, &lolimit, &hilimit, NULL, "", status ); - } else { - new = (AstRegion *) astNullRegion( cfrm, NULL, "negated=1", status ); - } - -/* If the supplied units differ from that of the supplied Frame, set the - units in the Region to those of the supplied Frame. This will cause the - encapsulated limits to be mapped into the required units. If the supplied - Frame had no set Units, set it to the supplied units. */ - if( astTestUnit( frm, 0 ) ) { - funit = astGetUnit( frm, 0 ); - if( strcmp( funit, unit ) ) astSetUnit( new, 0, funit ); - } else { - astSetUnit( frm, 0, unit ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - cfrm = astAnnul( cfrm ); - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static int ElemListD( AstXmlChan *this, AstXmlElement *elem, int n, - double *vals, int *status ) { -/* -* Name: -* ElemListD - -* Purpose: -* Read a floating point XML element value. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int ElemListD( AstXmlChan *this, AstXmlElement *elem, int n, -* double *vals, int *status ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function reads the content of the supplied element, converts its -* contents to a list of floating point values and returns these -* values in "values". A report is made if the element value is not a -* space separated list of floating point values, or if it contains -* more than "n" values. The number of values stored in "values" is -* returned as the function value. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the XmlElement. -* n -* The maximum number of floating point values to read from the supplied -* element. -* values -* Pointer to an array to hold the values read. This should have at -* least "n" elements. Any unused elements are left unchanged. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The number of values stored in "values". - -*/ - -/* Local Variables: */ - AstXmlContentItem *item; /* Item no. "i" */ - char *text; /* Pointer to string holding formatted item */ - char buff[200]; /* Message buffer */ - const char *p; /* Pointer to start of remaining text */ - const char *value; /* Pointer to element value */ - double dval; /* Value read from string */ - int i; /* Index of current item */ - int l; /* Used length of string */ - int nc; /* Number of characters read by astSscanf */ - int nitem; /* Number of items in the element */ - int rep; /* Has a warning about excess values been made? */ - int result; /* Value to be returned */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* No warning has yet been made avbout excess values */ - rep = 0; - -/* Loop through all content items within the supplied element. */ - nitem = astXmlGetNitem( elem ); - for( i = 0; i < nitem; i++ ) { - item = astXmlGetItem( elem, i ); - -/* If this is non-blank character data, attempt to read values from it. */ - if( astXmlCheckType( item, AST__XMLBLACK ) ) { - -/* Get the element value as a string. */ - value = astXmlGetValue( item, 0 ); - if( value ) { - -/* Loop round reading floating point values from the text until the - end of the string is reached. */ - l = astChrLen( value ); - p = value; - while( p < value + l ){ - -/* Read a floating point value from the start of the remaining string, - storing the result in the supplied array. If succesful, increment the - number of values read, and increment the pointer to the start of the - remaining string. Abort if too many values are found. */ - if( astSscanf( p, " %lf %n", &dval, &nc ) == 1 ) { - if( result < n ) { - vals[ result++ ] = dval; - p += nc; - } else { - if( !rep ) { - rep = 1; - if( n > 1 ) { - sprintf( buff, "contains more than %d values - " - "extra values will be ignored", n ); - } else { - sprintf( buff, "contains more than 1 value - " - "extra values will be ignored" ); - } - Report( this, elem, WARNING, buff, status ); - } - break; - } - -/* If the remaing text is not a floating point value, then issue a report. */ - } else { - Report( this, elem, FAILURE, "contains a non-numerical value", status ); - break; - } - } - } - -/* If this is not character data, nor a comment, issue a warning. */ - } else if( !astXmlCheckType( item, AST__XMLWHITE ) && - !astXmlCheckType( item, AST__XMLCOM ) ) { - text = (char *) astXmlFormat( item ); - if( text ) { - if( strlen( text ) > 30 ) text[ 30 ] = 0; - sprintf( buff, "contains the following which is being ignored: \"%s\"", - text ); - text = astFree( text ); - Report( this, elem, WARNING, buff, status ); - } - } - } - -/* Return the result. */ - return result; -} - -static double ElemValueD( AstXmlChan *this, AstXmlElement *elem, double def, int *status ) { -/* -* Name: -* ElemValueD - -* Purpose: -* Read a floating point XML element value. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* double ElemValueD( AstXmlChan *this, AstXmlElement *elem, double def ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function reads the content of the supplied element, converts its -* contents to a floating point value and returns this value. A report is -* made if the element value is not floating point. The supplied default -* value is returned if the element is not present. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the XmlElement. -* def -* If the content of the supplied element is not a flaoting point -* value, then this value will be returned instead. - -* Returned Value: -* The required element value, or the default if the value was not found. - -*/ - -/* Local Variables: */ - const char *value; /* Pointer to element value */ - double result; /* Value to be returned */ - int nc; /* Number of characters read by astSscanf */ - int ok; /* Value read OK? */ - -/* Initialise. */ - result = def; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Assume the value cannot be read. */ - ok = 0; - -/* Get the element value as a string. */ - value = astXmlGetValue( elem, 0 ); - -/* If succesful, convert the value to floating point. */ - if( value ) { - nc = 0; - ok = ( ( 1 == astSscanf( value, " %lf %n", &result, &nc ) ) - && ( nc >= (int) strlen( value ) ) ); - } - -/* Give a warning if not OK, and use default value. */ - if( !ok ) { - Report( this, elem, FAILURE, "does not contain a floating point value", status ); - result = def; - } - -/* Return the result. */ - return result; -} - -static AstRegion *EllipseReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* EllipseReader - -* Purpose: -* Make an AST Region from an IVOA Ellipse element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *EllipseReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Ellipse element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Ellipse element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstMapping *map; /* Mapping between units */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[4]; /* Names of the subelements to be searched for */ - const char *unit; /* Centre and radii unit string */ - double cen[2]; /* Centre */ - double pa; /* Major axis position angle */ - double rad[2]; /* Major and minor radii */ - int i; /* Axis count */ - int max[4]; /* Max allowed occurrences of each name */ - int min[4]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Scan the supplied element for the required sub-elements */ - names[ 0 ] = "Radius"; - names[ 1 ] = "Center"; - names[ 2 ] = "MinorRadius"; - names[ 3 ] = "PosAngle"; - min[ 0 ] = 1; - min[ 1 ] = 1; - min[ 2 ] = 1; - min[ 3 ] = 1; - max[ 0 ] = 1; - max[ 1 ] = 1; - max[ 2 ] = 1; - max[ 3 ] = 1; - scan = ScanIVOAElement( this, elem, 4, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the major radius */ - rad[ 0 ] = ElemValueD( this, scan->el[0][0], 0.0, status ); - -/* Get the minor radius. */ - rad[ 1 ] = ElemValueD( this, scan->el[2][0], 0.0, status ); - -/* Get the centre. */ - cen[0] = 0.0; - cen[1] = 0.0; - ElemListD( this, scan->el[1][0], 2, cen, status ); - -/* Get the position angle. This is returned in the AST convention, i.e. - measured in radians from from +ve second axis through positive first - axis. */ - pa = PosAngleReader( this, scan->el[3][0], status ); - -/* Get the units attribute from the supplied element. These are the units - of the centre and radii value. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( !unit ) { - Report( this, elem, FAILURE, "contains no unit attribute", status ); - unit = ""; - } - -/* Since the SkyFrame class does not have active Units we must handle it - separately. */ - if( astIsASkyFrame( frm ) ) { - -/* Convert the axis values and radii to radians. */ - map = astUnitMapper( unit, "rad", NULL, NULL ); - if( map ) { - astTran1( map, 2, cen, 1, cen ); - astTran1( map, 2, rad, 1, rad ); - map = astAnnul( map ); - } else if( astOK ) { - Report( this, elem, FAILURE, "contains unusable units", status ); - } - -/* Create the Ellipse. */ - new = (AstRegion *) astEllipse( frm, 1, cen, rad, &pa, NULL, "", status ); - -/* Now handles Frames other than SkyFrames. */ - } else { - -/* Take a copy of the supplied Frame and set its Units to the value - obtained from the supplied element. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - astSetUnit( cfrm, 1, unit ); - -/* Create a Ellipse within this modified Frame. */ - new = (AstRegion *) astEllipse( cfrm, 1, cen, rad, &pa, NULL, "", status ); - -/* If the Unit of this Region differs from that of the supplied Frame, - set it to the Unit of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new Unit. If the supplied - Frame had no set Unit, set it to the units obtained from the supplied - element. */ - for( i = 0; i < 2; i++ ) { - if( astTestUnit( frm, i ) ) { - funit = astGetUnit( frm, i ); - if( strcmp( funit, unit ) ) astSetUnit( new, i, funit ); - } else { - astSetUnit( frm, i, unit ); - } - } - -/* Free resources */ - cfrm = astAnnul( cfrm ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static double Error2PAReader( AstXmlChan *this, AstXmlElement *elem, - double *size, int *status ){ -/* -* Name: -* Error2PAReader - -* Purpose: -* Read the contents of an Stc Error2PA element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* double Error2PAReader( AstXmlChan *this, AstXmlElement *elem, -* double *size, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function reads the contents of an Stc Error2PA element. It can -* also be used to read Resolution2PA, Size2PAand PixSize2PA which -* have exactly the same structure as a Error2PA element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Ellipse element. -* size -* Pointer to an array to receive the 2 error sizes. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The position angle of the first error size, in radians, from positive -* second axis to positive first axis. - -*/ - -/* Local Variables: */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[4]; /* Names of the subelements to be searched for */ - double pa; /* Major axis position angle */ - int max[4]; /* Max allowed occurrences of each name */ - int min[4]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - pa = 0.0; - -/* Check the global error status. */ - if ( !astOK ) return pa; - -/* Scan the supplied element for the required sub-elements */ - names[ 0 ] = "Size"; - names[ 1 ] = "PosAngle"; - min[ 0 ] = 1; - min[ 1 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the sizes */ - ElemListD( this, scan->el[0][0], 2, size, status ); - -/* Get the position angle. This is returned in the AST convention, i.e. - measured in radians from from +ve second axis through positive first - axis. */ - pa = PosAngleReader( this, scan->el[1][0], status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Return the position angle. */ - return pa; -} - -static void FillAndLims( AstXmlChan *this, AstXmlElement *elem, AstRegion *new, int *status ){ -/* -* Name: -* FillAndLims - -* Purpose: -* Get fill factor and limit inclusion flags from IVOA element and -* assign to an AST Region. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void FillAndLims( AstXmlChan *this, AstXmlElement *elem, AstRegion *new, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function gets attributes from the supplied element describing -* fill factor and limit inclusion flags, and assigns suitable values -* to the supplied Region. Default values are used if the supplied -* element does not have the required attributes. - -* Parameters: -* this -* Pointer to the XmlChan in which to store warnings. -* elem -* Pointer to the AstXmlElement to search. -* new -* Pointer to the Region in which to store the values. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - const char *text; /* Attribute text */ - double ff; /* Fill factor */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get any fill factor attribute from the element and assign to the - returned Region. */ - ff = AttrValueD( this, elem, "fill_factor", AST__BAD, status ); - if( ff != AST__BAD ) astSetFillFactor( new, ff ); - -/* Get the flags indicating if the limits are included in the interval. - If either of the limits is not included in the interval, then make the - Region open. Assume a default of true ("included") if the attribute is - missing. */ - text = astXmlGetAttributeValue( elem, "lo_include" ); - if( text && !strcmp( text, "false" ) ) astSetClosed( new, 0 ); - - text = astXmlGetAttributeValue( elem, "hi_include" ); - if( text && !strcmp( text, "false" ) ) astSetClosed( new, 0 ); - -} - -static AstXmlElement *FindAttribute( AstXmlChan *this, const char *name, int *status ) { -/* -* Name: -* FindAttribute - -* Purpose: -* Find an XML element representing a named AST attribute. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlElement *FindAttribute( AstXmlChan *this, const char *name, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function searches the content of the current container element -* of the supplied XmlChan looking for an element which represents a -* named AST attribute. No error is reported if the attribute is not -* found. Attributes which represent defaul values are ignored. - -* Parameters: -* this -* Pointer to the XmlChan. -* name -* Pointer to a string holding the required AST attribute name -* (case-insensitive). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the XmlElement if found, and NULL otherwise. - -*/ - -/* Local Variables: */ - AstXmlContentItem *item; /* Item no. "i" */ - AstXmlElement *result; /* Returned pointer */ - const char *def; /* Value from XML DEFAULT attribute */ - const char *definedby; /* Name of class which defines the item */ - const char *xmlname; /* Value from XML NAME attribute */ - int i; /* Index of current item */ - int nitem; /* Number of items still in the element */ - -/* Initialise */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Report an error if the class being loaded has not been set. */ - if( !this->isa_class ) { - astError( AST__INTER, "astRead(XmlChan): astReadNextData not called " - "before reading values for a %s (internal AST programming " - "error).", status, astXmlGetName( this->container ) ); - } - -/* Check we have a container to search. */ - if( !this->container ) { - astError( AST__INTER, "astRead(XmlChan): No container before reading " - "values for a %s (internal AST programming error).", status, - astXmlGetName( this->container ) ); - } - -/* Check all is OK. */ - if( astOK ) { - -/* Loop round all items in the elements contents. */ - nitem = astXmlGetNitem( this->container ); - for( i = 0; i < nitem; i++ ) { - item = astXmlGetItem( this->container, i ); - -/* Ignore this item if it is not an element. */ - if( astXmlCheckType( item, AST__XMLELEM ) ) { - -/* Ignore this element if its name is not ATTR. */ - if( !astOK ) break; - if( !strcmp( astXmlGetName( item ), ATTR ) ){ - -/* Ignore this element if it represents a default value. */ - def = astXmlGetAttributeValue( item, DEFAULT ); - if( !def || strcmp( def, TRUE ) ) { - -/* If this ATTR element has an XML attribute called NAME with - the required value (case-insensitive), we may have found a matching - element. */ - xmlname = astXmlGetAttributeValue( item, NAME ); - if( xmlname && !Ustrcmp( xmlname, name, status ) ) { - -/* Ignore the attribute if it does not belong to the correct part of the - object's class hierarchy. If it does, we have found the required - attribute. */ - definedby = astXmlGetAttributeValue( item, DEFINEDBY ); - if( definedby && !strcmp( definedby, this->isa_class ) ) { - result = (AstXmlElement *) item; - break; - } - } - } - } - } - } - } - -/* Return the pointer. */ - return result; -} - -static AstXmlElement *FindElement( AstXmlChan *this, AstXmlElement *elem, - const char *name, int *status ) { -/* -* Name: -* FindElement - -* Purpose: -* Find a named element within a supplied element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlElement *FindElement( AstXmlChan *this, AstXmlElement *elem, -* const char *name, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function searches the content of the supplied element looking for -* an element with the supplied Name. No error is reported if the element -* is not found, but a Warning is issued if it found more than once. - -* Parameters: -* this -* Pointer to the XmlChan in which to store warnings. -* elem -* Pointer to the AstXmlElement to search. -* name -* Pointer to a string holding the required element name. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the XmlElement if found, and NULL otherwise. - -* Notes: -* - If the supplied element contains more than one element with the -* given name, the returned pointer locates the first element -* encountered with the required name, and a WARNING is issued that the -* second and subsequent elements will be ignored. - -*/ - -/* Local Variables: */ - AstXmlContentItem *item; /* Item no. "i" */ - AstXmlElement *result; /* Returned pointer */ - char buff[ 200 ]; /* Message buffer */ - int i; /* Index of current item */ - int nitem; /* Number of items still in the element */ - int warned; /* Has a warning been issued? */ - -/* Initialise */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Loop round all items in the elements contents. */ - warned = 0; - nitem = astXmlGetNitem( elem ); - for( i = 0; i < nitem; i++ ) { - item = astXmlGetItem( elem, i ); - -/* Ignore this item if it is not an element. */ - if( astXmlCheckType( item, AST__XMLELEM ) ) { - -/* If this element's name is the given name. */ - if( !strcmp( astXmlGetName( item ), name ) ){ - -/* If this is the first element with the required name, store its - pointer. */ - if( !result ) { - result = (AstXmlElement *) item; - -/* Otherwise add a Warning (unles a Warning has already been issued). */ - } else if( !warned ) { - warned = 1; - sprintf( buff, "contains more than one %s element. The " - "second and subsequent such elements will be " - "ignored", name ); - Report( this, elem, WARNING, buff, status ); - } - } - } - } - -/* Return the pointer. */ - return result; -} - -static IVOAReader FindIVOAClass( AstXmlElement *elem, int *is_ivoa, int *status ) { -/* -* Name: -* FindIVOAClass - -* Purpose: -* Return a pointer to a function which will create an AST Object from -* an IVOA element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* IVOAReader FindIVOAClass( AstXmlElement *elem, int *is_ivoa, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function checks the namespace of the supplied element to see if -* it is a known IVOA namespace. If it is, it returns the "is_ivoa" -* flag set to non-zero (otherwise it is returned as zero). It then -* checks to see if an AST object can be created from the IVOA -* element. If so, a pointer to the function which will do the -* conversion is returned. Otherwise a NULL pointer is returned. - -* Parameters: -* elem -* Pointer to the element to check. -* is_ivoa -* Pointer to an int in which to return a flag indicating if the -* supplied element belongs to a known IVOA namespace. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to the function (if any) which can produce an AST Object -* from the supplied element, or NULL if conversion is not possible. - -* Notes: -* - NULL is returned if this function is invoked with the error -* status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - IVOAReader result; /* Returned pointer */ - const char *ivoa; /* Pointer to "ivoa" substring */ - const char *name; /* Pointer to string holding element name */ - const char *stc; /* Pointer to "stc" substring */ - const char *uri; /* Pointer to string holding element namespace URI */ - -/* Initialise */ - *is_ivoa = 0; - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get the element name.*/ - name = astXmlGetName( elem ); - -/* Get the namespace URI for the element, and see if it contains - sub-strings "STC" (or "stc") and "IVOA" (or "ivoa"). */ - uri = astXmlGetURI( elem ); - if( uri ) { - stc = strstr( uri, "STC" ); - if( !stc ) stc = strstr( uri, "stc" ); - ivoa = strstr( uri, "IVOA" ); - if( !ivoa ) ivoa = strstr( uri, "ivoa" ); - - } else { - stc = NULL; - ivoa = NULL; - } - -/* If it is a known IVOA namespace, proceed. */ - if( name && ( stc || ivoa ) ){ - *is_ivoa = 1; - -/* Look for element types which can be converted to AST objects, and - return a pointer to the corresponding reader function. */ - if( !strcmp( name, STC_RESOURCE_PROFILE ) ) { - result = StcMetadataReader; - - } else if( !strcmp( name, SEARCH_LOCATION ) ) { - result = StcMetadataReader; - - } else if( !strcmp( name, CATALOG_ENTRY_LOCATION ) ) { - result = StcMetadataReader; - - } else if( !strcmp( name, OBSERVATION_LOCATION ) ) { - result = StcMetadataReader; - - } else if( !strcmp( name, OBS_DATA_LOCATION ) ) { - result = ObsDataLocationReader; - - } else if( !strcmp( name, ASTRO_COORD_SYSTEM ) ) { - result = AstroCoordSystemReader; - - } else if( !strcmp( name, TIME_FRAME ) ) { - result = TimeFrameReader; - - } else if( !strcmp( name, SPACE_FRAME ) ) { - result = SpaceFrameReader; - - } else if( !strcmp( name, SPECTRAL_FRAME ) ) { - result = SpectralFrameReader; - - } else if( !strcmp( name, REDSHIFT_FRAME ) ) { - result = RedshiftFrameReader; - - } else if( !strcmp( name, REDSHIFT_FRAME ) ) { - result = RedshiftFrameReader; - - } - } - -/* Return null if an error occurred. */ - if( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -static const char *FindNextIsA( AstXmlElement *elem, int start, int *status ) { -/* -* Name: -* FindNextIsA - -* Purpose: -* Find the next "isa" element within an XML element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* const char *FindNextIsA( AstXmlElement *elem, int start, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function searches the content of the specified element, -* starting at the item with the speicfied index, until it finds the -* next "isa" element. It returns the value of the "class" attribute -* of the found "isa" element, or the name of the supplied element -* if no "isa" element is found. - -* Parameters: -* elem -* Pointer to the XmlElement (an element describing an AST Object). -* start -* The index of the first content item to check. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the class string. - -*/ - -/* Local Variables: */ - AstXmlContentItem *item; /* Item no. "i" */ - const char *result; /* Returned string */ - int i; /* Index of current item */ - int nitem; /* Number of items still i nthe element */ - -/* Initialise */ - result = astXmlGetName( elem ); - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Loop round all items contained in the element, starting at the given - index. */ - nitem = astXmlGetNitem( elem ); - for( i = start; i < nitem; i++ ) { - item = astXmlGetItem( elem, i ); - -/* Check this item is an XmlElement with name ISA. */ - if( astXmlCheckType( item, AST__XMLELEM ) ) { - if( astOK && !strcmp( astXmlGetName( item ), ISA ) ) { - -/* The returned string is the value of the "class" attribute of this - element. */ - result = astXmlGetAttributeValue( item, "class" ); - -/* Report an error if the element does not have a class attribute. */ - if( !result && astOK ) { - astError( AST__BADIN, "astRead(XmlChan): The tag %s " - "does not include a \"class\" attribute.", status, - GetTag( (AstXmlObject *) item, 1, status ) ); - } - - break; - - } - } - } - -/* Return the result. */ - return result; -} - -static AstXmlElement *FindObject( AstXmlChan *this, const char *name, int *status ) { -/* -* Name: -* FindObject - -* Purpose: -* Find an XML element representing a named AST Object. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlElement *FindObject( AstXmlChan *this, const char *name, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function searches the content of the current container element -* of the supplied XmlChan looking for an element which represents a -* named AST Object. No error is reported if the object is not -* found. Objects which represent default values are ignored. - -* Parameters: -* this -* Pointer to the XmlChan. -* name -* Pointer to a string holding the required AST object name -* (case-insensitive). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the XmlElement if found, and NULL otherwise. - -*/ - -/* Local Variables: */ - AstXmlContentItem *item; /* Item */ - AstXmlElement *result; /* Returned pointer */ - const char *def; /* Value from XML DEFAULT attribute */ - const char *definedby; /* Name of class which defines the item */ - const char *xmlname; /* Value from XML LABEL attribute */ - int i; /* Index of current item */ - int nitem; /* Number of items still i nthe element */ - -/* Initialise */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Report an error if the class being loaded has not been set. */ - if( !this->isa_class ) { - astError( AST__INTER, "astRead(XmlChan): astReadNextData not called " - "before reading values for a %s (internal AST programming " - "error).", status, astXmlGetName( this->container ) ); - } - -/* Check we have a container to search. */ - if( !this->container ) { - astError( AST__INTER, "astRead(XmlChan): No container before reading " - "values for a %s (internal AST programming error).", status, - astXmlGetName( this->container ) ); - } - -/* Check all is OK. */ - if( astOK ) { - -/* Loop round all items in the elements contents. */ - nitem = astXmlGetNitem( this->container ); - for( i = 0; i < nitem; i++ ) { - item = astXmlGetItem( this->container, i ); - -/* Ignore this item if it is not an element. */ - if( astXmlCheckType( item, AST__XMLELEM ) ) { - -/* Ignore this element if its name is ATTR. */ - if( astOK && strcmp( astXmlGetName( item ), ATTR ) ){ - -/* Ignore this element if it represents a default value. */ - def = astXmlGetAttributeValue( item, DEFAULT ); - if( !def || strcmp( def, TRUE ) ) { - -/* If this non-ATTR element has an XML attribute called LABEL with - the required value (case-insensitive), we may have found a matching element. */ - xmlname = astXmlGetAttributeValue( item, LABEL ); - if( xmlname && !Ustrcmp( xmlname, name, status ) ) { - -/* Ignore the element if it does not belong to the correct part of the - object's class hierarchy. If it does, we have found the required - object. */ - definedby = astXmlGetAttributeValue( item, DEFINEDBY ); - if( definedby && !strcmp( definedby, this->isa_class ) ) { - result = (AstXmlElement *) item; - break; - } - } - } - } - } - } - } - -/* Return the pointer. */ - return result; -} - -static int FindString( int n, const char *list[], const char *test, - const char *text, const char *method, - const char *class, int *status ){ -/* -* Name: -* FindString - -* Purpose: -* Find a given string within an array of character strings. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int FindString( int n, const char *list[], const char *test, -* const char *text, const char *method, const char *class, int *status ) - -* Class Membership: -* XmlChan method. - -* Description: -* This function identifies a supplied string within a supplied -* array of valid strings, and returns the index of the string within -* the array. The test option may not be abbreviated, but case is -* insignificant. - -* Parameters: -* n -* The number of strings in the array pointed to be "list". -* list -* A pointer to an array of legal character strings. -* test -* A candidate string. -* text -* A string giving a description of the object, parameter, -* attribute, etc, to which the test value refers. -* This is only for use in constructing error messages. It should -* start with a lower case letter. -* method -* Pointer to a string holding the name of the calling method. -* This is only for use in constructing error messages. -* class -* Pointer to a string holding the name of the supplied object class. -* This is only for use in constructing error messages. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The index of the identified string within the supplied array, starting -* at zero. - -* Notes: -* - A value of -1 is returned if an error has already occurred, or -* if this function should fail for any reason (for instance if the -* supplied option is not specified in the supplied list). - -*/ - -/* Local Variables: */ - int ret; /* The returned index */ - -/* Check global status. */ - if( !astOK ) return -1; - -/* Compare the test string with each element of the supplied list. Leave - the loop when a match is found. */ - for( ret = 0; ret < n; ret++ ) { - if( !Ustrcmp( test, list[ ret ], status ) ) break; - } - -/* Report an error if the supplied test string does not match any element - in the supplied list. */ - if( ret >= n && astOK ) { - astError( AST__RDERR, "%s(%s): Illegal value '%s' supplied for %s.", status, - method, class, test, text ); - ret = -1; - } - -/* Return the answer. */ - return ret; -} - -static IVOAScan *FreeIVOAScan( IVOAScan *in, int *status ){ -/* -* Name: -* FreeIVOAScan - -* Purpose: -* Free resources used by an IVOAScan structure. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* IVOAScan *FreeIVOAScan( IVOAScan *in ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function frees resources used by an IVOAScan structure (such -* as returned by the ScanIVOAElement function). - -* Parameters: -* in -* Pointer to the IVOAScan structure. - -* Returned Value: -* A NULL pointer. - -*/ - -/* Local Variables: */ - int j; /* Index of current name */ - -/* Check the supplied pointer can be used safely. */ - if( in ) { - -/* Free the arrays holding the element pointers. */ - for( j = 0; j < in->n; j++ ) { - in->count[ j ] = 0; - in->el[ j ] = astFree( in->el[ j ] ); - } - -/* Free the array holding the pointers to the arrays holding the element - pointers. */ - in->el = astFree( in->el ); - -/* Free the array holding the number of element pointers stored. */ - in->count = astFree( in->count ); - -/* For safety, put a zero in the name count. */ - in->n = 0; - -/* Free the whole structure. */ - in = astFree( in ); - - } - - return NULL; -} - -static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* GetAttrib - -* Purpose: -* Get the value of a specified attribute for a XmlChan. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected astGetAttrib -* method inherited from the Channel class). - -* Description: -* This function returns a pointer to the value of a specified -* attribute for a XmlChan, formatted as a character string. - -* Parameters: -* this -* Pointer to the XmlChan. -* attrib -* Pointer to a null terminated string containing the name of -* the attribute whose value is required. This name should be in -* lower case, with all white space removed. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* - Pointer to a null terminated string containing the attribute -* value. - -* Notes: -* - The returned string pointer may point at memory allocated -* within the XmlChan, or at static memory. The contents of the -* string may be over-written or the pointer may become invalid -* following a further invocation of the same function or any -* modification of the XmlChan. A copy of the string should -* therefore be made if necessary. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - const char *result; /* Pointer value to return */ - int ival; /* Integer attribute value */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this_object); - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_object; - -/* Compare "attrib" with each recognised attribute name in turn, - obtaining the value of the required attribute. If necessary, write - the value into "getattrib_buff" as a null terminated string in an appropriate - format. Set "result" to point at the result string. */ - -/* XmlLength */ -/* --------- */ - if ( !strcmp( attrib, "xmllength" ) ) { - ival = astGetXmlLength( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", ival ); - result = getattrib_buff; - } - -/* XmlFormat */ -/* --------- */ - } else if ( !strcmp( attrib, "xmlformat" ) ) { - ival = astGetXmlFormat( this ); - if ( astOK ) { - if( ival == NATIVE_FORMAT ){ - result = NATIVE_STRING; - - } else if( ival == QUOTED_FORMAT ){ - result = QUOTED_STRING; - - } else if( ival == IVOA_FORMAT ){ - result = IVOA_STRING; - - } else { - result = UNKNOWN_STRING; - } - } - -/* XmlPrefix */ -/* --------- */ - } else if ( !strcmp( attrib, "xmlprefix" ) ) { - result = astGetXmlPrefix( this ); - -/* If the attribute name was not recognised, pass it on to the parent - method for further interpretation. */ - } else { - result = (*parent_getattrib)( this_object, attrib, status ); - } - -/* Return the result. */ - return result; -} - - -static int GetComment( AstChannel *this, int *status ) { -/* -* Name: -* GetComment - -* Purpose: -* Get the value of the Comment attribute of a Channel. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int GetComment( AstChannel *this, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected astGetComment -* method inherited from the Channel class). - -* Description: -* This function returns the value of the Comment attribute of the XmlChan. -* It changs the default value from 1 (provided by the parent Channel -* class) to zero. - -* Parameters: -* this -* Pointer to the XmlChan. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* - The Comment value. -*/ - - return astTestComment( this ) ? (*parent_getcomment)( this, status ) : 0; -} - -static int GetFull( AstChannel *this, int *status ) { -/* -* Name: -* GetFull - -* Purpose: -* Get the value of the Full attribute of a Channel. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int GetFull( AstChannel *this, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected astGetFull -* method inherited from the Channel class). - -* Description: -* This function returns the value of the Full attribute of the XmlChan. -* It changs the default value from zero (provided by the parent Channel -* class) to -1. - -* Parameters: -* this -* Pointer to the XmlChan. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* - The Full value. -*/ - - return astTestFull( this ) ? (*parent_getfull)( this, status ) : -1; -} - -static int GetIndent( AstChannel *this, int *status ) { -/* -* Name: -* GetIndent - -* Purpose: -* Get the value of the Indent attribute for an XmlChan. - -* Type: -* Private function. - -* Synopsis: -* #include "XmlChan.h" -* int GetIndent( AstChannel *this, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected astGetIndent -* method inherited from the Channel class). - -* Description: -* This function returns the value of the Indent attribute, supplying -* a default value appropriate to an XmlChan. - -* Parameters: -* this -* Pointer to the XmlChan. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* - The Indent value to use. - -*/ - -/* If the attribute is set, return its value. Otherwise return a value of - zero. */ - return astTestIndent( this ) ? (*parent_getindent)( this, status ) : 0; -} - - -static char GetNextChar( void *data, int *status ) { -/* -* Name: -* GetNextChar - -* Purpose: -* Get the next character from the XML source. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* char GetNextChar( void *data, int *status ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function returns the next character from the XML source, -* getting a new string if necessary. - -* Parameters: -* data -* Pointer to a structure holding data needed to perform the read. -* This should be a pointer to the XmlChan being read. If NULL is -* supplied, then any internal resources are freed and a value of -* zero is returned. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* - The next source character, or zero if NULL is supplied for "data". - -* Notes: -* - Zero is returned if there is no more text to read. -* - Zero is returned if an error has already occurred, or if this -* function should failed for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstXmlChan *this; /* Pointer to the XmlChan */ - char result; /* The returned character */ - -/* Initiialise */ - result = 0; - -/* Get a pointer to the XmlChan. */ - this = (AstXmlChan *) data; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this); - -/* If a NULL pointer is supplied free any memory holding text already - read from the source, and return zero. */ - if( !data ) { - getnextchar_buf = astFree( getnextchar_buf ); - return 0; - } - -/* Check the global status */ - if( !astOK ) return result; - -/* We read a new line from the source if: 1) the reset flag is set in the - XmlChan, 2) we have reached the terminating null in the previous line, - or 3) we do not yet have a line of text. */ - if( this->reset_source || *getnextchar_c == 0 || !getnextchar_buf ) { - this->reset_source = 0; - -/* Free the memory used to hold any previous text. */ - if( getnextchar_buf ) getnextchar_buf = astFree( getnextchar_buf ); - -/* Read a new line of text from the source. */ - getnextchar_buf = astGetNextText( this ); - -/* Read a new line if the previous line was empty. */ - while( getnextchar_buf && !getnextchar_buf[ 0 ] ) { - astFree( getnextchar_buf ); - getnextchar_buf = astGetNextText( this ); - } - -/* Reset the pointer to the next character to the start of the new - string. */ - getnextchar_c = getnextchar_buf; - -/* If all has gone OK, return the first character and then increment getnextchar_c to - point to the next character. */ - if( getnextchar_c && astOK ) result = *(getnextchar_c++); - -/* If we are reading a previously read line, return the character located - by getnextchar_c and increment getnextchar_c. */ - } else { - result = *(getnextchar_c++); - } - -/* Return the result */ - return result; - -} - -static const char *GetTag( AstXmlObject *this, int opening, int *status ){ -/* -* Name: -* GetTag - -* Purpose: -* Returns a string holding an XML tag describing the given XmlObject. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* const char *GetTag( AstXmlObject *this, int opening, int *status ) - -* Description: -* This function returns a pointer to static string -* containing an XML tag describing the given XmlObject. It is a -* wrapper for the astXmlGetTag function defined in xml.h, but it -* additionally removes any "definedby" attribute before formating the -* tag (the "definedby" attribute is added by the ReadClassData -* function and is not part of the XML text read from the source). - -* Parameters: -* this -* Pointer to the XmlObject. -* opening -* Indicates which tag is to be returned; the start tag or the end -* tag. If non-zero the start tag is returned. Otherwise, the -* end tag is returned. If the supplied XmlObject has no end -* tag (i.e. if it is an empty element, or if it is not an element), -* then NULL is returned but no error is reported. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a null terminated static string holding the tag. - -* Notes: -* - Empty elements are represented as an start tag of the form <.../>, -* with no corresponding end tag. -* - NULL is returned if an error has already occurred, or if this -* function should fail for any reason. -*- -*/ - -/* Local Variables: */ - AstXmlElement *elem; /* Pointer to XML element */ - const char *result; /* The returned pointer */ - const char *ptr; /* The value of the "definedby" attribute */ - const char *class; /* Copy of the value of the "definedby" attribute */ - -/* Initialise */ - result = NULL; - -/* If the object is an element, check for the "definedby" attribute. */ - if( astXmlCheckType( this, AST__XMLELEM ) ) { - elem = (AstXmlElement *) this; - -/* See if the element contains a "definedby" attribute. */ - ptr = astXmlGetAttributeValue( elem, DEFINEDBY ); - -/* If so, temporarily remove it, format the tag and then put it back. */ - if( ptr ) { - class = astStore( NULL, ptr, strlen( ptr ) + 1 ); - astXmlRemoveAttr( elem, DEFINEDBY, NULL ); - result = astXmlGetTag( elem, opening ); - astXmlAddAttr( elem, DEFINEDBY, class, NULL ); - class = astFree( (void *) class ); - -/* If not, just use astXmlGetTag. */ - } else { - result = astXmlGetTag( this, opening ); - } - -/* If the object is not an element, just use astXmlGetTag. */ - } else { - result = astXmlGetTag( this, opening ); - } - -/* Return the result. */ - return result; -} - -static AstRegion *IntersectionReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* IntersectionReader - -* Purpose: -* Make an AST Region from an IVOA Intersection region element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *IntersectionReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Intersection region element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Intersection region element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - AstRegion *reg; /* Pointer to component Region */ - AstRegion *tmp; /* Pointer to new Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[1]; /* Names of the subelements to be searched for */ - int i; /* Loop count */ - int max[1]; /* Max allowed occurrences of each name */ - int min[1]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for a Region sub-element. */ - names[ 0 ] = "Intersection|Union|Negation|AllSky|Circle|Ellipse|Polygon|" - "Convex|Box"; - min[ 0 ] = 2; - max[ 0 ] = INT_MAX; - scan = ScanIVOAElement( this, elem, 1, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create Regions from all the component region elements, and combine - them into nested CmpRegions, using the boolean AND operator to combine - them. */ - new = RegionReader( this, scan->el[0][0], frm, status ); - for( i = 1; i < scan->count[0]; i++ ) { - reg = RegionReader( this, scan->el[0][i], frm, status ); - tmp = (AstRegion *) astCmpRegion( new, reg, AST__AND, "", status ); - reg = astAnnul( reg ); - (void) astAnnul( new ); - new = tmp; - } - -/* Get any fill factor from the element and assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static int IsUsable( AstXmlElement *elem, int *status ){ -/* -* Name: -* IsUsable - -* Purpose: -* See if an XmlElement could describe an AST object. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* int IsUsable( AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function checks if an instance of an AST class could be -* created from the supplied XmlElement. - -* Parameters: -* elem -* A pointer to the XmlElement, or NULL. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* If an AST Object could be created from the supplied element, +1 is -* returned. Otherwise, -1 is returned. Zero is returned if the supplied -* pointer is NULL. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - const char *class; /* Pointer to element name */ - const char *uri; /* Pointer to namespace URI */ - IVOAReader reader; /* Pointer to reader function */ - int is_ivoa; /* Element belongs to an IVOA namespace? */ - int oldrep; /* Original value of the Reporting flag */ - int result; /* Result value to be returned */ - -/* Check the global error status, and the supplied pointer. */ - if ( !astOK || !elem ) return 0; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Initialise */ - result = -1; - -/* See if the element is in a supported IVOA namespace, and has a reader - function for converting it to an AST object. If so, set the default - XmlFormat to IVOA, and set the result non-zero. */ - reader = FindIVOAClass( elem, &is_ivoa, status ); - if( is_ivoa ){ - if( reader ) result = 1; - if( isusable_this ) isusable_this->formatdef = IVOA_FORMAT; - } - -/* If the element is not an IVOA class, only proceed if the URI is not - defined, or if it the AST URI. */ - uri = astXmlGetURI( elem ); - if( result == -1 && ( !uri || !strcmp( uri, AST__XMLNS ) ) ) { - -/* Get the element name. This will be an AST class name if the element - describes an AST Object. */ - class = astXmlGetName( elem ); - -/* Attempt to get the loader for a class of this name. If no loader exists an - error would normally be reported. Therefore we switch off error reporting - before making this call. After the class we clear any error status and - switch error reporting back on. If no error occurs whilst getting the - loader, then the class name must be a valid AST class name and so return - a non-zero result value. */ - if( astOK ) { - oldrep = astReporting( 0 ); - astGetLoader( class, status ); - if( astOK ) { - result = 1; - } else { - astClearStatus; - } - astReporting( oldrep ); - } - -/* If the element is in no namespace, use the AST URI as the default - namespace for it and its children. */ - if( !uri ) astXmlAddURI( elem, NULL, AST__XMLNS ); - - } - -/* Return the result. */ - return result; -} - -static AstObject *MakeAstFromXml( AstXmlChan *this, AstXmlElement *elem, int *status ) { -/* -* Name: -* MakeAstFromXml - -* Purpose: -* Make an AST Object from an XML element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *MakeAstFromXml( AstXmlChan *this, AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Object from the supplied XML element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the XML element containing a description of the AST -* object. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. -*/ - -/* Local Variables: */ - AstLoaderType *loader; /* Pointer to loader for Object */ - AstObject *new; /* Pointer to returned Object */ - AstXmlParent *old_container; /* Element from which items are being read */ - IVOAReader reader; /* Pointer to reader function */ - const char *class; /* Pointer to Object class name string */ - int is_ivoa; /* Element belongs to an IVOA namespace? */ - int i; /* Index of content item */ - int nitem; /* No. of items of content within element */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* First deal with IVOA format. */ -/* ---------------------------- */ - if( astGetXmlFormat( this ) == IVOA_FORMAT ) { - -/* Get a pointer to a function which will produce an AST object from - elements of the class of the supplied element. */ - reader = FindIVOAClass( elem, &is_ivoa, status ); - -/* If found, invoke the function to create the new AST object. */ - if( is_ivoa && reader ) { - new = ( *reader )( this, elem, status ); - -/* IVOA reader functions do not remove used content as they are read - from the element (unlike AST native readers). Therefore empty the - element of all content now to indicate that the element contained no - unrecognised content. This prevents an error being reported. If there - was in fact any unrecognised content, then an error will already have - been reported. */ - nitem = astXmlGetNitem( elem ); - for( i = nitem - 1; i >= 0; i-- ) astXmlDelete( astXmlGetItem( elem, i ) ); - -/* If not found, report an error. This should not happen since the IsUsable - function should already have checked that the element is usable. */ - } else if( astOK ){ - astError( AST__INTER, "astRead(XmlChan): MakeAstFromIVOA does not " - "support IVOA class \"%s\" (internal AST programming error).", status, - astXmlGetName( elem ) ); - } - -/* Now deal with other (i.e. NATIVE and QUOTED) format. */ -/* ---------------------------------------------------- */ - } else { - -/* Get the AST class name. This is the name of the XML element. */ - class = astXmlGetName( elem ); - -/* Use the associated class name to locate the loader for that - class. This function will then be used to build the Object. */ - loader = astGetLoader( class, status ); - -/* If OK, save the pointer to the current container element, and indicate - that the supplied element is now to be used as the current container. - The "current container" is the XML element from which values are being - read. */ - if( astOK ) { - old_container = this->container; - this->container = (AstXmlParent *) elem; - -/* The "isa_class" item in the XmlChan structure contains a pointer to - the name of the class whose loader is currently being invoked. It is set - by the loader itself as a side effect of calling the astReadClassData - function. Initialise it to NULL to indicate that astReadClassData has - not yet been called. */ - this->isa_class = NULL; - -/* Invoke the loader, which reads the Object definition from the - current XML container (i.e. the supplied XML element) and builds the - Object. Supply NULL/zero values to the loader so that it will substitute - values appropriate to its own class. */ - new = (*loader)( NULL, (size_t) 0, NULL, NULL, (AstChannel *) - this, status ); - -/* Re-instate the original container. */ - this->container = old_container; - } - } - -/* If an error occurred, clean up by deleting the new Object and - return a NULL pointer. */ - if ( !astOK ) new = astDelete( new ); - -/* Return the pointer to the new Object. */ - return new; -} - -static double MakeMJD( AstTimeFrame *frm, double time, int *status ) { -/* -* Name: -* MakeMJD - -* Purpose: -* Create an MJD value from a TimeFrame axis value. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* double MakeMJD( AstTimeFrame *frm, double time, int *status ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function converts the supplied time value from the system -* represented by the supplied TimeFrame into an absolute TBD MJD, -* in units of days. - -* Parameters: -* frm -* Pointer to the TimeFrame defining the system in which "time" is -* supplied. -* time -* The time value to convert. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The equivalent MJD value. - -*/ - -/* Local Variables: */ - AstFrameSet *fs; - AstTimeFrame *cfrm; - double result; - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Create a copy of the supplied TimeFrame, and set its attributes to - describe the required MJD system. */ - cfrm = astCopy( frm ); - astSetSystem( cfrm, AST__MJD ); - astSetUnit( cfrm, 0, "d" ); - astSetTimeScale( cfrm, AST__TDB ); - astSetTimeOrigin( cfrm, 0.0 ); - -/* Find the Mapping from the supplied TimeFrame to this TimeFrame. Use it to - transform the supplied time value */ - fs = astConvert( frm, cfrm, "" ); - if( fs ) { - astTran1( fs, 1, &time, 1, &result ); - -/* Free resources */ - fs = astAnnul( fs ); - } - cfrm = astAnnul( cfrm ); - -/* Result */ - return result; - -} - -static AstXmlElement *MakePos2D( AstXmlChan *this, AstXmlElement *elem, int *status ){ -/* -* Name: -* MakePos2D - -* Purpose: -* Create an STC Position2D element from the supplied Position3D. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlElement *MakePos2D( AstXmlChan *this, AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function returns a pointer to a Position2D element by throwing -* away the last axis in the supplied Position3D element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the Position3D element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Position2D element. - - -*/ - -/* Local Variables: */ - AstXmlElement *el; /* Pointer to subelement */ - AstXmlElement *new; /* Pointer to returned XmlElement */ - IVOAScan *scan; /* Structure holding scan results */ - char **words; /* Array of words read from string */ - char *unit2; /* New Unit string */ - char buff[100]; /* Text buffer */ - const char *names[3]; /* Names of the subelements to be searched for */ - const char *unit; /* Unit string */ - double pos[3]; /* Values read from Position3D */ - int i; /* Loop count */ - int l1; /* Length of word 1 */ - int l2; /* Length of word 2 */ - int max[3]; /* Max allowed occurrences of each name */ - int min[3]; /* Min allowed occurrences of each name */ - int n; /* Number of words read from string */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* If the supplied element is not a Position3D just copy it. */ - if( strcmp( astXmlGetName( elem ), "Position3D" ) ) { - new = (AstXmlElement *) astXmlCopy( elem ); - -/* Otherwise, we create a new Position2D and add required content to it. */ - } else { - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Name"; - names[ 1 ] = "Error3"; - names[ 2 ] = "Value3"; - max[ 0 ] = 1; - max[ 1 ] = 2; - max[ 2 ] = 1; - min[ 0 ] = 1; - min[ 1 ] = 0; - min[ 2 ] = 0; - scan = ScanIVOAElement( this, elem, 3, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create an empty XML element with name "Position2D". */ - new = astXmlAddElement( NULL, "Position2D", NULL ); - -/* Get the units attribute from the supplied element. These are the units - of the positional axis values. Copy the first 2 words to the unit - attribute of the new element. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( unit ) { - words = astChrSplit( unit, &n ); - if( words ) { - if( n > 2 ) { - l1 = strlen( words[ 0 ] ); - l2 = strlen( words[ 1 ] ); - unit2 = astMalloc( l1 + l2 + 2 ); - if( unit2 ) { - strcpy( unit2, words[ 0 ] ); - unit2[ l1 ] = ' '; - strcpy( unit2 + l1 + 1, words[ 1 ] ); - unit2[ l1 + l2 + 1 ] = 0; - astXmlAddAttr( new, "unit", unit2, NULL ); - unit2 = astFree( unit2 ); - } - } else { - astXmlAddAttr( new, "unit", unit, NULL ); - } - - if( words ) { - for( i = 0; i < n; i++ ) words[ i ] = astFree( words[ i ] ); - words = astFree( words ); - } - } - } - -/* If this Position3D contains a Name which can be read, obtain it - and store it in the returned Position2D. */ - if( scan->count[ 0 ] > 0 ) { - el = astXmlAddElement( new, "Name", NULL ); - astXmlAddCharData( el, 0, astXmlGetValue( scan->el[ 0 ][ 0 ], 0 ) ); - } - -/* If this Position3D contains a Value which can be read, obtain it, - format the first 2 values and store in the returned Position2D. */ - if( scan->count[ 2 ] > 0 ) { - ElemListD( this, scan->el[ 2 ][ 0 ], 3, pos, status ); - el = astXmlAddElement( new, "Value2", NULL ); - sprintf( buff, "%.*g %.*g", AST__DBL_DIG, pos[0], AST__DBL_DIG, pos[1] ); - astXmlAddCharData( el, 0, buff ); - } - -/* If this Position3D contains an Error which can be read, obtain it, - format the first 2 values and store in the returned Position2D. */ - if( scan->count[ 1 ] > 0 ) { - ElemListD( this, scan->el[ 1 ][ 0 ], 3, pos, status ); - el = astXmlAddElement( new, "Error2", NULL ); - sprintf( buff, "%.*g %.*g", AST__DBL_DIG, pos[0], AST__DBL_DIG, pos[1] ); - astXmlAddCharData( el, 0, buff ); - } - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - } - -/* Return the result.*/ - return new; - -} - -static AstRegion *NegationReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* NegationReader - -* Purpose: -* Make an AST Region from an IVOA Negation region element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *NegationReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Negation region element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Negation region element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[1]; /* Names of the subelements to be searched for */ - int max[1]; /* Max allowed occurrences of each name */ - int min[1]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for a Region sub-element. */ - names[ 0 ] = "Intersection|Union|Negation|AllSky|Circle|Ellipse|Polygon|" - "Convex|Box"; - min[ 0 ] = 1; - max[ 0 ] = 1; - scan = ScanIVOAElement( this, elem, 1, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create a Region from the component region element, and negate it. */ - new = RegionReader( this, scan->el[0][0], frm, status ); - astNegate( new ); - -/* Get any fill factor from the element and assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstObject *ObsDataLocationReader( AstXmlChan *this, - AstXmlElement *elem, int *status ) { -/* -* Name: -* ObsDataLocationReader - -* Purpose: -* Make an AST Object from an IVOA ObsDataLocationReader element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *ObsDataLocationReader( AstXmlChan *this, -* AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Object from the supplied IVOA -* ObsDataLocationReader element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA ObsDataLocationReader element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. -*/ - -/* Local Variables: */ - AstPointList *obs; /* PointList defining the observatory position */ - AstStcObsDataLocation *stc; /* Pointer to returned Object */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[2]; /* Names of the subelements to be searched for */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - stc = NULL; - -/* Check the global error status. */ - if ( !astOK ) return (AstObject *) stc; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "ObservatoryLocation"; - names[ 1 ] = "ObservationLocation"; - min[ 0 ] = 1; - min[ 1 ] = 1; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Read the observation location. */ - stc = (AstStcObsDataLocation *) StcMetadataReader( this, scan->el[ 1 ][ 0 ], status ); - -/* Read the observatory location, returning a Pointlist describing the - observatory position (if possible), and modifiying the observation - Region by (if possible) assigning the observatory location to the - ObsLon and ObsLat attributes of any SpecFrames in the Region, and the - ObsLon and ObsLat attributes of any TimeFrames in the Region. */ - obs = ObservatoryLocationReader( this, scan->el[ 0 ][ 0 ], stc, status ); - if( obs ) { - astStcSetObs( stc, obs ); - obs = astAnnul( obs ); - } - -/* Free resources. */ - scan = FreeIVOAScan( scan, status ); - } - -/* Return the pointer to the new Object. */ - return (AstObject *) stc; -} - -static AstPointList *ObservatoryLocationReader( AstXmlChan *this, - AstXmlElement *elem, - AstStcObsDataLocation *obs, int *status ){ -/* -* Name: -* ObservatoryLocationReader - -* Purpose: -* Make an AST PointList from an IVOA ObservatoryLocationReader element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstPointList *ObservatoryLocationReader( AstXmlChan *this, -* AstXmlElement *elem, -* AstStcObsDataLocation *obs, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST PointList from the supplied IVOA -* ObservatoryLocationReader element, and also modifies the supplied -* StcObsDataLocation so that the ObsLon and ObsLat attributes hold -* the observatory position (if appropriate). - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA ObservatoryLocation element. -* obs -* Pointer to the StcObsDataLocation in which to store the -* observatory position (if terrestrial). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new PointList. - -*/ - -/* Local Constants: */ -#define A0 6378140.0 /* Earth equatorial radius (metres) */ - -/* Local Variables: */ - AstFrame *frm; /* Pointer to obsvtory lon/lat Frame */ - AstFrame *obs_frm; /* Pointer to obsvation lon/lat Frame */ - AstFrame *pfrm; /* Pointer to axis primary Frame */ - AstKeyMap *km; /* KeyMap holding AstroCoords info */ - AstObject *new; /* Pointer to returned Region */ - AstObject *o; /* Pointer to retrieved Region */ - AstPointSet *ps; /* Pointer to PointSet holding obs lon/lat */ - AstRegion *err; /* Pointer to error Region */ - AstStc *stc; /* Pointer to Observatory location stc */ - char setting[ 100 ]; /* Attribute setting string */ - const char *dom; /* Domain string */ - double **ptr; /* Pointers to axis values for obs lon/lat */ - double lambda; /* Geodetic longitude radians */ - double phi; /* Geodetic latitude radians */ - double lon; /* Geocentric longitude radians */ - double lat; /* Geocentric latitude radians */ - int i; /* Index of Frame axis */ - int nax; /* Number of Frame axes */ - int paxis; /* Index of primary Frame axis */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Initialise */ - new = NULL; - -/* Read the ObservatoryLocation as an StcMetadata element (it will be - represented by a NullRegion). */ - stc = (AstStc *) StcMetadataReader( this, elem, status ); - -/* Extract the first AstroCoords KeyMap from the stc. */ - if( astGetStcNCoord( stc ) == 0 ) { - Report( this, elem, FAILURE, "contains no observatory position", status ); - } else { - km = astGetStcCoord( stc, 1 ); - -/* Extract the PointList holding the axis values from the KeyMap. */ - if( !astMapGet0A( km, AST__STCVALUE, &new ) ){ - Report( this, elem, FAILURE, "contains no observatory position", status ); - -/* Extract any position uncertainty, and store as the uncertainty in the - value PointList. */ - } else if( astMapGet0A( km, AST__STCERROR, &o ) ){ - err = (AstRegion *) o; - astSetUnc( new, err ); - -/* Free resources */ - err = astAnnul( err ); - } - km = astAnnul( km ); - } - stc = astAnnul( stc ); - -/* Check the Region is a PointList. */ - if( !astIsAPointList( new ) && astOK ) { - astError( AST__INTER, "ObservatoryLocationReader(XmlChan): The " - "observatory location is described by a %s rather than " - "a PointList (internal AST programming error).", status, - astGetClass( new ) ); - } - -/* If possible, we use the observatory location to set the value of the - ObsLon and ObsLat attributes of any SpecFrames, and the ObsLon and - ObsLat attributes of any TimeFrames, in the supplied ObsDataLocation. - For this to be possible, the PointList being returned must represent - either geodetic or geocentric longitude/latitude. If it is geocentric, - the values need to be converted to geodetic. */ - ps = astRegTransform( new, NULL, 1, NULL, &frm ); - ptr = astGetPoints( ps ); - if( ptr ){ - nax = astGetNaxes( frm ); - lon = AST__BAD; - lat = AST__BAD; - lambda = AST__BAD; - phi = AST__BAD; - for( i = 0; i < nax; i++ ) { - astPrimaryFrame( frm, i, &pfrm, &paxis ); - dom = astGetDomain( pfrm ); - if( dom ) { - if( !strcmp( dom, "GEO_C" ) ){ - if( lon == AST__BAD ) { - lon = ptr[i][0]; - astSetLabel( pfrm, 0, "Geodetic longitude" ); - } else { - lat = ptr[i][0]; - astSetLabel( pfrm, 1, "Geodetic latitude" ); - astSetDomain( pfrm, "GEO_D" ); - } - - } else if( !strcmp( dom, "GEO_D" ) ){ - if( lambda == AST__BAD ) { - lambda = ptr[i][0]; - } else { - phi = ptr[i][0]; - } - } - } - pfrm = astAnnul( pfrm ); - } - -/* If required, convert from geocentric lon/lat to geodetic lon/lat. */ - if( lon != AST__BAD ) { - double pos[ 3 ], height; - -/* Convert the supplied geocentric lon/lat to terrestrial Cartesian - (x,y,z) values. The (x,y,z) system has origin at the centre of the - earth, Z axis going through the north pole, X axis at (long,lat)=(0,0), - and Y axis at (long,lat) = (E90,0). Assume an equatorial sea level - position. */ - palDcs2c( lon, lat, pos ); - pos[ 0 ] *= A0; - pos[ 1 ] *= A0; - pos[ 2 ] *= A0; - -/* Get the corresponding geodetic lon/lat. */ - eraGc2gd( 1, pos, &lambda, &phi, &height ); - } - - if( lambda != AST__BAD ) { - obs_frm = astGetFrame( ((AstRegion *) obs)->frameset, AST__CURRENT ); - nax = astGetNaxes( obs ); - for( i = 0; i < nax; i++ ) { - astPrimaryFrame( obs_frm, i, &pfrm, &paxis ); - if( astIsASpecFrame( pfrm ) ) { - sprintf( setting, "ObsLon(%d)=%.*g", i + 1, AST__DBL_DIG, lambda*AST__DR2D ); - astRegSetAttrib( obs, setting, NULL ); - sprintf( setting, "ObsLat(%d)=%.*g", i + 1, AST__DBL_DIG, phi*AST__DR2D ); - astRegSetAttrib( obs, setting, NULL ); - } else if( astIsATimeFrame( pfrm ) ) { - sprintf( setting, "ObsLon(%d)=%.*g", i + 1, AST__DBL_DIG, lambda*AST__DR2D ); - astRegSetAttrib( obs, setting, NULL ); - sprintf( setting, "ObsLat(%d)=%.*g", i + 1, AST__DBL_DIG, phi*AST__DR2D ); - astRegSetAttrib( obs, setting, NULL ); - } - pfrm = astAnnul( pfrm ); - } - obs_frm = astAnnul( obs_frm ); - } - } - -/* Free resources */ - frm = astAnnul( frm ); - ps = astAnnul( ps ); - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return (AstPointList *) new; -} -#undef A0 - -static void OutputText( AstXmlChan *this, const char *text, int mxlen, int *status ) { -/* -* Name: -* OutputText - -* Purpose: -* Write a string to the sink. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* void OutputText( AstXmlChan *this, const char *text, int mxlen, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function writes the supplied text to the output sink, -* splitting it into lines of no more than "mxlen" characters, if -* required. - -* Parameters: -* this -* A pointer to the XmlChan. -* text -* Pointer to the (potentially long) null terminated string to write -* out to the sink. -* mxlen -* The maximum allowed output line length. If zero, no limit is -* placed on the output line length and the supplied text is always -* written out as a single string. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - char *breakat; /* Pointer to terminating character */ - char *c; /* Pointer to start of next chunk */ - char *lastend; /* Pointer to last closing quote */ - char *lastspace; /* Pointer to last whitespace character */ - char *linestart; /* Pointer to start of current line */ - char quote; /* Opening quote character */ - char tt; /* Character temporarily replaced by 0 */ - int len; /* Length of current line */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* If "mxlen" is zero, just output the string as supplied. */ - if( mxlen < 1 ) { - astPutNextText( this, text ); - -/* Otherwise, output the string split up into lines */ - } else { - c = (char *) text - 1; - quote = 0; - lastend = NULL; - lastspace = NULL; - len = 0; - linestart = (char *) text; - -/* Loop round each character in the text */ - while( *(++c ) ){ - -/* Note if we are currently inside a quoted string. Remember the quote - character (" or ') so that we can look out for the corresponding - closing quote. Note the position of the previous quote end. */ - if( !quote ) { - if( *c == '\"' || *c == '\'' ) quote = *c; - } else { - if( *c == quote ) { - quote = 0; - lastend = c; - } - } - -/* Note the position of hte previous space. */ - if( isspace( *c ) ) lastspace = c; - -/* If we have exceeded the maximum allowed line length, split it. If we - are inside a quote, we split it at the last quote end (if any). If we - are not in a quote, we split it at the last space, or the last quote - end (which ever is closest). To cover the case where the end quote is - first character beyoind the limit, reduce the limit a bit. */ - len++; - if( len >= mxlen - 2 ) { - if( !quote || !lastend ) { - if( lastend && lastspace ){ - breakat = ( lastend > lastspace ) ? lastend + 1: lastspace; - } else if( lastend ){ - breakat = lastend + 1; - } else if( lastspace ){ - breakat = lastspace; - } else { - breakat = c; - } - } else { - breakat = lastend + 1; - } - } else { - breakat = NULL; - } - -/* If we have a line break, output the current line. */ - if( breakat ) { - -/* Terminate the string, first saving the character which is replaced by the - terminating zero so that it can be re-instated later. */ - tt = *breakat; - *breakat = 0; - -/* Write out the newly terminated chunk. */ - astPutNextText( this, linestart ); - -/* Move on to ths start of the next chunk, decrement the number of characters - remaining, and re-instate the character previously over-written by - zero. */ - c = breakat; - linestart = c; - *c = tt; - len = 0; - quote = 0; - } - } - -/* Write out any remaining text (this will be less than "mxlen" - characters long)*/ - if( linestart && *linestart ) astPutNextText( this, linestart ); - } -} - -static AstRegion *PolygonReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* PolygonReader - -* Purpose: -* Make an AST Region from an IVOA Polygon element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *PolygonReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Polygon element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Polygon element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; - AstMapping *map; - AstRegion *new; - IVOAScan *scan; - const char *names[1]; - const char *unit; - const char *funit; - double *pos; - double *x0; - double *y0; - double lbnd[2]; - double ubnd[2]; - int axcon; - int axlon; - int i; - int is_box; - int is_sky; - int laxcon; - int max[1]; - int min[1]; - int nv; - int small[ 4 ]; - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Scan the supplied element for the required sub-elements */ - names[ 0 ] = "Vertex"; - min[ 0 ] = 1; - max[ 0 ] = INT_MAX; - scan = ScanIVOAElement( this, elem, 1, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* See if the Frame is a SkyFrame, and if so, get the index of the - longitude axis. */ - is_sky = astIsASkyFrame( frm ); - axlon = is_sky ? astGetLonAxis( (AstSkyFrame *) frm ) : -1; - -/* Get the units attribute from the supplied element. These are the units - of the vertex axis values. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( !unit ) { - Report( this, elem, FAILURE, "contains no unit attribute", status ); - unit = ""; - } - -/* Create an array to hold the axis values at the vertices. */ - nv = scan->count[0]; - pos = astMalloc( sizeof( double )*(size_t) (2*nv) ); - -/* Read each vertex element in turn. Record whether or not the first 4 - vertices have <SmallCircles>. */ - x0 = pos; - y0 = x0 + nv; - for( i = 0; i < nv; i++, x0++, y0++ ) { - small [ i % 4 ] = VertexReader( this, scan->el[0][i], x0, y0, status ); - } - -/* Reset the pointers so that they point to the first x and y values. */ - x0 = pos; - y0 = x0 + nv; - -/* Since the SkyFrame class does not have active Units we must handle it - separately. Convert the axis values from the supplied units (e.g. - degrees) to radians. */ - if( is_sky ) { - map = astUnitMapper( unit, "rad", NULL, NULL ); - if( map ) { - astTran1( map, nv*2, pos, 1, pos ); - map = astAnnul( map ); - } else if( astOK ) { - Report( this, elem, FAILURE, "contains unusable units", status ); - } - } - -/* If there are 4 vertices we may be able to create an AST Box (not the - same as an STC Box) instead of a Polygon.*/ - is_box = 0; - ubnd[0] = x0[ 0 ]; - lbnd[0] = ubnd[0]; - ubnd[1] = y0[ 0 ]; - lbnd[1] = ubnd[1]; - - if( nv == 4 ) { - -/* See if the edge which ends at the 1st vertex has a constant value on - either axis. Is so, note the index of the axis which is held constant. */ - is_box = 1; - if( is_sky && small[ 0 ] ) { - laxcon = 1 - axlon; - - } else if( astEQUAL( x0[ 0 ], x0[ 3 ] ) ) { - laxcon = 0; - - } else if( astEQUAL( y0[ 0 ], y0[ 3 ] ) ) { - laxcon = 1; - - } else { - is_box = 0; - } - -/* If the first edge represents a constant axis value, see if the others - do too (ensuring that the axes which are held constant alternate). Also - find the bounds of the box.*/ - if( is_box ) { - for( i = 1; i < 4; i++ ) { - if( is_sky && small[ i ] ) { - axcon = 1 - axlon; - - } else if( astEQUAL( x0[ i ], x0[ i - 1 ] ) ) { - axcon = 0; - - } else if( astEQUAL( y0[ i ], y0[ i - 1 ] ) ) { - axcon = 1; - - } else { - is_box = 0; - break; - } - - if( axcon != 1 - laxcon ) { - is_box = 0; - break; - } - - if( x0[ i ] > ubnd[0] ) { - ubnd[0] = x0[ i ]; - - } else if( x0[ i ] < lbnd[0] ) { - lbnd[0] = x0[ i ]; - } - - if( y0[ i ] > ubnd[1] ) { - ubnd[1] = y0[ i ]; - - } else if( y0[ i ] < lbnd[1] ) { - lbnd[1] = y0[ i ]; - } - - laxcon = axcon; - } - } - } - -/* Since the SkyFrame class does not have active Units we must handle it - separately. The axis values have already been converted from the supplied - units (e.g. degrees) to radians. */ - if( is_sky ) { - -/* Create the Polygon or Box within the SkyFrame. */ - if( is_box ) { - new = (AstRegion *) astBox( frm, 1, lbnd, ubnd, NULL, "", status ); - } else { - new = (AstRegion *) astPolygon( frm, nv, nv, pos, NULL, "", status ); - } - -/* Now handles Polygons in Frames other than SkyFrames. */ - } else { - -/* Take a copy of the supplied Frame and set its Units to the value - obtained from the supplied element. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - astSetUnit( cfrm, 1, unit ); - -/* Create the Polygon or Box within the SkyFrame. */ - if( is_box ) { - new = (AstRegion *) astBox( cfrm, 1, lbnd, ubnd, NULL, "", status ); - } else { - new = (AstRegion *) astPolygon( cfrm, nv, nv, pos, NULL, "", status ); - } - -/* If the Unit of this Region differs from that of the supplied Frame, - set it to the Unit of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new Unit. If the supplied - Frame had no set Unit, set it to the units obtained from the supplied - element. */ - for( i = 0; i < 2; i++ ) { - if( astTestUnit( frm, i ) ) { - funit = astGetUnit( frm, i ); - if( strcmp( funit, unit ) ) astSetUnit( new, i, funit ); - } else { - astSetUnit( frm, i, unit ); - } - } - -/* Free resources */ - cfrm = astAnnul( cfrm ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - pos = astFree( pos ); - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static double PosAngleReader( AstXmlChan *this, AstXmlElement *elem, int *status ){ -/* -* Name: -* PosAngleReader - -* Purpose: -* Read an AST position angle value from an IVOA PosAngle element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* double PosAngleReader( AstXmlChan *this, AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function reads the supplied PosANgle element and returns a value -* representing a position angle in the AST convention (radians from -* +ve second axis to +ve first axis). - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Ellipse element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The position angle. - -*/ - -/* Local Variables: */ - char buff[ 200 ]; /* Message buffer */ - const char *paunit; /* Position angle unit string */ - const char *ref; /* Reference axis string */ - double result; /* Position angle value */ - -/* Check the global error status. */ - if ( !astOK ) return 0.0; - -/* Get the numerical position angle stored in the supplied PosAngle - element. */ - result = ElemValueD( this, elem, 0.0, status ); - -/* Get the units attribute from the supplied element. These are the units - of the above value. Default is degrees. */ - paunit = astXmlGetAttributeValue( elem, "unit" ); - -/* Convert the position angle to radians. */ - if( !paunit || !strcmp( paunit, "deg" ) ) { - result *= AST__DD2R; - - } else if( !strcmp( paunit, "h" ) ) { - result *= 15*AST__DD2R; - - } else if( !strcmp( paunit, "arcmin" ) ) { - result *= AST__DD2R/60.0; - - } else if( !strcmp( paunit, "arcsec" ) ) { - result *= AST__DD2R/3600.0; - - } else { - sprintf( buff, "contains unusable angle units \"%s\"", paunit ); - Report( this, elem, FAILURE, buff, status ); - } - -/* Get the reference attribute from the supplied element. This indicates - the sense and origin of the stored angle value. Convert the result - to the AST convention, which is the equivalent of "Y" (which is the same - as "North"). "X" means "from X to Y", "Y" means "from Y to X". Default - is "X". */ - ref = astXmlGetAttributeValue( elem, "reference" ); - if( !ref || !Ustrcmp( ref, "X", status ) ) { - result = AST__DPIBY2 - result; - - } else if( Ustrcmp( ref, "Y", status ) && Ustrcmp( ref, "North", status ) ) { - sprintf( buff, "contains unusable reference attribute \"%s\" " - "(will assume \"Y\" instead)", ref ); - Report( this, elem, WARNING, buff, status ); - } - -/* Return the result. */ - return result; -} - -static AstRegion *Position2DReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, double *pos, - AstKeyMap **anc, int *status ){ -/* -* Name: -* Position2DReader - -* Purpose: -* Modify a Frame to take account of an STC <Position2D> element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *Position2DReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, double *pos, int axis, -* AstKeyMap **anc, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function reads the supplied STC <Position2D> element, and uses it, -* if possible, to create the uncertainty associated with the spatial -* axis in the supplied Frame. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Position2D element. -* frm -* Pointer to the 2D spatial Frame. -* pos -* Pointer to an array in which to return the spatial axis values -* represented by the supplied Position2D element. This array is -* returned filled with AST__BAD If the supplied Position2D element -* does not contain any axis values. -* anc -* Address of a location at which to put a pointer to a newly -* created KeyMap. This KeyMap will contain ancillary information -* from the Position2D. The keys identify the item of ancillary -* information (Name, Value, Error, Resolution, Size, Pixel Size). -* The value associated with the Name key is string containing -* the Name item from the Position2D. The value -* associated with each of the other keys is a pointer to a 2D Region -* within the supplied Frame, corresponding to the value, error, -* resolution, etc. Keys will not be present in the returned KeyMap -* if the corresponding item of ancillary information is not present -* in the Position2D. A NULL pointer is returned if there is no -* ancillary information at all. -* status -* Pointer to the inherited status variable. - -* Returned: -* The uncertainty Region, or NULL if the supplied Position2D element -* does not specify an uncertainty. - -*/ - -/* Local Variables: */ - AstMapping *map1; /* Mapping from first axis units to radians */ - AstMapping *map2; /* Mapping from second axis units to radians */ - AstPointSet *pset; /* Pointset holding Position2D axis values */ - AstRegion *r; /* Region to store in ancillary KeyMap */ - AstRegion *result; /* Returned uncertainty Region */ - IVOAScan *scan; /* Structure holding scan results */ - char **words; /* Array of words extracted from string */ - const char *name; /* Pointer to XML element name */ - const char *names[6]; /* Names of the subelements to be searched for */ - const char *unit1; /* Pointer to axis 1 unit attribute string */ - const char *unit2; /* Pointer to axis 2 unit attribute string */ - const char *unit; /* Pointer to Position2D's unit attribute string */ - double **ptr; /* Arrays holding Position2D axis values */ - double cen[ 2 ]; /* Centre values */ - double hw[ 2 ]; /* Half widths values */ - double pa; /* Error position angle */ - int i; /* Loop count */ - int max[6]; /* Max allowed occurrences of each name */ - int min[6]; /* Min allowed occurrences of each name */ - int nword; /* Number of words extracted from string */ - -/* Initialise */ - result = NULL; - pos[ 0 ] = AST__BAD; - pos[ 1 ] = AST__BAD; - *anc = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Name"; - names[ 1 ] = "Error2|Error2PA"; - names[ 2 ] = "Value2"; - names[ 3 ] = "Resolution2|Resolution2PA"; - names[ 4 ] = "Size2|Size2PA"; - names[ 5 ] = "PixSize2|PixSize2PA"; - max[ 0 ] = 1; - max[ 1 ] = 2; - max[ 2 ] = 1; - max[ 3 ] = 2; - max[ 4 ] = 2; - max[ 5 ] = 2; - min[ 0 ] = 1; - min[ 1 ] = 0; - min[ 2 ] = 0; - min[ 3 ] = 0; - min[ 4 ] = 0; - min[ 5 ] = 0; - scan = ScanIVOAElement( this, elem, 6, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create a KeyMap to return holding ancilary info, and put the Name into - it. */ - *anc = astKeyMap( "", status ); - if( scan->count[0] > 0 ) astMapPut0C( *anc, AST__STCNAME, - astXmlGetValue( scan->el[0][0], 0 ), NULL ); - -/* Get the units attribute from the supplied element. These are the units - of the positional axis values. Split into units for each of the two - axes. */ - unit1 = ""; - unit2 = ""; - words = NULL; - unit = astXmlGetAttributeValue( elem, "unit" ); - - if( !unit ) { - Report( this, elem, FAILURE, "contains no unit attribute", status ); - - } else { - words = astChrSplit( unit, &nword ); - if( words ) { - unit1 = words[ 0 ]; - unit2 = nword > 1 ? words[ 1 ] : words[ 0 ]; - } - } - -/* Since the SkyFrame class does not have active Units we must convert the - axis values from the supplied units (e.g. degrees) to radians. Allow - for different units on the two axes. */ - map1 = astUnitMapper( unit1, "rad", NULL, NULL ); - if( !map1 ) Report( this, elem, FAILURE, "contains unusable units for axis 1", status ); - - if( unit1 && unit2 && strcmp( unit1, unit2 ) ) { - map2 = astUnitMapper( unit2, "rad", NULL, NULL ); - if( !map2 ) Report( this, elem, FAILURE, "contains unusable units for axis 2", status ); - } else { - map2 = astClone( map1 ); - } - -/* If this Position2D contains a Value which can be read, obtain it. Otherwise, - issue a warning. */ - if( scan->count[ 2 ] > 0 ) { - ElemListD( this, scan->el[ 2 ][ 0 ], 2, pos, status ); - -/* Convert to radians. */ - if( map1 == map2 ) { - astTran1( map1, 2, pos, 1, pos ); - } else { - astTran1( map1, 1, pos, 1, pos ); - astTran1( map2, 1, pos + 1, 1, pos + 1 ); - } - -/* If this Position2D contains a value which cannot be used, issue a warning. */ - if( pos[ 1 ] == AST__BAD ) { - Report( this, elem, WARNING, "contains an unreadable <Value>", status ); - } - -/* Create a PointList from it and store in the returned ancillary KeyMap. */ - pset = astPointSet( 1, 2, "", status ); - ptr = astGetPoints( pset ); - if( astOK ) { - ptr[ 0 ][ 0 ] = pos[ 0 ]; - ptr[ 1 ][ 0 ] = pos[ 1 ]; - r = (AstRegion *) astPointList( frm, pset, NULL, "", status ); - astMapPut0A( *anc, AST__STCVALUE, r, NULL ); - r = astAnnul( r ); - } - pset = astAnnul( pset ); - } - -/* Does this Position2D contain any Error? */ - if( scan->count[ 1 ] > 0 && map1 ) { - -/* Issue a warning if more than 1 Error value was found. */ - if( scan->count[ 1 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Error>" - " element. AST can only use the first", status ); - } - -/* If the error has no position angle, just read it as a list of double. - Otherwise, read the Error2PA structure. */ - name = astXmlGetName( scan->el[ 1 ][ 0 ] ); - if( name ) { - if( !strcmp( name, "Error2" ) ) { - ElemListD( this, scan->el[ 1 ][ 0 ], 2, hw, status ); - pa = AST__BAD; - } else { - pa = Error2PAReader( this, scan->el[ 1 ][ 0 ], hw, status ); - } - -/* Convert to radians, and halve to get the half-width. */ - if( map1 == map2 ) { - astTran1( map1, 2, hw, 1, hw ); - } else { - astTran1( map1, 1, hw, 1, hw ); - astTran1( map2, 1, hw + 1, 1, hw + 1 ); - } - - if( hw[ 0 ] != AST__BAD ) hw[ 0 ] *= 0.5; - if( hw[ 1 ] != AST__BAD ) hw[ 1 ] *= 0.5; - -/* Create an Ellipse or Box to describe the error */ - cen[ 0 ] = 0.0; - cen[ 1 ] = 0.0; - if( pa != AST__BAD ) { - result = (AstRegion *) astEllipse( frm, 1, cen, hw, &pa, - NULL, "", status ); - } else { - result = (AstRegion *) astBox( frm, 0, cen, hw, NULL, "", status ); - } - -/* Store in the returned ancillary KeyMap. */ - astMapPut0A( *anc, AST__STCERROR, result, NULL ); - } - } - -/* Does this Position2D contain any Resolution? */ - if( scan->count[ 3 ] > 0 && map1 ) { - -/* Issue a warning if more than 1 Resolution value was found. */ - if( scan->count[ 3 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Resolution>" - " element. AST can only use the first", status ); - } - -/* If the resolution has no position angle, just read it as a list of double. - Otherwise, read the Resolution2PA structure (which is exactly the same - as an Error2PA structure). */ - name = astXmlGetName( scan->el[ 3 ][ 0 ] ); - if( name ) { - if( !strcmp( name, "Resolution2" ) ) { - ElemListD( this, scan->el[ 3 ][ 0 ], 2, hw, status ); - pa = AST__BAD; - } else { - pa = Error2PAReader( this, scan->el[ 3 ][ 0 ], hw, status ); - } - -/* Convert to radians, and halve to get the half-width. */ - if( map1 == map2 ) { - astTran1( map1, 2, hw, 1, hw ); - } else { - astTran1( map1, 1, hw, 1, hw ); - astTran1( map2, 1, hw + 1, 1, hw + 1 ); - } - - if( hw[ 0 ] != AST__BAD ) hw[ 0 ] *= 0.5; - if( hw[ 1 ] != AST__BAD ) hw[ 1 ] *= 0.5; - -/* Create an Ellipse or Box to describe the resolution */ - cen[ 0 ] = 0.0; - cen[ 1 ] = 0.0; - if( pa != AST__BAD ) { - r = (AstRegion *) astEllipse( frm, 1, cen, hw, &pa, - NULL, "", status ); - } else { - r = (AstRegion *) astBox( frm, 0, cen, hw, NULL, "", status ); - } - -/* Store in the returned ancillary KeyMap. */ - astMapPut0A( *anc, AST__STCRES, r, NULL ); - r = astAnnul( r ); - } - } - -/* Does this Position2D contain any Size? */ - if( scan->count[ 4 ] > 0 && map1 ) { - -/* Issue a warning if more than 1 Size value was found. */ - if( scan->count[ 4 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Size>" - " element. AST can only use the first", status ); - } - -/* If the size has no position angle, just read it as a list of double. - Otherwise, read the Size2PA structure (which is exactly the same - as an Error2PA structure). */ - name = astXmlGetName( scan->el[ 4 ][ 0 ] ); - if( name ) { - if( !strcmp( name, "Size2" ) ) { - ElemListD( this, scan->el[ 4 ][ 0 ], 2, hw, status ); - pa = AST__BAD; - } else { - pa = Error2PAReader( this, scan->el[ 4 ][ 0 ], hw, status ); - } - -/* Convert to radians, and halve to get the half-width. */ - if( map1 == map2 ) { - astTran1( map1, 2, hw, 1, hw ); - } else { - astTran1( map1, 1, hw, 1, hw ); - astTran1( map2, 1, hw + 1, 1, hw + 1 ); - } - - if( hw[ 0 ] != AST__BAD ) hw[ 0 ] *= 0.5; - if( hw[ 1 ] != AST__BAD ) hw[ 1 ] *= 0.5; - -/* Create an Ellipse or Box to describe the size */ - cen[ 0 ] = 0.0; - cen[ 1 ] = 0.0; - if( pa != AST__BAD ) { - r = (AstRegion *) astEllipse( frm, 1, cen, hw, &pa, - NULL, "", status ); - } else { - r = (AstRegion *) astBox( frm, 0, cen, hw, NULL, "", status ); - } - -/* Store in the returned ancillary KeyMap. */ - astMapPut0A( *anc, AST__STCSIZE, r, NULL ); - r = astAnnul( r ); - } - } - -/* Does this Position2D contain any PixSize? */ - if( scan->count[ 5 ] > 0 && map1 ) { - -/* Issue a warning if more than 1 PixSize value was found. */ - if( scan->count[ 5 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <PixSize>" - " element. AST can only use the first", status ); - } - -/* If the pixsize has no position angle, just read it as a list of double. - Otherwise, read the PixSize2PA structure (which is exactly the same - as an Error2PA structure). */ - name = astXmlGetName( scan->el[ 5 ][ 0 ] ); - if( name ) { - if( !strcmp( name, "PixSize2" ) ) { - ElemListD( this, scan->el[ 5 ][ 0 ], 2, hw, status ); - pa = AST__BAD; - } else { - pa = Error2PAReader( this, scan->el[ 5 ][ 0 ], hw, status ); - } - -/* Convert to radians, and halve to get the half-width. */ - if( map1 == map2 ) { - astTran1( map1, 2, hw, 1, hw ); - } else { - astTran1( map1, 1, hw, 1, hw ); - astTran1( map2, 1, hw + 1, 1, hw + 1 ); - } - - if( hw[ 0 ] != AST__BAD ) hw[ 0 ] *= 0.5; - if( hw[ 1 ] != AST__BAD ) hw[ 1 ] *= 0.5; - -/* Create an Ellipse or Box to describe the pixsize */ - cen[ 0 ] = 0.0; - cen[ 1 ] = 0.0; - if( pa != AST__BAD ) { - r = (AstRegion *) astEllipse( frm, 1, cen, hw, &pa, - NULL, "", status ); - } else { - r = (AstRegion *) astBox( frm, 0, cen, hw, NULL, "", status ); - } - -/* Store in the returned ancillary KeyMap. */ - astMapPut0A( *anc, AST__STCPIXSZ, r, NULL ); - r = astAnnul( r ); - } - } - -/* Free resources */ - if( map1 ) map1 = astAnnul( map1 ); - if( map2 ) map2 = astAnnul( map2 ); - scan = FreeIVOAScan( scan, status ); - if( words ) { - for( i = 0; i < nword; i++ ) words[ i ] = astFree( words[ i ] ); - words = astFree( words ); - } - - } - -/* Return NULL if an error occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the result */ - return result; - -} - -static AstRegion *PositionIntervalReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* PositionIntervalReader - -* Purpose: -* Make an AST Region from an IVOA PositionInterval element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *PositionIntervalReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* PositionInterval element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA PositionInterval element. -* frm -* Pointer to the Frame in which the returned Region should be -* defined. If the Unit or System attribute is not set, this -* function will decide on the values to be used, and set these -* values in the supplied Frame before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[1]; /* Names of the subelements to be searched for */ - const char *unit; /* Unit string from supplied element */ - int max[1]; /* Max allowed occurrences of each name */ - int min[1]; /* Min allowed occurrences of each name */ - int ndim; /* Number of axes in supplied Frame */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-element. */ - ndim = astGetNaxes( frm ); - if( ndim == 1 ) { - names[ 0 ] = "CoordScalarInterval"; - } else if( ndim == 2 ) { - names[ 0 ] = "Coord2VecInterval"; - } else if( ndim == 3 ) { - names[ 0 ] = "Coord3VecInterval"; - } else if( astOK ) { - astError( AST__INTER, "PositionIntervalReader(XmlChan): Supplied " - "Frame has more than 3 axes (internal AST programming error )." , status); - } - min[ 0 ] = 1; - max[ 0 ] = 1; - scan = ScanIVOAElement( this, elem, 1, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the units attribute from the supplied element. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( !unit ) { - Report( this, elem, FAILURE, "contains no unit attribute", status ); - unit = ""; - } - -/* Read 1-d intervals */ - if( ndim == 1 ) { - new = CoordScalarIntervalReader( this, scan->el[0][0], unit, frm, status ); - -/* Read 2-d intervals */ - } else if( ndim == 2 ) { - new = Coord2VecIntervalReader( this, scan->el[0][0], unit, frm, status ); - -/* Read 3-d intervals */ - } else if( ndim == 3 ) { - new = Coord3VecIntervalReader( this, scan->el[0][0], unit, frm, status ); - -/* Report error for other dimensionalities */ - } else if( astOK ) { - astError( AST__INTER, "PositionIntervalReader(XmlChan): Supplied " - "Frame has more than 3 axes (internal AST programming error )." , status); - } - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstObject *Read( AstChannel *this_channel, int *status ) { -/* -* Name: -* Read - -* Purpose: -* Read an Object from a Channel. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *Read( AstChannel *this_channel, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the astRead method -* inherited from the Channel class). - -* Description: -* This function reads an Object from an XmlChan. - -* Parameters: -* this -* Pointer to the XmlChan. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. -*/ - -/* Local Variables: */ - AstObject *new; /* Pointer to returned Object */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - AstXmlElement *elem; /* XML element holding AST Object */ - int def_fmt; /* Original default format */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* Save the current default format, and then reset it to NATIVE */ - def_fmt = this->formatdef; - this->formatdef = NATIVE_FORMAT; - -/* First we construct an in-memory XML representation of the data source, - by reading text up to the end of the first element encountered from - which an AST Object could be created. If the Skip attribute is zero, then - an error is reported if there is any text prior to the start of the first - usable element. If Skip is non-zero any initial text prior to the start - of the first usable element is ignored. */ - elem = ReadXmlText( this, status ); - -/* Check a usable element was found. */ - if( elem ) { - -/* The "current container element" is the XML element from which items - are currently being read. Indicate that we are currently not reading - any element (not used for IVOA formats). */ - this->container = NULL; - -/* Next we create a new AST Object from this in-memory XML representation - of the source. */ - new = MakeAstFromXml( this, elem, status ); - -/* Remove the element. This will cause an error to be reported if - the element contains any items which have not been used. */ - elem = Remove( this, elem, status ); - } - -/* If an error has occurred, annul the document. */ - if( !astOK ) this->readcontext = astXmlAnnul( this->readcontext ); - -/* If an error occurred, clean up by deleting the new Object and - return a NULL pointer, and re-instate original default format. */ - if ( !astOK ) { - new = astDelete( new ); - this->formatdef = def_fmt; - } - -/* Return the pointer to the new Object. */ - return new; -} - -static void ReadClassData( AstChannel *this_channel, const char *class, int *status ) { -/* -* Name: -* ReadClassData - -* Purpose: -* Read values from a data source for a class loader. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void ReadClassData( AstChannel *this, const char *class, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the astReadClassData method -* inherited from the Channel class). - -* Description: -* This function reads the data for a class from the data source -* associated with a Channel, so as to provide values for -* initialising the instance variables of that class as part of -* building a complete Object. This function should be invoked by -* the loader for each class immediately before it attempts to read -* these values. - -* Parameters: -* this -* Pointer to the Channel. -* class -* A pointer to a constant null-terminated string containing the -* name of the class whose loader is requesting the data (note -* this is not usually the same as the class name of the Object -* being built). This value allows the class structure of the -* input data to be validated. -*- -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - AstXmlContentItem *item; /* Pointer to next item of content */ - const char *definedby; /* Class defining current content items */ - int nitem; /* Number of items in container */ - int i; /* Loop counter */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* Check we have a container, and then store the name of the class being - loaded. */ - if( !this->container ){ - astError( AST__INTER, "astRead(XmlChan): Invalid attempt to read " - "%s data - there is currently no container element " - "(internal AST programming error).", status, class ); - - } else { - this->isa_class = class; - -/* Go through all the content elements within the current container and - give them an extra attribute named "definedby" the value of which is - the name of the class which defines the associated AST attribute or - object. This is determined by the the "isa" elements - an element is - "definedby" the class noted in the next following "isa" element, or by - the class being loaded if there is no following "isa" element. */ - -/* Find the first "isa" element and get the value of its "class" attribute. - If none is found the name of the class being loaded is used. */ - definedby = FindNextIsA( (AstXmlElement *) this->container, 0, status ); - -/* Loop round all elements within the container. */ - nitem = astXmlGetNitem( this->container ); - for( i = 0; astOK && i < nitem; i++ ) { - item = astXmlGetItem( this->container, i ); - if( astXmlCheckType( item, AST__XMLELEM ) ) { - -/* If this is an "ISA" element, then we have ended the scope of the - current "isa" class. All subsequent items will be defined by the class - mentioned in the next following "ISA" element. Find the next ISA - element and get its class. */ - if( astOK && !strcmp( astXmlGetName( item ), ISA ) ) { - definedby = FindNextIsA( (AstXmlElement *) this->container, i + 1, status ); - -/* For other element types, add a "definedby" attribute holding the name - of the class defined by the current ISA element. */ - } else { - astXmlAddAttr( item, DEFINEDBY, definedby, NULL ); - } - } - } - } -} - -static double ReadDouble( AstChannel *this_channel, const char *name, double def, int *status ) { -/* -* Name: -* ReadDouble - -* Purpose: -* Read a double value as part of loading a class. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* double ReadDouble( AstChannel *this, const char *name, double def, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the astReadDouble method -* inherited from the Channel class). - -* Description: -* This function searches the current container element of an XmlChan to -* identify a double value with a specified name. If such a value -* is found, it is returned, otherwise a default value is returned -* instead. -* -* This function should only be invoked from within the loader -* function associated with a class, in order to return a double -* value to be assigned to an instance variable. It must be -* preceded by a call to the astReadClassData function. - -* Parameters: -* this -* Pointer to the Channel. -* name -* Pointer to a constant null-terminated character string -* containing the name of the required value. This must be in -* lower case with no surrounding white space. Note that names -* longer than 6 characters will not match any value. -* def -* If no suitable value can be found (e.g. it is absent from the -* data stream being read), then this value will be returned -* instead. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The required value, or the default if the value was not found. - -* Notes: -* - A value of 0.0 will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - AstXmlElement *element; /* Pointer to element holding required value */ - const char *value; /* Pointer to attribute value */ - double result; /* Value to be returned */ - int nc; /* Number of characters read by astSscanf */ - -/* Initialise. */ - result = 0.0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* Search the current container element for an ATTR element - describing an AST attribute of the specified name. This call ignores - ATTR elements which represent default values. No error is - reported if an ATTR element with the given name cannot be - found. */ - element = FindAttribute( this, name, status ); - -/* If an element was found, attempt to decode the string to give a double - value, checking that the entire string is read (and checking for the - magic string used to represent bad values). If this fails, then the - wrong name has probably been given, or the input data are corrupt, - so report an error. */ - if( element ) { - value = astXmlGetAttributeValue( element, VALUE ); - if( value ) { - nc = 0; - if ( ( 0 == astSscanf( value, " " BAD_STRING " %n", - &nc ) ) - && ( nc >= (int) strlen( value ) ) ) { - result = AST__BAD; - - } else if ( !( ( 1 == astSscanf( value, " %lf %n", &result, &nc ) ) - && ( nc >= (int) strlen( value ) ) ) ) { - astError( AST__BADIN, "astRead(XmlChan): The value \"%s = %s\" " - "cannot be read as a double precision floating point " - "number.", status, name, value ); - -/* If the value was succesfully read, remove the ATTR element - from the container. */ - } else { - element = Remove( this, element, status ); - } - -/* Report an error if the attribute does not have a value. */ - } else { - astError( AST__BADIN, "astRead(XmlChan): No value for attribute " - "\"%s\" within element \"%s\".", status, name, - GetTag( (AstXmlObject *) element, 1, status ) ); - } - -/* If no suitable element was found, then use the default value instead. */ - } else { - result = def; - } - -/* Return the result. */ - return result; -} - -static int ReadInt( AstChannel *this_channel, const char *name, int def, int *status ) { -/* -* Name: -* ReadInt - -* Purpose: -* Read a int value as part of loading a class. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int ReadInt( AstChannel *this, const char *name, int def ) - -* Class Membership: -* XmlChan member function (over-rides the astReadInt method -* inherited from the Channel class). - -* Description: -* This function searches the current container element of an XmlChan to -* identify a int value with a specified name. If such a value -* is found, it is returned, otherwise a default value is returned -* instead. -* -* This function should only be invoked from within the loader -* function associated with a class, in order to return a int -* value to be assigned to an instance variable. It must be -* preceded by a call to the astReadClassData function. - -* Parameters: -* this -* Pointer to the Channel. -* name -* Pointer to a constant null-terminated character string -* containing the name of the required value. This must be in -* lower case with no surrounding white space. Note that names -* longer than 6 characters will not match any value. -* def -* If no suitable value can be found (e.g. it is absent from the -* data stream being read), then this value will be returned -* instead. - -* Returned Value: -* The required value, or the default if the value was not found. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - AstXmlElement *element; /* Pointer to element holding required value */ - const char *value; /* Pointer to attribute value */ - int result; /* Value to be returned */ - int nc; /* Number of characters read by astSscanf */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* Search the current container element for an ATTR element - describing an AST attribute of the specified name. This call ignores - ATTR elements which represent default values. No error is - reported if an ATTR element with the given name cannot be - found. */ - element = FindAttribute( this, name, status ); - -/* If an element was found, attempt to decode the string to give a int - value, checking that the entire string is read. If this fails, then the - wrong name has probably been given, or the input data are corrupt, - so report an error. */ - if( element ) { - value = astXmlGetAttributeValue( element, VALUE ); - if( value ) { - nc = 0; - if ( !( ( 1 == astSscanf( value, " %d %n", &result, &nc ) ) - && ( nc >= (int) strlen( value ) ) ) ) { - astError( AST__BADIN, - "astRead(XmlChan): The value \"%s = %s\" cannot " - "be read as an integer.", status, name, value ); - -/* If the value was succesfully read, remove the ATTR element - from the container. */ - } else { - element = Remove( this, element, status ); - } - -/* Report an error if the attribute does not have a value. */ - } else { - astError( AST__BADIN, "astRead(XmlChan): No value for attribute " - "\"%s\" within element \"%s\".", status, name, - GetTag( (AstXmlObject *) element, 1, status ) ); - } - -/* If no suitable element was found, then use the default value instead. */ - } else { - result = def; - } - -/* Return the result. */ - return result; -} - -static AstObject *ReadObject( AstChannel *this_channel, const char *name, - AstObject *def, int *status ) { -/* -* Name: -* ReadObject - -* Purpose: -* Read a (sub)Object as part of loading a class. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* char *ReadObject( AstChannel *this, const char *name, AstObject *def ) - -* Class Membership: -* XmlChan member function (over-rides the astReadObject method -* inherited from the Channel class). - -* Description: -* This function searches the current container element of an XmlChan to -* identify an Object with a specified name. If such an Object -* is found, a pointer to it is returned, otherwise a default pointer -* is returned instead. -* -* This function should only be invoked from within the loader -* function associated with a class, in order to return a int -* value to be assigned to an instance variable. It must be -* preceded by a call to the astReadClassData function. - -* Parameters: -* this -* Pointer to the Channel. -* name -* Pointer to a constant null-terminated character string -* containing the name of the required value. This must be in -* lower case with no surrounding white space. Note that names -* longer than 6 characters will not match any value. -* def -* If no suitable value can be found (e.g. it is absent from the -* data stream being read), then this value will be returned -* instead. - -* Returned Value: -* A pointer to the Object, or a clone of the default pointer if -* the Object was not found. - -* Notes: -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - AstXmlElement *element; /* Pointer to element holding required value */ - AstObject *result; /* Value to be returned */ - const char *isa_class; /* Class currently being loaded */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* Search the current container element for an element with a name which - is not ATTR and with the specified LABEL. This call ignores - elements which represent default values. No error is reported if an - element with the given label cannot be found. */ - element = FindObject( this, name, status ); - -/* If an element was found, make an AST object from it. First remember - the class currently being loaded so that it can be re-instated. */ - if( element ) { - isa_class = this->isa_class; - result = MakeAstFromXml( this, element, status ); - this->isa_class = isa_class; - -/* Remove the element from the container. */ - element = Remove( this, element, status ); - -/* If no suitable Value structure was found, clone the default - pointer, if given. */ - } else if ( def ) { - result = astClone( def ); - } - -/* Return the result. */ - return result; -} - -static char *ReadString( AstChannel *this_channel, const char *name, const char *def, int *status ) { -/* -* Name: -* ReadString - -* Purpose: -* Read a string value as part of loading a class. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* char *ReadString( AstChannel *this, const char *name, const char *def ) - -* Class Membership: -* XmlChan member function (over-rides the astReadString method -* inherited from the Channel class). - -* Description: -* This function searches the current container element of an XmlChan to -* identify a string value with a specified name. If such a value -* is found, it is returned, otherwise a default value is returned -* instead. -* -* This function should only be invoked from within the loader -* function associated with a class, in order to return a int -* value to be assigned to an instance variable. It must be -* preceded by a call to the astReadClassData function. - -* Parameters: -* this -* Pointer to the Channel. -* name -* Pointer to a constant null-terminated character string -* containing the name of the required value. This must be in -* lower case with no surrounding white space. Note that names -* longer than 6 characters will not match any value. -* def -* If no suitable value can be found (e.g. it is absent from the -* data stream being read), then this value will be returned -* instead. - -* Returned Value: -* A pointer to a dynamically allocated null-terminated string -* containing the value required, or to a copy of the default -* string if the value was not found (or NULL if the "def" pointer -* was NULL). - -* Notes: -* - It is the caller's responsibility to arrange for the memory -* holding the returned string to be freed (using astFree) when it -* is no longer required. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - AstXmlElement *element; /* Pointer to element holding required value */ - char *result; /* Value to be returned */ - const char *value; /* Pointer to attribute value */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* Search the current container element for an ATTR element - describing an AST attribute of the specified name. This call ignores - ATTR elements which represent default values. No error is - reported if an ATTR element with the given name cannot be - found. */ - element = FindAttribute( this, name, status ); - -/* If an element was found, return a copy of the "value" string. */ - if( element ) { - value = astXmlGetAttributeValue( element, VALUE ); - if( value ) { - result = astStore( NULL, value, strlen( value ) + 1 ); - -/* If the new default for XmlFormat has not yet been set, note if this - element contained a "quoted" attribute. */ - if( this->formatdef == NATIVE_FORMAT ) { - if( astXmlGetAttributeValue( element, QUOTED ) ) { - this->formatdef = QUOTED_FORMAT; - } - } - -/* Remove the ATTR element from the container. */ - element = Remove( this, element, status ); - -/* Report an error if the attribute does not have a value. */ - } else { - astError( AST__BADIN, "astRead(XmlChan): No value for attribute " - "\"%s\" within element \"%s\".", status, name, - GetTag( (AstXmlObject *) element, 1, status ) ); - } - -/* If no suitable Value structure was found, then make a dynamic copy - of the default string (if given) and return a pointer to this. */ - } else if ( def ) { - result = astStore( NULL, def, strlen( def ) + (size_t) 1 ); - } - -/* Return the result. */ - return result; -} - -static AstXmlElement *ReadXmlText( AstXmlChan *this, int *status ){ -/* -* Name: -* ReadXmlText - -* Purpose: -* Create an in-memory XML tree from an XML text source. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlElement *ReadXmlText( AstXmlChan *this, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function constructs an in-memory XML representation of the data -* source by reading text up to the end of the first element encountered -* from which an AST Object could be constructed. If the Skip attribute is -* zero, then an error is reported if there is any text prior to the start -* of the first AST Object. If Skip is non-zero any initial text prior to -* the start of the first usable element is ignored. - -* Parameters: -* this -* Pointer to the XmlChan. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the returned XmlElement. This should be annuled using -* astXmlAnnul when no longer needed. NULL is returned if the end of -* the source text is reached without finding a en element from which -* an AST Object could be read. - -* Notes: -* - A NULL pointer is returned if an error has already occurred, of -* if this function should fail for any reason. - -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstXmlElement *result; /* Returned pointer */ - int skip; /* Skip over initial irrelevant markup? */ - -/* Initialise */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this); - -/* Get the value of the Skip attribute. This indicates if we should skip - over any irrelevant markup prior to the first element from which an - AST object could be created. */ - skip = astGetSkip( this ); - -/* Store a pointer to the XmlChan in a module variable so that the IsUsable function - can access its properties. */ - isusable_this = this; - -/* Read characters from the XML source and return an XmlElement structure - containing the first usable element encountered. */ - result = astXmlReadDocument( &(this->readcontext), IsUsable, skip, - GetNextChar, this ); - -/* Nullify the module variable for safety. */ - isusable_this = NULL; - -/* If no usable element was found, annul the document. */ - if( !result ) this->readcontext = astXmlAnnul( this->readcontext ); - -/* Delete the returned element if an error has occurred. */ - if( !astOK ) result = astXmlAnnulTree( result ); - -/* Return the result. */ - return result; - -} - -static void ReCentreAnc( AstRegion *region, int nanc, AstKeyMap **ancs, int *status ){ -/* -* Name: -* ReCentreAnc - -* Purpose: -* Re-centre the Regions describing ancillary information extracted -* from an AstroCoords elements. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* ReCentreAnc( AstRegion *region, int nanc, AstKeyMap **ancs, int *status ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function recentres the Regions which describe ancillary -* information from an AstroCoords element so that it is centred at -* the centre of the associated AstroCoordsArea element. - -* Parameters: -* region -* Pointer to the Region defining the associated AstroCoordsArea. -* nanc -* Number of KeyMap pointers stored in "ancs" -* ancs -* Pointer to an array of "nanc" elements, each being a pointer to -* a KeyMap. Each one describes the ancilary information in an -* AstroCoords element associated with the AstroCoordsArea decribed -* by "region". Each KeyMap has elements with keys AST__STCERROR, -* AST__STCRES, AST__STCSIZE, AST__STCPIXSZ, AST__STCVALUE each of -* which holds a pointer to a Region. These Regions are modified on -* exit so that they are centred on a point which inside the supplied -* Region. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstFrame *frm; - AstFrame *pfrm; - AstFrameSet *fs; - AstMapping *map; - AstMapping *smap; - AstObject *o; - AstRegion *r2; - AstRegion *r; - char orgatt[ 20 ]; - char orgset[ 80 ]; - char setting[ 80 ]; - char sysatt[ 20 ]; - char sysset[ 80 ]; - const char *old_unit; - const char *time_unit; - double *lbnd; - double *mid; - double *ubnd; - double epoch; - int i; - int j; - int k; - int ndim; - int paxis; - int time_axis; - - static const char *key[ 5 ] = { AST__STCERROR, - AST__STCRES, - AST__STCSIZE, - AST__STCPIXSZ, - AST__STCVALUE }; - -/* Check the inherited status. Also return if no Keymaps supplied. */ - if( !nanc || !astOK ) return; - -/* Get the Frame encapsulated by the suipplied Region. */ - frm = astRegFrame( region ); - -/* Get the bounds of the supplied Region. */ - ndim = astGetNaxes( frm ); - lbnd = astMalloc( sizeof( double )*(size_t) ndim ); - ubnd = astMalloc( sizeof( double )*(size_t) ndim ); - mid = astMalloc( sizeof( double )*(size_t) ndim ); - if( mid ) { - astGetRegionBounds( region, lbnd, ubnd ); - -/* Get a mid point, taking account of unbounded axes. Also find the index of - the time axis (if any) in the supplied Region, and get the System and - TimeOrigin values for the time axis. */ - time_axis = -1; - time_unit = NULL; - orgatt[ 0 ] = 0; - sysatt[ 0 ] = 0; - for( i = 0; i < ndim; i++ ) { - if( lbnd[ i ] > -0.5*DBL_MAX ) { - if( ubnd[ i ] < 0.5*DBL_MAX ) { - mid[ i ] = 0.5*( lbnd[ i ] + ubnd[ i ] ); - } else { - mid[ i ] = lbnd[ i ]; - } - } else { - if( ubnd[ i ] < 0.5*DBL_MAX ) { - mid[ i ] = ubnd[ i ]; - } else { - mid[ i ] = 0.0; - } - } - -/* If we have not found a time axis, see if the current axis is a time axis. */ - if( time_axis == -1 ) { - astPrimaryFrame( frm, i, &pfrm, &paxis ); - if( astIsATimeFrame( pfrm ) ) { - -/* If so, record its index. */ - time_axis = i; - -/* If the TimeOrigin attribute is set, save its value. Create strings - holding the attribute name and appropriate setting string for use with - the ancillary regions. */ - if( astTestTimeOrigin( (AstTimeFrame *) pfrm ) ) { - sprintf( orgatt, "TimeOrigin(%d)", i + 1 ); - sprintf( orgset, "TimeOrigin(%d)=%s", i + 1, - astGetC( pfrm, "TimeOrigin" ) ); - } - -/* If the System attribute is set, save its value. Create strings - holding the attribute name and appropriate setting string for use with - the ancillary regions. */ - if( astTestSystem( pfrm ) ) { - sprintf( sysatt, "System(%d)", i + 1 ); - sprintf( sysset, "System(%d)=%s", i + 1, - astGetC( pfrm, "System" ) ); - } - - time_unit = astGetUnit( pfrm, 0 ); - } - pfrm = astAnnul( pfrm ); - } - - } - -/* Get the Region Epoch. */ - if( astTestEpoch( frm ) ){ - epoch = astGetEpoch( frm ); - sprintf( setting, "Epoch=MJD %.*g", AST__DBL_DIG, epoch ); - } else { - setting[ 0 ] = 0; - epoch = AST__BAD; - } - -/* Loop round each KeyMap. */ - for( j = 0; j < nanc; j++ ) { - -/* Loop round each of the relevant KeyMap elements (skip the "Value" - element since this should not be re-centred). */ - for( k = 0; k < 5; k++ ) { - if( astMapGet0A( ancs[ j ], key[ k ], &o ) ) { - r = (AstRegion *) o; - -/* The System and TimeOrigin attributes of the STC Region are set when the - AstroCoordArea is read. This occurs after the ancillary Coords Regions are - created. Consequently, the ancillary Coords Regions may not have set - System and/or TimeOrigin values. So, for System and TimeOrigin, if - the attribute is set in the supplied Region but not set in the ancillary - Region, transfer the set value to the ancillary Region. */ - if( strlen( sysatt ) && strlen( orgatt ) ) { - if( !astTest( r, sysatt ) && !astTest( r, orgatt ) ) { - astRegSetAttrib( r, sysset, NULL ); - - old_unit = astGetUnit( r, time_axis ); - if( old_unit && time_unit && - strcmp( old_unit, time_unit ) ) { - if( !astTestUnit( r, time_axis ) ) { - old_unit = NULL; - } else { - old_unit = astStore( NULL, old_unit, - strlen( old_unit ) + 1 ); - } - astSetUnit( r, time_axis, time_unit ); - } - astRegSetAttrib( r, orgset, NULL ); - if( !old_unit ) { - astClearUnit( r, time_axis ); - } else if( strcmp( old_unit, time_unit ) ) { - astSetUnit( r, time_axis, old_unit ); - old_unit = astFree( (void *) old_unit ); - } - } - } - -/* Re-centre the Regions held in this element of the KeyMap, and set - its Epoch (do not re-centre the "Value" element). */ - if( strcmp( key[ k ], AST__STCVALUE ) ) { - -/* First ensure the ancillary Region refers to the supplied Frame. */ - fs = astConvert( r, frm, "" ); - if( fs ) { - map = astGetMapping( fs, AST__BASE, AST__CURRENT ); - smap = astSimplify( map ); - if( !astIsAUnitMap( smap ) ) { - r2 = astMapRegion( r, smap, frm ); - astMapPut0A( ancs[ j ], key[ k ], r2, NULL ); - (void) astAnnul( r ); - r = r2; - } - map = astAnnul( map ); - smap = astAnnul( smap ); - fs = astAnnul( fs ); - -/* Now set the epoch and re-centre.*/ - if( epoch != AST__BAD ) astRegSetAttrib( r, setting, NULL ); - astRegCentre( r, mid, NULL, 0, AST__CURRENT ); - } - } - r = astAnnul( r ); - } - } - } - } - -/* Free resources. */ - lbnd = astFree( lbnd ); - ubnd = astFree( ubnd ); - mid = astFree( mid ); - frm = astAnnul( frm ); -} - -static AstObject *RedshiftFrameReader( AstXmlChan *this, - AstXmlElement *elem, int *status ) { -/* -* Name: -* RedshiftFrameReader - -* Purpose: -* Make an AST Object from an IVOA RedshiftFrame element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *RedshiftFrameReader( AstXmlChan *this, AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Object from the supplied IVOA -* RedshiftFrame element. The returned Object is a SpecFrame in which -* the Domain is set explicitly to REDSHIFT. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA RedshiftFrame element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. - -*/ - -/* Local Variables: */ - AstSpecFrame *new; /* Pointer to returned Object */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[3]; /* Names of the subelements to be searched for */ - const char *sor; /* StdOfRest for returned Frame */ - const char *type; /* Doppler type (velocity or redshift) */ - const char *sys; /* Spectral system */ - int max[3]; /* Max allowed occurrences of each name */ - int min[3]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return (AstObject *) new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "TOPOCENTER|BARYCENTER|HELIOCENTER|GEOCENTER|LSR|" - "LSRK|GALACTIC_CENTER|LOCAL_GROUP_CENTER|LSRD"; - names[ 1 ] = DOPPLER_DEFINITION; - names[ 2 ] = "Name"; - max[ 0 ] = 1; - max[ 1 ] = 1; - max[ 2 ] = 1; - min[ 0 ] = 1; - min[ 1 ] = 1; - min[ 2 ] = 0; - scan = ScanIVOAElement( this, elem, 3, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the name of the Element specifying the reference position and find - the corresponding AST name.*/ - sor = astXmlGetName( scan->el[0][0] ); - if( !strcmp( sor, "TOPOCENTER" ) ) { - sor = "Topo"; - } else if( !strcmp( sor, "BARYCENTER" ) ){ - sor = "Bary"; - } else if( !strcmp( sor, "GEOCENTER" ) ){ - sor = "Geo"; - } else if( !strcmp( sor, "LSR" ) || !strcmp( sor, "LSRK" ) ) { - sor = "LSRK"; - } else if( !strcmp( sor, "LSRD" ) ) { - sor = "LSRD"; - } else if( !strcmp( sor, "GALACTIC_CENTER" ) ) { - sor = "Galactic"; - } else if( !strcmp( sor, "LOCAL_GROUP_CENTER" ) ) { - sor = "Local_group"; - } else if( !strcmp( sor, "HELIOCENTER" ) ) { - sor = "Helio"; - } else if( astOK ){ - astError( AST__INTER, "RedshiftFrameReader(XmlChan): Unknown " - "standard of rest %s (internal AST programming error).", status, - sor ); - } - -/* Issue a warning if the reference position includes an ephemeris. */ - if( FindElement( this, scan->el[0][0], "PlanetaryEphem", status ) ) { - Report( this, scan->el[0][0], WARNING, "contains a <PlanetaryEphem> " - "element which will be ignored", status ); - } - -/* Get the value of the value_type attribute from the element. */ - type = astXmlGetAttributeValue( elem, "value_type" ); - if( !type ) type = "VELOCITY"; - -/* If the type is REDSHIFT, set the system to redshift. Also check that - any <DopplerDefinition> element is "OPTICAL". */ - if( !strcmp( type, "REDSHIFT" ) ) { - sys = astXmlGetValue( scan->el[1][0], 0 ); - if( sys && !strcmp( sys, "OPTICAL" ) ) { - sys = "REDSHIFT"; - } else { - Report( this, elem, FAILURE, "specifies dimensionless " - "redshift (z) but has non-optical <DopplerDefinition>", status ); - } - -/* Otherwise, get the value of the Doppler definition element, and translate - it to an AST value.*/ - } else { - sys = astXmlGetValue( scan->el[1][0], 0 ); - if( !sys ) { - Report( this, elem, FAILURE, "contains a <DopplerDefinition> " - "element which is not simply character data", status ); - - } else if( !strcmp( sys, "OPTICAL" ) ) { - sys = "VOPT"; - - } else if( !strcmp( sys, "RADIO" ) ) { - sys = "VRAD"; - - } else if( !strcmp( sys, "RELATIVISTIC" ) ) { - sys = "VREL"; - - } else { - Report( this, elem, FAILURE, "contains unsupported Doppler definition", status ); - } - } - -/* Create a suitable SpecFrame. */ - new = astSpecFrame( "Domain=REDSHIFT,System=%s,StdOfRest=%s", status, sys, sor); - -/* If the SpectralFrame has a <Name> element use it as the SpecFrame title. */ - if( scan->count[2] ) astSetTitle( new, astXmlGetValue( scan->el[2][0], 0 ) ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Object. */ - return (AstObject *) new; -} - -static AstRegion *RedshiftIntervalReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* RedshiftIntervalReader - -* Purpose: -* Make an AST Region from an IVOA RedshiftInterval element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *RedshiftIntervalReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* RedshiftInterval element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA RedshiftInterval element. -* frm -* Pointer to the Frame in which the returned Region should be -* defined. If the Unit or System attribute is not set, this -* function will decide on the values to be used, and set these -* values in the supplied Frame before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstRegion *new; /* Pointer to returned Region */ - AstSystemType sys; /* Redshift system */ - IVOAScan *scan; /* Structure holding scan results */ - char *unit; /* Unit string from supplied element */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[2]; /* Names of the subelements to be searched for */ - double hilimit; /* Upper spectral limit */ - double lolimit; /* Lower spectral limit */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "LoLimit"; - names[ 1 ] = "HiLimit"; - min[ 0 ] = 0; - min[ 1 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the limits. */ - lolimit = scan->count[0] ? ElemValueD( this, scan->el[0][0], 0.0, status ) : AST__BAD; - hilimit = scan->count[1] ? ElemValueD( this, scan->el[1][0], 0.0, status ) : AST__BAD; - -/* Use any unit and vel_time_unit attributes in the supplied element to - determine the system and units for the redshift Frame. */ - sys = RedshiftSys( this, elem, &unit, 1, status ); - -/* If no system has been set in the supplied Frame, set a default system - now (radio velocity if both units are present, dimensionaless redshift - otherwise). */ - if( !astTestSystem( frm ) ) { - astSetSystem( frm, sys ); - -/* The ReddshiftSys function always returns AST__VRADIO if the velocity - is not dimensionless. In this case, if the supplied Frame has system - explicitly set AST__VOPTICAL, we use the supplied Frame preference of - optical/radio instead of the default returned by RedshiftSys. */ - } else if( sys != AST__REDSHIFT ) { - sys = astGetSystem( frm ); - if( sys == AST__REDSHIFT ) sys = AST__VRADIO; - } - -/* Take a copy of the supplied Frame and set its Units to the value found - above. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - -/* If at least one limit was found, create an Interval within this - modified Frame. Otherwise create a negated NullRegion. */ - if( lolimit != AST__BAD || hilimit != AST__BAD ) { - new = (AstRegion *) astInterval( cfrm, &lolimit, &hilimit, NULL, "", status ); - } else { - new = (AstRegion *) astNullRegion( cfrm, NULL, "negated=1", status ); - } - -/* If the Units of this Region differs from that of the supplied Frame, - set it to the Units of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new Units. If the supplied - Frame had no set Units, set it to the units implied by the supplied - XML element. */ - if( astTestUnit( frm, 0 ) ) { - funit = astGetUnit( frm, 0 ); - if( strcmp( funit, unit ) ) astSetUnit( new, 0, funit ); - } else { - astSetUnit( frm, 0, unit ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - cfrm = astAnnul( cfrm ); - if( unit ) unit = astFree( unit ); - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstRegion *RedshiftReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, AstKeyMap **anc, int *status ){ -/* -* Name: -* RedshiftReader - -* Purpose: -* Modify a Frame to take account of an STC <Redshift> element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *RedshiftReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, AstKeyMap **anc, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function reads the supplied STC <Redshift> element, and uses it, -* if possible, to create the uncertainty associated with the redshift -* axis in the supplied Frame. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Redshift element. -* frm -* Pointer to the 1D redshift Frame. -* anc -* Address of a location at which to put a pointer to a newly -* created KeyMap. This KeyMap will contain ancillary information -* from the Redshift. The keys identify the item of ancillary -* information (Name, Value, Error, Resolution, Size, Pixel Size). -* The value associated with the Name key is string containing -* the Name item from the Redshift. The value associated with each of -* the other keys is a pointer to a 1D Region within the supplied -* Frame, corresponding to the value, error, resolution, etc. Keys -* will not be present in the returned KeyMap if the corresponding -* item of ancillary information is not present in the Redshift. A -* NULL pointer is returned if there is no ancillary information at all. -* status -* Pointer to the inherited status variable. - -* Returned: -* The uncertainty Region, or NULL if the supplied Redshift element -* does not specify an uncertainty. - -*/ - -/* Local Variables: */ - AstFrameSet *fs; /* FrameSet connecting "sf1" and "sf2" */ - AstMapping *map; /* Mapping from <Redshift> Frame to supplied Frame */ - AstRegion *r2; /* Region mapped into returned Frame */ - AstRegion *r3; /* Simplified Region mapped into returned Frame */ - AstRegion *r; /* Original Region */ - AstRegion *result; /* Returned uncertainty Region */ - AstSpecFrame *sf1; /* SpecFrame describing value element */ - AstSystemType fsys; /* Redshift system from supplied Stc */ - IVOAScan *scan; /* Structure holding scan results */ - const char *name; /* Pointer to XML element name */ - const char *names[6]; /* Names of the subelements to be searched for */ - char *unit; /* Pointer to Redshift's unit attribute string */ - double lbnd[ 1 ] ; /* Lower interval bounds */ - double tmp; /* Temporary storage */ - double ubnd[ 1 ] ; /* Upper interval bounds */ - double v; /* Axis value */ - int max[6]; /* Max allowed occurrences of each name */ - int min[6]; /* Min allowed occurrences of each name */ - -/* Initialise */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Name"; - names[ 1 ] = "Error"; - names[ 2 ] = "Value"; - names[ 3 ] = "Resolution"; - names[ 4 ] = "Size"; - names[ 5 ] = "PixSize"; - max[ 0 ] = 1; - max[ 1 ] = 2; - max[ 2 ] = 1; - max[ 3 ] = 2; - max[ 4 ] = 2; - max[ 5 ] = 2; - min[ 0 ] = 1; - min[ 1 ] = 0; - min[ 2 ] = 0; - min[ 3 ] = 0; - min[ 4 ] = 0; - min[ 5 ] = 0; - scan = ScanIVOAElement( this, elem, 6, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create a KeyMap to return holding ancilary info, and put the Name into - it. */ - *anc = astKeyMap( "", status ); - if( scan->count[0] > 0 ) astMapPut0C( *anc, AST__STCNAME, - astXmlGetValue( scan->el[0][0], 0 ), NULL ); - -/* Determine the units and system implied by the <Redshift> element. - The returned system is AST__REDSHIFT if there is no unit attribute in - the <Redshift> element, and is AST__VRADIO otherwise. */ - fsys = RedshiftSys( this, elem, &unit, 1, status ); - -/* If no system has been set in the supplied Frame, set it now to the system - determined above. */ - if( !astTestSystem( frm ) ) { - astSetSystem( frm, fsys ); - -/* The ReddshiftSys function above always returns AST__VRADIO if the velocity - is not dimensionless. However, the supplied Frame may have System set - explicitly to AST__VOPTICAL. In this case change the "fsys" value to use - AST__VOPTICAL. */ - } else if( fsys != AST__REDSHIFT ) { - fsys = astGetSystem( frm ); - if( fsys == AST__REDSHIFT ) fsys = AST__VRADIO; - } - -/* If the supplied Frame has no set units, set them now to the units of - the Redshift element (if any, and if the redshift is not dimensionless). */ - if( unit && fsys != AST__REDSHIFT && - astGetSystem( frm ) != AST__REDSHIFT && !astTestUnit( frm, 0 ) ) { - astSetUnit( frm, 0, unit ); - } - -/* The values represented by the <Redshift> element may not be in the same - system, units, etc as the supplied SpecFrame. We will need to be able to - convert from one to the other, so create a SpecFrame describing the - system and units used by the <Redshift> element. */ - sf1 = astCopy( frm ); - astSetSystem( sf1, fsys ); - if( unit ) { - astSetUnit( sf1, 0, unit ); - unit = astFree( unit ); - } - -/* Find the Mapping from Redshift value to the supplied SpecFrame value */ - fs = astConvert( sf1, frm, "" ); - if( fs ) { - map = astGetMapping( fs, AST__BASE, AST__CURRENT ); - fs = astAnnul( fs ); - } else { - map = NULL; - Report( this, elem, FAILURE, "connot convert AstroCoords " - "redshift values to the required redshift system", status ); - } - -/* If this Redshift contains a Value which can be read, obtain it. */ - if( scan->count[ 2 ] > 0 ) { - name = astXmlGetName( scan->el[ 2 ][ 0 ] ); - if( name && !strcmp( name, "Value" ) ) { - v = ElemValueD( this, scan->el[ 2 ][ 0 ], AST__BAD, status ); - -/* Convert the value into the supplied SpecFrame system. Create an - Interval describing it and store it in the returned ancillary keyMap. - Note we create an Interval rather than a PintList since the Prism - class can only extrude using Intervals. */ - astTran1( map, 1, &v, 1, &tmp ); - r = (AstRegion *) astInterval( frm, &tmp, &tmp, NULL, "", status ) ; - astMapPut0A( *anc, AST__STCVALUE, r, NULL ); - r = astAnnul( r ); - } - } - -/* Check for Error values in the Redshift. */ - if( scan->count[ 1 ] > 0 ) { - -/* Issue a warning if more than 1 Error value was found. */ - if( scan->count[ 1 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Error>" - " element. AST can only use the first", status ); - } - -/* Get the first Error value. */ - v = ElemValueD( this, scan->el[1][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an error bar centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the Frame represented by the Redshift element. - Map it into the supplied Frame. Simplify it. Store in the returned - ancillary KeyMap. */ - r = (AstRegion *) astInterval( sf1, lbnd, ubnd, NULL, "", status ); - r2 = astMapRegion( r, map, frm ); - result = astSimplify( r2 ); - astMapPut0A( *anc, AST__STCERROR, result, NULL ); - r2 = astAnnul( r2 ); - r = astAnnul( r ); - } - } - -/* Check for Resolution values in the Redshift. */ - if( scan->count[ 3 ] > 0 ) { - -/* Issue a warning if more than 1 value was found. */ - if( scan->count[ 3 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Resolution>" - " element. AST can only use the first", status ); - } - -/* Get the first value. */ - v = ElemValueD( this, scan->el[3][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an interval centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the Frame represented by the Redshift element. - Map it into the supplied Frame. Simplify it. Store in the returned - ancillary KeyMap. */ - r = (AstRegion *) astInterval( sf1, lbnd, ubnd, NULL, "", status ); - r2 = astMapRegion( r, map, frm ); - r3 = astSimplify( r2 ); - astMapPut0A( *anc, AST__STCRES, r3, NULL ); - r3 = astAnnul( r3 ); - r2 = astAnnul( r2 ); - r = astAnnul( r ); - } - } - -/* Check for Size values in the Redshift. */ - if( scan->count[ 4 ] > 0 ) { - -/* Issue a warning if more than 1 value was found. */ - if( scan->count[ 4 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Size>" - " element. AST can only use the first", status ); - } - -/* Get the first value. */ - v = ElemValueD( this, scan->el[4][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an interval centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the Frame represented by the Redshift element. - Map it into the supplied Frame. Simplify it. Store in the returned - ancillary KeyMap. */ - r = (AstRegion *) astInterval( sf1, lbnd, ubnd, NULL, "", status ); - r2 = astMapRegion( r, map, frm ); - r3 = astSimplify( r2 ); - astMapPut0A( *anc, AST__STCSIZE, r3, NULL ); - r3 = astAnnul( r3 ); - r2 = astAnnul( r2 ); - r = astAnnul( r ); - } - } - -/* Check for PixSize values in the Redshift. */ - if( scan->count[ 5] > 0 ) { - -/* Issue a warning if more than 1 value was found. */ - if( scan->count[ 5 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <PixSize>" - " element. AST can only use the first", status ); - } - -/* Get the first value. */ - v = ElemValueD( this, scan->el[5][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an interval centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the Frame represented by the Redshift element. - Map it into the supplied Frame. Simplify it. Store in the returned - ancillary KeyMap. */ - r = (AstRegion *) astInterval( sf1, lbnd, ubnd, NULL, "", status ); - r2 = astMapRegion( r, map, frm ); - r3 = astSimplify( r2 ); - astMapPut0A( *anc, AST__STCPIXSZ, r3, NULL ); - r3 = astAnnul( r3 ); - r2 = astAnnul( r2 ); - r = astAnnul( r ); - } - } - -/* Free resources. */ - scan = FreeIVOAScan( scan, status ); - sf1 = astAnnul( sf1 ); - map = astAnnul( map ); - } - -/* Return NULL if an error occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the result */ - return result; - -} - -static AstSystemType RedshiftSys( AstXmlChan *this, AstXmlElement *elem, - char **unit, int report, int *status ){ -/* -* Name: -* RedshiftSys - -* Purpose: -* Determine the redshift system described by the attributes in a -* given element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstSystemType RedshiftSys( AstXmlChan *this, AstXmlElement *elem, -* char **unit, int report, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function determines the redshift system described by the unit and -* vel_time_unit attributes in the supplied element. It optionally reports -* an error if the units are not recognised. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA element containing the unit attribute to be used. -* unit -* Pointer to a location at which to return a pointer to a -* dynamically allocated string in which is stored the total units string -* implied by the unit and vel_time_unit attributes. This string -* should be freed when no longer needed using astFree. A NULL -* pointer is returned if either of the two attributes (unit and -* vel_time_unit) is not found in the supplied element, or if an error -* occurs. -* report -* If non-zero, then a failure is reported if the spectral system -* cannot be determined from the supplied string. -* status -* Pointer to the inherited status variable. - -* Returned: -* The redshift system (radio velocity if both unit and vel_time_unit -* attributes are present in the supplied element, or dimensionaless -* redshift otherwise). - -*/ - -/* Local Variables: */ - const char *punit; /* Pointer to positional unit string */ - const char *tunit; /* Pointer to time unit string */ - int pl; /* Length of punit string */ - int tl; /* Length of tunit string */ - -/* Initialise. */ - *unit = NULL; - -/* Check the global error status. */ - if ( !astOK ) return AST__BADSYSTEM; - -/* Get the Unit attribute from the element (this describes units of position) */ - punit = astXmlGetAttributeValue( elem, "unit" ); - if( punit ) { - -/* Check it is a linear measure (not angular). */ - if( strstr( "m", punit ) && - strstr( "km", punit ) && - strstr( "mm", punit ) && - strstr( "AU", punit ) && - strstr( "kpc", punit ) && - strstr( "Mpc", punit ) && - strstr( "lyr", punit ) ) { - if( report ) Report( this, elem, FAILURE, "contains an angular unit attribute", status ); - } - } - -/* Get the vel_time_unit attribute from the element (this describes units of - time). If OK, construct the total unit string (eg "km/h") . */ - tunit = astXmlGetAttributeValue( elem, "vel_time_unit" ); - if( tunit ) { - if( !punit ) { - if( report ) Report( this, elem, FAILURE, "contains time units but not position units - assuming Z", status ); - } else { - pl = strlen( punit ); - tl = strlen( tunit ); - *unit = astMalloc( (size_t)( pl + tl + 2 ) ); - if( *unit ) { - strcpy( *unit, punit ); - (*unit)[ pl ] = '/'; - strcpy( *unit + pl + 1, tunit ); - } - } - - } else if( punit ) { - if( report ) Report( this, elem, FAILURE, "contains position units but not time units - assuming Z", status ); - } - -/* Return a default system (radio velocity if both units are present, - dimensionless redshift otherwise). */ - return ( punit && tunit ) ? AST__VRADIO : AST__REDSHIFT; -} - -static AstRegion *RegionReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* RegionReader - -* Purpose: -* Make an AST Region from any subclass of IVOA Region element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *RegionReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* element which can be of any subclass of Region. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - const char *name; /* Region type */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Process each supported type of STC Region. */ - name = astXmlGetName( elem ); - if( !strcmp( name, "Intersection" ) ) { - new = IntersectionReader( this, elem, frm, status ); - - } else if( !strcmp( name, "Union" ) ) { - new = UnionReader( this, elem, frm, status ); - - } else if( !strcmp( name, "Negation" ) ) { - new = NegationReader( this, elem, frm, status ); - - } else if( !strcmp( name, "AllSky" ) ) { - new = AllSkyReader( this, elem, frm, status ); - - } else if( !strcmp( name, "Circle" ) ) { - new = CircleReader( this, elem, frm, status ); - - } else if( !strcmp( name, "Ellipse" ) ) { - new = EllipseReader( this, elem, frm, status ); - - } else if( !strcmp( name, "Polygon" ) ) { - new = PolygonReader( this, elem, frm, status ); - - } else if( !strcmp( name, "Box" ) ) { - new = BoxReader( this, elem, frm, status ); - - } else if( !strcmp( name, "Convex" ) ) { - new = ConvexReader( this, elem, frm, status ); - - } else { - astError( AST__INTER, "RegionReader(XmlChan): Does not yet " - "support \"%s\" regions (internal AST programming " - "error).", status, name ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstXmlElement *Remove( AstXmlChan *this, AstXmlElement *element, int *status ) { -/* -* Name: -* Remove - -* Purpose: -* Remove an element from the current container element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlElement *Remove( AstXmlChan *this, AstXmlElement *element, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function removes the specified element from the current -* container element, and then annuls the removed element. An error is -* reported if the element being removed contains anything other than -* comments, "isa" elements and blank character data (all contents should -* have been consumed by the process of reading the object). - -* Parameters: -* this -* Pointer to the XmlChan. -* element -* Pointer to the XML element to be removed. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A NULL pointer is returned. - -*/ - -/* Local Variables: */ - AstXmlContentItem *item; /* Item */ - const char *def; /* Pointer to default attribute value */ - int i; /* Index of current item */ - int nitem; /* Number of items still in the element */ - -/* Check the global error status, and the supplied element. */ - if ( !astOK || !element ) return NULL; - -/* Check we have a container from which to remove the element. If so, - check that the container is the elements parent. If so, remove the - element from its parent container. */ - if( this->container ) { - if( (AstXmlParent *) this->container != astXmlGetParent( element ) ){ - astError( AST__INTER, "Remove(XmlChan): Supplied element is not " - "contained within the current container element (internal " - "AST programming error)." , status); - } else { - astXmlRemoveItem( element ); - } - } - -/* Check that the element being removed is empty (apart from comments, - defaulted values and "isa" elements). */ - nitem = astXmlGetNitem( element ); - for( i = 0; i < nitem; i++ ) { - item = astXmlGetItem( element, i ); - if( astXmlCheckType( item, AST__XMLELEM ) ) { - -/* See if this element represents a default value */ - def = astXmlGetAttributeValue( item, DEFAULT ); - -/* Default values and "isa" elements are OK. */ - if( ( !def || strcmp( def, TRUE ) ) && astOK && - strcmp( astXmlGetName( item ), ISA ) ) { - -/* Remove any "definedby" attribute (added by ReadClassData) so that it - does not appear in the error message. */ - if( astXmlGetAttributeValue( item, DEFINEDBY ) ) { - astXmlRemoveAttr( item, DEFINEDBY, NULL ); - } - -/* Report the error. */ - if( astOK ) astError( AST__BADIN, "astRead(XmlChan): The following " - "tag was not recognised as valid input within " - "a %s: %s", status, astXmlGetName( element ), - GetTag( (AstXmlObject *) item, 1, status ) ); - break; - } - -/* Character data is OK so long as it contains only white space */ - } else if( astXmlCheckType( item, AST__XMLBLACK ) ) { - astError( AST__BADIN, "astRead(XmlChan): The following character " - "data was not recognised as valid input within a %s: %s", status, - astXmlGetName( element ), astXmlGetValue( item, 0 ) ); - break; - - } else if( astXmlCheckType( item, AST__XMLCDATA ) ) { - astError( AST__BADIN, "astRead(XmlChan): The following CDATA section " - "data was not recognised as valid input within a %s: %s", status, - astXmlGetName( element ), astXmlGetValue( item, 0 ) ); - break; - - } else if( astXmlCheckType( item, AST__XMLPI ) ) { - astError( AST__BADIN, "astRead(XmlChan): The following processing " - "instruction was not recognised as valid input within " - "a %s: %s", status, astXmlGetName( element ), GetTag( (AstXmlObject *) item, 1, status ) ); - break; - } - } - -/* Remove the element from its parent and the annul it. */ - astXmlRemoveItem( element ); - astXmlAnnul( element ); - -/* Return a NULL pointer. */ - return NULL; -} - -static void Report( AstXmlChan *this, AstXmlElement *elem, int severity, - const char *msg, int *status ){ -/* -* Name: -* Report - -* Purpose: -* Handle problems reading supplied XML. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* void Report( AstXmlChan *this, AstXmlElement *elem, int severity, -* const char *msg, int *status ) - -* Class Membership: -* XmlChan member function - -* Description: -* This function handles conditions which arise whilst interpreting - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the XmlElement which cound not be interpreted. -* severity -* WARNING (in which case the message is added to a list of -* warnings, but execution continues), or FAILURE, in which case -* an error is reported using astError, or RESET in which case any -* warnings stored in the XmlChan are removed ("elem" and "msg" are -* ignored). -* msg -* A message describing the condition. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - char *text; /* Pointer to tformatted element text */ - const char *name; /* Element name */ - - if( severity == RESET ) astAddWarning( this, 0, NULL, NULL, status ); - - if( !astOK ) return; - - if( severity == WARNING && !astGetStrict( this ) ) { - name = astXmlGetName( elem ); - astAddWarning( this, 1, "astRead(%s): Warning whilst reading %s %s " - "element: %s", "astRead", status, astGetClass( this ), - ANA(name), name, msg ); - } else { - text = (char *) astXmlGetTag( elem, 1 ); - astError( AST__BADIN, "astRead(%s): Failed to read %s element: %s", status, - astGetClass( this ), text, msg ); - text = astFree( text ); - } -} - -static IVOAScan *ScanIVOAElement( AstXmlChan *this, AstXmlElement *elem, int n, - const char *names[], int min[], int max[], int *status ){ -/* -* Name: -* ScanIVOAElement - -* Purpose: -* Identify required sub-elements within an IVOA element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* IVOAScan *ScanIVOAElement( AstXmlChan *this, AstXmlElement *elem, int n, -* const char *names[], int min[], int max[], int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function searches the supplied XML element for named sub-elements. -* A structure is returned containing the number of sub-elements found -* with each name, and pointers to the sub-elements. This structure -* should be freed using FreeIVOAScan when no longer needed. -* -* Reports are made about any content in the supplied element which is -* not specified in the list of known sub-element names (excepting -* comments and white space). -* -* Reports are also made if the number of sub-elements found with each -* known name is inappropriate (the minimum and maximum allowed -* occurrences of each name is specified by the caller). - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the XML element to be searched. -* n -* The number of names supplied in "names" -* names -* An array holding pointers to strings giving the names of the known -* sub-elements. Each string may be either a single element name, -* or a set of element names separated by "|" (the string must -* also start and end with a "|"). If a set is supplied, then the -* associated "min" and "max" values specify the minimum and maximum -* total number of occurrences of all names in the set, and the -* occurrence count stored in the returned structure gives the total -* number of occurrences of all names in the set. -* min -* An array holding the mimimum number of occrrences of each name within -* the element being searched. Supplied in the same order as the names -* themselves. -* max -* An array holding the maximum number of occrrences of each name within -* the element being searched. Supplied in the same order as the names -* themselves. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the IVOAScan structure holding the results of the -* scan. A NULL pointer is returned unless all names have at least -* their minimum number of occurrences in the supplied element. A NULL -* pointer is returned if an error occurs. - -*/ - -/* Local Variables: */ - AstXmlContentItem *item; /* Current content item */ - IVOAScan *result; /* Pointer to returned structure */ - char *text; /* Pointer formatted item string */ - char buff[ 200 ]; /* Message buffer */ - const char *name; /* Pointer to element name string */ - const char *w1; /* Pointer to word to use in message */ - const char *w2; /* Pointer to word to use in message */ - const char *p; /* Pointer to start of name in string */ - int i; /* Index of current content item */ - int j; /* Index of current name */ - int k; /* Index of current occurrence of name */ - int l; /* Length of element name */ - int known; /* Was content item known? */ - int nitem; /* No. of content items in supplied element */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Initialise a structure to hold the results of the scan. */ - result = astMalloc( sizeof(IVOAScan) ); - if( result ) { - result->n = n; - result->count = astMalloc( sizeof(int)*(size_t)n); - result->el = astMalloc( sizeof(AstXmlElement **)*(size_t)n); - if( result->el ) { - for( j = 0; j < n; j++ ) { - result->count[ j ] = 0; - result->el[ j ] = NULL; - } - } - } - -/* Loop round all items in the elements contents. */ - if( astOK ) { - nitem = astXmlGetNitem( elem ); - for( i = 0; i < nitem; i++ ) { - item = astXmlGetItem( elem, i ); - known = 1; - -/* If it is not an XML element, it is not known. */ - if( !astXmlCheckType( item, AST__XMLELEM ) ) { - known = 0; - -/* If it is an element, get the name of the element. */ - } else { - name = astXmlGetName( item ); - -/* See if this name is in the supplied list of known names. */ - known = 0; - j = 0; - if( name ) { - l = strlen( name ); - for( j = 0; j < n; j++ ) { - p = strstr( names[ j ], name ); - if( p ){ - if( p == names[ j ] ) { - if( p[ l ] == 0 || p[ l ] == '|' ) { - known = 1; - break; - } - } else { - if( p[ -1 ] == '|' && ( p[ l ] == 0 || p[ l ] == '|' ) ) { - known = 1; - break; - } - } - } - } - } - -/* If it is known, store the element in the results structure */ - if( known ) { - k = ( result->count[ j ] )++; - result->el[ j ]= astGrow( result->el[ j ], k + 1, - sizeof( AstXmlElement * ) ); - if( result->el[ j ] ) { - result->el[ j ][ k ] = (AstXmlElement *) item; - } else { - break; - } - } - } - -/* If this content item was not known, issue a warning unless it is a comment - or white space. */ - if( !known && !astXmlCheckType( item, AST__XMLCOM ) && - !astXmlCheckType( item, AST__XMLWHITE ) ) { - text = (char *) astXmlFormat( item ); - if( text ) { - if( strlen( text ) > 30 ) text[ 30 ] = 0; - sprintf( buff, "contains the following which is being ignored: \"%s\"", - text ); - text = astFree( text ); - Report( this, elem, WARNING, buff, status ); - } - } - } - -/* Now check that the number of instances of each element found is OK. - Report warnings or failures if not. */ - if( astOK ) { - for( j = 0; j < n; j++ ) { - if( result->count[ j ] < min[ j ] ) { - w1 = ( result->count[ j ] == 1 ) ? "element" : "elements"; - w2 = ( min[ j ] == 1 ) ? "is" : "are"; - sprintf( buff, "contains %d <%s> %s but at least %d %s needed", - result->count[ j ], names[ j ], w1, min[ j ], w2 ); - Report( this, elem, FAILURE, buff, status ); - - } else if ( result->count[ j ] > max[ j ] ) { - w1 = ( result->count[ j ] == 1 ) ? "element" : "elements"; - w2 = ( max[ j ] == 1 ) ? "is" : "are"; - sprintf( buff, "contains %d <%s> %s but no more than %d %s " - "allowed (only the first will be used)", - result->count[ j ], names[ j ], w1, max[ j ], w2 ); - Report( this, elem, WARNING, buff, status ); - } - } - } - } - -/* Return NULL if an error occurred. */ - if( !astOK ) result = FreeIVOAScan( result, status ); - -/* Return the results structure.*/ - return result; -} - -static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { -/* -* Name: -* SetAttrib - -* Purpose: -* Set an attribute value for a XmlChan. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* void SetAttrib( AstObject *this, const char *setting ) - -* Class Membership: -* XmlChan member function (over-rides the astSetAttrib protected -* method inherited from the Channel class). - -* Description: -* This function assigns an attribute value for a XmlChan, the -* attribute and its value being specified by means of a string of -* the form: -* -* "attribute= value " -* -* Here, "attribute" specifies the attribute name and should be in -* lower case with no white space present. The value to the right -* of the "=" should be a suitable textual representation of the -* value to be assigned and this will be interpreted according to -* the attribute's data type. White space surrounding the value is -* only significant for string attributes. - -* Parameters: -* this -* Pointer to the XmlChan. -* setting -* Pointer to a null terminated string specifying the new attribute -* value. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - int ival; /* Integer attribute value */ - int len; /* Length of setting string */ - int nc; /* Number of characters read by "astSscanf" */ - int pr; /* Offset to start of string */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_object; - -/* Obtain the length of the setting string. */ - len = (int) strlen( setting ); - -/* Test for each recognised attribute in turn, using "astSscanf" to parse - the setting string and extract the attribute value (or an offset to - it in the case of string values). In each case, use the value set - in "nc" to check that the entire string was matched. Once a value - has been obtained, use the appropriate method to set it. */ - -/* XmlLength */ -/* ----------*/ - if ( nc = 0, - ( 1 == astSscanf( setting, "xmllength= %d %n", &ival, &nc ) ) - && ( nc >= len ) ) { - astSetXmlLength( this, ival ); - -/* XmlFormat */ -/* ----------*/ - } else if( nc = 0, - ( 0 == astSscanf( setting, "xmlformat=%n%*[^\n]%n", &ival, &nc ) ) - && ( nc >= len ) ) { - - nc = astChrLen( setting + ival ); - - if( !Ustrncmp( setting + ival, NATIVE_STRING, nc, status ) ){ - astSetXmlFormat( this, NATIVE_FORMAT ); - - } else if( !Ustrncmp( setting + ival, QUOTED_STRING, nc, status ) ){ - astSetXmlFormat( this, QUOTED_FORMAT ); - - } else if( !Ustrncmp( setting + ival, IVOA_STRING, nc, status ) ){ - astSetXmlFormat( this, IVOA_FORMAT ); - - } else { - astError( AST__BADAT, "astSet(%s): Unknown XML format '%s' " - "requested for a %s.", status, astGetClass( this ), setting + ival, - astGetClass( this ) ); - } - -/* XmlPrefix */ -/* ----------*/ - } else if ( nc = 0, ( 0 == astSscanf( setting, "xmlprefix=%n%*[^\n]%n", &pr, &nc ) ) - && ( nc >= len ) ) { - astSetXmlPrefix( this, setting + pr ); - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - (*parent_setattrib)( this_object, setting, status ); - } -} - -static void SinkWrap( void (* sink)( const char * ), const char *line, int *status ) { -/* -* Name: -* SinkWrap - -* Purpose: -* Wrapper function to invoke a C XmlChan sink function. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* void SinkWrap( void (* sink)( const char * ), const char *line, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function invokes the sink function whose pointer is -* supplied in order to write an output line to an external data -* store. - -* Parameters: -* sink -* Pointer to a sink function, whose single parameter is a -* pointer to a const, null-terminated string containing the -* text to be written, and which returns void. This is the form -* of XmlChan sink function employed by the C language interface -* to the AST library. -* status -* Pointer to the inherited status variable. -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Invoke the sink function. */ - ( *sink )( line ); -} - -static char *SourceWrap( const char *(* source)( void ), int *status ) { -/* -* Name: -* SourceWrap - -* Purpose: -* Wrapper function to invoke a C XmlChan source function. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* char *SourceWrap( const char *, int *status(* source)( void ) ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function invokes the source function whose pointer is -* supplied in order to read the next input line from an external -* data store. It then returns a pointer to a dynamic string -* containing a copy of the text that was read. - -* Parameters: -* source -* Pointer to a source function, with no parameters, that -* returns a pointer to a const, null-terminated string -* containing the text that it read. This is the form of XmlChan -* source function employed by the C language interface to the -* AST library. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to a dynamically allocated, null terminated string -* containing a copy of the text that was read. This string must be -* freed by the caller (using astFree) when no longer required. -* -* A NULL pointer will be returned if there is no more input text -* to read. - -* Notes: -* - A NULL pointer value will be returned if this function is -* invoked with the global error status set or if it should fail -* for any reason. -*/ - -/* Local Variables: */ - char *result; /* Pointer value to return */ - const char *line; /* Pointer to input line */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Invoke the source function to read the next input line and return a - pointer to the resulting string. */ - line = ( *source )(); - -/* If a string was obtained, make a dynamic copy of it and save the - resulting pointer. */ - if ( line ) result = astString( line, (int) strlen( line ) ); - -/* Return the result. */ - return result; -} - -static AstObject *SpaceFrameReader( AstXmlChan *this, - AstXmlElement *elem, int *status ) { -/* -* Name: -* SpaceFrameReader - -* Purpose: -* Make an AST Object from an IVOA SpaceFrame element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *SpaceFrameReader( AstXmlChan *this, AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Object from the supplied IVOA -* SpaceFrame element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA SpaceFrame element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. - -*/ - -/* Local Variables: */ - AstObject *new; /* Pointer to returned Object */ - AstXmlElement *el; /* Pointer to sub-element */ - IVOAScan *scan; /* Structure holding scan results */ - const char *dom; /* Domain string for returned SkyFrame */ - const char *eq; /* Equinox string for returned SkyFrame */ - const char *names[4]; /* Names of the subelements to be searched for */ - const char *sys; /* System for returned Frame */ - int ignore_h; /* Ignore 3rd spherical axis? */ - int max[4]; /* Max allowed occurrences of each name */ - int min[4]; /* Min allowed occurrences of each name */ - int isgeod; /* Is the system geodetic lon/lat? */ - int isgeoc; /* Is the system geocentric lon/lat? */ - int need_eq; /* Does system need an equinox? */ - -/* Initialise */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "ICRS|GALACTIC_II|SUPER_GALACTIC|HEE|FK4|FK5|ECLIPTIC|GEO_C|GEO_D"; - names[ 1 ] = "TOPOCENTER"; - names[ 2 ] = "Name"; - names[ 3 ] = "SPHERICAL|CARTESIAN|UNITSPHERE|POLAR"; - max[ 0 ] = 1; - max[ 1 ] = 1; - max[ 2 ] = 1; - max[ 3 ] = 1; - min[ 0 ] = 1; - min[ 1 ] = 1; - min[ 2 ] = 0; - min[ 3 ] = 1; - scan = ScanIVOAElement( this, elem, 4, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the sky coordinate system specified in the element. */ - sys = astXmlGetName( scan->el[0][0] ); - need_eq = 0; - dom = NULL; - -/* If the system is geodetic or geocentric, ignore height information if - supplied. This is so we can get an approximation to an observatory - position given in 3D, for use with SpecFrame. */ - ignore_h = 0; - isgeod = sys && !strcmp( sys, "GEO_D" ); - isgeoc = sys && !strcmp( sys, "GEO_C" ); - if( isgeod || isgeoc ){ - if( AttrValueI( this, scan->el[3][0], "coord_naxes", 2, status ) != 2 ) { - Report( this, elem, WARNING, "contains 3D spherical spatial " - "coords (unsupported by AST - height information will " - "be ignored)", status ); - ignore_h = 1; - } - -/* If the system is geodetic ignore any attributes specifying a reference - spheroid. */ - if( isgeod && astXmlGetNattr( scan->el[0][0] ) > 0 ) { - Report( this, elem, WARNING, "contains reference spheroid " - "(unsupported by AST - default values will be used)", status ); - } - } - -/* Check that the spatial axes are longitude/latitude */ - if( strcmp( "SPHERICAL", astXmlGetName( scan->el[3][0] ) ) ){ - Report( this, elem, FAILURE, "contains non-spherical spatial " - "coords (currently unsupported by AST)", status ); - - } else if( !ignore_h && AttrValueI( this, scan->el[3][0], "coord_naxes", 2, status ) != 2 ) { - Report( this, elem, FAILURE, "contains 3D spherical spatial " - "coords (currently unsupported by AST)", status ); - - } else if( AttrValueB( this, scan->el[3][0], "coord_vel", 0, status ) ) { - Report( this, elem, FAILURE, "contains velocity coords", status ); - -/* Now check for the supported sky coordinate systems and translate to the - equivalent AST value. Note if the system needs an equinox to qualify it. */ - } else if( !strcmp( sys, "GALACTIC_II" ) ){ - sys = "GALACTIC"; - need_eq = 0; - - } else if( !strcmp( sys, "SUPER_GALACTIC" ) ){ - sys = "SUPERGALACTIC"; - need_eq = 0; - - } else if( !strcmp( sys, "HEE" ) ){ - sys = "HELIOECLIPTIC"; - need_eq = 0; - - } else if( !strcmp( sys, "FK4" ) ) { - sys = "FK4"; - need_eq = 1; - - } else if( !strcmp( sys, "FK5" ) ) { - sys = "FK5"; - need_eq = 1; - - } else if( !strcmp( sys, "ECLIPTIC" ) ) { - sys = "ECLIPTIC"; - need_eq = 1; - - } else if( isgeoc ) { - dom = "GEO_C"; - sys = "UNKNOWN"; - need_eq = 0; - - } else if( isgeod ) { - dom = "GEO_D"; - sys = "UNKNOWN"; - need_eq = 0; - - } else { - sys = "ICRS"; - need_eq = 0; - } - -/* Extract the equinox if required. */ - if( need_eq ) { - el = FindElement( this, scan->el[0][0], "Equinox", status ); - if( el ) { - eq = astXmlGetValue( el, 0 ); - if( !eq ) Report( this, scan->el[0][0], WARNING, "contains an " - "<Equinox> element which is not simply " - "character data. The AST default (B1950 " - "or J2000) will be used", status ); - } else { - eq = NULL; - Report( this, scan->el[0][0], WARNING, "contains no <Equinox> element. " - "The AST default (B1950 or J2000) will be used", status ); - } - - } else { - eq = NULL; - } - -/* Create a suitable SkyFrame. */ - new = (AstObject *) astSkyFrame( "system=%s", status, sys); - if( eq ) astSetC( new, "Equinox", eq ); - if( dom ) astSetDomain( new, dom ); - - if( isgeod ){ - astSetLabel( new, 0, "Geodetic longitude" ); - astSetLabel( new, 1, "Geodetic latitude" ); - - } else if( isgeoc ){ - astSetLabel( new, 0, "Geocentric longitude" ); - astSetLabel( new, 1, "Geocentric latitude" ); - } - -/* If the SpaceFrame has a <Name> element use it as the Frame title. */ - if( scan->count[2] ) astSetTitle( new, astXmlGetValue( scan->el[2][0], 0 ) ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Object. */ - return (AstObject *) new; -} - -static AstSystemType SpecSys( AstXmlChan *this, AstXmlElement *elem, - const char *unit, int report, int *status ) { -/* -* Name: -* SpecSys - -* Purpose: -* Determine the spectral system described by a given units string. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstSystemType SpecSys( AstXmlChan *this, AstXmlElement *elem, -* const char *unit, int report, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function determines the spectral system described by a given units -* string. It optionally reports an error if the string is not -* recognised. - -* Parameters: -* this -* Pointer to the XmlChan. Only used if "report" is non-zero. -* elem -* Pointer to the IVOA element to which the unit relates. Only used -* if "report" is non-zero. -* unit -* Pointer to the units string. -* report -* If non-zero, then a failure is reported if the spectral system -* cannot be determined from the supplied string. -* status -* Pointer to the inherited status variable. - -* Returned: -* The spectral system, or AST__BADSYSTEM if an error occurs. - -*/ - -/* Local Variables: */ - AstMapping *map; /* Mapping from supplied unit to default unitl */ - AstSystemType sys; /* System value corresponding to "unit" */ - char buff[200]; /* Buffer for failure message */ - -/* Initialise */ - sys = AST__BADSYSTEM; - -/* Check inherited status */ - if( !astOK ) return sys; - -/* See if a Mapping can be found from the supplied units to "Hz". If - so, the supplied units are assumed to describe frequency. */ - map = astUnitMapper( unit, "Hz", NULL, NULL ); - if( map ) { - sys = AST__FREQ; - -/* Otherwise, see if a Mapping can be found from the supplied units to - "m" (metre). If so, the supplied units are assumed to describe wavelength. */ - } else { - map = astUnitMapper( unit, "m", NULL, NULL ); - if( map ) { - sys = AST__WAVELEN; - -/* Otherwise, see if a Mapping can be found from the supplied units to - "J" (Joule). If so, the supplied units are assumed to describe energy. */ - } else { - map = astUnitMapper( unit, "J", NULL, NULL ); - if( map ) { - sys = AST__ENERGY; - -/* Otherwise, see if a Mapping can be found from the supplied units to - "m^-1" (per metre). If so, the supplied units are assumed to describe - wave number. */ - } else { - map = astUnitMapper( unit, "m^-1", NULL, NULL ); - if( map ) { - sys = AST__WAVENUM; - -/* Otherwise, report an error if requested. */ - } else if( report ){ - sprintf( buff, "contains unsupported spectral units \"%s\"", unit ); - Report( this, elem, FAILURE, buff, status ); - } - } - } - } - -/* Free resources */ - if( map ) map = astAnnul( map ); - -/* Return the result. */ - return sys; -} - -static AstRegion *SpectralReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, double *rf, - AstKeyMap **anc, int *status ){ -/* -* Name: -* SpectralReader - -* Purpose: -* Modify a Frame to take account of an STC <Spectral> element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *SpectralReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, double *rf, -* AstKeyMap **anc, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function reads the supplied STC <Spectral> element, and uses it, -* if possible, to create the uncertainty associated with the spectral -* axis in the supplied Frame. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Spectral element. -* frm -* Pointer to the 1D spectral Frame. -* rf -* Point to double in which to return the rest frequency to be used -* with any redshift axis. Value is returned in Hz. AST__BAD will -* be returned if no rest frequency is found. -* anc -* Address of a location at which to put a pointer to a newly -* created KeyMap. This KeyMap will contain ancillary information -* from the Spectral. The keys identify the item of ancillary -* information (Name, Value, Error, Resolution, Size, Pixel Size). -* The value associated with the Name key is string containing -* the Name item from the Spectral. The value associated with each of -* the other keys is a pointer to a 1D Region within the supplied -* Frame, corresponding to the value, error, resolution, etc. Keys -* will not be present in the returned KeyMap if the corresponding -* item of ancillary information is not present in the Spectral. A -* NULL pointer is returned if there is no ancillary information at all. -* status -* Pointer to the inherited status variable. - -* Returned: -* The uncertainty Region, or NULL if the supplied Spectral element -* does not specify an uncertainty. - -*/ - -/* Local Variables: */ - AstFrameSet *fs; /* FrameSet connecting "sf1" and "sf2" */ - AstMapping *map; /* Mapping from <Spectral> Frame to supplied Frame */ - AstRegion *r2; /* Region mapped into returned Frame */ - AstRegion *r3; /* Simplified Region mapped into returned Frame */ - AstRegion *r; /* Original Region */ - AstRegion *result; /* Returned uncertainty Region */ - AstSpecFrame *sf1; /* SpecFrame describing value element */ - AstSpecFrame *sf2; /* SpecFrame describing returned "rf" value */ - AstSystemType fsys; /* Spectral system from supplied Stc */ - IVOAScan *scan; /* Structure holding scan results */ - const char *name; /* Pointer to XML element name */ - const char *names[6]; /* Names of the subelements to be searched for */ - const char *unit; /* Pointer to Spectral's unit attribute string */ - double lbnd[ 1 ] ; /* Lower interval bounds */ - double ubnd[ 1 ] ; /* Upper interval bounds */ - double tmp; /* Mapped value */ - double v; /* Axis value */ - int max[6]; /* Max allowed occurrences of each name */ - int min[6]; /* Min allowed occurrences of each name */ - -/* Initialise */ - result = NULL; - *rf = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Name"; - names[ 1 ] = "Error"; - names[ 2 ] = "Value"; - names[ 3 ] = "Resolution"; - names[ 4 ] = "Size"; - names[ 5 ] = "PixSize"; - max[ 0 ] = 1; - max[ 1 ] = 2; - max[ 2 ] = 1; - max[ 3 ] = 2; - max[ 4 ] = 2; - max[ 5 ] = 2; - min[ 0 ] = 1; - min[ 1 ] = 0; - min[ 2 ] = 0; - min[ 3 ] = 0; - min[ 4 ] = 0; - min[ 5 ] = 0; - scan = ScanIVOAElement( this, elem, 6, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create a KeyMap to return holding ancilary info, and put the Name into - it. */ - *anc = astKeyMap( "", status ); - if( scan->count[0] > 0 ) astMapPut0C( *anc, AST__STCNAME, - astXmlGetValue( scan->el[0][0], 0 ), NULL ); - -/* The values represented by the <Spectral> element may not be in the same - system,units, etc as the supplied SpecFrame. We will need to be able to - convert from one to the other, so create a SpecFrame describing the - system and units used by the <Spectral> element. If the element does not - have a unit attribute, assume the values are in the supplied SpecFrame - system and units. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( unit ) { - sf1 = astCopy( frm ); - fsys = SpecSys( this, elem, unit, 1, status ); - astSetSystem( sf1, fsys ); - astSetUnit( sf1, 0, unit ); - -/* If the supplied Frame did not have any set System, use the values from - the <Spectral> Frame. */ - if( !astTestSystem( frm ) ) { - astSetSystem( frm, fsys ); - astSetUnit( frm, 0, unit ); - } else if( astGetSystem( frm ) == fsys && !astTestUnit( frm, 0 ) ) { - astSetUnit( frm, 0, unit ); - } - - } else { - sf1 = astClone( frm ); - } - -/* Find the Mapping from Spectral value to the supplied SpecFrame value */ - fs = astConvert( sf1, frm, "" ); - if( fs ) { - map = astGetMapping( fs, AST__BASE, AST__CURRENT ); - fs = astAnnul( fs ); - } else { - map = NULL; - Report( this, elem, FAILURE, "connot convert AstroCoords " - "spectral values to the required spectral system", status ); - } - -/* If this Spectral contains a frequency Value which can be read, obtain - it. We will use the value to calculate the returned rest frequency. */ - if( scan->count[ 2 ] > 0 ) { - name = astXmlGetName( scan->el[ 2 ][ 0 ] ); - if( name && !strcmp( name, "Value" ) ) { - v = ElemValueD( this, scan->el[ 2 ][ 0 ], AST__BAD, status ); - -/* Convert the value into the supplied SpecFrame system. Create an - Interval describing it and store it in the returned ancillary keyMap. - Use an Interval rather than a PointList since an Interval can be used - within a Prism to extrude another Region, but a PointList cannot. */ - astTran1( map, 1, &v, 1, &tmp ); - r = (AstRegion *) astInterval( frm, &tmp, &tmp, NULL, "", status ) ; - astMapPut0A( *anc, AST__STCVALUE, r, NULL ); - r = astAnnul( r ); - -/* We also want the rest frequency in Hz. Create a SpecFrame describing Hz. */ - sf2 = astCopy( sf1 ); - astSet( sf2, "system=freq,unit=Hz", status ); - -/* Find the Mapping from the supplied value to frequency in Hz. Use it to - convert the rf value into Hz. */ - fs = astConvert( sf1, sf2, "" ); - if( fs ) { - astTran1( fs, 1, &v, 1, rf ); - fs = astAnnul( fs ); - } else if( astOK ) { - Report( this, elem, FAILURE, "Cannot convert spectral value" - "to frequency in Hz.", status ); - } - sf2 = astAnnul( sf2 ); - } - } - -/* Check for Error values in the Spectral. */ - if( scan->count[ 1 ] > 0 ) { - -/* Issue a warning if more than 1 Error value was found. */ - if( scan->count[ 1 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Error>" - " element. AST can only use the first", status ); - } - -/* Get the first Error value. */ - v = ElemValueD( this, scan->el[1][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an error bar centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the Frame represented by the Spectral element. - Map it into the supplied Frame. Simplify it. Store in the returned - ancillary KeyMap. */ - r = (AstRegion *) astInterval( sf1, lbnd, ubnd, NULL, "", status ); - r2 = astMapRegion( r, map, frm ); - result = astSimplify( r2 ); - astMapPut0A( *anc, AST__STCERROR, result, NULL ); - r2 = astAnnul( r2 ); - r = astAnnul( r ); - } - } - -/* Check for Resolution values in the Spectral. */ - if( scan->count[ 3 ] > 0 ) { - -/* Issue a warning if more than 1 value was found. */ - if( scan->count[ 3 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Resolution>" - " element. AST can only use the first", status ); - } - -/* Get the first value. */ - v = ElemValueD( this, scan->el[3][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an interval centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the Frame represented by the Spectral element. - Map it into the supplied Frame. Simplify it. Store in the returned - ancillary KeyMap. */ - r = (AstRegion *) astInterval( sf1, lbnd, ubnd, NULL, "", status ); - r2 = astMapRegion( r, map, frm ); - r3 = astSimplify( r2 ); - astMapPut0A( *anc, AST__STCRES, r3, NULL ); - r3 = astAnnul( r3 ); - r2 = astAnnul( r2 ); - r = astAnnul( r ); - } - } - -/* Check for Size values in the Spectral. */ - if( scan->count[ 4 ] > 0 ) { - -/* Issue a warning if more than 1 value was found. */ - if( scan->count[ 4 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Size>" - " element. AST can only use the first", status ); - } - -/* Get the first value. */ - v = ElemValueD( this, scan->el[4][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an interval centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the Frame represented by the Spectral element. - Map it into the supplied Frame. Simplify it. Store in the returned - ancillary KeyMap. */ - r = (AstRegion *) astInterval( sf1, lbnd, ubnd, NULL, "", status ); - r2 = astMapRegion( r, map, frm ); - r3 = astSimplify( r2 ); - astMapPut0A( *anc, AST__STCSIZE, r3, NULL ); - r3 = astAnnul( r3 ); - r2 = astAnnul( r2 ); - r = astAnnul( r ); - } - } - -/* Check for PixSize values in the Spectral. */ - if( scan->count[ 5] > 0 ) { - -/* Issue a warning if more than 1 value was found. */ - if( scan->count[ 5 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <PixSize>" - " element. AST can only use the first", status ); - } - -/* Get the first value. */ - v = ElemValueD( this, scan->el[5][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an interval centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the Frame represented by the Spectral element. - Map it into the supplied Frame. Simplify it. Store in the returned - ancillary KeyMap. */ - r = (AstRegion *) astInterval( sf1, lbnd, ubnd, NULL, "", status ); - r2 = astMapRegion( r, map, frm ); - r3 = astSimplify( r2 ); - astMapPut0A( *anc, AST__STCPIXSZ, r3, NULL ); - r3 = astAnnul( r3 ); - r2 = astAnnul( r2 ); - r = astAnnul( r ); - } - } - -/* Free resources. */ - scan = FreeIVOAScan( scan, status ); - sf1 = astAnnul( sf1 ); - map = astAnnul( map ); - } - -/* Return NULL if an error occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the result */ - return result; - -} - -static AstObject *SpectralFrameReader( AstXmlChan *this, - AstXmlElement *elem, int *status ) { -/* -* Name: -* SpectralFrameReader - -* Purpose: -* Make an AST Object from an IVOA SpectralFrame element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *SpectralFrameReader( AstXmlChan *this, AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Object from the supplied IVOA -* SpectralFrame element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA SpectralFrame element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. - -*/ - -/* Local Variables: */ - AstSpecFrame *new; /* Pointer to returned Object */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[2]; /* Names of the subelements to be searched for */ - const char *sor; /* StdOfRest for returned Frame */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return (AstObject *) new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "TOPOCENTER|BARYCENTER|HELIOCENTER|GEOCENTER|LSR|" - "LSRK|GALACTIC_CENTER|LOCAL_GROUP|LSRD"; - names[ 1 ] = "Name"; - max[ 0 ] = 1; - max[ 1 ] = 1; - min[ 0 ] = 1; - min[ 1 ] = 0; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the name of the Element specifying the reference position and find - the corresponding AST name.*/ - sor = astXmlGetName( scan->el[0][0] ); - if( !strcmp( sor, "TOPOCENTER" ) ) { - sor = "Topo"; - } else if( !strcmp( sor, "BARYCENTER" ) ){ - sor = "Bary"; - } else if( !strcmp( sor, "GEOCENTER" ) ){ - sor = "Geo"; - } else if( !strcmp( sor, "LSR" ) || !strcmp( sor, "LSRK" ) ) { - sor = "LSRK"; - } else if( !strcmp( sor, "LSRD" ) ) { - sor = "LSRD"; - } else if( !strcmp( sor, "GALACTIC_CENTER" ) ) { - sor = "Galactic"; - } else if( !strcmp( sor, "LOCAL_GROUP" ) ) { - sor = "Local_group"; - } else if( !strcmp( sor, "HELIOCENTER" ) ) { - sor = "Helio"; - } else if( astOK ){ - astError( AST__INTER, "SpectralFrameReader(XmlChan): Unknown " - "standard of rest %s (internal AST programming error).", status, - sor ); - } - -/* Issue a warning if the reference position includes an ephemeris. */ - if( FindElement( this, scan->el[0][0], "PlanetaryEphem", status ) ) { - Report( this, scan->el[0][0], WARNING, "contains a <PlanetaryEphem> " - "element which will be ignored", status ); - } - -/* Create a suitable SpecFrame. */ - new = astSpecFrame( "StdOfRest=%s", status, sor); - -/* If the SpectralFrame has a <Name> element use it as the SpecFrame title. */ - if( scan->count[1] ) astSetTitle( new, astXmlGetValue( scan->el[1][0], 0 ) ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Object. */ - return (AstObject *) new; -} - -static AstRegion *SpectralIntervalReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* SpectralIntervalReader - -* Purpose: -* Make an AST Region from an IVOA SpectralInterval element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *SpectralIntervalReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* SpectralInterval element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA SpectralInterval element. -* frm -* Pointer to the Frame in which the returned Region should be -* defined. If the Unit or System attribute is not set, this -* function will decide on the values to be used, and set these -* values in the supplied Frame before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstRegion *new; /* Pointer to returned Region */ - AstSystemType fsys; /* System value from supplied Frame */ - AstSystemType sys; /* System value corresponding to "unit" */ - IVOAScan *scan; /* Structure holding scan results */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[2]; /* Names of the subelements to be searched for */ - char *title; /* Title string */ - const char *unit; /* Unit string from supplied element */ - double hilimit; /* Upper spectral limit */ - double lolimit; /* Lower spectral limit */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "LoLimit"; - names[ 1 ] = "HiLimit"; - min[ 0 ] = 0; - min[ 1 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the limits. */ - lolimit = scan->count[0] ? ElemValueD( this, scan->el[0][0], 0.0, status ) : AST__BAD; - hilimit = scan->count[1] ? ElemValueD( this, scan->el[1][0], 0.0, status ) : AST__BAD; - -/* Get the Unit attribute from the element. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( !unit ) { - Report( this, elem, FAILURE, "contains no unit attribute", status ); - unit = ""; - -/* Find the spectral system corresponding to these units. */ - } else { - sys = SpecSys( this, elem, unit, 1, status ); - -/* Take a copy of the supplied Frame and set its System and Units to - these values. Ensure the title is preserved. */ - cfrm = astCopy( frm ); - if( astTestTitle( frm ) ) { - title = (char *) astGetTitle( frm ); - if( title ) title = astStore( NULL, title, strlen( title ) + 1 ); - } else { - title = NULL; - } - astSetSystem( cfrm, sys ); - astSetUnit( cfrm, 0, unit ); - if( title ) astSetTitle( cfrm, title ); - -/* If at least one limit was found, create an Interval within this - modified Frame. Otherwise create a negated NullRegion. */ - if( lolimit != AST__BAD || hilimit != AST__BAD ) { - new = (AstRegion *) astInterval( cfrm, &lolimit, &hilimit, NULL, "", status ); - } else { - new = (AstRegion *) astNullRegion( cfrm, NULL, "negated=1", status ); - } - -/* If the System of this Region differs from that of the supplied Frame, - set it to the System of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new System. If the supplied - Frame had no set system, set it to the system implied by th eunits in the - supplied XML element. */ - if( astTestSystem( frm ) ) { - fsys = astGetSystem( frm ); - if( fsys != sys ) astSetSystem( new, fsys ); - } else { - astSetSystem( frm, sys ); - } - -/* Do the same with the Units. */ - if( astTestUnit( frm, 0 ) ) { - funit = astGetUnit( frm, 0 ); - if( strcmp( funit, unit ) ) astSetUnit( new, 0, funit ); - } else { - astSetUnit( frm, 0, unit ); - } - -/* Ensure the original titleis preserved. */ - if( title ) { - astSetTitle( new, title ); - astSetTitle( frm, title ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - cfrm = astAnnul( cfrm ); - title = astFree( title ); - } - - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstRegion *SphereReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* SphereReader - -* Purpose: -* Make an AST Region from an IVOA Sphere element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *SphereReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Sphere element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Sphere element. -* frm -* Pointer to the Frame in which the returned Region should be -* defined. If the Unit or System attribute is not set, this -* function will decide on the values to be used, and set these -* values in the supplied Frame before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstFrame *cfrm; /* Frame used to define returned Region */ - AstMapping *map; /* Mapping between units */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - char buff[200]; /* Message buffer */ - const char *funit; /* Unit string from supplied Frame */ - const char *names[2]; /* Names of the subelements to be searched for */ - const char *runit; /* Radius unit string from supplied element */ - const char *unit; /* Centre unit string from supplied element */ - double cen[3]; /* Centre */ - double rad; /* Radius */ - double tmp; /* New radius value */ - int i; /* Axis count */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Check the supplied Frame has the correct number of axes. */ - if( astGetNaxes( frm ) != 3 && astOK ) { - astError( AST__INTER, "SphereReader(XmlChan): Supplied " - "Frame does not have 3 axes (internal AST programming error )." , status); - } - -/* Scan the supplied element for the required sub-elements */ - names[ 0 ] = "Radius"; - names[ 1 ] = "Center"; - min[ 0 ] = 1; - min[ 1 ] = 1; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the radius. */ - rad = ElemValueD( this, scan->el[0][0], 0.0, status ); - -/* Get the centre. */ - cen[0] = 0.0; - cen[1] = 0.0; - cen[2] = 0.0; - ElemListD( this, scan->el[1][0], 3, cen, status ); - -/* Get the units attribute from the supplied element. This applies to the - values describing the centre position. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - if( !unit ) { - Report( this, elem, FAILURE, "contains no unit attribute", status ); - unit = ""; - } - -/* Get the radius units attribute from the supplied element. */ - runit = astXmlGetAttributeValue( elem, "radius_unit" ); - -/* If necessary, convert the radius to the same units as the centre. */ - if( runit && strcmp( unit, runit ) ) { - map = astUnitMapper( runit, unit, NULL, NULL ); - if( map ) { - astTran1( map, 1, &rad, 1, &tmp ); - rad = tmp; - map = astAnnul( map ); - - } else if( astOK ) { - sprintf( buff, "has inconsistent units attributes \"%s\" and " - "\"%s\"", unit, runit ); - Report( this, elem, FAILURE, buff, status ); - } - } - -/* Take a copy of the supplied Frame and set its Units to the value - obtained from the supplied element. */ - cfrm = astCopy( frm ); - astSetUnit( cfrm, 0, unit ); - astSetUnit( cfrm, 1, unit ); - astSetUnit( cfrm, 2, unit ); - -/* Create a Circle within this modified Frame. */ - new = (AstRegion *) astCircle( cfrm, 1, cen, &rad, NULL, "", status ); - -/* If the Unit of this Region differs from that of the supplied Frame, - set it to the Unit of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new Unit. If the supplied - Frame had no set Unit, set it to the units obtained from the supplied - element. */ - for( i = 0; i < 3; i++ ) { - if( astTestUnit( frm, i ) ) { - funit = astGetUnit( frm, i ); - if( strcmp( funit, unit ) ) astSetUnit( new, i, funit ); - } else { - astSetUnit( frm, i, unit ); - } - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - cfrm = astAnnul( cfrm ); - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstObject *StcMetadataReader( AstXmlChan *this, - AstXmlElement *elem, int *status ) { -/* -* Name: -* StcMetadataReader - -* Purpose: -* Make an AST Object from an IVOA STCMetadata element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *StcMetadataReader( AstXmlChan *this, -* AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Object from the supplied IVOA -* STCMetadata element. The STCMetadata object can be of any subclass -* (e.g. STCResourceProfile, SearchLocation, CatalogEntryLocation, -* ObservationLocation, ObservatoryLocation). - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA STCMetadata element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. -*/ - -/* Local Variables: */ - AstFrame *frm; /* Frame representing the STC object */ - AstKeyMap *anc; /* Map holding AstroCoords ancillary data */ - AstKeyMap **ancs; /* List of KeyMaps holding ancillary data */ - AstKeyMap *map1; /* Map holding AstroCoordSystem elements */ - AstKeyMap *map2; /* Map holding AstroCoordArea elements */ - AstKeyMap *map3; /* Map holding CoordSpec elements */ - AstKeyMap *map; /* Map to use */ - AstRegion *region; /* Region representing the STC object */ - AstRegion *tuncs[ 4 ]; /* Temporary uncertainty Regions */ - AstRegion *uncs[ 4 ]; /* Uncertainty Regions for returned STC */ - AstStc *stc; /* Pointer to returned Object (an Stc) */ - AstXmlContentItem *item; /* Pointer to content item */ - AstXmlElement *aca; /* Pointer to AstroCoordArea element to use */ - AstXmlElement *aco; /* Pointer to AstroCoords element to use */ - AstXmlElement *acs; /* Pointer to AstroCoordSystem element to use */ - char *text; /* Formatted item text */ - char buff[ 200 ]; /* Message buffer */ - const char *id; /* Value of ID attribute */ - const char *ido; /* Value of ID attribute */ - const char *name; /* Element name */ - const char *stc_class; /* STC subclass name */ - int gotunc; /* Have any uncertainty Regions been obtained? */ - int i; /* Index of content item within element */ - int j; /* Index into list of map keys */ - int narea; /* Number of AstroCoordArea elements found */ - int ncoord; /* Number of CoordSpec elements found */ - int nanc; /* No.of KeyMaps in "ancs" array */ - int nitem; /* No. of items of content in element */ - int nsys; /* Number of AstroCoordSystem elements found */ - int reported; /* Have multiple uncertainies been reported? */ - int used; /* Was the content item used? */ - -/* Initialise. */ - stc = NULL; - -/* Check the global error status. */ - if ( !astOK ) return (AstObject *) stc; - -/* Avoid compiler warnings. */ - id = ""; - -/* Get name of the the STCMetadata subclass represented by the supplied - element. */ - stc_class = astXmlGetName( elem ); - -/* Create KeyMaps to hold the required sub-elements. We will store the - integer indices of the requried elements in these keymaps, using the - associated Xml ID attribute values as the keys. */ - map1 = astKeyMap( "", status ); - map2 = astKeyMap( "", status ); - map3 = astKeyMap( "", status ); - -/* Loop round all items in the elements contents. */ - nitem = astXmlGetNitem( elem ); - for( i = 0; i < nitem; i++ ) { - item = astXmlGetItem( elem, i ); - used = 1; - -/* Ignore this item if it is not an element. */ - if( astXmlCheckType( item, AST__XMLELEM ) ) { - -/* Choose the KeyMap in which to save this item. */ - name = astXmlGetName( item ); - if( !strcmp( name, ASTRO_COORD_SYSTEM ) ){ - map = map1; - - } else if( !strcmp( name, ASTRO_COORD_AREA ) ){ - map = map2; - - } else if( !strcmp( name, ASTRO_COORDS ) ){ - map = map3; - - } else { - map = NULL; - used = 0; - } - -/* If we are going to save the item, get the value of the ID attribute - and check it. */ - if( map ) { - id = astXmlGetAttributeValue( (AstXmlElement *) item, "ID" ); - if( !id ) { - id = ""; - if( map != map3 ) { - Report( this, elem, WARNING, "has no ID attribute. Assuming" - "a null ID value", status ); - } - } - -/* If the KeyMap already contains an object with this ID, issue a - warning and skip the element. */ - if( astMapHasKey( map, id ) ) { - if( map != map3 ) { - sprintf( buff, "contains two or more %s elements with the " - "same ID (\"%s\"). Only the first one will be used", - name, id ); - Report( this, elem, WARNING, buff, status ); - } else { - Report( this, elem, WARNING, "contains two or more AstroCoords " - "elements. Only the first one will be used", status ); - } - -/* Otherwise, save the index of the item in the KeyMap, using the ID as the - key. */ - } else { - astMapPut0I( map, id, i, "" ); - } - } - - } else { - used = 0; - } - -/* If this content item was not used, issue a warning unless it is a comment - or white space. */ - if( !used && !astXmlCheckType( item, AST__XMLCOM ) && - !astXmlCheckType( item, AST__XMLWHITE ) ) { - text = (char *) astXmlFormat( item ); - if( strlen( text ) > 30 ) text[ 30 ] = 0; - sprintf( buff, "contains the following which is being ignored: \"%s\"", - text ); - text = astFree( text ); - Report( this, elem, WARNING, buff, status ); - } - - } - -/* Note the number of each type of element found with unique ID values. */ - nsys = astMapSize( map1 ); - narea = astMapSize( map2 ); - ncoord = astMapSize( map3 ); - -/* If any CoordArea elements were found, find the first one for which the - coordesponding AstroCoordSystem is available. */ - acs = NULL; - aca = NULL; - for( j = 0; j < narea; j++ ) { - -/* Get the j'th key from "map2" (the ID associated with the j'th - AstroCoordArea found in the supplied element) and retrieve the value - associated with this key (the index "i" into the content of the - supplied element at which the j'th AstroCoordArea is stored). */ - astMapGet0I( map2, astMapKey( map2, j ), &i ); - -/* Get the i'th element in the supplied element. This will be the j'th - AstroCoordArea. */ - aca = (AstXmlElement *) astXmlGetItem( elem, i ); - -/* Get the "coord_system_id" attribute from this AstroCoordArea. Use null - if not available. */ - id = astXmlGetAttributeValue( aca, "coord_system_id" ); - if( !id ) { - id = ""; - Report( this, aca, WARNING, "has no coord_system_id attribute. " - "Assuming a null coord_system_id value", status ); - } - -/* Get the index within the supplied element of the AstroCoordSystem with this - ID. Jump forward if no AstroCoordSystem with this id is available. */ - if( astMapGet0I( map1, id, &i ) ) { - -/* Get a pointer to the AstroCoordSystem element with the required ID. */ - acs = (AstXmlElement *) astXmlGetItem( elem, i ); - -/* Leave the AstroCoordArea loop. */ - break; - -/* Report a warning if no AstroCoordSystem with this id is available. */ - } else { - sprintf( buff, "refers to an AstroCoordSystem with " - "ID \"%s\", but no such AstroCoordSystem is available " - "within the parent %s", id, stc_class ); - Report( this, aca, WARNING, buff, status ); - } - } - -/* If we did not find a corresponding pair of AstroCoordSystem and - AstroCoordArea, we either report a failure (if there were any - AstroCoordAreas), or get a pointer the AstroCoordSystem referred to by - the first AstroCoords element (we will create a Frame from this later). */ - if( !acs ) { - aca = NULL; - -/* Report a warning if there were some AstroCoordArea tags but no matching - AstroCoordSystem was found. */ - if( narea > 0 ) { - Report( this, elem, WARNING, "does not contain a pair of " - "matching AstroCoordArea and AstroCoordSystem tags", status ); - -/* If there are no AstroCoordAreas in the supplied element, look for a - pair of matching AstroCoords and AstroCoordSystem. The returned Region - will represent a NullRegion within this system. */ - } else if( ncoord > 0 ) { - -/* Get the 1st key from "map3" (the ID associated with the 1st - AstroCoords found in the supplied element) and retrieve the value - associated with this key (the index "i" into the content of the - supplied element at which the 1st AstroCoords is stored). */ - astMapGet0I( map3, astMapKey( map3, 0 ), &i ); - -/* Get the i'th element in the supplied element. This will be the 1st - AstroCoord. */ - aco = (AstXmlElement *) astXmlGetItem( elem, i ); - -/* Get the "coord_system_id" attribute from this AstroCoords. Use null - if not available. */ - id = astXmlGetAttributeValue( aco, "coord_system_id" ); - if( !id ) { - id = ""; - Report( this, aco, WARNING, "has no coord_system_id attribute. " - "Assuming a null coord_system_id value", status ); - } - -/* Get the index within the supplied element of the AstroCoordSystem with this - ID. Jump forward if no AstroCoordSystem with this id is available. */ - if( astMapGet0I( map1, id, &i ) ) { - -/* Get a pointer to the AstroCoordSystem element with the required ID. */ - acs = (AstXmlElement *) astXmlGetItem( elem, i ); - - } else { - Report( this, aco, FAILURE, "no corresponding AstroCoordSystem found", status ); - } - -/* If there are no AstroCoords in the supplied element we create a - NullRegion within the first supplied AstroCoordSystem. */ - } else if( nsys > 0 ) { - if( astMapGet0I( map1, astMapKey( map1, 0 ), &i ) ) { - acs = (AstXmlElement *) astXmlGetItem( elem, i ); - } - - } else { - Report( this, elem, FAILURE, "no usable content found", status ); - } - } - -/* Report failure if we still have no AstroCoordSystem. */ - if( !acs ) { - Report( this, elem, FAILURE, "does not contain a usable AstroCoordSystem", status ); - -/* Issue a warning if more than one AstroCoordArea was found. */ - } else { - if( narea > 1 ) Report( this, elem, WARNING, "contains more than one " - "AstroCoordArea. Only one will be used", status ); - -/* Create a Frame from the ASTRO_COORD_SYSTEM. */ - frm = (AstFrame *) AstroCoordSystemReader( this, acs, status ); - -/* Loop round all AstroCoords elements in the supplied element. */ - gotunc = 0; - reported = 0; - uncs[ 0 ] = NULL; - uncs[ 1 ] = NULL; - uncs[ 2 ] = NULL; - uncs[ 3 ] = NULL; - nanc = 0; - ancs = NULL; - for( j = 0; j < ncoord; j++ ) { - -/* Get the j'th key from "map3" (the ID associated with the j'th - AstroCoords found in the supplied element) and retrieve the value - associated with this key (the index "i" into the content of the - supplied element at which the j'th AstroCoords is stored). */ - astMapGet0I( map3, astMapKey( map3, j ), &i ); - -/* Get the i'th element in the supplied element. This will be the j'th - AstroCoords. */ - aco = (AstXmlElement *) astXmlGetItem( elem, i ); - -/* Get the "coord_system_id" attribute from this AstroCoords and compare it - with the ID of the AstrocCoordSys being used. If they match, incorporate - the effects of the AstroCoords into the "frm" Frame and get a set of 4 - Regions representing the uncertainty within each of the 4 STC domains - (space, time, spectral, redshift). */ - ido = astXmlGetAttributeValue( aco, "coord_system_id" ); - if( ido && !strcmp( id, ido ) ) { - if( AstroCoordsReader( this, aco, frm, tuncs, &anc, status ) ) { - if( !gotunc ) { - uncs[ 0 ] = tuncs[ 0 ]; - uncs[ 1 ] = tuncs[ 1 ]; - uncs[ 2 ] = tuncs[ 2 ]; - uncs[ 3 ] = tuncs[ 3 ]; - gotunc = 1; - } else { - if( tuncs[ 0 ] ) tuncs[ 0 ] = astAnnul( tuncs[ 0 ] ); - if( tuncs[ 1 ] ) tuncs[ 1 ] = astAnnul( tuncs[ 1 ] ); - if( tuncs[ 2 ] ) tuncs[ 2 ] = astAnnul( tuncs[ 2 ] ); - if( tuncs[ 3 ] ) tuncs[ 3 ] = astAnnul( tuncs[ 3 ] ); - if( !reported ) { - Report( this, elem, WARNING, "contains more than one " - "specification of the coordinate uncertainties. " - "Only the first will be used", status ); - reported= 1; - } - } - } - -/* If any ancillary information was read from the AstroCoords, add it to - the list of ancillary information to be stored in the Stc structure. */ - if( anc ) { - ancs = astGrow( ancs, nanc + 1, sizeof( AstKeyMap * ) ); - if( ancs ) ancs[ nanc++ ] = anc; - } - } - } - -/* Now create a Region from this Frame and the ASTRO_COORD_AREA. Note, - "aca" may be NULL in which case the returned Region will be NullRegion. */ - region = AstroCoordAreaReader( this, aca, frm, uncs, nanc, ancs, status ); - -/* Re-centre the Regions describing ancillary information extracted from - the AstroCoords elements. */ - ReCentreAnc( region, nanc, ancs, status ); - -/* Now create a Stc object of the appropriate sub-class. */ - if( !strcmp( stc_class, STC_RESOURCE_PROFILE ) ) { - stc = (AstStc *) astStcResourceProfile( region, nanc, ancs, "", status ); - - } else if( !strcmp( stc_class, SEARCH_LOCATION ) ) { - stc = (AstStc *) astStcSearchLocation( region, nanc, ancs, "", status ); - - } else if( !strcmp( stc_class, CATALOG_ENTRY_LOCATION ) ) { - stc = (AstStc *) astStcCatalogEntryLocation( region, nanc, ancs, "", status ); - - } else if( !strcmp( stc_class, OBSERVATION_LOCATION ) || - !strcmp( stc_class, OBSERVATORY_LOCATION ) ) { - stc = (AstStc *) astStcObsDataLocation( region, nanc, ancs, "", status ); - - } else if( astOK ){ - astError( AST__INTER, "astRead(XmlChan): StcMetadataReader knows " - "nothing about the %s class (internal AST programming " - "error).", status, stc_class ); - } - -/* Get the ID attribute from the supplied element and store in the - returned Object. */ - id = astXmlGetAttributeValue( elem, "ID" ); - if( id ) astSetIdent( stc, id ); - -/* Free resources. */ - if( uncs[ 0 ] ) uncs[ 0 ] = astAnnul( uncs[ 0 ] ); - if( uncs[ 1 ] ) uncs[ 1 ] = astAnnul( uncs[ 1 ] ); - if( uncs[ 2 ] ) uncs[ 2 ] = astAnnul( uncs[ 2 ] ); - if( uncs[ 3 ] ) uncs[ 3 ] = astAnnul( uncs[ 3 ] ); - frm = astAnnul( frm ); - region = astAnnul( region ); - if( ancs ) { - for( i = 0; i < nanc; i++ ) ancs[ i ] = astAnnul( ancs[ i ] ); - ancs = astFree( ancs ); - } - } - - map1 = astAnnul( map1 ); - map2 = astAnnul( map2 ); - map3 = astAnnul( map3 ); - -/* Return the pointer to the new Object. */ - return (AstObject *) stc; -} - -static AstRegion *StcRegionReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* StcRegionReader - -* Purpose: -* Make an AST Region from an IVOA Region element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *StcRegionReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Region element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Region element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[1]; /* Names of the subelements to be searched for */ - int max[1]; /* Max allowed occurrences of each name */ - int min[1]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for a Region sub-element. */ - names[ 0 ] = "Intersection|Union|Negation|AllSky|Circle|Ellipse|Polygon|" - "Convex|Box"; - min[ 0 ] = 1; - max[ 0 ] = 1; - scan = ScanIVOAElement( this, elem, 1, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create the Region */ - new = RegionReader( this, scan->el[0][0], frm, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* TestAttrib - -* Purpose: -* Test if a specified attribute value is set for a XmlChan. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* int TestAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the astTestAttrib protected -* method inherited from the Channel class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate whether -* a value has been set for one of a XmlChan's attributes. - -* Parameters: -* this -* Pointer to the XmlChan. -* attrib -* Pointer to a null terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if a value has been set, otherwise zero. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_object; - -/* Check the attribute name and test the appropriate attribute. */ - -/* XmlLength */ -/* --------- */ - if ( !strcmp( attrib, "xmllength" ) ) { - result = astTestXmlLength( this ); - -/* XmlFormat */ -/* --------- */ - } else if ( !strcmp( attrib, "xmlformat" ) ) { - result = astTestXmlFormat( this ); - -/* XmlPrefix */ -/* --------- */ - } else if ( !strcmp( attrib, "xmlprefix" ) ) { - result = astTestXmlPrefix( this ); - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - result = (*parent_testattrib)( this_object, attrib, status ); - } - -/* Return the result, */ - return result; -} - -static AstObject *TimeFrameReader( AstXmlChan *this, - AstXmlElement *elem, int *status ) { -/* -* Name: -* TimeFrameReader - -* Purpose: -* Make an AST Object from an IVOA TimeFrame element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstObject *TimeFrameReader( AstXmlChan *this, AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Object from the supplied IVOA -* TimeFrame element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA TimeFrame element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Object. - -*/ - -/* Local Variables: */ - AstTimeFrame *new; /* Pointer to returned Frame */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[3]; /* Names of the subelements to be searched for */ - const char *text; /* Pointer to Name value */ - int max[3]; /* Max allowed occurrences of each name */ - int min[3]; /* Min allowed occurrences of each name */ - -/* Initialise */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return (AstObject *) new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Name"; - names[ 1 ] = "TOPOCENTER"; - names[ 2 ] = "TimeScale|Timescale"; - min[ 0 ] = 0; - max[ 0 ] = 1; - min[ 1 ] = 0; - max[ 1 ] = 1; - min[ 2 ] = 1; - max[ 2 ] = 1; - scan = ScanIVOAElement( this, elem, 3, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create a suitable TimeFrame. Set the timescale, but leave the other - attributes unset since they will not be known until an AstronTimeType - is read. Except for unit. We set unit to "d" (day) because all the - time form,ats supported by STC have "d" as the default unit. This - avoids bad publicity which arises from presentin (say) MJD values in - units of "s" - which people will think is wrong until they have it - explained. */ - new = astTimeFrame( "unit=d", status ); - astSetTimeScale( new, TimeScaleReader( this, scan->el[ 2 ][ 0 ], status ) ); - -/* If the STC TimeFrame has a <Name> element use it as the AST TimeFrame title. */ - if( scan->count[ 0 ] > 0 ) { - text = astXmlGetValue( scan->el[ 0 ][ 0 ], 0 ); - if( text ) astSetTitle( new, text ); - } - -/* Free resources. */ - scan = FreeIVOAScan( scan, status ); - - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new= astAnnul( new ); - -/* Return the pointer to the new Object. */ - return (AstObject *) new; -} - -static AstRegion *TimeIntervalReader( AstXmlChan *this, AstXmlElement *elem, - AstTimeFrame *frm, int *status ){ -/* -* Name: -* TimeIntervalReader - -* Purpose: -* Make an AST Region from an IVOA TimeInterval element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *TimeIntervalReader( AstXmlChan *this, AstXmlElement *elem, -* AstTimeFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* TimeInterval element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA TimeInterval element. -* frm -* Pointer to the TimeFrame in which the returned Region should be -* defined. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[2]; /* Names of the subelements to be searched for */ - double start; /* Start time */ - double stop; /* Stop time */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "StartTime"; - names[ 1 ] = "StopTime"; - min[ 0 ] = 0; - min[ 1 ] = 0; - max[ 0 ] = 1; - max[ 1 ] = 1; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the limits. */ - start = scan->count[0] ? AstronTimeReader( this, scan->el[0][0], frm, status ) : AST__BAD; - stop = scan->count[1] ? AstronTimeReader( this, scan->el[1][0], frm, status ) : AST__BAD; - -/* If at least one limit was found, create an Interval. Otherwise create - a negated NullRegion. */ - if( start != AST__BAD || stop != AST__BAD ) { - -/* Use the stop or start time (converted to an MJD) as the Epoch within the - Frame. */ - if( start != AST__BAD ) { - astSetEpoch( frm, MakeMJD( frm, start, status ) ); - } else if( stop != AST__BAD ) { - astSetEpoch( frm, MakeMJD( frm, stop, status ) ); - } - new = (AstRegion *) astInterval( frm, &start, &stop, NULL, "", status ); - } else { - new = (AstRegion *) astNullRegion( frm, NULL, "negated=1", status ); - } - -/* Get any fill factor and lo/hi_include attributes from the element and - assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources. */ - scan = FreeIVOAScan( scan, status ); - - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static AstRegion *TimeReader( AstXmlChan *this, AstXmlElement *elem, - AstTimeFrame *frm, double *epoch, - AstKeyMap **anc, int *status ){ -/* -* Name: -* TimeReader - -* Purpose: -* Modify a Frame to take account of an STC <Time> element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *TimeReader( AstXmlChan *this, AstXmlElement *elem, -* AstTimeFrame *frm, double *epoch, -* AstKeyMap **anc, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function reads the supplied STC <Time> element, and uses it, -* if possible, to create the uncertainty associated with the time -* axis in the supplied Frame. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Time element. -* frm -* Pointer to the TimeFrame. -* epoch -* Pointer to double in which to return the epoch to be used -* with other axes. Value is returned as an Modified Julian Date -* in the barycentric dynamical timescale (TDB). AST__BAD will -* be returned if the supplied Time element has no value. -* anc -* Address of a location at which to put a pointer to a newly -* created KeyMap. This KeyMap will contain ancillary information -* from the Time. The keys identify the item of ancillary -* information (Name, Value, Error, Resolution, Size, Pixel Size). -* The value associated with the Name key is string containing -* the Name item from the Time. The value -* associated with each of the other keys is a pointer to a 1D Region -* within the supplied Frame, corresponding to the value, error, -* resolution, etc. Keys will not be present in the returned KeyMap -* if the corresponding item of ancillary information is not present -* in the Time. A NULL pointer is returned if there is no -* ancillary information at all. -* status -* Pointer to the inherited status variable. - -* Returned: -* The uncertainty Region, or NULL if the supplied Time element -* does not specify an uncertainty. - -*/ - -/* Local Variables: */ - AstTimeFrame *cfrm; /* Pointer to copy of time axis */ - AstRegion *result; /* Returned uncertainty Region */ - AstRegion *r; /* Ancillary Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *funit; /* Pointer to Frame's unit attribute string */ - const char *names[6]; /* Names of the subelements to be searched for */ - const char *title; /* Pointer to Frame title string */ - const char *unit; /* Pointer to Time's unit attribute string */ - double lbnd[ 1 ] ; /* Lower interval bounds */ - double ubnd[ 1 ] ; /* Upper interval bounds */ - double value; /* Time value */ - double v; /* Ancillary value */ - int max[6]; /* Max allowed occurrences of each name */ - int min[6]; /* Min allowed occurrences of each name */ - -/* Initialise */ - result = NULL; - *epoch = AST__BAD; - *anc = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Name"; - names[ 1 ] = "Error"; - names[ 2 ] = "TimeInstant"; - names[ 3 ] = "Resolution"; - names[ 4 ] = "Size"; - names[ 5 ] = "PixSize"; - max[ 0 ] = 1; - max[ 1 ] = 2; - max[ 2 ] = 1; - max[ 3 ] = 2; - max[ 4 ] = 2; - max[ 5 ] = 2; - min[ 0 ] = 1; - min[ 1 ] = 0; - min[ 2 ] = 0; - min[ 3 ] = 0; - min[ 4 ] = 0; - min[ 5 ] = 0; - scan = ScanIVOAElement( this, elem, 6, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create a KeyMap to return holding ancilary info, and put the Name into - it. */ - *anc = astKeyMap( "", status ); - if( scan->count[0] > 0 ) astMapPut0C( *anc, AST__STCNAME, - astXmlGetValue( scan->el[0][0], 0 ), NULL ); - -/* Get any Unit attribute from the Time element. */ - unit = astXmlGetAttributeValue( elem, "unit" ); - -/* We need to ensure the returned regions are mapped into units of "funit". - If this is NULL it means that the returned regions are already in the - required units. */ - funit = NULL; - -/* If the Time element has a unit attribute, we use it in preference to any - units values in the supplied Frame. Take a copy of the time Frame and set - its Units to this values. Ensure the title is preserved. */ - if( unit && astChrLen( unit ) ) { - cfrm = astCopy( frm ); - if( astTestTitle( frm ) ) { - title = (char *) astGetTitle( frm ); - if( title ) title = astStore( NULL, title, strlen( title ) + 1 ); - } else { - title = NULL; - } - astSetUnit( cfrm, 0, unit ); - if( title ) astSetTitle( cfrm, title ); - - if( astTestUnit( frm, 0 ) ) { - funit = astGetUnit( frm, 0 ); - if( !strcmp( funit, unit ) ) { - funit = NULL; - } else { - funit = astStore( NULL, funit, strlen( funit ) + 1 ); - } - } else { - astSetUnit( frm, 0, unit ); - } - - } else { - cfrm = astClone( frm ); - title = NULL; - } - -/* If this Time contains a Value which can be read, obtain it. Otherwise, - issue a warning. We will use the value to calculate the returned epoch. */ - if( scan->count[ 2 ] > 0 ) { - value = AstronTimeReader( this, scan->el[ 2 ][ 0 ], cfrm, status ); - *epoch = MakeMJD( cfrm, value, status ); - -/* Ensure any relevant attribute values which were set by AstronTimeReader - within "cfrm" are transferred to "frm". */ - if( astTestTimeScale( cfrm ) ) astSetTimeScale( frm, astGetTimeScale( cfrm ) ); - if( astTestSystem( cfrm ) ) astSetSystem( frm, astGetSystem( cfrm ) ); - if( astTestUnit( cfrm, 0 ) ) astSetUnit( frm, 0, astGetUnit( cfrm, 0 ) ); - if( astTestTimeOrigin( cfrm ) ) astSetTimeOrigin( frm, astGetTimeOrigin( cfrm ) ); - -/* Create a Interval from it and store in the returned ancillary KeyMap. If - the units of this Frame differs from that of the supplied Frame, set it - to the units of the supplied Frame. This will cause the encapsulated - limits to be mapped into the new units. Ensure the original title is - preserved. Use an Interval rather than a PointList since an Interval - can be used within a Prism to extrude another Region, but a PointList - cannot. */ - r = (AstRegion *) astInterval( cfrm, &value, &value, NULL, "", status ) ; - if( funit ) astSetUnit( r, 0, funit ); - if( title ) astSetTitle( r, title ); - astMapPut0A( *anc, AST__STCVALUE, r, NULL ); - r = astAnnul( r ); - } - -/* Does this Time contain any Error? */ - if( scan->count[ 1 ] > 0 ) { - -/* Issue a warning if more than 1 Error value was found. */ - if( scan->count[ 1 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Error>" - " element. AST can only use the first", status ); - } - -/* Get the first Error value. */ - v = ElemValueD( this, scan->el[1][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of an error bar centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the time Frame. */ - result = (AstRegion *) astInterval( cfrm, lbnd, ubnd, NULL, "", status ); - -/* If the units of this Frame differs from that of the supplied Frame, - set it to the units of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new units. */ - if( funit ) astSetUnit( result, 0, funit ); - -/* Ensure the original title is preserved. */ - if( title ) astSetTitle( result, title ); - -/* Store in the returned ancillary KeyMap. */ - astMapPut0A( *anc, AST__STCERROR, result, NULL ); - - } - } - -/* Does this Time contain any Resolution? */ - if( scan->count[ 3 ] > 0 ) { - -/* Issue a warning if more than 1 Resolution value was found. */ - if( scan->count[ 3 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Resolution>" - " element. AST can only use the first", status ); - } - -/* Get the first Resolution value. */ - v = ElemValueD( this, scan->el[3][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of a bar centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the time Frame. */ - r = (AstRegion *) astInterval( cfrm, lbnd, ubnd, NULL, "", status ); - -/* If the units of this Frame differs from that of the supplied Frame, - set it to the units of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new units. */ - if( funit ) astSetUnit( r, 0, funit ); - -/* Ensure the original title is preserved. */ - if( title ) astSetTitle( r, title ); - -/* Store in the returned ancillary KeyMap. */ - astMapPut0A( *anc, AST__STCRES, r, NULL ); - r = astAnnul( r ); - } - } - -/* Does this Time contain any Size? */ - if( scan->count[ 4 ] > 0 ) { - -/* Issue a warning if more than 1 Size value was found. */ - if( scan->count[ 4 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <Size>" - " element. AST can only use the first", status ); - } - -/* Get the first Size value. */ - v = ElemValueD( this, scan->el[4][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of a bar centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the time Frame. */ - r = (AstRegion *) astInterval( cfrm, lbnd, ubnd, NULL, "", status ); - -/* If the units of this Frame differs from that of the supplied Frame, - set it to the units of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new units. */ - if( funit ) astSetUnit( r, 0, funit ); - -/* Ensure the original title is preserved. */ - if( title ) astSetTitle( r, title ); - -/* Store in the returned ancillary KeyMap. */ - astMapPut0A( *anc, AST__STCSIZE, r, NULL ); - r = astAnnul( r ); - } - } - -/* Does this Time contain any PixSize? */ - if( scan->count[ 5 ] > 0 ) { - -/* Issue a warning if more than 1 PixSize value was found. */ - if( scan->count[ 5 ] > 1 ) { - Report( this, elem, WARNING, "contains more than one <PixSize>" - " element. AST can only use the first", status ); - } - -/* Get the first PixSize value. */ - v = ElemValueD( this, scan->el[5][0], AST__BAD, status ); - if( v != AST__BAD ) { - -/* Create the upper and lower limits of a bar centred on zero. */ - ubnd[ 0 ] = 0.5*fabs( v ); - lbnd[ 0 ] = -ubnd[ 0 ]; - -/* Create an Interval within the time Frame. */ - r = (AstRegion *) astInterval( cfrm, lbnd, ubnd, NULL, "", status ); - -/* If the units of this Frame differs from that of the supplied Frame, - set it to the units of the supplied Frame. This will cause the - encapsulated limits to be mapped into the new units. */ - if( funit ) astSetUnit( r, 0, funit ); - -/* Ensure the original title is preserved. */ - if( title ) astSetTitle( r, title ); - -/* Store in the returned ancillary KeyMap. */ - astMapPut0A( *anc, AST__STCPIXSZ, r, NULL ); - r = astAnnul( r ); - } - } - -/* Free resources */ - if( funit ) funit = astFree( (void *) funit ); - cfrm = astAnnul( cfrm ); - if( title ) title = astFree( (void *) title ); - scan = FreeIVOAScan( scan, status ); - } - -/* Return NULL if an error occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the result */ - return result; - -} - -static AstTimeScaleType TimeScaleReader( AstXmlChan *this, AstXmlElement *elem, int *status ){ -/* -* Name: -* TimeScaleReader - -* Purpose: -* Read a time value from an IVOA TimeScale element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstTimeScaleType TimeScaleReader( AstXmlChan *this, AstXmlElement *elem, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function returns a value representing the timescale specified by -* the supplied IVOA TimeScale element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA TimeScale element. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The timescale value (values are defined in timeframe.h). - -*/ - -/* Local Variables: */ - AstTimeScaleType result; - char buff[ 80 ]; - const char *tstxt; - -/* Initialise */ - result = AST__BADTS; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get the timescale string from the element, and find the corresponding - AST timescale value (if any). */ - tstxt = astXmlGetValue( elem, 0 ); - if( tstxt ) { - - if( !strcmp( tstxt, "TT" ) ) { - result = AST__TT; - - } else if( !strcmp( tstxt, "TDT" ) ) { - result = AST__TT; - - } else if( !strcmp( tstxt, "ET" ) ) { - Report( this, elem, WARNING, "TT will be used in place of ET", status ); - result = AST__TT; - - } else if( !strcmp( tstxt, "TDB" ) ) { - result = AST__TDB; - - } else if( !strcmp( tstxt, "TCG" ) ) { - result = AST__TCG; - - } else if( !strcmp( tstxt, "TCB" ) ) { - result = AST__TCB; - - } else if( !strcmp( tstxt, "TAI" ) ) { - result = AST__TAI; - - } else if( !strcmp( tstxt, "IAT" ) ) { - result = AST__TAI; - - } else if( !strcmp( tstxt, "UTC" ) ) { - result = AST__UTC; - - } else if( !strcmp( tstxt, "LST" ) ) { - result = AST__LMST; - - } else { - sprintf( buff, "contains unsupported timescale %s", tstxt ); - Report( this, elem, FAILURE, buff, status ); - result = AST__BADTS; - } - } - -/* Return the time value. */ - return result; -} - -static AstRegion *UnionReader( AstXmlChan *this, AstXmlElement *elem, - AstFrame *frm, int *status ){ -/* -* Name: -* UnionReader - -* Purpose: -* Make an AST Region from an IVOA Union region element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstRegion *UnionReader( AstXmlChan *this, AstXmlElement *elem, -* AstFrame *frm, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function makes a new AST Region from the supplied IVOA -* Union region element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Union region element. -* frm -* Pointer to the 2D Frame in which the returned Region should be -* defined. If the Unit attribute is not set, this function will -* set it to the value supplied in "unit" before returning. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the new Region. - -*/ - -/* Local Variables: */ - AstRegion *new; /* Pointer to returned Region */ - AstRegion *reg; /* Pointer to component Region */ - AstRegion *tmp; /* Pointer to new Region */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[1]; /* Names of the subelements to be searched for */ - int i; /* Loop count */ - int max[1]; /* Max allowed occurrences of each name */ - int min[1]; /* Min allowed occurrences of each name */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Search the supplied element for a Region sub-element. */ - names[ 0 ] = "Intersection|Union|Negation|AllSky|Circle|Ellipse|Polygon|" - "Convex|Box"; - min[ 0 ] = 2; - max[ 0 ] = INT_MAX; - scan = ScanIVOAElement( this, elem, 1, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Create Regions from all the component region elements, and combine - them into nested CmpRegions, using the boolean OR operator to combine - them. */ - new = RegionReader( this, scan->el[0][0], frm, status ); - for( i = 1; i < scan->count[0]; i++ ) { - reg = RegionReader( this, scan->el[0][i], frm, status ); - tmp = (AstRegion *) astCmpRegion( new, reg, AST__OR, "", status ); - reg = astAnnul( reg ); - (void) astAnnul( new ); - new = tmp; - } - -/* Get any fill factor from the element and assign to the returned Region. */ - FillAndLims( this, elem, new, status ); - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - -/* Annul any returned Frame if an error has occurred. */ - if( !astOK ) new = astAnnul( new ); - -/* Return the pointer to the new Region. */ - return new; -} - -static int Use( AstXmlChan *this, int set, int helpful, int *status ) { -/* -* Name: -* Use - -* Purpose: -* Decide whether to write a value to a data sink. - -* Type: -* Private function. - -* Synopsis: -* #include "channel.h" -* int Use( AstXmlChan *this, int set, int helpful, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function decides whether a value supplied by a class "Dump" -* function, via a call to one of the astWrite... protected -* methods, should actually be written to the data sink associated -* with a XmlChan. -* -* This decision is based on the settings of the "set" and -* "helpful" flags supplied to the astWrite... method, plus the -* attribute settings of the XmlChan. - -* Parameters: -* this -* A pointer to the XmlChan. -* set -* The "set" flag supplied. -* helpful -* The "helpful" value supplied. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if the value should be written out, otherwise zero. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - int full; /* Full attribute value */ - int result; /* Result value to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* If "set" is non-zero, then so is the result ("set" values must - always be written out). */ - result = ( set != 0 ); - -/* Otherwise, obtain the value of the XmlChan's Full attribute. */ - if ( !set ) { - full = astGetFull( this ); - -/* If Full is positive, display all values, if zero, display only - "helpful" values, if negative, display no (un-"set") values. */ - if ( astOK ) result = ( ( helpful && ( full > -1 ) ) || ( full > 0 ) ); - } - -/* Return the result. */ - return result; -} - -static int Ustrcmp( const char *a, const char *b, int *status ){ -/* -* Name: -* Ustrcmp - -* Purpose: -* A case blind version of strcmp. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int Ustrcmp( const char *a, const char *b, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* Returns 0 if there are no differences between the two strings, and 1 -* otherwise. Comparisons are case blind. - -* Parameters: -* a -* Pointer to first string. -* b -* Pointer to second string. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Zero if the strings match, otherwise one. - -* Notes: -* - This function does not consider the sign of the difference between -* the two strings, whereas "strcmp" does. -* - This function attempts to execute even if an error has occurred. - -*/ - -/* Local Variables: */ - const char *aa; /* Pointer to next "a" character */ - const char *bb; /* Pointer to next "b" character */ - int ret; /* Returned value */ - -/* Initialise the returned value to indicate that the strings match. */ - ret = 0; - -/* Initialise pointers to the start of each string. */ - aa = a; - bb = b; - -/* Loop round each character. */ - while( 1 ){ - -/* We leave the loop if either of the strings has been exhausted. */ - if( !(*aa ) || !(*bb) ){ - -/* If one of the strings has not been exhausted, indicate that the - strings are different. */ - if( *aa || *bb ) ret = 1; - -/* Break out of the loop. */ - break; - -/* If neither string has been exhausted, convert the next characters to - upper case and compare them, incrementing the pointers to the next - characters at the same time. If they are different, break out of the - loop. */ - } else { - - if( toupper( (int) *(aa++) ) != toupper( (int) *(bb++) ) ){ - ret = 1; - break; - } - - } - - } - -/* Return the result. */ - return ret; - -} - -static int Ustrncmp( const char *a, const char *b, size_t n, int *status ){ -/* -* Name: -* Ustrncmp - -* Purpose: -* A case blind version of strncmp. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int Ustrncmp( const char *a, const char *b, size_t n, int *status ) - -* Class Membership: -* XmlChan member function. - -* Description: -* Returns 0 if there are no differences between the first "n" -* characters of the two strings, and 1 otherwise. Comparisons are -* case blind. - -* Parameters: -* a -* Pointer to first string. -* b -* Pointer to second string. -* n -* The maximum number of characters to compare. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Zero if the strings match, otherwise one. - -* Notes: -* - This function does not consider the sign of the difference between -* the two strings, whereas "strncmp" does. -* - This function attempts to execute even if an error has occurred. - -*/ - -/* Local Variables: */ - const char *aa; /* Pointer to next "a" character */ - const char *bb; /* Pointer to next "b" character */ - int i; /* Character index */ - int ret; /* Returned value */ - -/* Initialise the returned value to indicate that the strings match. */ - ret = 0; - -/* Initialise pointers to the start of each string. */ - aa = a; - bb = b; - -/* Compare up to "n" characters. */ - for( i = 0; i < (int) n; i++ ){ - -/* We leave the loop if either of the strings has been exhausted. */ - if( !(*aa ) || !(*bb) ){ - -/* If one of the strings has not been exhausted, indicate that the - strings are different. */ - if( *aa || *bb ) ret = 1; - -/* Break out of the loop. */ - break; - -/* If neither string has been exhausted, convert the next characters to - upper case and compare them, incrementing the pointers to the next - characters at the same time. If they are different, break out of the - loop. */ - } else { - - if( toupper( (int) *(aa++) ) != toupper( (int) *(bb++) ) ){ - ret = 1; - break; - } - - } - - } - -/* Return the result. */ - return ret; - -} - -static int VertexReader( AstXmlChan *this, AstXmlElement *elem, double *x, - double *y, int *status ){ -/* -* Name: -* VertexReader - -* Purpose: -* Read a position from an IVOA Vertex element. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* int VertexReader( AstXmlChan *this, AstXmlElement *elem, double *x, -* double *y ) - -* Class Membership: -* XmlChan member function. - -* Description: -* This function reads a 2D position from the supplied IVOA Vertex -* element. - -* Parameters: -* this -* Pointer to the XmlChan. -* elem -* Pointer to the IVOA Vertex element. -* x -* Pointer to the double in which to put the returned X value. -* y -* Pointer to the double in which to put the returned Y value. - -* Returned Value: -* Non-zero if the <Vertex> contains a <pole> tag. - -*/ - -/* Local Variables: */ - IVOAScan *scan; /* Structure holding scan results */ - const char *names[2]; /* Names of the subelements to be searched for */ - double xy[ 2 ]; /* Axis values read from Position */ - int max[2]; /* Max allowed occurrences of each name */ - int min[2]; /* Min allowed occurrences of each name */ - int result; /* Returned value */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Initialise */ - result = 0; - *x = AST__BAD; - *y = AST__BAD; - -/* Search the supplied element for the required sub-elements. */ - names[ 0 ] = "Position"; - max[ 0 ] = 1; - min[ 0 ] = 1; - names[ 1 ] = "SmallCircle"; - max[ 1 ] = 1; - min[ 1 ] = 0; - scan = ScanIVOAElement( this, elem, 2, names, min, max, status ); - -/* If succesfull.. */ - if( scan ) { - -/* Get the axis values from the Position element. */ - xy[ 0 ] = AST__BAD; - xy[ 1 ] = AST__BAD; - ElemListD( this, scan->el[0][0], 2, xy, status ); - *x = xy[ 0 ]; - *y = xy[ 1 ]; - -/* Get any SmallCircle element. If it has a Pole issue a warning. */ - result = scan->count[ 1 ]; - if( result ) { - if( FindElement( this, scan->el[1][0], "Pole", status ) ) { - Report( this, scan->el[1][0], WARNING, "contains a <Pole> " - "tag (poles are not supported by AST)", status ); - } - } - -/* Free resources */ - scan = FreeIVOAScan( scan, status ); - } - - return result; -} - -static void WriteBegin( AstChannel *this_channel, const char *class, - const char *comment, int *status ) { -/* -* Name: -* WriteBegin - -* Purpose: -* Write a "Begin" data item to a data sink. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void WriteBegin( AstChannel *this_channel, const char *class, -* const char *comment, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected -* astWriteBegin method inherited from the Channel class). - -* Description: -* This function writes a "Begin" data item to the data sink -* associated with a Channel, so as to begin the output of a new -* Object definition. - -* Parameters: -* this -* Pointer to the XmlChan. -* class -* Pointer to a constant null-terminated string containing the -* name of the class to which the Object belongs. -* comment -* Pointer to a constant null-terminated string containing a -* textual comment to be associated with the "Begin" -* item. Normally, this will describe the purpose of the Object. -* status -* Pointer to the inherited status variable. - -* Notes: -* - The comment supplied may not actually be used, depending on -* the nature of the Channel supplied. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* A pointer to the XmlChan structure. */ - AstXmlElement *elem; /* The XML element to hodl the new AST object */ - const char *pref; /* XML namespace prefix to use */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* If this is a top level object (i.e. if there is no container element), - reset all the other values in the XmlChan for safety. */ - if( !this->container ) { - this->objectname = NULL; - this->objectset = 1; - this->objectcomment = NULL; - } - -/* Initialise a flag to indicate that the next "IsA" item should not be - written. This flag will be changed if and when an item is added which - related to the class described by the "IsA" item. Save the old value - first. */ - this->write_isa = 0; - -/* Store the namespace prefix. */ - pref = astGetXmlPrefix( this ); - -/* Create a new XmlElement with a name equal to the AST class name of the - object being dumped (and no namespace prefix), and add it into the - current container (i.e. parent) element. */ - elem = astXmlAddElement( this->container, class, pref ); - -/* If this is a top level container, store the namespace URI for - the element, either default or named depending on the value of - XmlPrefix. */ - if( !this->container ) astXmlAddURI( elem, pref, AST__XMLNS ); - -/* If non-blank, append a "Label" atttribute to the element holding the - name of the object (stored in the XmlChan structure). */ - if( this->objectname ) astXmlAddAttr( elem, LABEL, this->objectname, NULL ); - -/* If the object has all default values, store a true value for the - DEFAULT attribute. */ - if( !this->objectset ) astXmlAddAttr( elem, DEFAULT, TRUE, NULL ); - -/* Add commments if required. */ - if( astGetComment( this_channel ) ) { - -/* If we are adding comments, and if a comment was supplied as a - parameter to this function, then store the commment as an attribute of - the element. This comment describes the class function as a whole, not - the specific usage of this instance of the class (this is given by the - comment in this->objectcomment). */ - if( comment && *comment ) astXmlAddComment( elem, 0, comment ); - -/* If the object has a usage comment, add it to the content of the - element if required. */ - if( this->objectcomment ) astXmlAddAttr( elem, DESC, this->objectcomment, NULL ); - } - -/* Make the new element the current container. */ - this->container = (AstXmlParent *) elem; - -/* If an error has occurred, annul the container element in the XmlChan. */ - if( !astOK ) this->container = astXmlAnnulTree( this->container ); - -} - -static void WriteDouble( AstChannel *this_channel, const char *name, - int set, int helpful, - double value, const char *comment, int *status ) { -/* -* Name: -* WriteDouble - -* Purpose: -* Write a double value to a data sink. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void WriteDouble( AstChannel *this, const char *name, -* int set, int helpful, -* double value, const char *comment, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected -* astWriteDouble method inherited from the Channel class). - -* Description: -* This function writes a named double value, representing the -* value of a class instance variable, to the data sink associated -* with a Channel. It is intended for use by class "Dump" functions -* when writing out class information which will subsequently be -* re-read. - -* Parameters: -* this -* Pointer to the Channel. -* name -* Pointer to a constant null-terminated string containing the -* name to be used to identify the value in the external -* representation. This will form the key for identifying it -* again when it is re-read. The name supplied should be unique -* within its class. -* -* Mixed case may be used and will be preserved in the external -* representation (where possible) for cosmetic effect. However, -* case is not significant when re-reading values. -* -* It is recommended that a maximum of 6 alphanumeric characters -* (starting with an alphabetic character) be used. This permits -* maximum flexibility in adapting to standard external data -* representations (e.g. FITS). -* set -* If this is zero, it indicates that the value being written is -* a default value (or can be re-generated from other values) so -* need not necessarily be written out. Such values will -* typically be included in the external representation with -* (e.g.) a comment character so that they are available to -* human readers but will be ignored when re-read. They may also -* be completely omitted in some circumstances. -* -* If "set" is non-zero, the value will always be explicitly -* included in the external representation so that it can be -* re-read. -* helpful -* This flag provides a hint about whether a value whose "set" -* flag is zero (above) should actually appear at all in the -* external representaton. -* -* If the external representation allows values to be "commented -* out" then, by default, values will be included in this form -* only if their "helpful" flag is non-zero. Otherwise, they -* will be omitted entirely. When possible, omitting the more -* obscure values associated with a class is recommended in -* order to improve readability. -* -* This default behaviour may be further modified if the -* Channel's Full attribute is set - either to permit all values -* to be shown, or to suppress non-essential information -* entirely. -* value -* The value to be written. -* comment -* Pointer to a constant null-terminated string containing a -* textual comment to be associated with the value. -* -* Note that this comment may not actually be used, depending on -* the nature of the Channel supplied and the setting of its -* Comment attribute. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Constants: */ -#define BUFF_LEN 100 /* Size of local formatting buffer */ - -/* Local Variables: */ - AstXmlChan *this; /* A pointer to the XmlChan structure. */ - AstXmlElement *elem; /* Pointer to new element */ - char buff[ BUFF_LEN + 1 ]; /* Local formatting buffer */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* If the object to be written is a component of a default AST object (i.e. - an object which is "not set"), then we do not write out this item. */ - if( this->objectset ) { - -/* Use the "set" and "helpful" flags, along with the Channel's - attributes to decide whether this value should actually be - written. */ - if( Use( this, set, helpful, status ) ) { - -/* Create a new XmlElement with a name of ATTR (and no namespace - prefix), and add it into the current container (i.e. parent) element. */ - elem = astXmlAddElement( this->container, ATTR, - astGetXmlPrefix( this ) ); - -/* Add a NAME attribute to this element containing the item name. */ - astXmlAddAttr( elem, NAME, name, NULL ); - -/* Format the value as a string and store it as the VALUE attribute. - Make sure "-0" isn't produced. Use a magic string to represent bad - values. */ - if( value != AST__BAD ) { - (void) sprintf( buff, "%.*g", AST__DBL_DIG, value ); - if ( !strcmp( buff, "-0" ) ) { - buff[ 0 ] = '0'; - buff[ 1 ] = '\0'; - } - } else { - strcpy( buff, BAD_STRING ); - } - astXmlAddAttr( elem, VALUE, buff, NULL ); - -/* If we are adding comments, and if a comment was supplied as a - parameter to this function, then store the commment as an attribute of - the element. */ - if( comment && *comment && astGetComment( this_channel ) ) { - astXmlAddAttr( elem, DESC, comment, NULL ); - } - -/* If the object has all default values, store a true value for the - DEFAULT attribute. */ - if( !set ) astXmlAddAttr( elem, DEFAULT, TRUE, NULL ); - -/* Initialise a flag to indicate that the next "IsA" item should be - written. */ - this->write_isa = 1; - } - } - -/* If an error has occurred, annul the container element in the XmlChan. */ - if( !astOK ) this->container = astXmlAnnulTree( this->container ); - -/* Undefine macros local to this function. */ -#undef BUFF_LEN -} - -static void WriteEnd( AstChannel *this_channel, const char *class, int *status ) { -/* -* Name: -* WriteEnd - -* Purpose: -* Write an "End" data item to a data sink. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void WriteEnd( AstChannel *this, const char *class, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected -* astWriteEnd method inherited from the Channel class). - -* Description: -* This function writes an "End" data item to the data sink -* associated with a Channel. This item delimits the end of an -* Object definition. - -* Parameters: -* this -* Pointer to the Channel. -* class -* Pointer to a constant null-terminated string containing the -* class name of the Object whose definition is being terminated -* by the "End" item. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - AstXmlParent *parent; /* Pointer to parent element */ - char *d; /* Pointer to end of next sub-string */ - char *c; /* Pointer to start of next sub-string */ - char *text; /* Pointer to complete string */ - int mxlen; /* Max allowed length of text */ - -#ifdef DEBUG - int nobj; /* No. of XmlObjects in existence */ -#endif - -/* Check the global error status. */ - if ( !astOK ) return; - -#ifdef DEBUG -/* Save the number of XmlObjects currently in existenece. */ - nobj = astXmlTrace(3); -#endif - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* Get the parent of the current container element. */ - if( this->container ) { - parent = astXmlGetParent( this->container ); - -/* If the current container element has no parent, we have completed the - construction of the in-memory XML representation of the AST object being - written out. In this case, we convert the in-memory representation - into a set of strings and write them out using the supplied sink - function. */ - if( !parent ) { - -/* First get a single string holding the complete formatted XML - representation of the AST object. */ - if( astGetIndent( this ) ) { - text = (char *) astXmlShow( this->container ); - } else { - text = (char *) astXmlFormat( this->container ); - } - -/* Now, if we have any text, split it into separate lines. The end of a line - is indicated by a "\n" character in the text returned by astXmlFormat. */ - if( text ) { - -/* Get the maximum allowed line length. */ - mxlen = astGetXmlLength( this ); - -/* Loop round locating each '\n' character in the string. Replace the - '\n' character by 0, so that the previous part of the string is then - null terminated, and write it out using the astPutNextText method - (splitting the text up into lines no longer than "mxlen"). */ - c = text; - d = strchr( c, '\n' ); - while( d ) { - *d = 0; - OutputText( this, c, mxlen, status ); - c = d + 1; - d = strchr( c, '\n' ); - } - -/* Write out any text following the last '\n' character. */ - if( *c ) OutputText( this, c, mxlen, status ); - -/* Free the memory holding the text and in-memory representations of the AST - Object. */ - text = astFree( (void *) text ); - astXmlRemoveItem( this->container ); - this->container = astXmlAnnul( this->container ); - -#ifdef DEBUG -/* Report an error if there is a memory leak. */ - if( astXmlTrace(3) > nobj && astOK ) { - astError( AST__INTER, "astWriteEnd(XmlChan): %d XmlObjects " - "remain in existence - should be %d (internal AST " - "programming error).", status, astXmlTrace(3), nobj ); - } -#endif - - } - } - -/* Reset the current container element to be the parent found above. */ - if( !parent || astXmlCheckType( parent, AST__XMLELEM ) ) { - this->container = parent; - } else if( astOK ) { - astError( AST__INTER, "astWriteEnd(XmlChan): Cannot update " - "container: parent is not an XmlElement (internal " - "AST programming error)." , status); - } - } - -/* If an error has occurred, annul the container element in the XmlChan. */ - if( !astOK ) this->container = astXmlAnnulTree( this->container ); - -} - -static void WriteInt( AstChannel *this_channel, const char *name, int set, int helpful, - int value, const char *comment, int *status ) { -/* -* Name: -* WriteInt - -* Purpose: -* Write an integer value to a data sink. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void WriteInt( AstChannel *this, const char *name, int set, int helpful, -* int value, const char *comment, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected -* astWriteInt method inherited from the Channel class). - -* Description: -* This function writes a named integer value, representing the -* value of a class instance variable, to the data sink associated -* with a Channel. It is intended for use by class "Dump" functions -* when writing out class information which will subsequently be -* re-read. - -* Parameters: -* this -* Pointer to the Channel. -* name -* Pointer to a constant null-terminated string containing the -* name to be used to identify the value in the external -* representation. This will form the key for identifying it -* again when it is re-read. The name supplied should be unique -* within its class. -* -* Mixed case may be used and will be preserved in the external -* representation (where possible) for cosmetic effect. However, -* case is not significant when re-reading values. -* -* It is recommended that a maximum of 6 alphanumeric characters -* (starting with an alphabetic character) be used. This permits -* maximum flexibility in adapting to standard external data -* representations (e.g. FITS). -* set -* If this is zero, it indicates that the value being written is -* a default value (or can be re-generated from other values) so -* need not necessarily be written out. Such values will -* typically be included in the external representation with -* (e.g.) a comment character so that they are available to -* human readers but will be ignored when re-read. They may also -* be completely omitted in some circumstances. -* -* If "set" is non-zero, the value will always be explicitly -* included in the external representation so that it can be -* re-read. -* helpful -* This flag provides a hint about whether a value whose "set" -* flag is zero (above) should actually appear at all in the -* external representaton. -* -* If the external representation allows values to be "commented -* out" then, by default, values will be included in this form -* only if their "helpful" flag is non-zero. Otherwise, they -* will be omitted entirely. When possible, omitting the more -* obscure values associated with a class is recommended in -* order to improve readability. -* -* This default behaviour may be further modified if the -* Channel's Full attribute is set - either to permit all values -* to be shown, or to suppress non-essential information -* entirely. -* value -* The value to be written. -* comment -* Pointer to a constant null-terminated string containing a -* textual comment to be associated with the value. -* -* Note that this comment may not actually be used, depending on -* the nature of the Channel supplied and the setting of its -* Comment attribute. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Constants: */ -#define BUFF_LEN 50 /* Size of local formatting buffer */ - -/* Local Variables: */ - AstXmlChan *this; /* A pointer to the XmlChan structure. */ - AstXmlElement *elem; /* Pointer to new element */ - char buff[ BUFF_LEN + 1 ]; /* Local formatting buffer */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* If the object to be written is a component of a default AST object (i.e. - an object which is "not set"), then we do not write out this item. */ - if( this->objectset ) { - -/* Use the "set" and "helpful" flags, along with the Channel's - attributes to decide whether this value should actually be - written. */ - if( Use( this, set, helpful, status ) ) { - -/* Create a new XmlElement with a name of ATTR (and no namespace - prefix), and add it into the current container (i.e. parent) element. */ - elem = astXmlAddElement( this->container, ATTR, - astGetXmlPrefix( this ) ); - -/* Add a NAME attribute to this element containing the item name. */ - astXmlAddAttr( elem, NAME, name, NULL ); - -/* Format the value as a decimal string and add it to the element as the - VALUE attribute. */ - (void) sprintf( buff, "%d", value ); - astXmlAddAttr( elem, VALUE, buff, NULL ); - -/* If we are adding comments, and if a comment was supplied as a - parameter to this function, then store the commment as an attribute of - the element. */ - if( comment && *comment && astGetComment( this_channel ) ) { - astXmlAddAttr( elem, DESC, comment, NULL ); - } - -/* If the object has all default values, store a true value for the - DEFAULT attribute. */ - if( !set ) astXmlAddAttr( elem, DEFAULT, TRUE, NULL ); - -/* Initialise a flag to indicate that the next "IsA" item should be - written. */ - this->write_isa = 1; - } - } - -/* If an error has occurred, annul the container element in the XmlChan. */ - if( !astOK ) this->container = astXmlAnnulTree( this->container ); - -/* Undefine macros local to this function. */ -#undef BUFF_LEN -} - -static void WriteIsA( AstChannel *this_channel, const char *class, - const char *comment, int *status ) { -/* -* Name: -* WriteIsA - -* Purpose: -* Write an "IsA" data item to a data sink. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void WriteIsA( AstChannel *this, const char *class, -* const char *comment, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected -* astWriteIsA method inherited from the Channel class). - -* Description: -* This function writes an "IsA" data item to the data sink -* associated with a Channel. This item delimits the end of the -* data associated with the instance variables of a class, as part -* of an overall Object definition. - -* Parameters: -* this -* Pointer to the Channel. -* class -* Pointer to a constant null-terminated string containing the -* name of the class whose data are terminated by the "IsA" -* item. -* comment -* Pointer to a constant null-terminated string containing a -* textual comment to be associated with the "IsA" -* item. Normally, this will describe the purpose of the class -* whose data are being terminated. -* status -* Pointer to the inherited status variable. - -* Notes: -* - The comment supplied may not actually be used, depending on -* the nature of the Channel supplied. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* A pointer to the XmlChan structure. */ - AstXmlElement *elem; /* Pointer to new element */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* If the object to be written is a component of a default AST object (i.e. - an object which is "not set"), then we do not write out this item. */ - if( this->objectset ) { - -/* Output an "IsA" item only if there has been at least one item - written since the last "Begin" or "IsA" item, or if the Full - attribute for the Channel is greater than zero (requesting maximum - information). */ - if ( this->write_isa || astGetFull( this ) > 0 ) { - -/* Create a new XmlElement with a name of "_isa" (and no namespace prefix), - and add it into the current container (i.e. parent) element. */ - elem = astXmlAddElement( this->container, ISA, - astGetXmlPrefix( this ) ); - -/* Add a "class" attribute to this element containing the class name. */ - astXmlAddAttr( elem, "class", class, NULL ); - -/* If we are adding comments, and if a comment was supplied as a - parameter to this function, then store the commment as an attribute of - the element. This comment describes the class function as a whole, not - the specific usage of this instance of the class. */ - if( comment && *comment && astGetComment( this_channel ) ) { - astXmlAddAttr( elem, DESC, comment, NULL ); - } - } - } - -/* Initialise a flag to indicate that the next "IsA" item should not be - written. This flag will be changed if and when an item is added which - related to the class described by the "IsA" item. */ - this->write_isa = 0; - -/* If an error has occurred, annul the container element in the XmlChan. */ - if( !astOK ) this->container = astXmlAnnulTree( this->container ); -} - -static void WriteObject( AstChannel *this_channel, const char *name, - int set, int helpful, - AstObject *value, const char *comment, int *status ) { -/* -* Name: -* WriteObject - -* Purpose: -* Write an Object as a value to a data sink. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void WriteObject( AstChannel *this_channel, const char *name, -* int set, int helpful, -* AstObject *value, const char *comment, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected -* astWriteObject method inherited from the Channel class). - -* Description: -* This function writes an Object as a named value, representing -* the value of a class instance variable, to the data sink -* associated with an XmlChan. It is intended for use by class -* "Dump" functions when writing out class information which will -* subsequently be re-read. - -* Parameters: -* this -* Pointer to the XmlChan. -* name -* Pointer to a constant null-terminated string containing the -* name to be used to identify the value in the external -* representation. This will form the key for identifying it -* again when it is re-read. The name supplied should be unique -* within its class. -* -* Mixed case may be used and will be preserved in the external -* representation (where possible) for cosmetic effect. However, -* case is not significant when re-reading values. -* -* It is recommended that a maximum of 6 alphanumeric characters -* (starting with an alphabetic character) be used. This permits -* maximum flexibility in adapting to standard external data -* representations. -* set -* If this is zero, it indicates that the value being written is -* a default value (or can be re-generated from other values) so -* need not necessarily be written out. Such values will -* typically be included in the external representation with -* (e.g.) a comment character so that they are available to -* human readers but will be ignored when re-read. They may also -* be completely omitted in some circumstances. -* -* If "set" is non-zero, the value will always be explicitly -* included in the external representation so that it can be -* re-read. -* helpful -* This flag provides a hint about whether a value whose "set" -* flag is zero (above) should actually appear at all in the -* external representaton. -* -* If the external representation allows values to be "commented -* out" then, by default, values will be included in this form -* only if their "helpful" flag is non-zero. Otherwise, they -* will be omitted entirely. When possible, omitting the more -* obscure values associated with a class is recommended in -* order to improve readability. -* -* This default behaviour may be further modified if the -* Channel's Full attribute is set - either to permit all values -* to be shown, or to suppress non-essential information -* entirely. -* value -* A Pointer to the Object to be written. -* comment -* Pointer to a constant null-terminated string containing a -* textual comment to be associated with the value. -* -* Note that this comment may not actually be used, depending on -* the nature of the Channel supplied and the setting of its -* Comment attribute. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* A pointer to the XmlChan structure. */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* If the object to be written is a component of a default AST object (i.e. - an object which is "not set"), then we do not write out the object. */ - if( this->objectset ) { - -/* Use the "set" and "helpful" flags, along with the Channel's - attributes to decide whether this value should actually be - written. */ - if ( Use( this, set, helpful, status ) ) { - -/* Save the supplied name associated with the object being written so - that it is available for use within the following invocation of the - WriteBegin method. The name is stored within the XmlChan structure - (NULL is used to indicate "no name supplied"). */ - this->objectname = ( name && strlen( name ) ) ? name : NULL; - -/* Also save the supplied comment and a flag indicating if the object is - set. These will be used by the WriteBegin method. They are stored within - the XmlChan structure. */ - this->objectset = set; - this->objectcomment = comment; - -/* Write the object to the XmlChan. */ - (void) astWrite( this, value ); - -/* Nullify the components of the XmlChan set above. */ - this->objectname = NULL; - this->objectset = 1; - this->objectcomment = NULL; - -/* Initialise a flag to indicate that the next "IsA" item should be - written. */ - this->write_isa = 1; - } - } - -/* If an error has occurred, annul the container element in the XmlChan. */ - if( !astOK ) this->container = astXmlAnnulTree( this->container ); - -} - -static void WriteString( AstChannel *this_channel, const char *name, int set, - int helpful, const char *value, const char *comment, int *status ){ -/* -* Name: -* WriteString - -* Purpose: -* Write a string value to a data sink. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* void WriteString( AstChannel *this, const char *name, int set, int helpful, -* const char *value, const char *comment, int *status ) - -* Class Membership: -* XmlChan member function (over-rides the protected -* astWriteString method inherited from the Channel class). - -* Description: -* This function writes a named string value, representing the -* value of a class instance variable, to the data sink associated -* with a Channel. It is intended for use by class "Dump" functions -* when writing out class information which will subsequently be -* re-read. - -* Parameters: -* this -* Pointer to the Channel. -* name -* Pointer to a constant null-terminated string containing the -* name to be used to identify the value in the external -* representation. This will form the key for identifying it -* again when it is re-read. The name supplied should be unique -* within its class. -* -* Mixed case may be used and will be preserved in the external -* representation (where possible) for cosmetic effect. However, -* case is not significant when re-reading values. -* -* It is recommended that a maximum of 6 alphanumeric characters -* (starting with an alphabetic character) be used. This permits -* maximum flexibility in adapting to standard external data -* representations (e.g. FITS). -* set -* If this is zero, it indicates that the value being written is -* a default value (or can be re-generated from other values) so -* need not necessarily be written out. Such values will -* typically be included in the external representation with -* (e.g.) a comment character so that they are available to -* human readers but will be ignored when re-read. They may also -* be completely omitted in some circumstances. -* -* If "set" is non-zero, the value will always be explicitly -* included in the external representation so that it can be -* re-read. -* helpful -* This flag provides a hint about whether a value whose "set" -* flag is zero (above) should actually appear at all in the -* external representaton. -* -* If the external representation allows values to be "commented -* out" then, by default, values will be included in this form -* only if their "helpful" flag is non-zero. Otherwise, they -* will be omitted entirely. When possible, omitting the more -* obscure values associated with a class is recommended in -* order to improve readability. -* -* This default behaviour may be further modified if the -* Channel's Full attribute is set - either to permit all values -* to be shown, or to suppress non-essential information -* entirely. -* value -* Pointer to a constant null-terminated string containing the -* value to be written. -* comment -* Pointer to a constant null-terminated string containing a -* textual comment to be associated with the value. -* -* Note that this comment may not actually be used, depending on -* the nature of the Channel supplied and the setting of its -* Comment attribute. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* A pointer to the XmlChan structure. */ - AstXmlElement *elem; /* Pointer to new element */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_channel; - -/* If the object to be written is a component of a default AST object (i.e. - an object which is "not set"), then we do not write out this item. */ - if( this->objectset ) { - -/* Use the "set" and "helpful" flags, along with the Channel's - attributes to decide whether this value should actually be - written. */ - if( Use( this, set, helpful, status ) ) { - -/* Create a new XmlElement with a name of ATTR (and no namespace - prefix), and add it into the current container (i.e. parent) element. */ - elem = astXmlAddElement( this->container, ATTR, - astGetXmlPrefix( this ) ); - -/* Add a NAME attribute to this element containing the item name. */ - astXmlAddAttr( elem, NAME, name, NULL ); - -/* If we are using QUOTED format, add an attribute to indicate that this is a - string value (mainly included for compatibility with JNIAST). */ - if( astGetXmlFormat( this ) == QUOTED_FORMAT ) { - astXmlAddAttr( elem, QUOTED, TRUE, NULL ); - } - -/* Add it the value to the element as the VALUE attribute. */ - astXmlAddAttr( elem, VALUE, value, NULL ); - -/* If we are adding comments, and if a comment was supplied as a - parameter to this function, then store the commment as an attribute of - the element. */ - if( comment && *comment && astGetComment( this_channel ) ) { - astXmlAddAttr( elem, DESC, comment, NULL ); - } - -/* If the object has all default values, store a true value for the - DEFAULT attribute. */ - if( !set ) astXmlAddAttr( elem, DEFAULT, TRUE, NULL ); - -/* Initialise a flag to indicate that the next "IsA" item should be - written. */ - this->write_isa = 1; - } - } - -/* If an error has occurred, annul the container element in the XmlChan. */ - if( !astOK ) this->container = astXmlAnnulTree( this->container ); - -} - - -/* Functions which access class attributes. */ -/* ---------------------------------------- */ -/* Implement member functions to access the attributes associated with - this class using the macros defined for this purpose in the - "object.h" file. For a description of each attribute, see the class - interface (in the associated .h file). */ - -/* XmlFormat */ -/* ========= */ -/* -*att++ -* Name: -* XmlFormat - -* Purpose: -* System for formatting Objects as XML. - -* Type: -* Public attribute. - -* Synopsis: -* String. - -* Description: -* This attribute specifies the formatting system to use when AST -* Objects are written out as XML through an XmlChan. It -c affects the behaviour of the astWrite function when -f affects the behaviour of the AST_WRITE routine when -* they are used to transfer any AST Object to or from an external -* XML representation. -* -* The XmlChan class allows AST objects to be represented in the form -* of XML in several ways (conventions) and the XmlFormat attribute is -* used to specify which of these should be used. The formatting options -* available are outlined in the "Formats Available" section below. -* -* By default, an XmlChan will attempt to determine which format system -* is already in use, and will set the default XmlFormat value -* accordingly (so that subsequent I/O operations adopt the same -* conventions). It does this by looking for certain critical items -* which only occur in particular formats. For details of how this -* works, see the "Choice of Default Format" section below. If you wish -* to ensure that a particular format system is used, independently of -* any XML already read, you should set an explicit XmlFormat value -* yourself. -* -* Formats Available: -* The XmlFormat attribute can take any of the following (case -* insensitive) string values to select the corresponding formatting -* system: -* -* - "NATIVE": This is a direct conversion to XML of the heirarchical -* format used by a standard XML channel (and also by the NATIVE -* encoding of a FitsChan). -* -* - "QUOTED": This is the same as NATIVE format except that extra -* information is included which allows client code to convert the -* XML into a form which can be read by a standard AST Channel. This -* extra information indicates which AST attribute values should be -* enclosed in quotes before being passed to a Channel. -* -* - "IVOA": This is a format that uses an early draft of the STC-X schema -* developed by the International Virtual Observatory Alliance (IVOA - -* see "http://www.ivoa.net/") to describe coordinate systems, regions, -* mappings, etc. Support is limited to V1.20 described at -* "http://www.ivoa.net/Documents/WD/STC/STC-20050225.html". Since the -* version of STC-X finally adopted by the IVOA differs in several -* significant respects from V1.20, this format is now mainly of -* historical interest. Note, the alternative "STC-S" format (a -* simpler non-XML encoding of the STC metadata) is supported by the -* StcsChan class. - -* Choice of Default Format; -* If the XmlFormat attribute of an XmlChan is not set, the default -* value it takes is determined by the presence of certain critical -* items within the document most recently read using -c astRead. -f AST_READ. -* The sequence of decision used to arrive at the default value is as -* follows: -* -* - If the previous document read contained any elements in any of the STC -* namespaces ("urn:nvo-stc", "urn:nvo-coords" or "urn:nvo-region"), then -* the default value is IVOA. -* - If the previous document read contained any elements in the AST -* namespace which had an associated XML attribute called "quoted", then -* the default value is QUOTED. -* - Otherwise, if none of these conditions is met (as would be the -* case if no document had yet been read), then NATIVE format is -* used. -* -* Setting an explicit value for the XmlFormat attribute always -* over-rides this default behaviour. - -* The IVOA Format: -* The IVOA support caters only for certain parts of V1.20 of the -* draft Space-Time Coordinate (STC) schema (see -* http://www.ivoa.net/Documents/WD/STC/STC-20050225.html). Note, this -* draft has now been superceded by an officially adopted version that -* differs in several significant respects from V1.20. Consequently, -* the "IVOA" XmlChan format is of historical interest only. -* -* The following points should be noted when using an XmlChan to read -* or write STC information (note, this list is currently incomplete): -* -* - Objects can currently only be read using this format, not written. -* - The AST object generated by reading an <STCMetadata> element will -* be an instance of one of the AST "Stc" classes: StcResourceProfile, -* StcSearchLocation, StcCatalogEntryLocation, StcObsDataLocation. -* - When reading an <STCMetadata> element, the axes in the returned -* AST Object will be in the order space, time, spectral, redshift, -* irrespective of the order in which the axes occur in the <STCMetadata> -* element. If the supplied <STCMetadata> element does not contain all of -* these axes, the returned AST Object will also omit them, but the -* ordering of those axes which are present will be as stated above. If -* the spatial frame represents a celestial coordinate system the -* spatial axes will be in the order (longitude, latitude). -* - Until such time as the AST TimeFrame is complete, a simple -* 1-dimensional Frame (with Domain set to TIME) will be used to -* represent the STC <TimeFrame> element. Consequently, most of the -* information within a <TimeFrame> element is currently ignored. -* - <SpaceFrame> elements can only be read if they describe a celestial -* longitude and latitude axes supported by the AST SkyFrame class. The -* space axes will be returned in the order (longitude, latitude). -* - Velocities associated with SpaceFrames cannot be read. -* - Any <GenericCoordFrame> elements within an <AstroCoordSystem> element -* are currently ignored. -* - Any second or subsequent <AstroCoordSystem> found within an -* STCMetaData element is ignored. -* - Any second or subsequent <AstroCoordArea> found within an -* STCMetaData element is ignored. -* - Any <OffsetCenter> found within a <SpaceFrame> is ignored. -* - Any CoordFlavor element found within a <SpaceFrame> is ignored. -* - <SpaceFrame> elements can only be read if they refer to -* one of the following space reference frames: ICRS, GALACTIC_II, -* SUPER_GALACTIC, HEE, FK4, FK5, ECLIPTIC. -* - <SpaceFrame> elements can only be read if the reference -* position is TOPOCENTER. Also, any planetary ephemeris is ignored. -* - Regions: there is currently no support for STC regions of type -* Sector, ConvexHull or SkyIndex. -* - The AST Region read from a CoordInterval element is considered to -* be open if either the lo_include or the hi_include attribute is -* set to false. -* - <RegionFile> elements are not supported. -* - Vertices within <Polygon> elements are always considered to be -* joined using great circles (that is, <SmallCircle> elements are -* ignored). - -* Applicability: -* XmlChan -* All XmlChans have this attribute. -*att-- -*/ -astMAKE_CLEAR(XmlChan,XmlFormat,xmlformat,UNKNOWN_FORMAT) -astMAKE_SET(XmlChan,XmlFormat,int,xmlformat,( - value == NATIVE_FORMAT || - value == IVOA_FORMAT || - value == QUOTED_FORMAT ? value : - (astError( AST__BADAT, "astSetXmlFormat: Unknown XML formatting system %d " - "supplied.", status, value ), UNKNOWN_FORMAT ))) -astMAKE_TEST(XmlChan,XmlFormat,( this->xmlformat != UNKNOWN_FORMAT )) -astMAKE_GET(XmlChan,XmlFormat,int,0,(this->xmlformat == UNKNOWN_FORMAT ? - this->formatdef : this->xmlformat)) - -/* -*att++ -* Name: -* XmlLength - -* Purpose: -* Controls output buffer length. - -* Type: -* Public attribute. - -* Synopsis: -* Integer. - -* Description: -* This attribute specifies the maximum length to use when writing out -* text through the sink function supplied when the XmlChan was created. -* -* The number of characters in each string written out through the sink -* function will not be greater than the value of this attribute (but -* may be less). A value of zero (the default) means there is no limit - -* each string can be of any length. -* -f Note, the default value of zero is unlikely to be appropriate when -f an XmlChan is used within Fortran code. In this case, XmlLength -f should usually be set to the size of the CHARACTER variable used to -f receive the text returned by AST_GETLINE within the sink function. -f This avoids the possibility of long lines being truncated invisibly -f within AST_GETLINE. - -* Applicability: -* XmlChan -* All XmlChans have this attribute. -*att-- -*/ -astMAKE_CLEAR(XmlChan,XmlLength,xmllength,-INT_MAX) -astMAKE_GET(XmlChan,XmlLength,int,0,( ( this->xmllength != -INT_MAX ) ? this->xmllength : 0 )) -astMAKE_SET(XmlChan,XmlLength,int,xmllength,(value<0?0:value)) -astMAKE_TEST(XmlChan,XmlLength,( this->xmllength != -INT_MAX )) - -/* -*att++ -* Name: -* XmlPrefix - -* Purpose: -* The namespace prefix to use when writing. - -* Type: -* Public attribute. - -* Synopsis: -* String. - -* Description: -* This attribute is a string which is to be used as the namespace -* prefix for all XML elements created as a result of writing an AST -* Object out through an XmlChan. The URI associated with the namespace -* prefix is given by the symbolic constant AST__XMLNS defined in -f AST_PAR. -c ast.h. -* A definition of the namespace prefix is included in each top-level -* element produced by the XmlChan. -* -* The default value is a blank string which causes no prefix to be -* used. In this case each top-level element will set the default -* namespace to be the value of AST__XMLNS. - -* Applicability: -* Object -* All Objects have this attribute. - -*att-- -*/ -astMAKE_CLEAR(XmlChan,XmlPrefix,xmlprefix,astFree( this->xmlprefix )) -astMAKE_GET(XmlChan,XmlPrefix,const char *,NULL,( this->xmlprefix ? this->xmlprefix : "" )) -astMAKE_SET(XmlChan,XmlPrefix,const char *,xmlprefix,astStore( this->xmlprefix, value, - strlen( value ) + (size_t) 1 )) -astMAKE_TEST(XmlChan,XmlPrefix,( this->xmlprefix != NULL )) - - -/* Copy constructor. */ -/* ----------------- */ -static void Copy( const AstObject *objin, AstObject *objout, int *status ) { -/* -* Name: -* Copy - -* Purpose: -* Copy constructor for XmlChan objects. - -* Type: -* Private function. - -* Synopsis: -* void Copy( const AstObject *objin, AstObject *objout, int *status ) - -* Description: -* This function implements the copy constructor for XmlChan objects. - -* Parameters: -* objin -* Pointer to the object to be copied. -* objout -* Pointer to the object being constructed. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This constructor makes a deep copy. -*/ - -/* Local Variables: */ - AstXmlChan *in; /* Pointer to input XmlChan */ - AstXmlChan *out; /* Pointer to output XmlChan */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain pointers to the input and output XmlChans. */ - in = (AstXmlChan *) objin; - out = (AstXmlChan *) objout; - -/* Clear the non-persistent values in the new XmlChan. */ - out->objectname = NULL; /* Name of object being written */ - out->objectset = 1; /* Is object being written set?*/ - out->objectcomment = NULL;/* Comment for object class being written */ - out->readcontext = NULL; /* XmlElement giving context for current read */ - out->container = NULL; /* XmlElement to which content will be added */ - out->write_isa = 0; /* Write out the next "IsA" item? */ - out->reset_source = 1; /* A new line should be read from the source */ - out->isa_class = NULL; /* Class being loaded */ - -/* Store a copy of the prefix string.*/ - if ( in->xmlprefix ) out->xmlprefix = astStore( NULL, in->xmlprefix, - strlen( in->xmlprefix ) + (size_t) 1 ); -} - - -/* Destructor. */ -/* ----------- */ -static void Delete( AstObject *obj, int *status ) { -/* -* Name: -* Delete - -* Purpose: -* Destructor for XmlChan objects. - -* Type: -* Private function. - -* Synopsis: -* void Delete( AstObject *obj, int *status ) - -* Description: -* This function implements the destructor for XmlChan objects. - -* Parameters: -* obj -* Pointer to the object to be deleted. -* status -* Pointer to the inherited status variable. - -* Notes: -* This function attempts to execute even if the global error status is -* set. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to XmlChan */ - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) obj; - -/* Free any unread part of the document. */ - this->readcontext = astXmlAnnul( this->readcontext ); - -/* Free the memory used for the XmlPrefix string if necessary. */ - this->xmlprefix = astFree( this->xmlprefix ); - -/* Free any memory used to store text read from the source */ - GetNextChar( NULL, status ); - -} - -/* Dump function. */ -/* -------------- */ -static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { -/* -* Name: -* Dump - -* Purpose: -* Dump function for XmlChan objects. - -* Type: -* Private function. - -* Synopsis: -* void Dump( AstObject *this, AstChannel *channel, int *status ) - -* Description: -* This function implements the Dump function which writes out data -* for the XmlChan class to an output Channel. - -* Parameters: -* this -* Pointer to the XmlChan whose data are being written. -* channel -* Pointer to the Channel to which the data are being written. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstXmlChan *this; /* Pointer to the XmlChan structure */ - const char *sval; /* String attribute value */ - int ival; /* Integer attribute value */ - int set; /* Has the attribute got a set value? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the XmlChan structure. */ - this = (AstXmlChan *) this_object; - -/* Write out values representing the instance variables for the - XmlChan class. Accompany these with appropriate comment strings, - possibly depending on the values being written.*/ - - -/* Now do instance variables which are not attributes. */ -/* =================================================== */ - -/* XmlLength */ -/* --------- */ - set = TestXmlLength( this, status ); - ival = set ? GetXmlLength( this, status ) : astGetXmlLength( this ); - astWriteInt( channel, "XmlLen", set, 0, ival, "XML buffer length" ); - -/* XmlFormat. */ -/* --------- */ - set = TestXmlFormat( this, status ); - ival = set ? GetXmlFormat( this, status ) : astGetXmlFormat( this ); - if( ival > UNKNOWN_FORMAT && ival <= MAX_FORMAT ) { - astWriteString( channel, "XmlFmt", set, 1, xformat[ival], "Formatting system" ); - } else { - astWriteString( channel, "XmlFmt", set, 1, UNKNOWN_STRING, "Formatting system" ); - } - -/* XmlPrefix */ -/* --------- */ - set = TestXmlPrefix( this, status ); - sval = set ? GetXmlPrefix( this, status ) : astGetXmlPrefix( this ); - astWriteString( channel, "XmlPrf", set, 1, sval, - "Namespace prefix" ); -} - - -/* Standard class functions. */ -/* ========================= */ -/* Implement the astIsAXmlChan and astCheckXmlChan functions using the macros - defined for this purpose in the "object.h" header file. */ -astMAKE_ISA(XmlChan,Channel) -astMAKE_CHECK(XmlChan) - -AstXmlChan *astXmlChan_( const char *(* source)( void ), - void (* sink)( const char * ), - const char *options, int *status, ...) { -/* -*++ -* Name: -c astXmlChan -f AST_XMLCHAN - -* Purpose: -* Create an XmlChan. - -* Type: -* Public function. - -* Synopsis: -c #include "xmlchan.h" -c AstXmlChan *astXmlChan( const char *(* source)( void ), -c void (* sink)( const char * ), -c const char *options, ... ) -f RESULT = AST_XMLCHAN( SOURCE, SINK, OPTIONS, STATUS ) - -* Class Membership: -* XmlChan constructor. - -* Description: -* This function creates a new XmlChan and optionally initialises -* its attributes. -* -* A XmlChan is a specialised form of Channel which supports XML I/O -* operations. Writing an Object to an XmlChan (using -c astWrite) will, if the Object is suitable, generate an -f AST_WRITE) will, if the Object is suitable, generate an -* XML description of that Object, and reading from an XmlChan will -* create a new Object from its XML description. -* -* Normally, when you use an XmlChan, you should provide "source" -c and "sink" functions which connect it to an external data store -f and "sink" routines which connect it to an external data store -* by reading and writing the resulting XML text. By default, however, -* an XmlChan will read from standard input and write to standard -* output. -* -* Alternatively, an XmlChan can be told to read or write from -* specific text files using the SinkFile and SourceFile attributes, -* in which case no sink or source function need be supplied. - -* Parameters: -c source -f SOURCE = SUBROUTINE (Given) -c Pointer to a source function that takes no arguments and -c returns a pointer to a null-terminated string. If no value -c has been set for the SourceFile attribute, this function -c will be used by the XmlChan to obtain lines of input text. On -c each invocation, it should return a pointer to the next input -c line read from some external data store, and a NULL pointer -c when there are no more lines to read. -c -c If "source" is NULL and no value has been set for the SourceFile -c attribute, the XmlChan will read from standard input instead. -f A source routine, which is a subroutine which takes a single -f integer error status argument. If no value has been set -f for the SourceFile attribute, this routine will be used by -f the XmlChan to obtain lines of input text. On each -f invocation, it should read the next input line from some -f external data store, and then return the resulting text to -f the AST library by calling AST_PUTLINE. It should supply a -f negative line length when there are no more lines to read. -f If an error occurs, it should set its own error status -f argument to an error value before returning. -f -f If the null routine AST_NULL is suppied as the SOURCE value, -f and no value has been set for the SourceFile attribute, -f the XmlChan will read from standard input instead. -c sink -f SINK = SUBROUTINE (Given) -c Pointer to a sink function that takes a pointer to a -c null-terminated string as an argument and returns void. -c If no value has been set for the SinkFile attribute, this -c function will be used by the XmlChan to deliver lines of -c output text. On each invocation, it should deliver the -c contents of the string supplied to some external data store. -c -c If "sink" is NULL, and no value has been set for the SinkFile -c attribute, the XmlChan will write to standard output instead. -f A sink routine, which is a subroutine which takes a single -f integer error status argument. If no value has been set -f for the SinkFile attribute, this routine will be used by -f the XmlChan to deliver lines of output text. On each -f invocation, it should obtain the next output line from the -f AST library by calling AST_GETLINE, and then deliver the -f resulting text to some external data store. If an error -f occurs, it should set its own error status argument to an -f error value before returning. -f -f If the null routine AST_NULL is suppied as the SINK value, -f and no value has been set for the SinkFile attribute, -f the XmlChan will write to standard output instead. -c options -f OPTIONS = CHARACTER * ( * ) (Given) -c Pointer to a null-terminated string containing an optional -c comma-separated list of attribute assignments to be used for -c initialising the new XmlChan. The syntax used is identical to -c that for the astSet function and may include "printf" format -c specifiers identified by "%" symbols in the normal way. -f A character string containing an optional comma-separated -f list of attribute assignments to be used for initialising the -f new XmlChan. The syntax used is identical to that for the -f AST_SET routine. -c ... -c If the "options" string contains "%" format specifiers, then -c an optional list of additional arguments may follow it in -c order to supply values to be substituted for these -c specifiers. The rules for supplying these are identical to -c those for the astSet function (and for the C "printf" -c function). -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astXmlChan() -f AST_XMLCHAN = INTEGER -* A pointer to the new XmlChan. - -* Notes: -f - The names of the routines supplied for the SOURCE and SINK -f arguments should appear in EXTERNAL statements in the Fortran -f routine which invokes AST_XMLCHAN. However, this is not generally -f necessary for the null routine AST_NULL (so long as the AST_PAR -f include file has been used). -* - If the external data source or sink uses a character encoding -* other than ASCII, the supplied source and sink functions should -* translate between the external character encoding and the internal -* ASCII encoding used by AST. -* - A null Object pointer (AST__NULL) will be returned if this -* function is invoked with the AST error status set, or if it -* should fail for any reason. -f - Note that the null routine AST_NULL (one underscore) is -f different to AST__NULL (two underscores), which is the null Object -f pointer. -*-- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstXmlChan *new; /* Pointer to new XmlChan */ - va_list args; /* Variable argument list */ - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* Initialise the XmlChan, allocating memory and initialising the - virtual function table as well if necessary. This interface is for - use by other C functions within AST, and uses the standard "wrapper" - functions included in this class. */ - new = astInitXmlChan( NULL, sizeof( AstXmlChan ), !class_init, - &class_vtab, "XmlChan", source, SourceWrap, - sink, SinkWrap ); - -/* If successful, note that the virtual function table has been - initialised. */ - if ( astOK ) { - class_init = 1; - -/* Obtain the variable argument list and pass it along with the - options string to the astVSet method to initialise the new - XmlChan's attributes. */ - va_start( args, status ); - astVSet( new, options, NULL, args ); - va_end( args ); - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return a pointer to the new XmlChan. */ - return new; -} - -AstXmlChan *astXmlChanId_( const char *(* source)( void ), - void (* sink)( const char * ), - const char *options, ... ) { -/* -* Name: -* astXmlChanId_ - -* Purpose: -* Create an XmlChan. - -* Type: -* Private function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlChan *astXmlChanId_( const char *(* source)( void ), -* void (* sink)( const char * ), -* const char *options, ... ) - -* Class Membership: -* XmlChan constructor. - -* Description: -* This function implements the external (public) C interface to the -* astXmlChan constructor function. Another function (astXmlChanForId) -* should be called to create an XmlChan for use within other languages. -* Both functions return an ID value (instead of a true C pointer) to -* external users, and must be provided because astXmlChan_ has a variable -* argument list which cannot be encapsulated in a macro (where this conversion would otherwise -* occur). -* -* The variable argument list also prevents this function from -* invoking astXmlChan_ directly, so it must be a re-implementation -* of it in all respects, except for the final conversion of the -* result to an ID value. - -* Parameters: -* As for astXmlChan_. - -* Returned Value: -* The ID value associated with the new XmlChan. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstXmlChan *new; /* Pointer to new XmlChan */ - va_list args; /* Variable argument list */ - - int *status; /* Pointer to inherited status value */ - -/* Get a pointer to the inherited status value. */ - status = astGetStatusPtr; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* Initialise the XmlChan, allocating memory and initialising the - virtual function table as well if necessary. This interface is for - use by external C functions and uses the standard "wrapper" - functions included in this class. */ - new = astInitXmlChan( NULL, sizeof( AstXmlChan ), !class_init, - &class_vtab, "XmlChan", source, SourceWrap, - sink, SinkWrap ); - -/* If successful, note that the virtual function table has been - initialised. */ - if ( astOK ) { - class_init = 1; - -/* Obtain the variable argument list and pass it along with the - options string to the astVSet method to initialise the new - XmlChan's attributes. */ - va_start( args, options ); - astVSet( new, options, NULL, args ); - va_end( args ); - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return an ID value for the new XmlChan. */ - return astMakeId( new ); -} - -AstXmlChan *astXmlChanForId_( const char *(* source)( void ), - char *(* source_wrap)( const char *(*)( void ), int * ), - void (* sink)( const char * ), - void (* sink_wrap)( void (*)( const char * ), - const char *, int * ), - const char *options, ... ) { -/* -*+ -* Name: -* astXmlChanFor - -* Purpose: -* Initialise an XmlChan from a foreign language interface. - -* Type: -* Public function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlChan *astXmlChanFor( const char *(* source)( void ), -* char *(* source_wrap)( const char *(*) -* ( void ), int * ), -* void (* sink)( const char * ), -* void (* sink_wrap)( void (*)( const char * ), -* const char *, int * ), -* const char *options, ... ) - -* Class Membership: -* XmlChan constructor. - -* Description: -* This function creates a new XmlChan from a foreign language -* interface and optionally initialises its attributes. -* -* A XmlChan implements low-level XML input/output for the AST library. -* Writing an Object to an XmlChan (using astWrite) will generate a -* XML representation of that Object, and reading from a -* XmlChan (using astRead) will create a new Object from its -* XML representation. -* -* Normally, when you use an XmlChan, you should provide "source" -* and "sink" functions which connect it to an external data store -* by reading and writing the resulting text. This function also -* requires you to provide "wrapper" functions which will invoke -* the source and sink functions. By default, however, an XmlChan -* will read from standard input and write to standard output. - -* Parameters: -* source -* Pointer to a "source" function which will be used to obtain -* lines of input text. Generally, this will be obtained by -* casting a pointer to a source function which is compatible -* with the "source_wrap" wrapper function (below). The pointer -* should later be cast back to its original type by the -* "source_wrap" function before the function is invoked. -* -* If "source" is NULL, the XmlChan will read from standard -* input instead. -* source_wrap -* Pointer to a function which can be used to invoke the -* "source" function supplied (above). This wrapper function is -* necessary in order to hide variations in the nature of the -* source function, such as may arise when it is supplied by a -* foreign (non-C) language interface. -* -* The single parameter of the "source_wrap" function is a -* pointer to the "source" function, and it should cast this -* function pointer (as necessary) and invoke the function with -* appropriate arguments to obtain the next line of input -* text. The "source_wrap" function should then return a pointer -* to a dynamically allocated, null terminated string containing -* the text that was read. The string will be freed (using -* astFree) when no longer required and the "source_wrap" -* function need not concern itself with this. A NULL pointer -* should be returned if there is no more input to read. -* -* If "source_wrap" is NULL, the XmlChan will read from standard -* input instead. -* sink -* Pointer to a "sink" function which will be used to deliver -* lines of output text. Generally, this will be obtained by -* casting a pointer to a sink function which is compatible with -* the "sink_wrap" wrapper function (below). The pointer should -* later be cast back to its original type by the "sink_wrap" -* function before the function is invoked. -* -* If "sink" is NULL, the XmlChan will write to standard output -* instead. -* sink_wrap -* Pointer to a function which can be used to invoke the "sink" -* function supplied (above). This wrapper function is necessary -* in order to hide variations in the nature of the sink -* function, such as may arise when it is supplied by a foreign -* (non-C) language interface. -* -* The first parameter of the "sink_wrap" function is a pointer -* to the "sink" function, and the second parameter is a pointer -* to a const, null-terminated character string containing the -* text to be written. The "sink_wrap" function should cast the -* "sink" function pointer (as necessary) and invoke the -* function with appropriate arguments to deliver the line of -* output text. The "sink_wrap" function then returns void. -* -* If "sink_wrap" is NULL, the Channel will write to standard -* output instead. -* options -* Pointer to a null-terminated string containing an optional -* comma-separated list of attribute assignments to be used for -* initialising the new XmlChan. The syntax used is identical to -* that for the astSet function and may include "printf" format -* specifiers identified by "%" symbols in the normal way. -* ... -* If the "options" string contains "%" format specifiers, then -* an optional list of additional arguments may follow it in -* order to supply values to be substituted for these -* specifiers. The rules for supplying these are identical to -* those for the astSet function (and for the C "printf" -* function). - -* Returned Value: -* astXmlChanFor() -* A pointer to the new XmlChan. - -* Notes: -* - A null Object pointer (AST__NULL) will be returned if this -* function is invoked with the global error status set, or if it -* should fail for any reason. -* - This function is only available through the public interface -* to the XmlChan class (not the protected interface) and is -* intended solely for use in implementing foreign language -* interfaces to this class. -*- - -* Implememtation Notes: -* - This function behaves exactly like astXmlChanId_, in that it -* returns ID values and not true C pointers, but it has two -* additional arguments. These are pointers to the "wrapper -* functions" which are needed to accommodate foreign language -* interfaces. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstXmlChan *new; /* Pointer to new XmlChan */ - va_list args; /* Variable argument list */ - int *status; /* Pointer to inherited status value */ - -/* Get a pointer to the inherited status value. */ - status = astGetStatusPtr; - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Initialise the XmlChan, allocating memory and initialising the - virtual function table as well if necessary. */ - new = astInitXmlChan( NULL, sizeof( AstXmlChan ), !class_init, - &class_vtab, "XmlChan", source, source_wrap, - sink, sink_wrap ); - -/* If successful, note that the virtual function table has been - initialised. */ - if ( astOK ) { - class_init = 1; - -/* Obtain the variable argument list and pass it along with the - options string to the astVSet method to initialise the new - XmlChan's attributes. */ - va_start( args, options ); - astVSet( new, options, NULL, args ); - va_end( args ); - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return an ID value for the new XmlChan. */ - return astMakeId( new ); -} - -AstXmlChan *astInitXmlChan_( void *mem, size_t size, int init, - AstXmlChanVtab *vtab, const char *name, - const char *(* source)( void ), - char *(* source_wrap)( const char *(*)( void ), int * ), - void (* sink)( const char * ), - void (* sink_wrap)( void (*)( const char * ), - const char *, int * ), int *status ) { -/* -*+ -* Name: -* astInitXmlChan - -* Purpose: -* Initialise an XmlChan. - -* Type: -* Protected function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlChan *astInitXmlChan( void *mem, size_t size, int init, -* AstXmlChanVtab *vtab, const char *name, -* const char *(* source)( void ), -* char *(* source_wrap)( const char *(*)( void ), int * ), -* void (* sink)( const char * ), -* void (* sink_wrap)( void (*)( const char * ), -* const char *, int * ) ) - -* Class Membership: -* XmlChan initialiser. - -* Description: -* This function is provided for use by class implementations to -* initialise a new XmlChan object. It allocates memory (if -* necessary) to accommodate the XmlChan plus any additional data -* associated with the derived class. It then initialises a -* XmlChan structure at the start of this memory. If the "init" -* flag is set, it also initialises the contents of a virtual -* function table for an XmlChan at the start of the memory passed -* via the "vtab" parameter. - -* Parameters: -* mem -* A pointer to the memory in which the XmlChan is to be -* initialised. This must be of sufficient size to accommodate -* the XmlChan data (sizeof(XmlChan)) plus any data used by the -* derived class. If a value of NULL is given, this function -* will allocate the memory itself using the "size" parameter to -* determine its size. -* size -* The amount of memory used by the XmlChan (plus derived class -* data). This will be used to allocate memory if a value of -* NULL is given for the "mem" parameter. This value is also -* stored in the XmlChan structure, so a valid value must be -* supplied even if not required for allocating memory. -* init -* A boolean flag indicating if the XmlChan's virtual function -* table is to be initialised. If this value is non-zero, the -* virtual function table will be initialised by this function. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new XmlChan. -* name -* Pointer to a constant null-terminated character string which -* contains the name of the class to which the new object -* belongs (it is this pointer value that will subsequently be -* returned by the astGetClass method). -* source -* Pointer to a "source" function which will be used to obtain -* lines of text. Generally, this will be obtained by -* casting a pointer to a source function which is compatible -* with the "source_wrap" wrapper function (below). The pointer -* should later be cast back to its original type by the -* "source_wrap" function before the function is invoked. -* -* If "source" is NULL, the Channel will read from standard -* input instead. -* source_wrap -* Pointer to a function which can be used to invoke the -* "source" function supplied (above). This wrapper function is -* necessary in order to hide variations in the nature of the -* source function, such as may arise when it is supplied by a -* foreign (non-C) language interface. -* -* The single parameter of the "source_wrap" function is a -* pointer to the "source" function, and it should cast this -* function pointer (as necessary) and invoke the function with -* appropriate arguments to obtain the next line of input -* text. The "source_wrap" function should then return a pointer -* to a dynamically allocated, null terminated string containing -* the text that was read. The string will be freed (using -* astFree) when no longer required and the "source_wrap" -* function need not concern itself with this. A NULL pointer -* should be returned if there is no more input to read. -* -* If "source_wrap" is NULL, the Channel will read from standard -* input instead. -* sink -* Pointer to a "sink" function which will be used to deliver -* lines of text. Generally, this will be obtained by -* casting a pointer to a sink function which is compatible with -* the "sink_wrap" wrapper function (below). The pointer should -* later be cast back to its original type by the "sink_wrap" -* function before the function is invoked. -* -* If "sink" is NULL, the contents of the XmlChan will not be -* written out before being deleted. -* sink_wrap -* Pointer to a function which can be used to invoke the "sink" -* function supplied (above). This wrapper function is necessary -* in order to hide variations in the nature of the sink -* function, such as may arise when it is supplied by a foreign -* (non-C) language interface. -* -* The first parameter of the "sink_wrap" function is a pointer -* to the "sink" function, and the second parameter is a pointer -* to a const, null-terminated character string containing the -* text to be written. The "sink_wrap" function should cast the -* "sink" function pointer (as necessary) and invoke the -* function with appropriate arguments to deliver the line of -* output text. The "sink_wrap" function then returns void. -* -* If "sink_wrap" is NULL, the Channel will write to standard -* output instead. - -* Returned Value: -* A pointer to the new XmlChan. - -* Notes: -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - AstXmlChan *new; /* Pointer to new XmlChan */ - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* If necessary, initialise the virtual function table. */ - if ( init ) astInitXmlChanVtab( vtab, name ); - -/* Initialise a Channel structure (the parent class) as the first - component within the XmlChan structure, allocating memory if - necessary. */ - new = (AstXmlChan *) astInitChannel( mem, size, 0, - (AstChannelVtab *) vtab, name, - source, source_wrap, sink, - sink_wrap ); - - if ( astOK ) { - -/* Initialise the XmlChan data. */ -/* ---------------------------- */ - new->objectname = NULL; /* Name of object being written */ - new->objectset = 1; /* Is object being written set?*/ - new->objectcomment = NULL;/* Comment for object class being written */ - new->container = NULL; /* XmlElement to which content will be added */ - new->readcontext = NULL; /* XmlElement giving context for current read */ - new->write_isa = 0; /* Write out the next "IsA" item? */ - new->xmllength = -INT_MAX;/* Buffer length */ - new->xmlprefix = NULL; /* Xml prefix */ - new->xmlformat = UNKNOWN_FORMAT; /* Xml format */ - new->formatdef = NATIVE_FORMAT; /* Default Xml format */ - new->reset_source = 1; /* A new line should be read from the source */ - new->isa_class = NULL; /* Class being loaded */ - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return a pointer to the new object. */ - return new; -} - -AstXmlChan *astLoadXmlChan_( void *mem, size_t size, - AstXmlChanVtab *vtab, const char *name, - AstChannel *channel, int *status ) { -/* -*+ -* Name: -* astLoadXmlChan - -* Purpose: -* Load an XmlChan. - -* Type: -* Protected function. - -* Synopsis: -* #include "xmlchan.h" -* AstXmlChan *astLoadXmlChan( void *mem, size_t size, -* AstXmlChanVtab *vtab, const char *name, -* AstChannel *channel ) - -* Class Membership: -* XmlChan loader. - -* Description: -* This function is provided to load a new XmlChan using data read -* from a Channel. It first loads the data used by the parent class -* (which allocates memory if necessary) and then initialises a -* XmlChan structure in this memory, using data read from the input -* Channel. -* -* If the "init" flag is set, it also initialises the contents of a -* virtual function table for an XmlChan at the start of the memory -* passed via the "vtab" parameter. - - -* Parameters: -* mem -* A pointer to the memory into which the XmlChan is to be -* loaded. This must be of sufficient size to accommodate the -* XmlChan data (sizeof(XmlChan)) plus any data used by derived -* classes. If a value of NULL is given, this function will -* allocate the memory itself using the "size" parameter to -* determine its size. -* size -* The amount of memory used by the XmlChan (plus derived class -* data). This will be used to allocate memory if a value of -* NULL is given for the "mem" parameter. This value is also -* stored in the XmlChan structure, so a valid value must be -* supplied even if not required for allocating memory. -* -* If the "vtab" parameter is NULL, the "size" value is ignored -* and sizeof(AstXmlChan) is used instead. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new XmlChan. If this is NULL, a pointer -* to the (static) virtual function table for the XmlChan class -* is used instead. -* name -* Pointer to a constant null-terminated character string which -* contains the name of the class to which the new object -* belongs (it is this pointer value that will subsequently be -* returned by the astGetClass method). -* -* If the "vtab" parameter is NULL, the "name" value is ignored -* and a pointer to the string "XmlChan" is used instead. - -* Returned Value: -* A pointer to the new XmlChan. - -* Notes: -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstXmlChan *new; /* Pointer to the new XmlChan */ - char *text; /* Textual version of integer value */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if( !astOK ) return new; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(channel); - -/* If a NULL virtual function table has been supplied, then this is - the first loader to be invoked for this XmlChan. In this case the - XmlChan belongs to this class, so supply appropriate values to be - passed to the parent class loader (and its parent, etc.). */ - if ( !vtab ) { - size = sizeof( AstXmlChan ); - vtab = &class_vtab; - name = "XmlChan"; - -/* If required, initialise the virtual function table for this class. */ - if ( !class_init ) { - astInitXmlChanVtab( vtab, name ); - class_init = 1; - } - } - -/* Invoke the parent class loader to load data for all the ancestral - classes of the current one, returning a pointer to the resulting - partly-built XmlChan. */ - new = astLoadChannel( mem, size, (AstChannelVtab *) vtab, name, - channel ); - - if ( astOK ) { - -/* Read input data. */ -/* ================ */ -/* Request the input Channel to read all the input data appropriate to - this class into the internal "values list". */ - astReadClassData( channel, "XmlChan" ); - -/* Now read each individual data item from this list and use it to - initialise the appropriate instance variable(s) for this class. */ - -/* Ensure other items in the XmlChan structure are initialised properly. */ - new->objectname = NULL; /* Name of object being written */ - new->objectset = 1; /* Is object being written set?*/ - new->objectcomment = NULL;/* Comment for object class being written */ - new->container = NULL; /* XmlElement to which content will be added */ - new->readcontext = NULL; /* XmlElement giving context for current read */ - new->write_isa = 0; /* Write out the next "IsA" item? */ - new->xmllength = -INT_MAX;/* Buffer length */ - new->xmlprefix = NULL; /* Xml prefix */ - new->reset_source = 1; /* A new line should be read from the source */ - new->isa_class = NULL; /* Class being loaded */ - new->formatdef = NATIVE_FORMAT; /* Default Xml format */ - -/* Now restore presistent values. */ - -/* XmlLength */ -/* --------- */ - new->xmllength = astReadInt( channel, "xmllen", -INT_MAX ); - -/* XmlPrefix */ -/* --------- */ - new->xmlprefix = astReadString( channel, "xmlprf", NULL ); - -/* XmlFormat. */ -/* --------- */ - text = astReadString( channel, "xmlfmt", UNKNOWN_STRING ); - if( strcmp( text, UNKNOWN_STRING ) ) { - new->xmlformat = FindString( MAX_FORMAT + 1, xformat, text, - "the XmlChan component 'XmlFmt'", - "astRead", astGetClass( channel ), status ); - } else { - new->xmlformat = UNKNOWN_FORMAT; - } - if ( TestXmlFormat( new, status ) ) SetXmlFormat( new, new->xmlformat, status ); - text = astFree( text ); - } - -/* If an error occurred, clean up by deleting the new XmlChan. */ - if ( !astOK ) new = astDelete( new ); - -/* Return the new XmlChan pointer. */ - return new; -} - -/* Virtual function interfaces. */ -/* ============================ */ -/* These provide the external interface to the virtual functions defined by - this class. Each simply checks the global error status and then locates and - executes the appropriate member function, using the function pointer stored - in the object's virtual function table (this pointer is located using the - astMEMBER macro defined in "object.h"). - - Note that the member function may not be the one defined here, as it may - have been over-ridden by a derived class. However, it should still have the - same interface. */ - - - - - - - - - - - - - |