/****************************************************************************
 *   gdbf.h : 
 *   		header file for handling .DBF class
 *
 *   Change Log :
 *		 May 1997 Initial version,  Liujian Qian
 *
 *   $Id: gdbf.h,v 1.13 1999/02/23 04:27:54 qian Exp $
 ***************************************************************************/

#ifndef _DBF_H_
#define _DBF_H_

#include "gcxx.h"

#ifndef Align
#define ALIGNON 0x8
#define ALIGNON1 (ALIGNON-1)
#define Align(sz) ((sz + ALIGNON1) & ~ALIGNON1)
#endif

///
//end of file header (DBFileHdr + DBFieldDescs)
#define TERMINATOR	0x0D	

///
//flaging the begining of a deleted record
#define DELETED		0x2A	

///
//maximum characters for 'C' type field in dbase file
#define MAX_CHRS	1024	

class ostream;

// all possible data types for the fileds (all versions of dBase combined)
enum FieldTypes {
    C='C', 	//character
    D='D',	//Date (8 digits: YYYYMMDD)
    F='F',	//Floating point binary numeric: -. 0 1 2 3 4 5 6 7 8 9
    G='G',	//General. All OEM characters or OLE.
    L='L', 	//Logical: ? Y y N  n T t F f (? initially)
    M='M', 	//Memo
    N='N'	//Numeric: - . 0 1 2 3 4 5 6 7 8 9
};


/**
 * structure describing individual DBF fields.
 */
struct GDBFieldDesc
{
    char		name[11];
    unsigned char	field_type;	// C-chracter; N-number
    int			field_offset;	// (FoxPro only?) inside the record
    unsigned char	field_len;
    unsigned char	decimal_cnt;
    char		unused1[2];
    unsigned char	work_area_id;
    char		unused2[2];
    char		set_field_flag;
    char		unused3[7];
    char		index_flag;
};

/*
     * the value of a particular field in a record; 
     * interpration depends on the type of the field.
     * ToDo: implement all the types
     */
union GDBFValue
{
    char  	str_v[MAX_CHRS];
    int   	int_v;
    double	double_v;
};    

/**
 *  @short class for reading DBF records (tabular data).
 * 
 *  This class handles the extraction of individual records out of
 *  a DBF file associated with a ArcView shape file. Each record 
 *  is an array of fixed number of fields. You can also  extract 
 *  the value of each field in a record, as well as the name and
 *  type of a field. 
 */
class GDBFile
{
    /**
     * structure describing the 32-byte DBF file header 
     */
    struct GDBFileHdr 
    {
	unsigned char	version;  //bits 0-2 --> version number
	//       3 --> presence of a dBASE IV memo file 
	//     4-6 --> presence of an SQL table         
	//       7 --> presence of any memo file        

	unsigned char	last_update[3]; 	//YYMMDD
    
	int			n_records;
	unsigned short	header_sz;	//16-bit number
	unsigned short	record_sz;	//16-bit number
	char		unused1[2];
	char		xct_flag;	//transaction flag
	char		encrypt_flag;   //0x01 for encrypted records
	char		unused2[12];
	char		mdx_flag;
	char		lang_drv_id;
	char		unused3[2];
    };


    //attributes
    GDBFileHdr		file_hdr;
    GDBFieldDesc*	fields;
    int			n_fields;
    int			n_records;
    int			record_sz;
    char*		buffer;
    int			buffer_sz;
    int			fd;
    GDBFValue*		values;
    char		field_buffer[MAX_CHRS];
    bool		big_endian;
    
    //private operations
    void		init();
    int 		extendBuffer(int new_sz);

public:	

    /**
     */
    GDBFile();
    /**
     * construct an object out of the specified shape file's DBF file. 
     */
    GDBFile(const char* name);
    /**
     */
    ~GDBFile();


    /**
     * Given a DBF file's name, open the file and read the header info.
     * Also setup interal variables/attributes.                        	
     */
    Result			openDBF(const char* name);

    /**
     * return the number of records in the DBF file.
     */
    int			numRecords() const {return n_records;}

    /**
     * return the number of fields in each record
     */
    int			numFields()  const {return n_fields;}
    /**
     * return the record size in the DBF file
     */
    int			recordSize() const {return record_sz;}
    /**
     * retrieve the nth record in the file. return the 
     * pointer to the beginning of the record. the recordDeform
     * method can be called on this pointer to interpretate 
     * individual fields.
     */
    char*		getRecord(int nth);
    /**
     * retrieve the nth field's desription 
     */
    GDBFieldDesc*	getFieldDesc(int nth);
    /**
     * decompose a previously retrieved record into an
     * array of individual field values. Return the pointer
     * to the beginning of the array. 
     * <b> This method is deprecated. </b>
     */
    GDBFValue*		recordDeform(char* rec);
    /**
     * returns the name for the ith field of records in this file.
     */
    char*		getFieldName(int ith);
    /**
     * get the type for the ith field in a record. returns
     * a single character the meaning of which is defined as below:
     * <pre>
     * 	'C': character
     *	'D': Date (8 digits: YYYYMMDD)
     *	'F': Floating point binary numeric: -. 0 1 2 3 4 5 6 7 8 9
     *	'G': General. All OEM characters or OLE.
     *	'L': Logical: ? Y y N  n T t F f (? initially)
     *	'M': Memo
     *	'N': Float: - . 0 1 2 3 4 5 6 7 8 9
     *  'I': Integer: - 0 1 2 3 4 5 6 7 8 9
     * </pre>
     */
    char		getFieldType(int ith);

    /**
     * get the value string for the ith field in the given record.
     * This is an ascii representation of this field's actual value.
     * For fields with type 'I' or 'N', Use atoi() or strtod() accordingly
     * to convert the returned string into an integer or double. Null is
     * returned if something is wrong (e.g., invalid field index).
     */
    char*		getField(int ith, const char* rec);
    
    /**
     * 
     */
    friend ostream&     operator<<(ostream& os, const GDBFile& dbf);

};

    

#endif




Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999