#ifndef H__DBFTABLE
#define H__DBFTABLE 1

#include <stdio.h>
#include <dos.h>
#include <mem.h>

const int DBF_READ   = 0;
const int DBF_WRITE  = 1;
const int DBF_APPEND = 2;
const int DBF_UPDATE = 3;

struct dbf_field_descriptor
{
  char type;
  char name[12];
  int width;
  int precision;
  int offset;
};

class dbf_table
{
  private:
    class internal_field_descriptor : public dbf_field_descriptor
    {
      public:
        internal_field_descriptor *next;
    };
    FILE *fp;
    long nrecs;
    long recno;
    int header_size;
    int recsize;
    struct date hdate;
    struct date ffdate;
    struct time fftime;
    int xmode;
    bool write_error;
    internal_field_descriptor *first;
    char *record;
    void set_recno(long);
    const dbf_field_descriptor *check_recno_and_find_field(const char *) const;
    bool isopen(void) const {return fp != NULL;}
    bool isdeleted(void) const;
    void makedeleted(bool) const;
    void clear_record_buffer(void);
    void finish_header_if_necessary(void);
  public:
    dbf_table(void) {fp = NULL; first = NULL; record = NULL;}
    bool open(const char *, int);
    bool close(void);
    ~dbf_table() {close();}
    __property long record_number = {read=recno, write=set_recno};
    __property long number_of_records = {read=nrecs};
    __property struct date header_date = {read=hdate};
    __property struct date file_date = {read=ffdate};
    __property struct time file_time = {read=fftime};
    __property bool is_open = {read=isopen};
    __property bool deleted = {read=isdeleted, write=makedeleted};
    __property int mode = {read=xmode};
    __property bool error = {read=write_error};
    const dbf_field_descriptor *field_info(int) const;
    const dbf_field_descriptor *field_info(const char *) const;
    bool isblank(const dbf_field_descriptor *) const;
    bool get(char *, int, const dbf_field_descriptor *) const;
    bool get(__int64 &, const dbf_field_descriptor *) const;
    bool get(double &, const dbf_field_descriptor *) const;
    bool get(int &, const dbf_field_descriptor *) const;
    bool get(bool &, const dbf_field_descriptor *) const;
    bool get(struct date &, const dbf_field_descriptor *, struct date) const;
    bool isblank(const char *name) const
      {return isblank(check_recno_and_find_field(name));}
    bool get(char *buf, int buflen, const char *name) const
      {return get(buf, buflen, check_recno_and_find_field(name));}
    bool get(__int64 &value, const char *name) const
      {return get(value, check_recno_and_find_field(name));}
    bool get(double &value, const char *name) const
      {return get(value, check_recno_and_find_field(name));}
    bool get(int &value, const char *name) const
      {return get(value, check_recno_and_find_field(name));}
    bool get(bool &value, const char *name) const
      {return get(value, check_recno_and_find_field(name));}
    bool get(struct date &value, const char *name, struct date def) const
      {return get(value, check_recno_and_find_field(name), def);}
    bool delimited(char *, int) const;
    bool put(const char *, const dbf_field_descriptor *);
    bool put(__int64, const dbf_field_descriptor *);
    bool put(double, const dbf_field_descriptor *);
    bool put(int, const dbf_field_descriptor *);
    bool put(bool, const dbf_field_descriptor *);
    bool put(struct date, const dbf_field_descriptor *);
    bool put(const char *buf, const char *name)
      {return put(buf, field_info(name));}
    bool put(__int64 value, const char *name)
      {return put(value, field_info(name));}
    bool put(double value, const char *name)
      {return put(value, field_info(name));}
    bool put(int value, const char *name)
      {return put(value, field_info(name));}
    bool put(bool value, const char *name)
      {return put(value, field_info(name));}
    bool put(struct date value, const char *name)
      {return put(value, field_info(name));}
    const dbf_field_descriptor *add_field(char, const char *, int = 0,
      int = 0);
    bool append(void);
    void update(void);
    void operator << (const dbf_table &t) {memcpy(record, t.record, recsize);}
    void copy_fields(const dbf_table &);
    static bool scan(__int64 &, const char *, int = 0);
    static int edit(char *, __int64, int = 0);
    static long pack(const char *);
    static bool insert_blank(const char *, long);
    bool sort(const char *, const char *);
};

#endif

