#ifndef CGATS_H

/* 
 * Committee for Graphics Arts Technologies Standards
 * CGATS.5 and IT8.7 family file I/O class
 * Version 2.05
 */

/*
 * Author: Graeme W. Gill
 * Date:   20/12/95
 *
 * Copyright 1995, 1996, 2002, 2022 Graeme W. Gill
 * All rights reserved.
 *
 * This material is licensed with an "MIT" free use license:-
 * see the License4.txt file in this directory for licensing details.
 */

/* Version of cgatslib release */

#define CGATSLIB_VERSION 0x030200
#define CGATSLIB_VERSION_STR "3.2.0"

#ifdef __cplusplus
	extern "C" {
#endif

#include "pars.h"		/* We use the ASCII parsing class */

/* Possible table types */
typedef enum { it8_7_1, it8_7_2, it8_7_3, it8_7_4, cgats_5, cgats_X, tt_other, tt_none } table_type;

/* Possible data types - real, integer, char string, non-quoted char string, no value */
typedef enum { r_t, i_t, cs_t, nqcs_t, none_t } data_type;

union _cgats_set_elem {
	int i;
	double d;
	char *c;
}; typedef union _cgats_set_elem cgats_set_elem;

struct _cgats_table {
	cgatsAlloc *al;		/* Copy of parent memory allocator */
	table_type tt;		/* Table type */
	int oi;				/* other type index */

	/* Read only */
	int nkwords;		/* Number of keywords */
	int nfields;		/* Number of fields of data */
	int nsets;			/* Number of data sets */

	char **ksym;		/* Pointer to [nkwords] array of pointers to keyword symbols */
	char **kdata;		/* Pointer to [nkwords] array of pointers to keyword values */
	
	char **fsym;		/* Pointer to [nfields] array of pointers to field symbols */
	data_type *ftype;	/* Pointer to [nfields] array of field types */
	char ***rfdata;		/* Pointer to [nsets] array of pointers */
						/*         to [nfields] array of pointers to read file field text values */
	void ***fdata;		/* Pointer to [nsets] array of pointers */
						/*         to [nfields] array of pointers to field set values of ftype */
	/* Private */
	int nkwordsa;		/* Number of keywords allocated */
	int nfieldsa;		/* Number of fields allocated */
	int nsetsa;			/* Number of sets allocated */
	char **kcom;		/* Pointer to [nkwords] array of pointers to keyword comments */
	int ndf;			/* Next data field - used by add_data_item() */
	int sup_id;			/* Set to non-zero if table ID output is to be suppressed */
	int sup_kwords;		/* Set to non-zero if table default keyword output is to be suppressed */
	int sup_fields;		/* Set to non-zero if table field output is to be suppressed */
}; typedef struct _cgats_table cgats_table;

struct _cgats {
	/* Private */
	cgatsAlloc *al;		/* Memory allocator */
	int del_al;			/* Flag to indicate we al->del() */

	/* Read only Variables */
	int ntables;		/* Number of tables */

	cgats_table *t;		/* Pointer to an array of ntable table structures */

	/* Undefined CGATS table type */
	char *cgats_type;

	/* User defined table types */
	int nothers;		/* Number of other identifiers */
	char **others;		/* Other file type identifiers */

	/* Options */
	int emit_keywords;	/* NZ to emit "KEYWORD" for non-standard keywords (default no) */

	/* Public Methods */
	int (*set_cgats_type)(struct _cgats *p, const char *osym);
											/* Define the (one) variable CGATS type */
											/* Return -2, set e.c & e.m on system error */

	int (*add_other)(struct _cgats *p, const char *osym);
											/* Add a user defined file identifier string. */
											/* Use a zero length string for wildcard. */
											/* Returns existing if already registered. */
											/* Return the oi */
											/* Return -2, set e.c & e.m on system error */

	int (*get_oi)(struct _cgats *p, const char *osym);
											/* Return the oi of the given other type */
											/* return -ve and e.c & e.m set on error */

	int (*read)(struct _cgats *p, cgatsFile *fp);	/* Read a cgats file into structure */
												/* return -ve and e.c & e.m set on error */

	/* NULL if SEPARATE_STD is defined: */ 
	int (*read_name)(struct _cgats *p, const char *filename);	/* Standard file I/O */
												/* return -ve and e.c & e.m set on error */

	int (*find_kword)(struct _cgats *p, int table, const char *ksym);
												/* Return index of the keyword, -1 on fail */
												/* -2 on illegal table index, e.c & e.m */
	int (*find_field)(struct _cgats *p, int table, const char *fsym);
												/* Return index of the field, -1 on fail */
												/* -2 on illegal table index, e.c & e.m */

	int (*add_table)(struct _cgats *p, table_type tt, int oi);
	                                        /* Add a new (empty) table to the structure */
											/* Return the index of the table */
											/* Return -2, set e.c & e.m on system error */
											/* if tt is tt_other, io sets the other index */
	int (*set_table_type)(struct _cgats *p, int table, table_type tt, int oi);
						/* Override the table type */
	int (*set_table_flags)(struct _cgats *p, int table, int sup_id,int sup_kwords,int sup_fields);
						/* Set or reset table output suppresion flags */
						/* Return -ve, set e.c & e.m on error */
	int (*del_table)(struct _cgats *p, int table);
						/* Delete an existing table. Return error if it doesn't exist */
						/* Note that any following tables will be shuffled down. */
	int (*add_kword)(struct _cgats *p, int table, const char *ksym, const char *kdata, const char *kcom);
						/* Add a new keyword/value pair + optional comment to the table */
						/* Return index of new keyword, or -1, e.c & e.m on error */
	int (*add_kword_at)(struct _cgats *p, int table, int pos, const char *ksym,
	                                      const char *kdata, const char *kcom);
						/* Replace or append a new keyword/value pair + optional comment */
	int (*add_field)(struct _cgats *p, int table, const char *fsym, data_type ftype);
						/* Add a new field to the table */
						/* Return index of new field, or -1, -2, e.c & e.m on error */
	int (*add_set)(struct _cgats *p, int table, ...);	/* Add a set of data */
						/* Return 0 normally, -1, -2, e.c & e.m if error */
	int (*add_setarr)(struct _cgats *p, int table, cgats_set_elem *ary); /* Add data from array */
						/* Return 0 normally, -1, -2, e.c & e.m if error */
	int (*write)(struct _cgats *p, cgatsFile *fp);	/* Write structure into cgats file */
										/* return -ve and e.c & e.m set on error */

	int (*get_setarr)(struct _cgats *p, int table, int set_index, cgats_set_elem *ary);
						/* Fill a suitable set_element with a line of data */
						/* Return 0 normally, -1, -2, e.c & e.m if error */
	/* NULL if SEPARATE_STD is defined: */ 
	int (*write_name)(struct _cgats *p, const char *filename);	/* Standard file I/O */
										/* return -ve and e.c & e.m set on error */


	int (*error)(struct _cgats *p, char **mes);		/* Return error code and message */
													/* for the first error, if any error */
													/* has occured since object creation. */
	void (*del)(struct _cgats *p);					/* Delete the object */

	cgats_err e;			/* Error message * code */
	cgats_err fe;			/* First error message * code */
}; typedef struct _cgats cgats;

/* Creator */
extern cgats *new_cgats_al(cgatsAlloc *al);	/* with allocator object */

#ifdef COMBINED_STD
#define CGATS_STATIC static
#else
#define CGATS_STATIC
#endif

/* Available if SEPARATE_STD is not defined */ 
extern cgats *new_cgats(void);							/* Standard allocator */

/* Available from cgatsstd.obj SEPARATE_STD is defined: */ 
CGATS_STATIC int cgats_read_name(cgats *p, const char *filename);
CGATS_STATIC int cgats_write_name(cgats *p, const char *filename);

#ifdef __cplusplus
	}
#endif

#define CGATS_H
#endif /* CGATS_H */
