Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

dbf.cpp

Go to the documentation of this file.
00001 
00002 //
00003 // Copyright (C) 2000
00004 // Ralf Westram
00005 // (Coded@ReallySoft.de)
00006 //
00007 // Permission to use, copy, modify, distribute and sell this software
00008 // and its documentation for any purpose is hereby granted without fee,
00009 // provided that the above copyright notice appear in all copies and
00010 // that both that copyright notice and this permission notice appear
00011 // in supporting documentation.  Ralf Westram makes no
00012 // representations about the suitability of this software for any
00013 // purpose.  It is provided "as is" without express or implied warranty.
00014 //
00015 // This code is part of my library.
00016 // You may find a more recent version at http://www.reallysoft.de/
00017 //
00019 
00020 #include <functional>
00021 #include <algorithm>
00022 
00023 #include <Tools.h>
00024 
00025 #include "dbf.h"
00026 
00027 using namespace std;
00028 using namespace rs;
00029 using namespace rs::dbf;
00030 using namespace rs::err;
00031 
00032 #if defined(DEBUG)
00033 #define DUMP_DBF_DEFINITION
00034 #endif // DEBUG
00035 
00036 //  ---------------------------------------------------------------------------------------------------------------------------------------
00037 //      DBF_EntryDeclaration::DBF_EntryDeclaration(unsigned char firstChar, istream& in, unsigned& offset_in_record, unsigned& index_)
00038 //  ---------------------------------------------------------------------------------------------------------------------------------------
00039 DBF_EntryDeclaration::DBF_EntryDeclaration(unsigned char firstChar, istream& in, unsigned& offset_in_record, unsigned& index_) {
00040 #if defined(DUMP_DBF_DEFINITION)
00041     cout << "pos=" << int(in.tellg())-1 << ' ';
00042 #endif // DUMP_DBF_DEFINITION
00043     char buf[12];
00044     in.read(buf+1, 10);
00045     buf[0] = firstChar;
00046     buf[11] = 0;
00047     name = buf;
00048 
00049 #if defined(DUMP_DBF_DEFINITION)
00050     cout << "buf='" << buf << "'\n";
00051 #endif // DUMP_DBF_DEFINITION
00052 
00053     in.read(&type, 1);
00054     in.read(xtra, 4);
00055     in.read(reinterpret_cast<char*>(&fieldlen), 1);
00056     in.read(&right, 1);
00057 
00058     in.ignore(14);
00059 
00060     offset = offset_in_record;
00061     offset_in_record += fieldlen;
00062     index = index_++;
00063 
00064     if (!in.good()) throw IOError("while reading DBF structure");
00065 }
00066 
00067 // ------------------------------------------------------------
00068 //      inline void get_us(istream& in, unsigned char& uc)
00069 // ------------------------------------------------------------
00070 inline void get_us(istream& in, unsigned char& uc) {
00071     char c;
00072     in.get(c);
00073     uc = c;
00074 }
00075 
00076 // --------------------------------------------------------------------------------
00077 //     DBF_Reader::DBF_Reader(const string& filename_)
00078 // --------------------------------------------------------------------------------
00079 DBF_Reader::DBF_Reader(const string& filename_)
00080     : filename(filename_),
00081       in(filename.c_str(), ios::in | ios::binary)
00082 {
00083     try {
00084         if (!in.good()) throw IOError(filename);
00085 
00086         unsigned char c;
00087         //         in.get(c_s);            // >> c;
00088         get_us(in, c);
00089         if (c!=3 && c!=83) throw Error("Wrong filetype (not DBASE)");
00090 
00091 
00092         get_us(in, c); created.tm_year = c; // creation date
00093         get_us(in, c); created.tm_mon = c;
00094         get_us(in, c); created.tm_mday = c;
00095         created.tm_hour = 0;
00096         created.tm_min = 0;
00097         created.tm_sec = 0;
00098         mktime(&created);
00099 
00100         get_us(in, c); no_of_records = c;
00101         get_us(in, c); no_of_records += c*256;
00102         get_us(in, c); no_of_records += c*256*256;
00103         get_us(in, c); no_of_records += c*256*256*256;
00104         //in.read((char*)&no_of_records, sizeof(no_of_records));
00105 
00106         get_us(in, c); length_of_header = c;
00107         get_us(in, c); length_of_header += c*256;
00108         //in.read((char*)&data_offset, sizeof(data_offset));
00109 
00110         get_us(in, c); record_size = c;
00111         get_us(in, c); record_size += c*256;
00112         //in.read((char*)&record_size, sizeof(record_size));
00113 
00114 #if defined(DUMP_DBF_DEFINITION)
00115         cout << "no_of_records=" << no_of_records << "\n";
00116         cout << "length_of_header=" << length_of_header << "\n";
00117         cout << "record_size=" << record_size << "\n";
00118 #endif // DUMP_DBF_DEFINITION
00119 
00120         if (no_of_records==0) throw Error("Database is empty");
00121 
00122         in.ignore(2); // reserved
00123 
00124         get_us(in, c); if (c) throw Error("Can't lock database");
00125         get_us(in, c); if (c) throw Error("Database is encrypted");
00126 
00127         in.ignore(16); // unused/reserved
00128 
00129         unsigned offset = 0;
00130         unsigned idx = 0;
00131         unsigned fields = 0;
00132 
00133         while (1) {
00134             get_us(in, c);
00135             if (c==0x0d) break; // end of field-declarations
00136             DBF_EntryDeclarationPtr decl(new DBF_EntryDeclaration(c, in, offset, idx));
00137             entryTypes[decl->Name()] = decl;
00138             ++fields;
00139         }
00140 
00141 #if defined(DUMP_DBF_DEFINITION)
00142         cout << "fields=" << fields << "\n";
00143 #endif // DUMP_DBF_DEFINITION
00144 
00145 //        streampos db_start(length_of_header);
00146 //         in.ignore(20);
00147 
00148 //         int fields = (db_start-in.tellg())/32;
00149 
00150 //         unsigned offset = 0;
00151 //         unsigned idx = 0;
00152 //         for (int f=0; f<fields; ++f) {
00153 //             DBF_EntryDeclarationPtr decl(new DBF_EntryDeclaration(in, offset, idx));
00154 //             entryTypes[decl->Name()] = decl;
00155 //         }
00156 
00157 // #if defined(DUMP_DBF_DEFINITION)
00158 //         dumpEntryDefinition(cout);
00159 //         cout << "sum of fieldlens=" << offset << "\n";
00160 // #endif // DUMP_DBF_DEFINITION
00161 
00162         current_record_data = new char[record_size];
00163         current_record = -1U;
00164         read_record(0);
00165     }
00166     catch (Error& err) {
00167         throw Error(string("While opening DBF '")+filename+"': "+err.get_message());
00168     }
00169 }
00170 
00171 // --------------------------------------------------------------------------------
00172 //     void DBF_Reader::dumpEntryDefinition(ostream& out) const
00173 // --------------------------------------------------------------------------------
00174 void DBF_Reader::dumpEntryDefinition(ostream& out) const {
00175     out << "Database defines " << entryTypes.size() << " fields:\n";
00176     for (DBF_EntryDeclarationList::const_iterator e=entryTypes.begin(); e!=entryTypes.end(); ++e) {
00177         out << *(e->second);
00178     }
00179 }
00180 
00181 // --------------------------------------------------------------------------------
00182 //     struct hasIndex
00183 // -------------------------------------------------c-------------------------------
00185 struct hasIndex {
00186     unsigned num;
00187     hasIndex(unsigned num_) : num(num_) {}
00188     bool operator()(const pair<string, DBF_EntryDeclarationPtr>& decl) { return decl.second->Index()==num; }
00189 };
00190 
00191 // --------------------------------------------------------------------------------
00192 //     const string& DBF_Reader::FieldName(int num) const
00193 // --------------------------------------------------------------------------------
00194 const string& DBF_Reader::FieldName(unsigned num) const {
00195     DBF_EntryDeclarationList::const_iterator found =
00196         find_if(entryTypes.begin(), entryTypes.end(), hasIndex(num));
00197 
00198     if (found==entryTypes.end()) throw Error("Field index out of range");
00199     return found->second->Name();
00200 }
00201 
00202 // --------------------------------------------------------------------------------
00203 //     string DBF_Reader::FieldContent(const string& fieldName, bool crop) const
00204 // --------------------------------------------------------------------------------
00205 string DBF_Reader::FieldContent(const string& fieldName, bool crop) const {
00206     DBF_EntryDeclarationList::const_iterator field = entryTypes.find(fieldName);
00207 
00208     if (field==entryTypes.end()) throw Error(string("Database has no field '")+fieldName+'\'');
00209 
00210     string result = string(current_record_data+field->second->Offset(),
00211                            field->second->Fieldlen());
00212     return crop ? str::cropString(result) : result;
00213 }
00214 
00215 // start of implementation of class DBF_EntryDeclaration:
00216 
00217 // -----------------------------------------------------------------
00218 //      void DBF_EntryDeclaration::dump(std::ostream& out) const
00219 // -----------------------------------------------------------------
00220 void DBF_EntryDeclaration::dump(std::ostream& out) const
00221 {
00222     out << name << std::string(12-name.length(), ' ') << type
00223         << " size=" << Fieldlen()
00224         << " offset=" << Offset()
00225         << "\n";
00226 }
00227 
00228 // -end- of implementation of class DBF_EntryDeclaration.
00229 

Contact me in case of errors or questions.
This documentation is powered by Doxygen.
(C) 2000-2002 Doxygen