1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
/*
* pdbfile.cpp
*
* (c) 2002-2003,2009 by Jeremy Bowman <jmbowman@alum.mit.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
/** @file pdbfile.cpp
* Source file for PDBFile
*/
#include <QFile>
#include <QMessageBox>
#include <time.h>
#include "pdbfile.h"
/**
* Constructor.
*
* @param f The path of the file to be parsed
*/
PDBFile::PDBFile(const QString &f) : fd(0), filename(f), file_attributes(0),
version(0), create_date(0), modification_date(0), backup_date(0),
modification_number(0), appinfo_offset(0), sortinfo_offset(0),
unique_seed(0), next_record_list_id(0), number_records(0), record_list(0)
{
memset(pdb_name, 0, sizeof(pdb_name));
memset(db_type, 0, sizeof(db_type));
memset(create_id, 0, sizeof(create_id));
};
/**
* Destructor.
*/
PDBFile::~PDBFile()
{
if (record_list) {
delete [] record_list;
record_list = 0;
}
if (fd) {
fd->close();
delete fd;
fd = 0;
}
}
/**
* Parse the file, loading data from the header and basic information
* about each record in the file.
*
* @return True if the file was successfully parsed, false otherwise
*/
bool PDBFile::read()
{
fd = new QFile(filename);
if (!fd->open(QIODevice::ReadOnly)) {
return false;
}
return readHeader() ? readRecordList() : false;
}
/**
* Convert the provided raw file data to an unsigned short.
*
* @param v The data from the file to be converted
* @return The unsigned short represented by the input data
*/
unsigned short PDBFile::toshort(unsigned char *v) const
{
return ((unsigned short)(v[0] << 8)) + v[1];
}
/**
* Convert the provided raw file data to an unsigned int.
*
* @param v The data from the file to be converted
* @return The unsigned int represented by the input data
*/
unsigned int PDBFile::toint(unsigned char *v) const {
return ((unsigned int)(v[0] << 24)) +
((unsigned int)(v[1] << 16)) +
((unsigned int)(v[2] << 8)) +
((unsigned int)(v[3] << 0));
}
/**
* Convert the provided time-representing integer from the file to a UNIX
* time in seconds since the epoch. Conversion needed since Palm OS counts
* seconds since 1904-01-01, but UNIX counts time since 1970-01-01.
*
* @param p The Palm OS time integer to be converted
* @return The converted UNIX time integer
*/
time_t PDBFile::palm2unix_time(unsigned int p) const
{
//number of seconds between 01/01/1904 and 01/01/1970
return p - 2082844886LU;
}
/**
* Parse the file's header data.
*
* @return True if successfully parsed, false otherwise
*/
bool PDBFile::readHeader()
{
unsigned int offset = 0;
unsigned char header [78];
if (fd->read((char*)header, sizeof(header)) == -1) {
//set error
return false;
}
memcpy(pdb_name, header + offset, sizeof(pdb_name) - 1);
offset += sizeof(pdb_name) - 1;
file_attributes = toshort(header + offset);
offset += sizeof(file_attributes);
version = toshort(header + offset);
offset += sizeof(version);
create_date = toint(header + offset);
offset += sizeof(create_date);
modification_date = toint(header + offset);
offset += sizeof(modification_date);
backup_date = toint(header + offset);
offset += sizeof(backup_date);
appinfo_offset = toint(header + offset);
offset += sizeof(appinfo_offset);
sortinfo_offset = toint(header + offset);
offset += sizeof(sortinfo_offset);
modification_number = toint(header + offset);
offset += sizeof(modification_number);
memcpy(db_type, header + offset, sizeof(db_type) - 1);
offset += sizeof(db_type) - 1;
memcpy(create_id, header + offset, sizeof(create_id) - 1);
offset += sizeof(create_id) - 1;
unique_seed = toint(header + offset);
offset += sizeof(unique_seed);
next_record_list_id = toint(header + offset);
offset += sizeof(next_record_list_id);
number_records = toshort(header + offset);
offset += sizeof(number_records);
return true;
}
/*
unsigned int record_data_offset;
unsigned char record_attributes;
unsigned int unique_id;
*/
/**
* Parse the metadata about each record in the file (offset within the file,
* attributes, unique ID, and record size).
*
* @return True if successfully parsed, false otherwise
*/
bool PDBFile::readRecordList()
{
if (fd == NULL) {
return false;
}
record_list = new PDBFile::RecordInfo[number_records];
unsigned char record_buf[8];
int i;
for (i = 0 ; i < number_records; i++) {
if (fd->read((char*)record_buf, sizeof(record_buf)) == -1) {
return false;
}
record_list[i].record_data_offset = toint(record_buf);
record_list[i].record_attributes = record_buf[4];
record_buf[4] = 0;
record_list[i].unique_id = toint(record_buf + 4);
}
//calculate record size
for (i = 0 ; i < number_records - 1; i++) {
record_list[i].record_size = record_list[i + 1].record_data_offset - record_list[i].record_data_offset;
}
record_list[number_records - 1].record_size = fd->size() - record_list[number_records - 1].record_data_offset;
return true;
}
|