summaryrefslogtreecommitdiffstats
path: root/src/translators/pilotdb/libflatfile
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:17:32 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:17:32 +0000
commite38d2351b83fa65c66ccde443777647ef5cb6cff (patch)
tree1897fc20e9f73a81c520a5b9f76f8ed042124883 /src/translators/pilotdb/libflatfile
downloadtellico-e38d2351b83fa65c66ccde443777647ef5cb6cff.tar.gz
tellico-e38d2351b83fa65c66ccde443777647ef5cb6cff.zip
Added KDE3 version of Tellico
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/tellico@1097620 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/translators/pilotdb/libflatfile')
-rw-r--r--src/translators/pilotdb/libflatfile/DB.cpp1437
-rw-r--r--src/translators/pilotdb/libflatfile/DB.h166
-rw-r--r--src/translators/pilotdb/libflatfile/Database.cpp331
-rw-r--r--src/translators/pilotdb/libflatfile/Database.h320
-rw-r--r--src/translators/pilotdb/libflatfile/FType.h48
-rw-r--r--src/translators/pilotdb/libflatfile/Field.h119
-rw-r--r--src/translators/pilotdb/libflatfile/ListView.h77
-rw-r--r--src/translators/pilotdb/libflatfile/ListViewColumn.h19
-rw-r--r--src/translators/pilotdb/libflatfile/Makefile.am20
-rw-r--r--src/translators/pilotdb/libflatfile/Record.h45
10 files changed, 2582 insertions, 0 deletions
diff --git a/src/translators/pilotdb/libflatfile/DB.cpp b/src/translators/pilotdb/libflatfile/DB.cpp
new file mode 100644
index 0000000..40e639a
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/DB.cpp
@@ -0,0 +1,1437 @@
+/*
+ * palm-db-tools: Read/write DB-format databases
+ * Copyright (C) 1999-2001 by Tom Dyas ([email protected])
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifh Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <iostream>
+#include <vector>
+#include <string>
+#include <stdexcept>
+#include <sstream>
+#include <time.h>
+
+#include <cstring>
+
+#include <kdebug.h>
+
+#include "../strop.h"
+
+#include "DB.h"
+
+#include <kdebug.h>
+
+#define charSeperator '/'
+#define VIEWFLAG_USE_IN_EDITVIEW 0x01
+
+#define INVALID_DEFAULT 0
+#define NOW_DEFAULT 1
+#define CONSTANT_DEFAULT 2
+
+using namespace PalmLib::FlatFile;
+using namespace PalmLib;
+
+namespace {
+ static const pi_uint16_t CHUNK_FIELD_NAMES = 0;
+ static const pi_uint16_t CHUNK_FIELD_TYPES = 1;
+ static const pi_uint16_t CHUNK_FIELD_DATA = 2;
+ static const pi_uint16_t CHUNK_LISTVIEW_DEFINITION = 64;
+ static const pi_uint16_t CHUNK_LISTVIEW_OPTIONS = 65;
+ static const pi_uint16_t CHUNK_LFIND_OPTIONS = 128;
+ static const pi_uint16_t CHUNK_ABOUT = 254;
+}
+
+template <class Map, class Key>
+static inline bool has_key(const Map& map, const Key& key)
+{
+ return map.find(key) != map.end();
+}
+
+bool PalmLib::FlatFile::DB::classify(PalmLib::Database& pdb)
+{
+ return (! pdb.isResourceDB())
+ && (pdb.creator() == PalmLib::mktag('D','B','O','S'))
+ && (pdb.type() == PalmLib::mktag('D','B','0','0'));
+}
+
+bool PalmLib::FlatFile::DB::match_name(const std::string& name)
+{
+ return (name == "DB") || (name == "db");
+}
+
+void PalmLib::FlatFile::DB::extract_chunks(const PalmLib::Block& appinfo)
+{
+ size_t i;
+ pi_uint16_t chunk_type;
+ pi_uint16_t chunk_size;
+
+ if (appinfo.size() > 4) {
+ // Loop through each chunk in the block while data remains.
+ i = 4;
+ while (i < appinfo.size()) {
+ /* Stop the loop if there is not enough room for even one
+ * chunk header.
+ */
+ if (i + 4 >= appinfo.size()) {
+// throw PalmLib::error("header is corrupt");
+ kdDebug() << "header is corrupt" << endl;
+ }
+ // Copy the chunk type and size into the local buffer.
+ chunk_type = get_short(appinfo.data() + i);
+ chunk_size = get_short(appinfo.data() + i + 2);
+ i += 4;
+
+ // Copy the chunk into seperate storage.
+ Chunk chunk(appinfo.data() + i, chunk_size);
+ chunk.chunk_type = chunk_type;
+ m_chunks[chunk.chunk_type].push_back(chunk);
+
+ /* Advance the index by the size of the chunk. */
+ i += chunk.size();
+ }
+
+ // If everything was correct, then we should be exactly at the
+ // end of the block.
+ if (i != appinfo.size()) {
+// throw PalmLib::error("header is corrupt");
+ kdDebug() << "header is corrupt" << endl;
+ }
+ } else {
+// throw PalmLib::error("header is corrupt");
+ kdDebug() << "header is corrupt" << endl;
+ }
+}
+
+void PalmLib::FlatFile::DB::extract_schema(unsigned numFields)
+{
+ unsigned i;
+
+ if (!has_key(m_chunks, CHUNK_FIELD_NAMES)
+ || !has_key(m_chunks, CHUNK_FIELD_TYPES)) {
+// throw PalmLib::error("database is missing its schema");
+ kdDebug() << "database is missing its schema" << endl;
+ return;
+ }
+
+ Chunk names_chunk = m_chunks[CHUNK_FIELD_NAMES][0];
+ Chunk types_chunk = m_chunks[CHUNK_FIELD_TYPES][0];
+ pi_char_t* p = names_chunk.data();
+ pi_char_t* q = types_chunk.data();
+
+ // Ensure that the types chunk has the expected size.
+ if (types_chunk.size() != numFields * sizeof(pi_uint16_t)) {
+// throw PalmLib::error("types chunk is corrupt");
+ kdDebug() << "types chunk is corrupt" << endl;
+ }
+ // Loop for each field and extract the name and type.
+ for (i = 0; i < numFields; ++i) {
+ PalmLib::FlatFile::Field::FieldType type;
+ int len;
+
+ // Determine the length of the name string. Ensure that the
+ // string does not go beyond the end of the chunk.
+ pi_char_t* null_p = reinterpret_cast<pi_char_t*>
+ (memchr(p, 0, names_chunk.size() - (p - names_chunk.data())));
+ if (!null_p) {
+// throw PalmLib::error("names chunk is corrupt");
+ kdDebug() << "names chunk is corrupt" << endl;
+ }
+ len = null_p - p;
+
+ switch (PalmLib::get_short(q)) {
+ case 0:
+ type = PalmLib::FlatFile::Field::STRING;
+ break;
+
+ case 1:
+ type = PalmLib::FlatFile::Field::BOOLEAN;
+ break;
+
+ case 2:
+ type = PalmLib::FlatFile::Field::INTEGER;
+ break;
+
+ case 3:
+ type = PalmLib::FlatFile::Field::DATE;
+ break;
+
+ case 4:
+ type = PalmLib::FlatFile::Field::TIME;
+ break;
+
+ case 5:
+ type = PalmLib::FlatFile::Field::NOTE;
+ break;
+
+ case 6:
+ type = PalmLib::FlatFile::Field::LIST;
+ break;
+
+ case 7:
+ type = PalmLib::FlatFile::Field::LINK;
+ break;
+
+ case 8:
+ type = PalmLib::FlatFile::Field::FLOAT;
+ break;
+
+ case 9:
+ type = PalmLib::FlatFile::Field::CALCULATED;
+ break;
+
+ case 10:
+ type = PalmLib::FlatFile::Field::LINKED;
+ break;
+
+ default:
+// throw PalmLib::error("unknown field type");
+ kdDebug() << "PalmLib::FlatFile::DB::extract_schema() - unknown field type" << endl;
+ type = PalmLib::FlatFile::Field::STRING;
+ break;
+ }
+
+ // Inform the superclass about this field.
+ appendField(std::string((char *) p, len), type, extract_fieldsdata(i, type));
+
+ // Advance to the information on the next field.
+ p += len + 1;
+ q += 2;
+ }
+}
+
+void PalmLib::FlatFile::DB::extract_listviews()
+{
+ if (!has_key(m_chunks, CHUNK_LISTVIEW_DEFINITION))
+ return;
+
+/* throw PalmLib::error("no list views in database");*/
+
+ const std::vector<Chunk>& chunks = m_chunks[CHUNK_LISTVIEW_DEFINITION];
+
+ for (std::vector<Chunk>::const_iterator iter = chunks.begin();
+ iter != chunks.end(); ++iter) {
+ const Chunk& chunk = (*iter);
+ PalmLib::FlatFile::ListView lv;
+
+ if (chunk.size() < (2 + 2 + 32)) {
+// throw PalmLib::error("list view is corrupt");
+ kdDebug() << "list view is corrupt" << endl;
+ }
+ pi_uint16_t flags = PalmLib::get_short(chunk.data());
+ pi_uint16_t num_cols = PalmLib::get_short(chunk.data() + 2);
+
+ lv.editoruse = false;
+ if (flags & VIEWFLAG_USE_IN_EDITVIEW)
+ lv.editoruse = true;
+
+ if (chunk.size() != static_cast<unsigned> (2 + 2 + 32 + num_cols * 4)) {
+// throw PalmLib::error("list view is corrupt");
+ kdDebug() << "list view is corrupt" << endl;
+ }
+ // Determine the length of the name string.
+ pi_char_t* null_ptr = reinterpret_cast<pi_char_t*>
+ (memchr(chunk.data() + 4, 0, 32));
+ if (null_ptr)
+ lv.name = std::string((char *) (chunk.data() + 4),
+ null_ptr - (chunk.data() + 4));
+ else
+ lv.name = "Unknown";
+
+ const pi_char_t* p = chunk.data() + 2 + 2 + 32;
+ for (int i = 0; i < num_cols; ++i) {
+ pi_uint16_t field = PalmLib::get_short(p);
+ pi_uint16_t width = PalmLib::get_short(p + 2);
+ p += 2 * sizeof(pi_uint16_t);
+
+ if (field >= getNumOfFields()) {
+// throw PalmLib::error("list view is corrupt");
+ kdDebug() << "list view is corrupt" << endl;
+ }
+ PalmLib::FlatFile::ListViewColumn col(field, width);
+ lv.push_back(col);
+ }
+
+ appendListView(lv);
+ }
+}
+
+std::string PalmLib::FlatFile::DB::extract_fieldsdata(pi_uint16_t field_search, PalmLib::FlatFile::Field::FieldType type)
+{
+ std::ostringstream theReturn;
+
+ if (!has_key(m_chunks, CHUNK_FIELD_DATA))
+ return std::string(theReturn.str());
+
+ std::vector<Chunk>& chunks = m_chunks[CHUNK_FIELD_DATA];
+
+ pi_uint16_t field_num = 0;
+ bool find = false;
+ std::vector<Chunk>::const_iterator iter = chunks.begin();
+ for ( ; iter != chunks.end(); ++iter) {
+ const Chunk& chunk = (*iter);
+
+ field_num = PalmLib::get_short(chunk.data());
+
+ if (field_num == field_search) {
+ find = true;
+ break;
+ }
+ }
+
+ if (find) {
+ const Chunk& chunk = (*iter);
+
+ switch (type) {
+
+ case PalmLib::FlatFile::Field::STRING:
+ theReturn << std::string((const char *)chunk.data()+2, chunk.size() - 2);
+ break;
+
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ break;
+
+ case PalmLib::FlatFile::Field::INTEGER:
+ theReturn << PalmLib::get_long(chunk.data() + sizeof(pi_uint16_t));
+ theReturn << charSeperator;
+ theReturn << PalmLib::get_short(chunk.data() + sizeof(pi_uint16_t) + sizeof(pi_uint32_t));
+ break;
+
+ case PalmLib::FlatFile::Field::FLOAT: {
+ pi_double_t value;
+ value.words.hi = PalmLib::get_long(chunk.data() + 2);
+ value.words.lo = PalmLib::get_long(chunk.data() + 6);
+
+ theReturn << value.number;
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::DATE:
+ if (*(chunk.data() + sizeof(pi_uint16_t)) == NOW_DEFAULT)
+ theReturn << "now";
+ else if (*(chunk.data() + sizeof(pi_uint16_t)) == CONSTANT_DEFAULT) {
+ const pi_char_t * ptr = chunk.data() + sizeof(pi_uint16_t) + 1;
+ struct tm date;
+ date.tm_year = PalmLib::get_short(ptr) - 1900;
+ date.tm_mon = (static_cast<int> (*(ptr + 2))) - 1;
+ date.tm_mday = static_cast<int> (*(ptr + 3));
+
+ (void) mktime(&date);
+
+ char buf[1024];
+
+ // Clear out the output buffer.
+ memset(buf, 0, sizeof(buf));
+
+ // Convert and output the date using the format.
+ strftime(buf, sizeof(buf), "%Y/%m/%d", &date);
+
+ theReturn << buf;
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::TIME:
+ if (*(chunk.data() + sizeof(pi_uint16_t)) == NOW_DEFAULT)
+ theReturn << "now";
+ else if (*(chunk.data() + sizeof(pi_uint16_t)) == CONSTANT_DEFAULT) {
+ const pi_char_t * ptr = chunk.data() + sizeof(pi_uint16_t) + 1;
+ struct tm t;
+ const struct tm * tm_ptr;
+ time_t now;
+
+ time(&now);
+ tm_ptr = localtime(&now);
+ memcpy(&t, tm_ptr, sizeof(tm));
+
+ t.tm_hour = static_cast<int> (*(ptr));
+ t.tm_min = static_cast<int> (*(ptr + 1));
+ t.tm_sec = 0;
+
+ char buf[1024];
+
+ // Clear out the output buffer.
+ memset(buf, 0, sizeof(buf));
+
+ // Convert and output the date using the format.
+ strftime(buf, sizeof(buf), "%H:%M", &t);
+
+ theReturn << buf;
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::NOTE:
+ break;
+
+ case PalmLib::FlatFile::Field::LIST: {
+ unsigned short numItems = PalmLib::get_short(chunk.data() + sizeof(pi_uint16_t));
+ int prevLength = 0;
+ std::string item;
+
+ if (numItems > 0) {
+ for (unsigned short i = 0; i < numItems - 1; i++) {
+ item = std::string((const char *)chunk.data() + 3 * sizeof(pi_uint16_t) + prevLength);
+ theReturn << item << charSeperator;
+ prevLength += item.length() + 1;
+ }
+ item = std::string((const char *)chunk.data() + 3 * sizeof(pi_uint16_t) + prevLength);
+ theReturn << item;
+ }
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::LINK:
+ theReturn << std::string((const char *)chunk.data()+sizeof(pi_uint16_t));
+// theReturn << std::string((const char *)chunk.data()+sizeof(pi_uint16_t), chunk.size() - 2);
+ theReturn << charSeperator;
+ theReturn << PalmLib::get_short(chunk.data() + sizeof(pi_uint16_t) + 32 * sizeof(pi_char_t));
+ break;
+
+ case PalmLib::FlatFile::Field::LINKED:
+ theReturn << PalmLib::get_short(chunk.data() + sizeof(pi_uint16_t));
+ theReturn << charSeperator;
+ theReturn << PalmLib::get_short(chunk.data() + 2 * sizeof(pi_uint16_t));
+ break;
+
+ case PalmLib::FlatFile::Field::CALCULATED:
+ break;
+
+ default:
+ kdDebug() << "unknown field type" << endl;
+ break;
+ }
+ }
+ return std::string(theReturn.str());
+}
+
+void PalmLib::FlatFile::DB::extract_aboutinfo()
+{
+ if (!has_key(m_chunks, CHUNK_ABOUT))
+ return;
+
+ Chunk chunk = m_chunks[CHUNK_ABOUT][0];
+ pi_char_t* header = chunk.data();
+ pi_char_t* q = chunk.data() + PalmLib::get_short(header);
+
+ setAboutInformation( (char*)q);
+}
+
+void PalmLib::FlatFile::DB::parse_record(PalmLib::Record& record,
+ std::vector<pi_char_t *>& ptrs,
+ std::vector<size_t>& sizes)
+{
+ unsigned i;
+
+ // Ensure that enough space for the offset table exists.
+ if (record.size() < getNumOfFields() * sizeof(pi_uint16_t)) {
+// throw PalmLib::error("record is corrupt");
+ kdDebug() << "record is corrupt" << endl;
+ }
+ // Extract the offsets from the record. Determine field pointers.
+ std::vector<pi_uint16_t> offsets(getNumOfFields());
+ for (i = 0; i < getNumOfFields(); ++i) {
+ offsets[i] = get_short(record.data() + i * sizeof(pi_uint16_t));
+ if (offsets[i] >= record.size()) {
+// throw PalmLib::error("record is corrupt");
+ kdDebug() << "record is corrupt" << endl;
+ }
+ ptrs.push_back(record.data() + offsets[i]);
+ }
+
+ // Determine the field sizes.
+ for (i = 0; i < getNumOfFields() - 1; ++i) {
+ sizes.push_back(offsets[i + 1] - offsets[i]);
+ }
+ sizes.push_back(record.size() - offsets[getNumOfFields() - 1]);
+}
+
+PalmLib::FlatFile::DB::DB(PalmLib::Database& pdb)
+ : Database("db", pdb), m_flags(0)
+{
+ // Split the application information block into its component chunks.
+ extract_chunks(pdb.getAppInfoBlock());
+
+ // Pull the header fields and schema out of the databasse.
+ m_flags = get_short(pdb.getAppInfoBlock().data());
+ unsigned numFields = get_short(pdb.getAppInfoBlock().data() + 2);
+ extract_schema(numFields);
+
+ // Extract all of the list views.
+ extract_listviews();
+
+ extract_aboutinfo();
+
+ for (unsigned i = 0; i < pdb.getNumRecords(); ++i) {
+ PalmLib::Record record = pdb.getRecord(i);
+ Record rec;
+
+ std::vector<pi_char_t *> ptrs;
+ std::vector<size_t> sizes;
+ parse_record(record, ptrs, sizes);
+ for (unsigned j = 0; j < getNumOfFields(); ++j) {
+ PalmLib::FlatFile::Field f;
+ f.type = field_type(j);
+
+ switch (field_type(j)) {
+ case PalmLib::FlatFile::Field::STRING:
+ f.type = PalmLib::FlatFile::Field::STRING;
+ f.v_string = std::string((char *) ptrs[j], sizes[j] - 1);
+ break;
+
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ f.type = PalmLib::FlatFile::Field::BOOLEAN;
+ if (*(ptrs[j]))
+ f.v_boolean = true;
+ else
+ f.v_boolean = false;
+ break;
+
+ case PalmLib::FlatFile::Field::INTEGER:
+ f.type = PalmLib::FlatFile::Field::INTEGER;
+ f.v_integer = PalmLib::get_long(ptrs[j]);
+ break;
+
+ case PalmLib::FlatFile::Field::FLOAT: {
+ // Place data from database in a union for conversion.
+ pi_double_t value;
+ value.words.hi = PalmLib::get_long(ptrs[j]);
+ value.words.lo = PalmLib::get_long(ptrs[j] + 4);
+
+ // Fill out the information for this field.
+ f.type = PalmLib::FlatFile::Field::FLOAT;
+ f.v_float = value.number;
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::DATE:
+ f.type = PalmLib::FlatFile::Field::DATE;
+ f.v_date.year = PalmLib::get_short(ptrs[j]);
+ f.v_date.month = static_cast<int> (*(ptrs[j] + 2));
+ f.v_date.day = static_cast<int> (*(ptrs[j] + 3));
+ break;
+
+ case PalmLib::FlatFile::Field::TIME:
+ f.type = PalmLib::FlatFile::Field::TIME;
+ f.v_time.hour = static_cast<int> (*(ptrs[j]));
+ f.v_time.minute = static_cast<int> (*(ptrs[j] + 1));
+ break;
+
+ case PalmLib::FlatFile::Field::NOTE:
+ f.type = PalmLib::FlatFile::Field::NOTE;
+ f.v_string = std::string((char *) ptrs[j], sizes[j] - 3);
+ f.v_note = std::string((char *) (record.data() + get_short(ptrs[j] + strlen(f.v_string.c_str()) + 1)));
+ break;
+
+ case PalmLib::FlatFile::Field::LIST:
+ f.type = PalmLib::FlatFile::Field::LIST;
+ if (!field(j).argument().empty()) {
+ std::string data = field(j).argument();
+ unsigned int k;
+ std::string::size_type pos = 0;
+ pi_uint16_t itemID = *ptrs[j]; // TR: a list value is stored on 1 byte
+
+ for (k = 0; k < itemID; k++) {
+ if ((pos = data.find(charSeperator, pos)) == std::string::npos) {
+ break;
+ }
+ pos++;
+ }
+ if (pos == std::string::npos) {
+ f.v_string = "N/A";
+ } else {
+ if (data.find(charSeperator, pos) == std::string::npos) {
+ f.v_string = data.substr( pos, std::string::npos);
+ } else {
+ f.v_string = data.substr( pos, data.find(charSeperator, pos) - pos);
+ }
+ }
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::LINK:
+ f.type = PalmLib::FlatFile::Field::LINK;
+ f.v_integer = PalmLib::get_long(ptrs[j]);
+ f.v_string = std::string((char *) (ptrs[j] + 4), sizes[j] - 5);
+ break;
+
+ case PalmLib::FlatFile::Field::LINKED:
+ f.type = PalmLib::FlatFile::Field::LINKED;
+ f.v_string = std::string((char *) ptrs[j], sizes[j] - 1);
+ break;
+
+ case PalmLib::FlatFile::Field::CALCULATED: {
+ std::ostringstream value;
+ f.type = PalmLib::FlatFile::Field::CALCULATED;
+ switch (ptrs[j][0]) {
+ case 1: //string
+ value << std::string((char *) ptrs[j] + 1, sizes[j] - 2);
+ break;
+ case 2: //integer
+ value << PalmLib::get_long(ptrs[j] + 1);
+ break;
+ case 9: //float
+ {
+ pi_double_t fvalue;
+ fvalue.words.hi = PalmLib::get_long(ptrs[j] + 1);
+ fvalue.words.lo = PalmLib::get_long(ptrs[j] + 5);
+
+ value << fvalue.number;
+ }
+ default:
+ value << "N/A";
+ }
+ f.v_string = value.str();
+ } break;
+
+ default:
+ kdDebug() << "unknown field type" << endl;
+ break;
+ }
+
+ // Append this field to the record.
+ rec.appendField(f);
+ }
+ rec.unique_id(record.unique_id());
+ // Append this record to the database.
+ appendRecord(rec);
+ }
+}
+
+void PalmLib::FlatFile::DB::make_record(PalmLib::Record& pdb_record,
+ const Record& record) const
+{
+ unsigned int i;
+
+ // Determine the packed size of this record.
+ size_t size = getNumOfFields() * sizeof(pi_uint16_t);
+ for (i = 0; i < getNumOfFields(); i++) {
+#ifdef HAVE_VECTOR_AT
+ const Field field = record.fields().at(i);
+#else
+ const Field field = record.fields()[i];
+#endif
+ switch (field.type) {
+ case PalmLib::FlatFile::Field::STRING:
+ size += field.v_string.length() + 1;
+ break;
+
+ case PalmLib::FlatFile::Field::NOTE:
+ size += field.v_string.length() + 3;
+ size += field.v_note.length() + 1;
+ break;
+
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ size += 1;
+ break;
+
+ case PalmLib::FlatFile::Field::INTEGER:
+ size += 4;
+ break;
+
+ case PalmLib::FlatFile::Field::FLOAT:
+ size += 8;
+ break;
+
+ case PalmLib::FlatFile::Field::DATE:
+ size += sizeof(pi_uint16_t) + 2 * sizeof(pi_char_t);
+ break;
+
+ case PalmLib::FlatFile::Field::TIME:
+ size += 2 * sizeof(pi_char_t);
+ break;
+
+ case PalmLib::FlatFile::Field::LIST:
+ size += sizeof(pi_char_t);
+ break;
+
+ case PalmLib::FlatFile::Field::LINK:
+ size += sizeof(pi_int32_t);
+ size += field.v_string.length() + 1;
+ break;
+
+ case PalmLib::FlatFile::Field::LINKED:
+ size += field.v_string.length() + 1;
+ break;
+
+ case PalmLib::FlatFile::Field::CALCULATED:
+ size += 1;
+ break;
+
+ default:
+ kdDebug() << "unsupported field type" << endl;
+ break;
+ }
+ }
+
+ // Allocate a block for the packed record and setup the pointers.
+ pi_char_t* buf = new pi_char_t[size];
+ pi_char_t* p = buf + getNumOfFields() * sizeof(pi_uint16_t);
+ pi_char_t* offsets = buf;
+
+ // Pack the fields into the buffer.
+ for (i = 0; i < getNumOfFields(); i++) {
+ pi_char_t* noteOffsetOffset = 0;
+ bool setNote = false;
+#ifdef HAVE_VECTOR_AT
+ const Field fieldData = record.fields().at(i);
+#else
+ const Field fieldData = record.fields()[i];
+#endif
+
+ // Mark the offset to the start of this field in the offests table.
+ PalmLib::set_short(offsets, static_cast<pi_uint16_t> (p - buf));
+ offsets += sizeof(pi_uint16_t);
+
+ // Pack the field.
+ switch (fieldData.type) {
+ case PalmLib::FlatFile::Field::STRING:
+ memcpy(p, fieldData.v_string.c_str(), fieldData.v_string.length() + 1);
+ p += fieldData.v_string.length() + 1;
+ break;
+
+ case PalmLib::FlatFile::Field::NOTE:
+ if (setNote)
+ kdDebug() << "unsupported field type";
+ memcpy(p, fieldData.v_string.c_str(), fieldData.v_string.length() + 1);
+ p += fieldData.v_string.length() + 1;
+ noteOffsetOffset = p;
+ p += 2;
+ setNote = true;
+ break;
+
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ *p++ = ((fieldData.v_boolean) ? 1 : 0);
+ break;
+
+ case PalmLib::FlatFile::Field::INTEGER:
+ PalmLib::set_long(p, fieldData.v_integer);
+ p += sizeof(pi_int32_t);
+ break;
+
+ case PalmLib::FlatFile::Field::FLOAT: {
+ // Place data the data in a union for easy conversion.
+ pi_double_t value;
+ value.number = fieldData.v_float;
+ PalmLib::set_long(p, value.words.hi);
+ p += sizeof(pi_uint32_t);
+ PalmLib::set_long(p, value.words.lo);
+ p += sizeof(pi_uint32_t);
+ break;
+ }
+
+ case PalmLib::FlatFile::Field::DATE:
+ PalmLib::set_short(p, fieldData.v_date.year);
+ p += sizeof(pi_uint16_t);
+ *p++ = static_cast<pi_char_t> (fieldData.v_date.month & 0xFF);
+ *p++ = static_cast<pi_char_t> (fieldData.v_date.day & 0xFF);
+ break;
+
+ case PalmLib::FlatFile::Field::TIME:
+ *p++ = static_cast<pi_char_t> (fieldData.v_time.hour & 0xFF);
+ *p++ = static_cast<pi_char_t> (fieldData.v_time.minute & 0xFF);
+ break;
+
+ case PalmLib::FlatFile::Field::LIST:
+ if (!field(i).argument().empty()) {
+ std::string data = field(i).argument();
+ std::string::size_type pos = 0, next;
+ unsigned int j = 0;
+ pi_int16_t itemID = -1;
+
+ while ( (next = data.find(charSeperator, pos)) != std::string::npos) {
+ if (fieldData.v_string == data.substr( pos, next - pos)) {
+ itemID = j;
+ break;
+ }
+ j++;
+ pos = next + 1;
+ }
+ // TR: the following test handles the case where the field value
+ // equals the last item in list (bugfix)
+ if (itemID == -1 && fieldData.v_string == data.substr( pos, std::string::npos)) {
+ itemID = j;
+ }
+ p[0] = itemID; // TR: a list value is stored on 1 byte
+ p += sizeof(pi_char_t);
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::LINK:
+ PalmLib::set_long(p, fieldData.v_integer);
+ p += sizeof(pi_int32_t);
+ memcpy(p, fieldData.v_string.c_str(), fieldData.v_string.length() + 1);
+ p += fieldData.v_string.length() + 1;
+ break;
+
+ case PalmLib::FlatFile::Field::LINKED:
+ memcpy(p, fieldData.v_string.c_str(), fieldData.v_string.length() + 1);
+ p += fieldData.v_string.length() + 1;
+ break;
+
+ case PalmLib::FlatFile::Field::CALCULATED:
+ *p = 13;
+ p++;
+ break;
+
+ default:
+ kdDebug() << "unsupported field type";
+ break;
+ }
+ if (setNote) {
+ if (fieldData.v_note.length()) {
+ memcpy(p, fieldData.v_note.c_str(), fieldData.v_note.length() + 1);
+ PalmLib::set_short(noteOffsetOffset, (pi_uint16_t)(p - buf));
+ p += fieldData.v_note.length() + 1;
+ } else {
+ PalmLib::set_short(noteOffsetOffset, 0);
+ }
+ }
+ }
+
+ // Place the packed data into the PalmOS record.
+ pdb_record.set_raw(buf, size);
+ delete [] buf;
+}
+
+void PalmLib::FlatFile::DB::build_fieldsdata_chunks(std::vector<DB::Chunk>& chunks) const
+{
+ pi_char_t * buf = 0, * p;
+ unsigned int size, i;
+
+ for (i = 0; i < getNumOfFields(); ++i) {
+ size = 0;
+ switch (field_type(i)) {
+ case PalmLib::FlatFile::Field::STRING:
+ if (!field(i).argument().empty()) {
+ size = (field(i).argument().length() + 1) + 2;
+ buf = new pi_char_t[size];
+ PalmLib::set_short(buf, i);
+ strcpy((char *) (buf + 2), field(i).argument().c_str());
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ break;
+
+ case PalmLib::FlatFile::Field::INTEGER:
+ if (!field(i).argument().empty()) {
+ std::string data = field(i).argument();
+ std::pair< PalmLib::pi_int32_t, PalmLib::pi_int16_t> values(0, 0);
+
+ if ( data.find(charSeperator) != std::string::npos) {
+ StrOps::convert_string(data.substr( 0, data.find(charSeperator)), values.first);
+ StrOps::convert_string(data.substr( data.find(charSeperator) + 1, std::string::npos), values.second);
+ } else
+ StrOps::convert_string(data, values.first);
+
+ size = 2 + sizeof(pi_uint32_t) + sizeof(pi_uint16_t);
+ buf = new pi_char_t[size];
+ p = buf;
+ PalmLib::set_short(p, i);
+ p += sizeof(pi_uint16_t);
+ PalmLib::set_long(p, values.first);
+ p += sizeof(pi_uint32_t);
+ PalmLib::set_short(p, values.second);
+ p += sizeof(pi_uint16_t);
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::FLOAT:
+ if (!field(i).argument().empty()) {
+ std::string data = field(i).argument();
+ pi_double_t value;
+
+ StrOps::convert_string(data, value.number);
+
+ size = 2 + 2 * sizeof(pi_uint32_t);
+ buf = new pi_char_t[size];
+ p = buf;
+ PalmLib::set_short(p, i);
+ p += sizeof(pi_uint16_t);
+ PalmLib::set_long(p, value.words.hi);
+ p += sizeof(pi_uint32_t);
+ PalmLib::set_long(p, value.words.lo);
+ p += sizeof(pi_uint32_t);
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::DATE:
+ if (!field(i).argument().empty()) {
+ std::string data = field(i).argument();
+ struct tm date;
+ pi_char_t type;
+
+ if (data.substr(0, 3) == "now") {
+ type = NOW_DEFAULT;
+ const struct tm * tm_ptr;
+ time_t now;
+
+ time(&now);
+ tm_ptr = localtime(&now);
+ memcpy(&date, tm_ptr, sizeof(tm));
+ } else
+#ifdef strptime
+ if (strptime(data.c_str(), "%Y/%m/%d", &date))
+#else
+ if (StrOps::strptime(data.c_str(), "%Y/%m/%d", &date))
+#endif
+ type = CONSTANT_DEFAULT;
+ else
+ type = INVALID_DEFAULT;
+
+ if (type != INVALID_DEFAULT) {
+ size = sizeof(pi_uint16_t) + 1 + sizeof(pi_uint16_t) + 2;
+ buf = new pi_char_t[size];
+ p = buf;
+ PalmLib::set_short(p, i);
+ p += sizeof(pi_uint16_t);
+ *p++ = static_cast<pi_char_t> (type & 0xFF);
+ PalmLib::set_short(p, date.tm_year + 1900);
+ p += sizeof(pi_uint16_t);
+ *p++ = static_cast<pi_char_t> ((date.tm_mon + 1) & 0xFF);
+ *p++ = static_cast<pi_char_t> (date.tm_mday & 0xFF);
+ }
+
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::TIME:
+ if (!field(i).argument().empty()) {
+ std::string data = field(i).argument();
+ struct tm t;
+ pi_char_t type;
+
+ if (data == "now") {
+ type = NOW_DEFAULT;
+ const struct tm * tm_ptr;
+ time_t now;
+
+ time(&now);
+ tm_ptr = localtime(&now);
+ memcpy(&t, tm_ptr, sizeof(tm));
+ } else
+#ifdef strptime
+ if (!strptime(data.c_str(), "%H/%M", &t))
+#else
+ if (!StrOps::strptime(data.c_str(), "%H/%M", &t))
+#endif
+ type = CONSTANT_DEFAULT;
+ else
+ type = INVALID_DEFAULT;
+
+ if (type != INVALID_DEFAULT) {
+ size = sizeof(pi_uint16_t) + 1 + sizeof(pi_uint16_t) + 2;
+ buf = new pi_char_t[size];
+ p = buf;
+ PalmLib::set_short(p, i);
+ p += sizeof(pi_uint16_t);
+ *p++ = static_cast<pi_char_t> (type & 0xFF);
+ *p++ = static_cast<pi_char_t> (t.tm_hour & 0xFF);
+ *p++ = static_cast<pi_char_t> (t.tm_min & 0xFF);
+ }
+
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::NOTE:
+ break;
+
+ case PalmLib::FlatFile::Field::LIST:
+ if (!field(i).argument().empty()) {
+ std::string data = field(i).argument();
+ std::vector<std::string> items;
+ std::string::size_type pos = 0, next;
+ std::vector<std::string>::iterator iter;
+ size = 2 + 2 * sizeof(pi_uint16_t);
+ while ( (next = data.find(charSeperator, pos)) != std::string::npos) {
+ std::string item = data.substr( pos, next - pos);
+ items.push_back(item);
+ size += item.length() + 1;
+ pos = next + 1;
+ }
+ if (pos != std::string::npos) {
+ std::string item = data.substr( pos, std::string::npos);
+ items.push_back(item);
+ size += item.length() + 1;
+ }
+
+ buf = new pi_char_t[size];
+ p = buf;
+ PalmLib::set_short(p, i);
+ p += sizeof(pi_uint16_t);
+ PalmLib::set_short(p, items.size());
+ p += sizeof(pi_uint16_t);
+ p += sizeof(pi_uint16_t);
+ for (iter = items.begin(); iter != items.end(); ++iter) {
+ std::string& item = (*iter);
+ strcpy((char *) p, item.c_str());
+ p[item.length()] = 0;
+ p += item.length() + 1;
+ }
+
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::LINK:
+ if (!field(i).argument().empty()) {
+ std::string data = field(i).argument();
+ std::string databasename;
+ pi_uint16_t fieldnum;
+
+ if ( data.find(charSeperator) != std::string::npos) {
+ databasename = data.substr( 0, data.find(charSeperator));
+ StrOps::convert_string(data.substr( data.find(charSeperator) + 1, std::string::npos), fieldnum);
+ } else {
+ databasename = data;
+ fieldnum = 0;
+ }
+
+ size = 2 + 32 * sizeof(pi_char_t) + sizeof(pi_uint16_t);
+ buf = new pi_char_t[size];
+ p = buf;
+ PalmLib::set_short(p, i);
+ p += sizeof(pi_uint16_t);
+ strcpy((char *) p, databasename.c_str());
+ p += 32 * sizeof(pi_char_t);
+ PalmLib::set_short(p, fieldnum);
+ p += sizeof(pi_uint16_t);
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::LINKED:
+ if (!field(i).argument().empty()) {
+ std::string data = field(i).argument();
+ pi_uint16_t linknum;
+ pi_uint16_t fieldnum;
+
+ if ( data.find(charSeperator) != std::string::npos) {
+ StrOps::convert_string(data.substr( 0, data.find(charSeperator)), linknum);
+ StrOps::convert_string(data.substr( data.find(charSeperator) + 1, std::string::npos), fieldnum);
+ if (field_type(linknum) != PalmLib::FlatFile::Field::LINK) {
+ unsigned int j = 0;
+ while (field_type(j) != PalmLib::FlatFile::Field::LINK && j < i) j++;
+ linknum = j;
+ }
+ } else {
+ unsigned int j = 0;
+ while (field_type(j) != PalmLib::FlatFile::Field::LINK && j < i) j++;
+ linknum = j;
+ fieldnum = 0;
+ }
+
+ size = 2 + 2 * sizeof(pi_uint16_t);
+ buf = new pi_char_t[size];
+ p = buf;
+ PalmLib::set_short(p, i);
+ p += sizeof(pi_uint16_t);
+ PalmLib::set_short(p, linknum);
+ p += sizeof(pi_uint16_t);
+ PalmLib::set_short(p, fieldnum);
+ p += sizeof(pi_uint16_t);
+ }
+ break;
+
+ case PalmLib::FlatFile::Field::CALCULATED:
+ break;
+
+ default:
+ kdDebug() << "unknown field type" << endl;
+ break;
+ }
+
+ if (size) {
+ Chunk data_chunk(buf, size);
+ data_chunk.chunk_type = CHUNK_FIELD_DATA;
+ delete [] buf;
+ chunks.push_back(data_chunk);
+ }
+ }
+}
+
+void PalmLib::FlatFile::DB::build_about_chunk(std::vector<DB::Chunk>& chunks) const
+{
+ pi_char_t* buf;
+ pi_char_t* p;
+ int headersize = 2*sizeof(pi_uint16_t);
+ std::string information = getAboutInformation();
+
+ if (!information.length())
+ return;
+ // Build the names chunk.
+ buf = new pi_char_t[headersize + information.length() + 1];
+ p = buf;
+
+ PalmLib::set_short(p, headersize);
+ p += 2;
+ PalmLib::set_short(p, 1); //about type version
+ p += 2;
+ memcpy(p, information.c_str(), information.length() + 1);
+ p += information.length() + 1;
+ Chunk chunk(buf, headersize + information.length() + 1);
+ chunk.chunk_type = CHUNK_ABOUT;
+ delete [] buf;
+ chunks.push_back(chunk);
+
+}
+
+void PalmLib::FlatFile::DB::build_standard_chunks(std::vector<DB::Chunk>& chunks) const
+{
+ pi_char_t* buf;
+ pi_char_t* p;
+ unsigned i;
+
+ // Determine the size needed for the names chunk.
+ size_t names_chunk_size = 0;
+ for (i = 0; i < getNumOfFields(); ++i) {
+ names_chunk_size += field_name(i).length() + 1;
+ }
+
+ // Build the names chunk.
+ buf = new pi_char_t[names_chunk_size];
+ p = buf;
+ for (i = 0; i < getNumOfFields(); ++i) {
+ const std::string name = field_name(i);
+ memcpy(p, name.c_str(), name.length() + 1);
+ p += name.length() + 1;
+ }
+ Chunk names_chunk(buf, names_chunk_size);
+ names_chunk.chunk_type = CHUNK_FIELD_NAMES;
+ delete [] buf;
+
+ // Build the types chunk.
+ buf = new pi_char_t[getNumOfFields() * sizeof(pi_uint16_t)];
+ p = buf;
+ for (i = 0; i < getNumOfFields(); ++i) {
+ // Pack the type of the current field.
+ switch (field_type(i)) {
+ case PalmLib::FlatFile::Field::STRING:
+ PalmLib::set_short(p, 0);
+ break;
+
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ PalmLib::set_short(p, 1);
+ break;
+
+ case PalmLib::FlatFile::Field::INTEGER:
+ PalmLib::set_short(p, 2);
+ break;
+
+ case PalmLib::FlatFile::Field::DATE:
+ PalmLib::set_short(p, 3);
+ break;
+
+ case PalmLib::FlatFile::Field::TIME:
+ PalmLib::set_short(p, 4);
+ break;
+
+ case PalmLib::FlatFile::Field::NOTE:
+ PalmLib::set_short(p, 5);
+ break;
+
+ case PalmLib::FlatFile::Field::LIST:
+ PalmLib::set_short(p, 6);
+ break;
+
+ case PalmLib::FlatFile::Field::LINK:
+ PalmLib::set_short(p, 7);
+ break;
+
+ case PalmLib::FlatFile::Field::FLOAT:
+ PalmLib::set_short(p, 8);
+ break;
+
+ case PalmLib::FlatFile::Field::CALCULATED:
+ PalmLib::set_short(p, 9);
+ break;
+
+ case PalmLib::FlatFile::Field::LINKED:
+ PalmLib::set_short(p, 10);
+ break;
+
+ default:
+ kdDebug() << "unsupported field type" << endl;
+ break;
+ }
+
+ // Advance to the next position.
+ p += sizeof(pi_uint16_t);
+ }
+ Chunk types_chunk(buf, getNumOfFields() * sizeof(pi_uint16_t));
+ types_chunk.chunk_type = CHUNK_FIELD_TYPES;
+ delete [] buf;
+
+ // Build the list view options chunk.
+ buf = new pi_char_t[2 * sizeof(pi_uint16_t)];
+ PalmLib::set_short(buf, 0);
+ PalmLib::set_short(buf + sizeof(pi_uint16_t), 0);
+ Chunk listview_options_chunk(buf, 2 * sizeof(pi_uint16_t));
+ listview_options_chunk.chunk_type = CHUNK_LISTVIEW_OPTIONS;
+ delete [] buf;
+
+ // Build the local find options chunk.
+ buf = new pi_char_t[sizeof(pi_uint16_t)];
+ PalmLib::set_short(buf, 0);
+ Chunk lfind_options_chunk(buf, 1 * sizeof(pi_uint16_t));
+ lfind_options_chunk.chunk_type = CHUNK_LFIND_OPTIONS;
+ delete [] buf;
+
+ // Add all the chunks to the chunk list.
+ chunks.push_back(names_chunk);
+ chunks.push_back(types_chunk);
+ chunks.push_back(listview_options_chunk);
+ chunks.push_back(lfind_options_chunk);
+}
+
+void PalmLib::FlatFile::DB::build_listview_chunk(std::vector<DB::Chunk>& chunks,
+ const ListView& lv) const
+{
+ // Calculate size and allocate space for the temporary buffer.
+ size_t size = 2 * sizeof(pi_uint16_t) + 32
+ + lv.size() * (2 * sizeof(pi_uint16_t));
+ pi_char_t* buf = new pi_char_t[size];
+
+ // Fill in the header details.
+ pi_uint16_t flags = 0;
+ if (lv.editoruse) {
+ std::cout << "editoruse\n";
+ flags |= VIEWFLAG_USE_IN_EDITVIEW;
+ }
+ PalmLib::set_short(buf, flags);
+ PalmLib::set_short(buf + sizeof(pi_uint16_t), lv.size());
+ memset((char *) (buf + 4), 0, 32);
+ strncpy((char *) (buf + 4), lv.name.c_str(), 32);
+
+ // Fill in the column details.
+ pi_char_t* p = buf + 4 + 32;
+ for (ListView::const_iterator i = lv.begin(); i != lv.end(); ++i) {
+ const ListViewColumn& col = (*i);
+ PalmLib::set_short(p, col.field);
+ PalmLib::set_short(p + sizeof(pi_uint16_t), col.width);
+ p += 2 * sizeof(pi_uint16_t);
+ }
+
+ // Create the chunk and place it in the chunks list.
+ Chunk chunk(buf, size);
+ chunk.chunk_type = CHUNK_LISTVIEW_DEFINITION;
+ delete [] buf;
+ chunks.push_back(chunk);
+}
+
+void PalmLib::FlatFile::DB::build_appinfo_block(const std::vector<DB::Chunk>& chunks, PalmLib::Block& appinfo) const
+{
+ std::vector<Chunk>::const_iterator iter;
+
+ // Determine the size of the final app info block.
+ size_t size = 2 * sizeof(pi_uint16_t);
+ for (iter = chunks.begin(); iter != chunks.end(); ++iter) {
+ const Chunk& chunk = (*iter);
+ size += 2 * sizeof(pi_uint16_t) + chunk.size();
+ }
+
+ // Allocate the temporary buffer. Fill in the header.
+ pi_char_t* buf = new pi_char_t[size];
+ PalmLib::set_short(buf, m_flags);
+ PalmLib::set_short(buf + sizeof(pi_uint16_t), getNumOfFields());
+
+ // Pack the chunks into the buffer.
+ size_t i = 4;
+ for (iter = chunks.begin(); iter != chunks.end(); ++iter) {
+ const Chunk& chunk = (*iter);
+ // Set the chunk type and size.
+ PalmLib::set_short(buf + i, chunk.chunk_type);
+ PalmLib::set_short(buf + i + 2, chunk.size());
+ i += 4;
+
+ // Copy the chunk data into the buffer.
+ memcpy(buf + i, chunk.data(), chunk.size());
+ i += chunk.size();
+ }
+
+ // Finally, move the buffer into the provided appinfo block.
+ appinfo.set_raw(buf, size);
+ delete [] buf;
+}
+
+void PalmLib::FlatFile::DB::outputPDB(PalmLib::Database& pdb) const
+{
+ unsigned i;
+
+ // Let the superclass have a chance.
+ SUPERCLASS(PalmLib::FlatFile, Database, outputPDB, (pdb));
+
+ // Set the database's type and creator.
+ pdb.type(PalmLib::mktag('D','B','0','0'));
+ pdb.creator(PalmLib::mktag('D','B','O','S'));
+
+ // Create the app info block.
+ std::vector<Chunk> chunks;
+ build_standard_chunks(chunks);
+ for (i = 0; i < getNumOfListViews(); ++i) {
+ build_listview_chunk(chunks, getListView(i));
+ }
+ build_fieldsdata_chunks(chunks);
+ build_about_chunk(chunks);
+
+ PalmLib::Block appinfo;
+ build_appinfo_block(chunks, appinfo);
+ pdb.setAppInfoBlock(appinfo);
+
+ // Output each record to the PalmOS database.
+ for (i = 0; i < getNumRecords(); ++i) {
+ Record record = getRecord(i);
+ PalmLib::Record pdb_record;
+
+ make_record(pdb_record, record);
+ pdb.appendRecord(pdb_record);
+ }
+}
+
+unsigned PalmLib::FlatFile::DB::getMaxNumOfFields() const
+{
+ return 0;
+}
+
+bool
+PalmLib::FlatFile::DB::supportsFieldType(const Field::FieldType& type) const
+{
+ switch (type) {
+ case PalmLib::FlatFile::Field::STRING:
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ case PalmLib::FlatFile::Field::INTEGER:
+ case PalmLib::FlatFile::Field::FLOAT:
+ case PalmLib::FlatFile::Field::DATE:
+ case PalmLib::FlatFile::Field::TIME:
+ case PalmLib::FlatFile::Field::NOTE:
+ case PalmLib::FlatFile::Field::LIST:
+ case PalmLib::FlatFile::Field::LINK:
+ case PalmLib::FlatFile::Field::LINKED:
+ case PalmLib::FlatFile::Field::CALCULATED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+std::vector<std::string>
+PalmLib::FlatFile::DB::field_argumentf(int i, std::string& format)
+{
+ std::vector<std::string> vtitles(0, std::string(""));
+ int j;
+
+ switch (field_type(i)) {
+ case PalmLib::FlatFile::Field::STRING:
+ format = std::string("%s");
+ vtitles.push_back(std::string("default value"));
+ break;
+ case PalmLib::FlatFile::Field::INTEGER:
+ format = std::string("%ld/%d");
+ vtitles.push_back(std::string("default value"));
+ vtitles.push_back(std::string("increment"));
+ break;
+ case PalmLib::FlatFile::Field::FLOAT:
+ format = std::string("%f");
+ vtitles.push_back(std::string("default value"));
+ break;
+ case PalmLib::FlatFile::Field::DATE:
+ format = std::string("%d/%d/%d");
+ vtitles.push_back(std::string("Year (or now)"));
+ vtitles.push_back(std::string("Month"));
+ vtitles.push_back(std::string("Day in the month"));
+ break;
+ case PalmLib::FlatFile::Field::TIME:
+ format = std::string("%d/%d");
+ vtitles.push_back(std::string("Hour (or now)"));
+ vtitles.push_back(std::string("Minute"));
+ break;
+ case PalmLib::FlatFile::Field::LIST:
+ format = std::string("");
+ for (j = 0; j < 31; i++) {
+ format += std::string("%s/");
+ std::ostringstream title;
+ title << "item " << j;
+ vtitles.push_back(title.str());
+ }
+ format += std::string("%s");
+ vtitles.push_back(std::string("item 32"));
+ break;
+ case PalmLib::FlatFile::Field::LINK:
+ format = std::string("%s/%d");
+ vtitles.push_back(std::string("database"));
+ vtitles.push_back(std::string("field number"));
+ break;
+ case PalmLib::FlatFile::Field::LINKED:
+ format = std::string("%d/%d");
+ vtitles.push_back(std::string("link field number"));
+ vtitles.push_back(std::string("field number"));
+ break;
+ case PalmLib::FlatFile::Field::CALCULATED:
+ case PalmLib::FlatFile::Field::BOOLEAN:
+ case PalmLib::FlatFile::Field::NOTE:
+ default:
+ format = std::string("");
+ break;
+ }
+ return vtitles;
+}
+
+unsigned PalmLib::FlatFile::DB::getMaxNumOfListViews() const
+{
+ return 0;
+}
+
+void PalmLib::FlatFile::DB::doneWithSchema()
+{
+ // Let the superclass have a chance.
+ SUPERCLASS(PalmLib::FlatFile, Database, doneWithSchema, ());
+/* false from the 0.3.3 version
+ if (getNumOfListViews() < 1)
+ throw PalmLib::error("at least one list view must be specified");
+*/
+}
+
+void PalmLib::FlatFile::DB::setOption(const std::string& name,
+ const std::string& value)
+{
+ if (name == "find") {
+ if (!StrOps::string2boolean(value))
+ m_flags &= ~(1);
+ else
+ m_flags |= 1;
+ } else if (name == "read-only"
+ || name == "readonly") {
+ if (!StrOps::string2boolean(value))
+ m_flags &= ~(0x8000);
+ else
+ m_flags |= 0x8000;
+ } else {
+ SUPERCLASS(PalmLib::FlatFile, Database, setOption, (name, value));
+ }
+}
+
+PalmLib::FlatFile::Database::options_list_t
+PalmLib::FlatFile::DB::getOptions(void) const
+{
+ typedef PalmLib::FlatFile::Database::options_list_t::value_type value;
+ PalmLib::FlatFile::Database::options_list_t result;
+
+ result = SUPERCLASS(PalmLib::FlatFile, Database, getOptions, ());
+
+ if (m_flags & 1)
+ result.push_back(value("find", "true"));
+
+ if (m_flags & 0x8000)
+ result.push_back(value("read-only", "true"));
+
+ return result;
+}
diff --git a/src/translators/pilotdb/libflatfile/DB.h b/src/translators/pilotdb/libflatfile/DB.h
new file mode 100644
index 0000000..dd09d36
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/DB.h
@@ -0,0 +1,166 @@
+/*
+ * This class provides access to DB-format databases.
+ */
+
+#ifndef __PALMLIB_FLATFILE_DB_H__
+#define __PALMLIB_FLATFILE_DB_H__
+
+#include <map>
+#include <string>
+
+#include "../libpalm/Block.h"
+#include "../libpalm/Database.h"
+#include "Database.h"
+
+namespace PalmLib {
+ namespace FlatFile {
+
+ class DB : public Database {
+ public:
+ /**
+ * Return true if this class can handle the given PalmOS
+ * database.
+ *
+ * @param pdb PalmOS database to check for support.
+ */
+ static bool classify(PalmLib::Database& pdb);
+
+ /**
+ * Return true if this class is the database identified by
+ * name.
+ *
+ * @param name A database type name to check.
+ */
+ static bool match_name(const std::string& name);
+
+ /**
+ * Default constructor for an initially empty database.
+ */
+ DB():Database("db"), m_flags(0) { }
+
+ /**
+ * Constructor which fills the flat-file structure from a
+ * PalmOS database.
+ */
+ DB(PalmLib::Database&);
+
+ // destructor
+ virtual ~DB() { }
+
+ /**
+ * After all processing to add fields and records is done,
+ * outputPDB is called to create the actual file format
+ * used by the flat-file database product.
+ *
+ * @param pdb An instance of PalmLib::Database.
+ */
+ virtual void outputPDB(PalmLib::Database& pdb) const;
+
+ /**
+ * Return the maximum number of fields allowed in the
+ * database. This class returns 0 since there is no limit.
+ */
+ virtual unsigned getMaxNumOfFields() const;
+
+ /**
+ * Return true for the field types that this class
+ * currently supports. Returns false otherwise.
+ *
+ * @param type The field type to check for support.
+ */
+ virtual bool supportsFieldType(const Field::FieldType& type) const;
+
+ /**
+ * write the format of the field's argument in format,
+ * and return a strings' vector with name of each argument part.
+ * the format use the same display as used by printf
+ */
+ virtual std::vector<std::string> field_argumentf(int i, std::string& format);
+
+ /**
+ * Return the maximum number of views supported by this
+ * type of flat-file database.
+ */
+ virtual unsigned getMaxNumOfListViews() const;
+
+ /**
+ * Hook the end of the schema processing.
+ */
+ virtual void doneWithSchema();
+
+ /**
+ * Set a extra option.
+ *
+ * @param opt_name The name of the option to set.
+ * @param opt_value The value to assign to this option.
+ */
+ virtual void setOption(const std::string& name,
+ const std::string& value);
+
+ /**
+ * Get a list of extra options.
+ */
+ virtual options_list_t getOptions(void) const;
+
+ // Produce a PalmOS record from a flat-file record.
+ void make_record(PalmLib::Record& pdb_record,
+ const PalmLib::FlatFile::Record& record) const;
+
+ private:
+ pi_uint16_t m_flags;
+
+ class Chunk : public PalmLib::Block {
+ public:
+ Chunk() : PalmLib::Block(), chunk_type(0) { }
+ Chunk(const Chunk& rhs)
+ : PalmLib::Block(rhs), chunk_type(rhs.chunk_type) { }
+ Chunk(PalmLib::Block::const_pointer data,
+ const PalmLib::Block::size_type size)
+ : PalmLib::Block(data, size), chunk_type(0) { }
+ Chunk& operator = (const Chunk& rhs) {
+ Block::operator = (rhs);
+ chunk_type = rhs.chunk_type;
+ return *this;
+ }
+
+ pi_uint16_t chunk_type;
+ };
+
+ typedef std::map<pi_uint16_t, std::vector<Chunk> > chunks_t;
+ chunks_t m_chunks;
+
+ // Extract the chunks from an app info block to m_chunks.
+ void extract_chunks(const PalmLib::Block&);
+
+ // Extract the schema.
+ void extract_schema(unsigned numFields);
+
+ // Extract the list views from the app info block.
+ void extract_listviews();
+
+ //extract the field data
+ std::string extract_fieldsdata(pi_uint16_t field_search,
+ PalmLib::FlatFile::Field::FieldType type);
+
+ void extract_aboutinfo();
+
+ // Determine location and size of each field.
+ void parse_record(PalmLib::Record& record,
+ std::vector<pi_char_t *>& ptrs,
+ std::vector<size_t>& sizes);
+
+ // The following routines build various types of chunks
+ // for the app info block and assemble them all.
+ void build_fieldsdata_chunks(std::vector<Chunk>& chunks) const;
+ void build_standard_chunks(std::vector<Chunk>&) const;
+ void build_listview_chunk(std::vector<Chunk>&,
+ const ListView&) const;
+ void build_about_chunk(std::vector<Chunk>& chunks) const;
+ void build_appinfo_block(const std::vector<Chunk>&,
+ PalmLib::Block&) const;
+ };
+
+ }
+}
+
+#endif
diff --git a/src/translators/pilotdb/libflatfile/Database.cpp b/src/translators/pilotdb/libflatfile/Database.cpp
new file mode 100644
index 0000000..578b82d
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/Database.cpp
@@ -0,0 +1,331 @@
+/*
+ * palm-db-tools: Abstract adaptor for flat-file databases.
+ * Copyright (C) 1999-2000 by Tom Dyas ([email protected])
+ */
+
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <sstream>
+#include <utility>
+#include <cctype>
+
+#include <kdebug.h>
+
+#include "Database.h"
+
+PalmLib::FlatFile::Database::Database(std::string p_Type, const PalmLib::Database& pdb)
+ : m_Type(p_Type)
+{
+ title(pdb.name());
+ m_backup = pdb.backup();
+ m_readonly = pdb.readonly();
+ m_copy_prevention = pdb.copy_prevention();
+}
+
+void
+PalmLib::FlatFile::Database::outputPDB(PalmLib::Database& pdb) const
+{
+ pdb.name(title());
+ pdb.backup(m_backup);
+ pdb.readonly(m_readonly);
+ pdb.copy_prevention(m_copy_prevention);
+}
+
+std::string
+PalmLib::FlatFile::Database::title() const
+{
+ return m_title;
+}
+
+void
+PalmLib::FlatFile::Database::title(const std::string& title)
+{
+ m_title = title;
+}
+
+unsigned
+PalmLib::FlatFile::Database::getNumOfFields() const
+{
+ return m_fields.size();
+}
+
+std::string
+PalmLib::FlatFile::Database::field_name(int i) const
+{
+ return m_fields[i].title();
+/* return m_fields[i].first;*/
+}
+
+PalmLib::FlatFile::Field::FieldType
+PalmLib::FlatFile::Database::field_type(int i) const
+{
+ return m_fields[i].type();
+/* return m_fields[i].second;*/
+}
+
+PalmLib::FlatFile::FType
+PalmLib::FlatFile::Database::field(int i) const
+{
+ return m_fields[i];
+}
+
+void
+PalmLib::FlatFile::Database::appendField(PalmLib::FlatFile::FType field)
+{
+ if (! supportsFieldType(field.type())) {
+// throw PalmLib::error("unsupported field type");
+ kdDebug() << "unsupported field type" << endl;
+ return;
+ }
+ if (getMaxNumOfFields() != 0 && getNumOfFields() + 1 > getMaxNumOfFields()) {
+// throw PalmLib::error("maximum number of fields reached");
+ kdDebug() << "maximum number of fields reached" << endl;
+ return;
+ }
+ m_fields.push_back(field);
+}
+
+void
+PalmLib::FlatFile::Database::appendField(const std::string& name,
+ Field::FieldType type, std::string data)
+{
+ if (! supportsFieldType(type)) {
+ kdDebug() << "PalmLib::FlatFile::Database::appendField() - unsupported field type" << endl;
+ return;
+ }
+// throw PalmLib::error("unsupported field type");
+ if (getMaxNumOfFields() != 0 && getNumOfFields() + 1 > getMaxNumOfFields()) {
+ kdDebug() << "PalmLib::FlatFile::Database::appendField() - maximum number of fields reached" << endl;
+ return;
+ }
+// throw PalmLib::error("maximum number of fields reached");
+
+/* m_fields.push_back(std::make_pair(name, type));*/
+/* m_fields.push_back(PalmLib::FlatFile::make_ftype(name, type));*/
+ m_fields.push_back(PalmLib::FlatFile::FType(name, type, data));
+}
+
+void
+PalmLib::FlatFile::Database::insertField(int i, PalmLib::FlatFile::FType field)
+{
+ if (! supportsFieldType(field.type())) {
+// throw PalmLib::error("unsupported field type");
+ kdDebug() << "unsupported field type" << endl;
+ return;
+ }
+ if (getMaxNumOfFields() != 0 && getNumOfFields() + 1 > getMaxNumOfFields()) {
+// throw PalmLib::error("maximum number of fields reached");
+ kdDebug() << "maximum number of fields reached" << endl;
+ return;
+ }
+/* m_fields.push_back(std::make_pair(name, type));*/
+/* m_fields.push_back(PalmLib::FlatFile::make_ftype(name, type));*/
+ m_fields.insert(m_fields.begin() + i, field);
+}
+
+void
+PalmLib::FlatFile::Database::insertField(int i, const std::string& name,
+ Field::FieldType type, std::string data)
+{
+ if (! supportsFieldType(type)) {
+// throw PalmLib::error("unsupported field type");
+ kdDebug() << "unsupported field type" << endl;
+ return;
+ }
+ if (getMaxNumOfFields() != 0 && getNumOfFields() + 1 > getMaxNumOfFields()) {
+// throw PalmLib::error("maximum number of fields reached");
+ kdDebug() << "maximum number of fields reached" << endl;
+ return;
+ }
+/* m_fields.push_back(std::make_pair(name, type));*/
+/* m_fields.push_back(PalmLib::FlatFile::make_ftype(name, type));*/
+ m_fields.insert(m_fields.begin() + i, PalmLib::FlatFile::FType(name, type, data));
+}
+
+void
+PalmLib::FlatFile::Database::removeField(int i)
+{
+ m_fields.erase(m_fields.begin() + i);
+}
+
+unsigned
+PalmLib::FlatFile::Database::getNumRecords() const
+{
+ return m_records.size();
+}
+
+PalmLib::FlatFile::Record
+PalmLib::FlatFile::Database::getRecord(unsigned index) const
+{
+ if (index >= getNumRecords()) {
+ kdDebug() << "invalid index" << endl;
+ //throw std::out_of_range("invalid index");
+ }
+ return m_records[index];
+}
+
+void
+PalmLib::FlatFile::Database::appendRecord(PalmLib::FlatFile::Record rec)
+{
+ if (rec.fields().size() != getNumOfFields()) {
+// throw PalmLib::error("the number of fields mismatch");
+ kdDebug() << "the number of fields mismatch" << endl;
+ return;
+ }
+ for (unsigned int i = 0; i < getNumOfFields(); i++) {
+#ifdef HAVE_VECTOR_AT
+ const Field field = rec.fields().at(i);
+#else
+ const Field field = rec.fields()[i];
+#endif
+ if (field.type != field_type(i)) {
+ kdDebug() << "field " << i << " type " << field_type(i) << " mismatch: " << field.type << endl;
+ return;
+// throw PalmLib::error(buffer.str());
+ }
+ }
+ m_records.push_back(rec);
+}
+
+void
+PalmLib::FlatFile::Database::deleteRecord(unsigned index)
+{
+ m_records.erase(m_records.begin() + index);
+}
+
+void
+PalmLib::FlatFile::Database::clearRecords()
+{
+ m_records.clear();
+}
+
+unsigned
+PalmLib::FlatFile::Database::getNumOfListViews() const
+{
+ return m_listviews.size();
+}
+
+PalmLib::FlatFile::ListView
+PalmLib::FlatFile::Database::getListView(unsigned index) const
+{
+ return m_listviews[index];
+}
+
+void
+PalmLib::FlatFile::Database::setListView(unsigned index,
+ const PalmLib::FlatFile::ListView& lv)
+{
+ // Ensure that the field numbers are within range.
+ for (PalmLib::FlatFile::ListView::const_iterator i = lv.begin();
+ i != lv.end(); ++i) {
+ if ((*i).field >= getNumOfFields())
+ return;
+ }
+
+ m_listviews[index] = lv;
+}
+
+void
+PalmLib::FlatFile::Database::appendListView(const ListView& lv)
+{
+ // Enforce any limit of the maximum number of list views.
+ if (getMaxNumOfListViews() != 0
+ && getNumOfListViews() + 1 > getMaxNumOfListViews())
+ return;
+// throw PalmLib::error("too many list views for this database type");
+
+ // Ensure that the field numbers are within range.
+ for (PalmLib::FlatFile::ListView::const_iterator i = lv.begin();
+ i != lv.end(); ++i) {
+ if ((*i).field >= getNumOfFields())
+ return;
+ }
+ m_listviews.push_back(lv);
+}
+
+void
+PalmLib::FlatFile::Database::removeListView(unsigned index)
+{
+ if (index < getNumOfListViews())
+ m_listviews.erase( m_listviews.begin()+index);
+}
+
+static void
+strlower(std::string& str)
+{
+ for (std::string::iterator p = str.begin(); p != str.end(); ++p) {
+ if (isupper(*p))
+ *p = tolower(*p);
+ }
+}
+
+static bool
+string2boolean(std::string str)
+{
+ strlower(str);
+ if (str == "on")
+ return true;
+ else if (str == "off")
+ return false;
+ else if (str == "true")
+ return true;
+ else if (str == "t")
+ return true;
+ else if (str == "false")
+ return false;
+ else if (str == "f")
+ return false;
+ else {
+ int num = 0;
+
+ std::istringstream(str.c_str()) >> num;
+ return num != 0 ? true : false;
+ }
+}
+
+void
+PalmLib::FlatFile::Database::setOption(const std::string& name,
+ const std::string& value)
+{
+ if (name == "backup")
+ m_backup = string2boolean(value);
+ else if (name == "inROM")
+ m_readonly = string2boolean(value);
+ else if (name == "copy-prevention")
+ m_copy_prevention = string2boolean(value);
+}
+
+PalmLib::FlatFile::Database::options_list_t
+PalmLib::FlatFile::Database::getOptions() const
+{
+ PalmLib::FlatFile::Database::options_list_t set;
+ typedef PalmLib::FlatFile::Database::options_list_t::value_type value;
+
+ if (m_backup)
+ set.push_back(value("backup", "true"));
+ else
+ set.push_back(value("backup", "false"));
+
+ if (m_readonly)
+ set.push_back(value("inROM", "true"));
+
+ if (m_copy_prevention)
+ set.push_back(value("copy-prevention", "true"));
+
+ return set;
+}
+
+void
+PalmLib::FlatFile::Database::doneWithSchema()
+{
+ // Ensure that the database has at least one field.
+ if (getNumOfFields() == 0)
+ return;
+// throw PalmLib::error("at least one field must be specified");
+
+ // Ensure that the database has a title.
+ if (title().empty())
+ return;
+// throw PalmLib::error("a title must be specified");
+}
diff --git a/src/translators/pilotdb/libflatfile/Database.h b/src/translators/pilotdb/libflatfile/Database.h
new file mode 100644
index 0000000..5bcba32
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/Database.h
@@ -0,0 +1,320 @@
+/*
+ * palm-db-tools: Abstract adaptor for flat-file databases.
+ * Copyright (C) 1999-2000 by Tom Dyas ([email protected])
+ */
+
+#ifndef __PALMLIB_FLATFILE_DATABASE_H__
+#define __PALMLIB_FLATFILE_DATABASE_H__
+
+#include <vector>
+#include <string>
+#include <utility>
+
+#include "../libpalm/Database.h"
+#include "Field.h"
+#include "Record.h"
+#include "ListView.h"
+#include "FType.h"
+
+#define NOTETITLE_LENGTH 32
+
+namespace PalmLib {
+ namespace FlatFile {
+
+ // This class is an in-memory representation of a typical
+ // PalmOS flat-file database. The caller can request write the
+ // data to a real PalmLib::Database object at any time to
+ // actually obtain the data in a format usable on the Palm
+ // Pilot.
+
+ class Database {
+ public:
+ // convenience type for the options list parsing
+ typedef std::vector< std::pair< std::string, std::string> > options_list_t;
+
+ /**
+ * Default constructor which creates an empty
+ * database. Subclasses should provide a default
+ * constructor and an additional constructorwhich takes a
+ * PalmOS::Database as an argument.
+ */
+ Database(std::string p_Type)
+ : m_backup(false), m_readonly(false),
+ m_copy_prevention(false), m_Type(p_Type)
+ { }
+
+ /**
+ * Constructor which fills the flat-file structure from a
+ * PalmOS database.
+ *
+ * @param pdb PalmOS database to read from.
+ */
+ Database(std::string p_Type, const PalmLib::Database& pdb);
+
+ /**
+ * The destructor is empty since we have no other objects
+ * to dispose of. It is virtual since we have subclasses
+ * for specific flat-file database products.
+ */
+ virtual ~Database() { }
+
+ /**
+ * After all processing to add fields and records is done,
+ * outputPDB is called to create the actual file format
+ * used by the flat-file database product. This method is
+ * abstract since only subclasses know the specific file
+ * formats.
+ *
+ * @param pdb An instance of PalmLib::Database.
+ */
+ virtual void outputPDB(PalmLib::Database& pdb) const;
+
+ /**
+ * Return the title of this flat-file database.
+ */
+ virtual std::string title() const;
+
+ /**
+ * Set the title of this database.
+ *
+ * @param title New title of the database.
+ */
+ virtual void title(const std::string& title);
+
+ /**
+ * Return the maximum number of fields allowed in the
+ * database. The object will not allow the number of
+ * fields to exceed the returned value. This method is
+ * abstract since only the subclasses know the limit on
+ * fields. 0 is returned if there is no limit.
+ */
+ virtual unsigned getMaxNumOfFields() const = 0;
+
+ /**
+ * Return the number of fields in the database.
+ */
+ virtual unsigned getNumOfFields() const;
+
+ /**
+ * Accessor function for the name of a field.
+ */
+ virtual std::string field_name(int i) const;
+
+ /**
+ * Accessor function for type of a field.
+ */
+ virtual Field::FieldType field_type(int i) const;
+
+ /**
+ * Accessor function for the field informations
+ */
+ virtual FType field(int i) const;
+
+ /**
+ * write the format of the field's argument in format,
+ * and return a strings' vector with name of each argument part.
+ * the format use the same display as used by printf
+ */
+ virtual std::vector<std::string> field_argumentf(int, std::string& format)
+ { format = std::string(""); return std::vector<std::string>(0, std::string(""));}
+
+ /**
+ * Add a field to the flat-file database. An exception
+ * will be thrown if the maximum number of fields would be
+ * exceeded or the field type is unsupported.
+ *
+ * @param name Name of the new field.
+ * @param type The type of the new field.
+ */
+ virtual void appendField(FType field);
+ virtual void appendField(const std::string& name,
+ Field::FieldType type, std::string data = std::string(""));
+
+ /**
+ * Insert a field to the flat-file database. An exception
+ * will be thrown if the maximum number of fields would be
+ * exceeded or the field type is unsupported.
+ *
+ * @param name Name of the new field.
+ * @param type The type of the new field.
+ */
+ virtual void insertField(int i, FType field);
+ virtual void insertField(int i, const std::string& name,
+ Field::FieldType type, std::string data = std::string(""));
+
+ /**
+ * Remove a Field in the flat-file database. An Exception
+ * will thrown if the field doesn't exist.
+ */
+ virtual void removeField(int i);
+
+ /**
+ * Returns true if this database supports a specific field
+ * type. This method is abstract since only the subclasses
+ * know which field types are supported.
+ *
+ * @param type The field type that should be checked for support.
+ */
+ virtual bool supportsFieldType(const Field::FieldType& type) const = 0;
+
+ /**
+ * Return the number of records in the database.
+ */
+ virtual unsigned getNumRecords() const;
+
+ /**
+ * Return the record with the given index. The caller gets
+ * a private copy of the data and _not_ a reference to the
+ * data.
+ *
+ * @param index Index of the record to retrieve.
+ */
+ virtual Record getRecord(unsigned index) const;
+
+ /**
+ * Append a record to the database. An exception will be
+ * thrown if their are not enough fields or if field types
+ * mismatch.
+ *
+ * @param rec The record to append.
+ */
+ virtual void appendRecord(Record rec);
+
+ /**
+ * Remove all records from the database
+ */
+ virtual void clearRecords();
+
+ /**
+ * Remove a record from the database
+ */
+ virtual void deleteRecord(unsigned index);
+
+ /**
+ * Return the maximum number of views supported by this
+ * type of flat-file database. This method is abstract
+ * since only the subclasses know the exact value.
+ */
+ virtual unsigned getMaxNumOfListViews() const = 0;
+
+ /**
+ * Return the actual number of views present in this
+ * database.
+ */
+ virtual unsigned getNumOfListViews() const;
+
+ /**
+ * Return a copy of the list view at the given index.
+ *
+ * @param index Index of the list view to return.
+ */
+ virtual ListView getListView(unsigned index) const;
+
+ /**
+ * Set the list view at the given index to the new list
+ * view. An exception may be thrown if field numbers are
+ * invalid or the list view doesn't pass muster with the
+ * subclass.
+ *
+ * @param index Index of the list view to set.
+ * @param listview The new list view.
+ */
+ virtual void setListView(unsigned index, const ListView& listview);
+
+ /**
+ * Append a new list view. This will fail if the maximum
+ * number of list views would be exceeded.
+ *
+ * @param listview The new list view to append.
+ */
+ virtual void appendListView(const ListView& listview);
+
+ /**
+ * Remove a list view.
+ *
+ * @param index Index of the list view to remove.
+ */
+ virtual void removeListView(unsigned index);
+
+ /**
+ * Process a special option. If the option is not
+ * supported, then it is silently ignored. Subclasses
+ * should call the base class first so that options common
+ * to all flat-file databases can be processed.
+ *
+ * @param name Name of the option.
+ * @param value String value assigned to the option. */
+ virtual void setOption(const std::string& name,
+ const std::string& value);
+
+ /**
+ * Return a list of of all extra options supported by this
+ * database. Subclasses should call the base class first
+ * and then merge any extra options. Get a list of extra
+ * options.
+ */
+ virtual options_list_t getOptions(void) const;
+
+ /**
+ * Hook function which should be invoked by a caller after
+ * all calls the meta-deta functions have completed. This
+ * allows the database type-specific code to do final
+ * checks on the meta-data. An exception will be throw if
+ * there is an error. Otherwise, nothing will happen.
+ */
+ virtual void doneWithSchema();
+
+ /**
+ * Change and Return the about information
+ * of the database when it's supportted
+ */
+ virtual void setAboutInformation(std::string _string)
+ {
+ about.information = _string;
+ }
+
+ virtual std::string getAboutInformation() const
+ {
+ return about.information;
+ }
+
+ std::string type() const
+ {
+ return m_Type;
+ }
+
+ private:
+ // We provide a dummy copy constructor and assignment
+ // operator in order to prevent any copying of the object.
+ Database(const Database&) { }
+ Database& operator = (const Database&) { return *this; }
+
+/* typedef std::vector< std::pair< std::string, Field::FieldType > >*/
+ typedef std::vector< FType>
+ field_list_t;
+ typedef std::vector<Record> record_list_t;
+ typedef std::vector<ListView> listview_list_t;
+
+ typedef std::vector< std::pair< std::string, std::vector< std::string > > >
+ listitems_list_t;
+
+ field_list_t m_fields; // database schema
+ record_list_t m_records; // the database itself
+ listitems_list_t m_list; // the items lists include in the database
+ listview_list_t m_listviews; // list views
+ bool m_backup; // backup flag for PDB
+ bool m_readonly; // readonly flag for PDB
+ bool m_copy_prevention; // copy prevention for PDB
+ std::string m_title; // name of database
+ class About
+ {
+ public:
+ std::string information;
+ } about;
+ std::string m_Type;
+ };
+
+ } // namespace FlatFile
+} // namespace PalmLib
+
+#endif
diff --git a/src/translators/pilotdb/libflatfile/FType.h b/src/translators/pilotdb/libflatfile/FType.h
new file mode 100644
index 0000000..86396b3
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/FType.h
@@ -0,0 +1,48 @@
+/*
+ * palm-db-tools: Field Type definitions for flat-file database objects.
+ * Copyright (C) 2000 by Tom Dyas ([email protected])
+ */
+
+#ifndef __PALMLIB_FLATFILE_FTYPE_H__
+#define __PALMLIB_FLATFILE_FTYPE_H__
+
+#include <string>
+#include <utility>
+
+#include "../libpalm/palmtypes.h"
+#include "Field.h"
+
+namespace PalmLib {
+ namespace FlatFile {
+
+ class FType {
+ public:
+ friend class PalmLib::FlatFile::Field;
+ FType(std::string title, PalmLib::FlatFile::Field::FieldType type) :
+ m_title(title), m_type(type), m_data("") { }
+
+ FType(std::string title, PalmLib::FlatFile::Field::FieldType type, std::string data) :
+ m_title(title), m_type(type), m_data(data) { }
+
+ virtual ~FType() { }
+
+ std::string title() const {return m_title;}
+ virtual PalmLib::FlatFile::Field::FieldType type() const
+ { return m_type;}
+
+ virtual std::string argument() const { return m_data;}
+
+ void set_argument( const std::string data) { m_data = data;}
+
+ void setTitle( const std::string value) { m_title = value;}
+ void setType( const PalmLib::FlatFile::Field::FieldType value) { m_type = value;}
+ private:
+ std::string m_title;
+ PalmLib::FlatFile::Field::FieldType m_type;
+
+ std::string m_data;
+ };
+ }
+}
+
+#endif
diff --git a/src/translators/pilotdb/libflatfile/Field.h b/src/translators/pilotdb/libflatfile/Field.h
new file mode 100644
index 0000000..583bc21
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/Field.h
@@ -0,0 +1,119 @@
+/*
+ * palm-db-tools: Field definitions for flat-file database objects.
+ * Copyright (C) 2000 by Tom Dyas ([email protected])
+ */
+
+#ifndef __PALMLIB_FLATFILE_FIELD_H__
+#define __PALMLIB_FLATFILE_FIELD_H__
+
+#include <string>
+
+#include "../libpalm/palmtypes.h"
+
+namespace PalmLib {
+ namespace FlatFile {
+
+ class Field {
+ public:
+ Field() : no_value(false), type(STRING), v_boolean(false),
+ v_integer(0), v_float(0) { }
+ ~Field() { }
+
+ // True if this field has no value. (NULL in SQL terms)
+ bool no_value;
+
+ enum FieldType {
+ STRING,
+ BOOLEAN,
+ INTEGER,
+ FLOAT,
+ DATE,
+ TIME,
+ DATETIME,
+ LIST,
+ LINK,
+ NOTE,
+ CALCULATED,
+ LINKED,
+ LAST
+ };
+
+ enum FieldType type;
+
+ std::string v_string;
+ std::string v_note;
+ bool v_boolean;
+ PalmLib::pi_int32_t v_integer;
+ long double v_float;
+ struct {
+ int month;
+ int day;
+ int year;
+ } v_date; // valid for DATE and DATETIME
+ struct {
+ int hour;
+ int minute;
+ } v_time; // valid for TIME and DATETIME
+
+ /*
+ friend Field operator = (const Field& y)
+ {
+ this.v_string = y.v_string;
+ this.v_boolean = y.v_boolean;
+ this.v_integer = y.v_integer;
+ this.v_float = y.v_float;
+ this.v_date.month = y.v_date.month;
+ this.v_date.day = y.v_date.day;
+ this.v_date.year = y.v_date.year;
+ this.v_time.hour = y.v_time.hour;
+ this.v_time.minute = y.v_time.minute;
+ this.v_note = y.v_note;
+ }
+*/
+ friend bool operator==(const Field& x, const Field& y)
+ {
+ if (x.type != y.type)
+ return false;
+ switch (x.type) {
+ case STRING:
+ return (x.v_string == y.v_string);
+ case BOOLEAN:
+ return (x.v_boolean == y.v_boolean);
+ case INTEGER:
+ return (x.v_integer == y.v_integer);
+ case FLOAT:
+ return (x.v_float == y.v_float);
+ case DATE:
+ return (x.v_date.month == y.v_date.month
+ && x.v_date.day == y.v_date.day
+ && x.v_date.year == y.v_date.year);
+ case TIME:
+ return (x.v_time.hour == y.v_time.hour
+ && x.v_time.minute == y.v_time.minute);
+ case DATETIME:
+ return (x.v_date.month == y.v_date.month
+ && x.v_date.day == y.v_date.day
+ && x.v_date.year == y.v_date.year
+ && x.v_time.hour == y.v_time.hour
+ && x.v_time.minute == y.v_time.minute);
+ case LIST:
+ return (x.v_string == y.v_string);
+ case LINK:
+ return (x.v_string == y.v_string);
+ case NOTE:
+ return (x.v_string == y.v_string
+ && x.v_note == y.v_note);
+ case CALCULATED:
+ return true; //a calculated field could be recalculate at each time
+ case LINKED:
+ return (x.v_string == y.v_string);
+ default:
+ return (x.v_string == y.v_string);
+ }
+ }
+ };
+
+ }
+}
+
+#endif
diff --git a/src/translators/pilotdb/libflatfile/ListView.h b/src/translators/pilotdb/libflatfile/ListView.h
new file mode 100644
index 0000000..4229548
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/ListView.h
@@ -0,0 +1,77 @@
+#ifndef __PALMOS__FLATFILE__VIEW_H__
+#define __PALMOS__FLATFILE__VIEW_H__
+
+#include <string>
+#include <vector>
+
+#include "ListViewColumn.h"
+
+namespace PalmLib {
+ namespace FlatFile {
+
+ // The ListView class represents the a "list view" as
+ // implemented by the major PalmOS flat-file programs. The
+ // main idea is a series of columns that display a field of
+ // the database.
+ //
+ // For fun, this class exports the STL interface of the STL
+ // class it uses to store the ListViewColumn classes.
+
+ class ListView {
+ private:
+ typedef std::vector<ListViewColumn> rep_type;
+ rep_type rep;
+
+ public:
+ typedef rep_type::value_type value_type;
+ typedef rep_type::iterator iterator;
+ typedef rep_type::const_iterator const_iterator;
+ typedef rep_type::reference reference;
+ typedef rep_type::const_reference const_reference;
+ typedef rep_type::size_type size_type;
+ typedef rep_type::difference_type difference_type;
+ typedef rep_type::reverse_iterator reverse_iterator;
+ typedef rep_type::const_reverse_iterator const_reverse_iterator;
+
+ // global fields
+ std::string name;
+ bool editoruse;
+
+ // STL pull-up interface (probably not complete)
+ iterator begin() { return rep.begin(); }
+ const_iterator begin() const { return rep.begin(); }
+ iterator end() { return rep.end(); }
+ const_iterator end() const { return rep.end(); }
+ reverse_iterator rbegin() { return rep.rbegin(); }
+ const_reverse_iterator rbegin() const { return rep.rbegin(); }
+ reverse_iterator rend() { return rep.rend(); }
+ const_reverse_iterator rend() const { return rep.rend(); }
+ size_type size() const { return rep.size(); }
+ size_type max_size() const { return rep.max_size(); }
+ bool empty() const { return rep.empty(); }
+ reference front() { return rep.front(); }
+ const_reference front() const { return rep.front(); }
+ reference back() { return rep.back(); }
+ const_reference back() const { return rep.back(); }
+ void push_back(const ListViewColumn& x) { rep.push_back(x); }
+ void pop_back() { rep.pop_back(); }
+ void clear() { rep.clear(); }
+ void resize(size_type new_size, const ListViewColumn& x)
+ { rep.resize(new_size, x); }
+ void resize(size_type new_size)
+ { rep.resize(new_size, ListViewColumn()); }
+
+ ListView() : rep(), name(""), editoruse(false) { }
+ ListView(const ListView& rhs) : rep(rhs.rep), name(rhs.name), editoruse(false) { }
+ ListView& operator = (const ListView& rhs) {
+ name = rhs.name;
+ rep = rhs.rep;
+ return *this;
+ }
+
+ };
+
+ }
+}
+
+#endif
diff --git a/src/translators/pilotdb/libflatfile/ListViewColumn.h b/src/translators/pilotdb/libflatfile/ListViewColumn.h
new file mode 100644
index 0000000..7b5330e
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/ListViewColumn.h
@@ -0,0 +1,19 @@
+#ifndef __PALMLIB_FLATFILE_LISTVIEWCOLUMN_H__
+#define __PALMLIB_FLATFILE_LISTVIEWCOLUMN_H__
+
+namespace PalmLib {
+ namespace FlatFile {
+
+ // The ListViewColumn class stores the field number and column
+ // width for a column in a list view.
+
+ struct ListViewColumn {
+ ListViewColumn() : field(0), width(80) { }
+ ListViewColumn(unsigned a1, unsigned a2) : field(a1), width(a2) { }
+ unsigned field;
+ unsigned width;
+ };
+ }
+}
+
+#endif
diff --git a/src/translators/pilotdb/libflatfile/Makefile.am b/src/translators/pilotdb/libflatfile/Makefile.am
new file mode 100644
index 0000000..d3ab012
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/Makefile.am
@@ -0,0 +1,20 @@
+####### kdevelop will overwrite this part!!! (begin)##########
+noinst_LIBRARIES = liblibflatfile.a
+
+AM_CPPFLAGS = $(all_includes)
+
+liblibflatfile_a_METASOURCES = AUTO
+
+liblibflatfile_a_SOURCES = DB.cpp Database.cpp
+
+
+EXTRA_DIST = Database.cpp Database.h DB.cpp DB.h Field.h FType.h ListView.h ListViewColumn.h Record.h
+
+####### kdevelop will overwrite this part!!! (end)############
+
+# is this the right way to do this? I need to include the strop.o object file since its
+# in the parent directory
+liblibflatfile_a_LIBADD = ../strop.o
+CLEANFILES = strop.Po
+
+KDE_OPTIONS = noautodist
diff --git a/src/translators/pilotdb/libflatfile/Record.h b/src/translators/pilotdb/libflatfile/Record.h
new file mode 100644
index 0000000..537953e
--- /dev/null
+++ b/src/translators/pilotdb/libflatfile/Record.h
@@ -0,0 +1,45 @@
+/*
+ * palm-db-tools: Field definitions for flat-file database objects.
+ * Copyright (C) 2000 by Tom Dyas ([email protected])
+ */
+
+#ifndef __PALMLIB_FLATFILE_RECORD_H__
+#define __PALMLIB_FLATFILE_RECORD_H__
+
+#include <vector>
+
+#include "Field.h"
+
+namespace PalmLib {
+ namespace FlatFile {
+// typedef std::vector<Field> Record;
+
+ class Record{
+ public:
+
+ const std::vector<Field> fields() const { return m_Fields; }
+
+ void appendField(Field newfield) { m_Fields.push_back(newfield); }
+ bool created() const { return m_New;}
+ void created(bool on){ m_New = on;}
+ bool secret() const { return m_Secret;}
+ void secret(bool on) { m_Secret = on;}
+
+ bool dirty() const { return m_Dirty; }
+ void dirty( bool on) { m_Dirty = on; }
+
+ pi_uint32_t unique_id() const { return m_UID; }
+ void unique_id(pi_uint32_t id) { m_UID = id; }
+ private:
+
+ std::vector<Field> m_Fields;
+ bool m_Secret;
+ bool m_New;
+
+ bool m_Dirty;
+ pi_uint32_t m_UID;
+ };
+ }
+}
+
+#endif