// // ResultMatch.cc // // ResultMatch: Contains information related to a given // document that was matched by a search. For instance, the // score of the document for this search. Similar to the // DocMatch class but designed for result display purposes. // // Part of the ht://Dig package // Copyright (c) 1995-2004 The ht://Dig Group // For copyright details, see the file COPYING in your distribution // or the GNU Library General Public License (LGPL) version 2 or later // // // $Id: ResultMatch.cc,v 1.10 2004/05/28 13:15:24 lha Exp $ // #ifdef HAVE_CONFIG_H #include "htconfig.h" #endif /* HAVE_CONFIG_H */ #include "ResultMatch.h" // Definition of how to search ResultMatch::SortType ResultMatch::mySortType; //***************************************************************************** // ResultMatch::ResultMatch() { } //***************************************************************************** // ResultMatch::~ResultMatch() { } //***************************************************************************** // Default-access-methods. Just dummies when that data is not used. char *ResultMatch::getTitle() { return ""; } time_t ResultMatch::getTime() { return 0; } void ResultMatch::setTitle(char *) { } void ResultMatch::setTime(time_t) { } // Then for each sort-type, we derive a class, which will keep // any necessary additional piece of data, and return the compare-function. // We could have a real cute implementation with global // constructors registering a factory method with ResultMatch, // so it would just check a list and never need to be changed // when new search methods are introduced, but that seems futile. // It is more practical to just add search methods here and // change the createMatch method, last. //***************************************************************************** class ScoreMatch : public ResultMatch { // This one needs no additional data public: virtual ResultMatch::CmpFun getSortFun(); ScoreMatch(); ~ScoreMatch(); private: static int compare(const void *a1, const void *a2); }; ScoreMatch::ScoreMatch() {} ScoreMatch::~ScoreMatch() {} int ScoreMatch::compare(const void *a1, const void *a2) { ResultMatch *m1 = *((ResultMatch **) a1); ResultMatch *m2 = *((ResultMatch **) a2); double score1 = m1->getScore(); double score2 = m2->getScore(); if(score1 == score2) return 0; else if(score1 < score2) return 1; else return -1; // return m2->getScore() - m1->getScore(); } ResultMatch::CmpFun ScoreMatch::getSortFun() { return compare; } //***************************************************************************** class TimeMatch : public ResultMatch { public: virtual ResultMatch::CmpFun getSortFun(); virtual void setTime(time_t); virtual time_t getTime(); TimeMatch(); ~TimeMatch(); private: // We need a time_t here, and to override the get/setTime methods. time_t myTime; static int compare(const void *a1, const void *a2); }; TimeMatch::TimeMatch() {} TimeMatch::~TimeMatch() {} void TimeMatch::setTime(time_t t) { myTime = t; } time_t TimeMatch::getTime() { return myTime; } int TimeMatch::compare(const void *a1, const void *a2) { ResultMatch *m1 = *((ResultMatch **) a1); ResultMatch *m2 = *((ResultMatch **) a2); time_t t1 = m1->getTime(); time_t t2 = m2->getTime(); return (int) (t2 - t1); } ResultMatch::CmpFun TimeMatch::getSortFun() { return compare; } //***************************************************************************** class IDMatch : public ResultMatch { // This one needs no additional data public: virtual ResultMatch::CmpFun getSortFun(); IDMatch(); ~IDMatch(); private: static int compare(const void *a1, const void *a2); }; IDMatch::IDMatch() {} IDMatch::~IDMatch() {} int IDMatch::compare(const void *a1, const void *a2) { ResultMatch *m1 = *((ResultMatch **) a1); ResultMatch *m2 = *((ResultMatch **) a2); int i1 = m1->getID(); int i2 = m2->getID(); return (i1 - i2); } ResultMatch::CmpFun IDMatch::getSortFun() { return compare; } //***************************************************************************** class TitleMatch : public ResultMatch { public: virtual ResultMatch::CmpFun getSortFun(); virtual void setTitle(char *t); virtual char *getTitle(); TitleMatch(); ~TitleMatch(); private: // We need a String here, and to override the get/setTitle methods. // It has to be a String, as the "char *" goes away shortly // after creating the object. String myTitle; static int compare(const void *a1, const void *a2); }; TitleMatch::TitleMatch() {} TitleMatch::~TitleMatch() {} void TitleMatch::setTitle(char *t) { myTitle = t; } char * TitleMatch::getTitle() { return myTitle; } int TitleMatch::compare(const void *a1, const void *a2) { ResultMatch *m1 = *((ResultMatch **) a1); ResultMatch *m2 = *((ResultMatch **) a2); char *t1 = m1->getTitle(); char *t2 = m2->getTitle(); if (!t1) t1 = ""; if (!t2) t2 = ""; return mystrcasecmp(t1, t2); } ResultMatch::CmpFun TitleMatch::getSortFun() { return compare; } //***************************************************************************** int ResultMatch::setSortType(const String& sorttype) { static const struct { char *typest; SortType type; } sorttypes[] = { {"score", SortByScore}, {"date", SortByTime}, {"time", SortByTime}, {"title", SortByTitle}, {"id", SortByID} }; int i = 0; const char *st = sorttype; if (st && *st) { if (mystrncasecmp("rev", st, 3) == 0) st += 3; for (i = sizeof(sorttypes)/sizeof(sorttypes[0]); --i >= 0; ) { if (mystrcasecmp(sorttypes[i].typest, st) == 0) { mySortType = sorttypes[i].type; return 1; } } return 0; } else { // If not specified, default to SortByScore mySortType = SortByScore; return 1; } } //***************************************************************************** // Now here's the switchboard: a create-function that returns a // "new":ed object of the right class for what to compare. // To have the pairing managed in a (dynamically registered) // list may seem interesting, but since everything is here // anyway, there's little need but a small cuteness-factor. // We could also change the guts to use some kind of creator // object, if there would be a win. ResultMatch * ResultMatch::create() { switch (mySortType) { case ResultMatch::SortByScore: return new ScoreMatch(); case ResultMatch::SortByTime: return new TimeMatch(); case ResultMatch::SortByTitle: return new TitleMatch(); case ResultMatch::SortByID: return new IDMatch(); default: // It is doubtful which is better: to abort() or paper // over something bad here. return new ScoreMatch(); } }