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 ![]() |
(C) 2000-2002 ![]() |