/* * Name : found.cpp * Aufgabe : Vektor der gefundenen Eintraege * Version : $Revision: 1.2 $ * Datum : $Date: 2000/01/26 23:09:39 $ * Beschreibung : Komfortables Durchsuchen der Heise-Register-Datei * * Copyright (C) 1998 Alexander Bednarz * Martin Habbecke * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include "found.h" #include "entry.h" #define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember)) typedef int (Found::*CompareMemberFn)(Entry const *, Entry const *); // Deep Copy anfuegen void Found::append( Entry const & e ) { ++size_; v_ = (Entry **) realloc( v_, sizeof(Entry *) * size_ ); assert( v_ != 0); v_[write_] = new Entry(e); // Deep copy anlegen write_++; } // Sortieren nach, Jahr, Augabe, Aufsteigend int Found::cmpJahrUp( Entry const * a, Entry const * b ) { // cout << "cmpJahrUp" << endl; // Jahr zuerst beruecksichtigen // cout << "Jahrgang a:" << a->Jahrgang() << endl; // cout << "Jahrgang b:" << b->Jahrgang() << endl; int aj = atoi(a->Jahrgang()); int bj = atoi(b->Jahrgang()); // Y2K-Workaround von Erik Hansen (Danke!) if ( aj < 81 ) { aj = aj + 100; }; if ( bj < 81 ) { bj = bj + 100; }; if ( aj > bj ) { return 1; } else if ( aj < bj ) { return -1; } else { // Jahrgang gleich -> Ausgabe vergleichen int aa = atoi(a->Ausgabe()); int ba = atoi(b->Ausgabe()); if ( aa > ba ) { return 1; } else if ( aa < ba ) { return -1; } } return 0; // sind gleich } // Sortieren nach, Ausgabe, Jahr, aufsteigend int Found::cmpAusgUp( Entry const * a, Entry const * b ) { // cout << "cmpAusgUp" << endl; // Ausgabe zuerst beruecksichtigen // cout << "Jahrgang a:" << a->Jahrgang() << endl; // cout << "Jahrgang b:" << b->Jahrgang() << endl; int aa = atoi(a->Ausgabe()); int ba = atoi(b->Ausgabe()); if ( aa > ba ) { return 1; } else if ( aa < ba ) { return -1; } else { // Ausgabe gleich -> Jahrgang vergleichen int aj = atoi(a->Jahrgang()); int bj = atoi(b->Jahrgang()); if ( aj > bj ) { return 1; } else if ( aj < bj ) { return -1; } } return 0; // sind gleich } // Sortieren nach, Jahr, Augabe, absteigend int Found::cmpJahrDown( Entry const * a, Entry const * b ) { return -cmpJahrUp( a, b); } // Sortieren nach, Ausgabe, Jahr, absteigend int Found::cmpAusgDown( Entry const * a, Entry const * b ) { return -cmpAusgUp( a, b); } /// Sortierend nach Titel, aufsteigend int Found::cmpTitelUp( Entry const * a, Entry const * b) { return strcmp( a->Titel(), b->Titel() ); } int Found::cmpTitelDown( Entry const * a, Entry const * b) { return -strcmp( a->Titel(), b->Titel() ); } /// nach Zeitschrifttyp sortieren, aufsteigend int Found::cmpTypUp( Entry const * a, Entry const * b) { return a->Zeitschrift() - b->Zeitschrift(); } /// nach Zeitschrifttyp sortieren, absteigend int Found::cmpTypDown( Entry const * a, Entry const * b) { return b->Zeitschrift() - a->Zeitschrift(); } /// Sortieren nach Rating, Jahrgang -- aufsteigend int Found::cmpRatingUp( Entry const * a, Entry const * b ) { int ar = a->Rating(); int br = b->Rating(); if ( ar > br ) { return 1; } else if ( ar < br ) { return -1; } else { // Rating gleich -> Jahrgang int aj = atoi(a->Jahrgang()); int bj = atoi(b->Jahrgang()); if ( aj > bj ) { return 1; } else if ( aj < bj ) { return -1; } } return 0; // sind gleich } /// Sortieren nach Rating, Jahrgang -- absteigend int Found::cmpRatingDown( Entry const * a, Entry const * b ) { return -cmpRatingUp( a, b); } // swap - given two pointers to Entrys, swap their contents // geklaut von http://wannabe.guru.org/alg/ void Found::swap (Entry ** a, Entry ** b) { Entry * temp = *a; *a = *b; *b = temp; } // q_sort - Quicksort a v_ range // geklaut von http://wannabe.guru.org/alg/ void Found::q_sort (int low, int hi, cmpFunc cmp ) { int pivot_index; // index in the v_ set of the pivot Entry * pivot_value; // the value of the pivot element int left, right; /* select the pivot element and remember its value */ pivot_index = ( callMemberFunction(*this, cmp)( v_[low], v_[low+1]) > 0 ) ? low : (low+1); pivot_value = v_[pivot_index]; /* do the partitioning */ left = low; right = hi; do { /* move left to the right bypassing elements already on the correct side */ while ((left <= hi) && ( callMemberFunction(*this, cmp)( v_[left], pivot_value) < 0 )) { left++; } /* move right to the left bypassing elements already on the correct side */ while ((right >= low) && ( callMemberFunction(*this, cmp)( pivot_value, v_[right]) < 0)) { right--; } /* * if the pointers are in the correct order then they are pointing to two * items that are on the wrong side of the pivot value, swap them... */ if (left <= right) { swap(&v_[left], &v_[right]); left++; right--; } } while (left <= right); /* now recurse on both partitions as long as they are large enough */ if (low < right) q_sort(low, right, cmp); if (left < hi) q_sort(left, hi, cmp); } // Reihenfolge der Vektorelemente umdrehen void Found::reverse( void ) { register int i = 0; register int j = count() - 1; // Index ist interessant while ( i < j ) { swap( &v_[i], &v_[j] ); i++; j--; } } void Found::sort( SortType const st ) { cmpFunc cmp; /* Ist nur ein Eintrag im Found ? */ if( count() <= 1 ) return; SortType last = getSortType(); // Danach war sortiert switch( st ) { case JAHR_UP: setSortType( JAHR_UP ); if ( last == JAHR_DOWN) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpJahrUp; break; case JAHR_DOWN: setSortType( JAHR_DOWN ); if ( last == JAHR_UP ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpJahrDown; break; case AUSG_UP: setSortType( AUSG_UP ); if ( last == AUSG_DOWN ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpAusgUp; break; case AUSG_DOWN: setSortType( AUSG_DOWN ); if ( last == AUSG_UP ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpAusgDown; break; case TITEL_UP: setSortType( TITEL_UP ); if ( last == TITEL_DOWN ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpTitelUp; break; case TITEL_DOWN: setSortType( TITEL_DOWN ); if ( last == TITEL_UP ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpTitelDown; break; case TYP_UP: setSortType( TYP_UP ); if ( last == TYP_DOWN ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpTypUp; break; case TYP_DOWN: setSortType( TYP_DOWN ); if ( last == TYP_UP ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpTypDown; break; case RATING_UP: setSortType( RATING_UP ); if ( last == RATING_DOWN ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpRatingUp; break; case RATING_DOWN: setSortType( RATING_DOWN ); if ( last == RATING_UP ) { reverse(); // Vektor umdrehen reicht schon return; } else cmp = &Found::cmpRatingDown; break; default: return; } // und sortieren, wenn wir ueberhaupt bis hierhin kommen // und nicht vorher reverse() aufgerufen haben q_sort( 0, size_ - 1, cmp); } void Found::reset( void ) { // Pruefen, ob ueberhaupt was angelegt worden ist if ( v_ == 0 ) return; // noch nix angelegt, also nix zu loeschen // alle Elemente freigeben for(int i = 0; i < size_; i++) delete v_[i]; // Vektor freigeben free( v_ ); v_ = 0; size_ = 0; read_ = 0; write_ = 0; }