The GroupIndex Template Library
Main Page | Class Hierarchy | Class List | File List | Class Members

GInvertedList.h

00001 #ifndef DEF_GINVERTEDLIST
00002 #define DEF_GINVERTEDLIST
00003 
00004 #pragma warning( disable : 4786 )        
00005 
00006 #ifndef maxStabSize
00007 #define maxStabSize 6
00008 #endif
00009 
00010 #include "ListTupel.h"
00011 #include "default_containers.h"
00012 #include "consts.h"
00013 #include "heap.h"
00014 #ifndef DEF_LIMITS
00015 #include <climits>
00016 #define DEF_LIMITS
00017 #endif
00018 #ifndef VISUALC_INCLUDES
00019 #include <unistd.h>
00020 #include <sys/stat.h>
00021 #include <mingw/stdlib.h>
00022 #endif
00023 const unsigned short power2[] = { 128, 64, 32, 16, 8, 4, 2, 1 } ;
00024 #include <cstdio>
00025 #include <cstdlib>
00026 #include <io.h>
00027 
00028 
00029 namespace groupindex
00030 {
00031 
00032 
00033 template <class Group>
00034 std::ofstream& operator<<(std::ofstream& ofs, ListTupel<Group>& lt)
00035 {
00036     ofs<<lt.g;
00037     ofs.write((char*)&(lt.i),sizeof(int));
00038     return ofs;
00039 
00040 }
00041 
00042 template <class Group>
00043 std::ifstream& operator>>(std::ifstream& ifs, ListTupel<Group>& lt)
00044 {
00045     ifs>>lt.g;
00046     ifs.read((char*)&(lt.i),sizeof(int));
00047     return ifs;
00048 
00049 }
00050 
00058 template<class Group>
00059 class GInvertedList
00060 {
00061 
00062 protected:
00063     class read_iterator;
00064 
00065 public:
00066 
00071     class iterator;
00072 
00081     //typedef iterator iterator;
00082 
00083 protected:
00084 
00085     ListTupel<Group>* insertion_buffer;
00086     int ins_buffer_size;
00087     int ins_buffer_pos;
00090         // Änderung für MultiDimGList (r.b. 23.01.2002)
00091         //std::ifstream* m_stream;              // Datei        
00092         std::fstream* m_stream;
00093         // MultiDimGList Ende
00094         
00096         long m_fileoffset; 
00097 
00099         long m_id; 
00100 
00102         char m_insertion_file_name[1024];
00103         
00105     Group m_factor_inverse;
00106 
00108     Group m_factor;
00109 
00111         ListTupel<Group>* m_pos_beg;
00112 
00114     ListTupel<Group>* m_pos_end;
00115  
00117         int m_element_count; 
00118 
00121         int m_new_element_count; 
00122 
00124         ListTupel<Group>* m_elements;
00125 
00128     std::set<int> m_deleted_fileindices;
00129 
00130     void initFileRead(std::ifstream& ifs);
00131     void initFileRead(std::fstream& ifs);
00132 
00134     virtual void readElements();
00135 
00137     virtual void readElements(int credit);
00138 
00140         virtual void readElements(ListTupel<Group>* buffer, int credit);
00141 
00143     void clear();
00144 
00146     inline void setFileName(long id);
00147 
00164         virtual void writeToFile(std::ofstream& ofs);
00165 
00167     inline read_iterator find(const ListTupel<Group>& lt);
00168         
00169         inline read_iterator find(const ListTupel<Group>& lt, read_iterator& it);
00170         
00171         inline void remove(read_iterator& it);
00172 
00173     // vermindert den \c credit des Elements an der Position \c lt und löscht das Element ggf. aus der Liste
00174     inline void decrease(read_iterator& it);
00175     
00181         inline void assign(const read_iterator& new_beg, const read_iterator& new_end);
00182                 
00194         void initInsertion();
00195 
00200     void insert(read_iterator& pos, const ListTupel<Group>& lt);
00201 
00202         void initUpdate();
00203 
00204 public:
00205    
00207     GInvertedList<Group>(const GInvertedList<Group>& glist);
00208 
00212     GInvertedList<Group>(long id);
00213 
00215     GInvertedList<Group>();
00216 
00225     GInvertedList(std::/*i*/fstream& ifs);
00226 
00231     inline GInvertedList<Group>& operator*=(const Group& g);
00232 
00234     inline iterator begin();
00235         inline iterator begin(bool dummy);
00236 
00238     inline iterator end();
00239         inline iterator end(bool dummy);
00240 
00241 protected:
00242     inline read_iterator _begin(void*);
00243 
00244     inline read_iterator _end(void*);
00245 
00246 public:
00248     inline int size() const;
00249 
00250     void setCredit(int credit)
00251     {
00252     }
00253 
00255     friend std::ofstream& operator<< ANSI_BRACES (std::ofstream& o, GInvertedList<Group>& l);
00256 
00270         virtual void insert(const Group& g, int i);
00271 
00273         void remove(int fileindex);
00274 
00284         void intersect(GInvertedList<Group>& set2, int& mismatches);
00285 
00286         void merge(GInvertedList<Group>& set2);
00287 
00289         inline void setHeapStream(std::fstream& hps)
00290         {
00291         }
00292 
00294         ~GInvertedList();
00295 
00296 protected:
00297     
00303     class read_iterator
00304     {
00305 
00306     protected:
00307             
00308             ListTupel<Group>* lt;
00309 
00310     public:
00311             
00312         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00313             inline read_iterator() {}
00314         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00315             
00316         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00317             inline read_iterator(ListTupel<Group>* l)
00318         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00319             {
00320                     lt = l;
00321             }
00322 
00323         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00324             inline ListTupel<Group>& operator*() const
00325         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00326             {
00327                     return *lt;
00328             }
00329 
00331         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00332             inline read_iterator& operator++()
00333         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00334             {
00335         
00336             do
00337             {
00338                             lt = &lt[1];
00339             } while (lt->credit<0);
00340 
00341             return *this;
00342             }
00343 
00345         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00346             inline read_iterator& operator++(int)
00347         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00348             {
00349 
00350             do
00351             {
00352                             lt = &lt[1];
00353             } while (lt->credit<0);
00354 
00355             return *this;
00356             }
00357 
00358         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00359             inline bool operator!=(const read_iterator& it)
00360         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00361             {
00362                     return !(lt == it.lt);
00363             }
00364 
00365         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00366             inline bool operator==(const read_iterator& it)
00367         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00368             {
00369                     return (lt == it.lt);
00370             }
00371 
00372     };
00373 
00374 
00375 public:    
00376     // Einen Orden bekommt derjenige, der es schafft, den folgenden Klassen-Rumpf aus der Klassendefinition
00377     // herauszuholen (und zwar so, dass der MS-Compiler es trotzdem noch mag...)
00378 
00384     class iterator : public read_iterator
00385     {
00386 
00387     protected:
00388         Group* m_factor;
00389 
00390     public:
00391 
00392         inline iterator() {}
00393 
00394         inline iterator(const read_iterator& it) : read_iterator(it) {}
00395 
00396         inline iterator(const iterator& it) : read_iterator((read_iterator)it) 
00397         {
00398             m_factor = it.m_factor;
00399         }
00400 
00401         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00402             inline iterator(ListTupel<Group>* l, Group* g)
00403         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00404             {
00405                     lt = l;
00406             while (lt->credit<0)
00407                 lt = &lt[1];
00408             m_factor = g;
00409             }
00410 
00411         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00412             inline ListTupel<Group> operator*()
00413         // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00414             {
00415 
00416             ListTupel<Group> r_lt;
00417 
00418             // m_factor von rechts an (*lt).g 'dranmultiplizieren und 
00419             // das Ganze in r_lt festhalten
00420                         r_lt.g = (*lt).g;
00421             r_lt.g *= (*m_factor);
00422             r_lt.credit = (*lt).credit;
00423 
00424             r_lt.i = (*lt).i;
00425                     return r_lt;
00426             }
00427 
00428     };
00429 
00430 };
00431 
00432         
00433 
00434 
00448 template<class Group>
00449 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00450 void GInvertedList<Group>::writeToFile(std::ofstream& ofs)
00451 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00452 {
00453 
00454     // insertion_buffer Flushen
00455     if (insertion_buffer != NULL)
00456     {
00457 
00458         if (chdir("list")==-1)
00459             #ifdef VISUALC_INCLUDES
00460             mkdir("list");
00461             #else
00462             mkdir("list",0);
00463             #endif
00464         else
00465             chdir("..");
00466 
00467             std::/*o*/fstream insertion_stream;
00468         insertion_stream.open(m_insertion_file_name, std::ios::app | std::ios::out | std::ios::binary);
00469             if (!insertion_stream)
00470             {
00471             throw IndexingException(IndexingException::FILE_ERROR_OPEN);
00472                     return;
00473             }
00474 
00475         for (int j=0; j<ins_buffer_pos; j++)
00476             insertion_stream<<insertion_buffer[j];
00477         ins_buffer_pos = 0;
00478 
00479         insertion_stream.close();
00480 
00481     }
00482 
00483     // Bereits indexierte Elemente in m_elements lesen
00484     readElements();
00485 
00486         ListTupel<Group>* new_elements = NULL;
00487     if (m_new_element_count>0)
00488     {
00489             std::ifstream insertion_stream;
00490         insertion_stream.open(m_insertion_file_name,std::ios::binary);
00491 
00492         if (insertion_stream == NULL || !insertion_stream)
00493             throw IndexingException(IndexingException::FILE_ERROR_OPEN);
00494 
00495         new_elements = new ListTupel<Group>[m_new_element_count+1];
00496         // stop-Element für iterator einfügen
00497         new_elements[m_new_element_count].credit = 0;
00498 
00499         // Alle ListTupel aus glist_-Datei in array lesen
00500             for (int i=0; i<m_new_element_count; i++)
00501             {
00502                     insertion_stream>>new_elements[i];
00503                     if (!insertion_stream)
00504                 throw IndexingException(IndexingException::FILE_ERROR_READ);
00505             }
00506 
00507             insertion_stream.close();
00508 
00509             // array sortieren 
00510             heapsort< ListTupel<Group> >(new_elements,m_new_element_count);
00511 
00512     }
00513     
00514         ListTupel<Group>* all_elements = new ListTupel<Group>[m_element_count+m_new_element_count];
00515     long bytesize = 0;
00516 
00517         // mergen von m_elements und new_elements nach all_elements
00518     int i_old = 0;
00519     int i_new = 0;
00520     int i_all = 0;
00521 
00522     while (i_old<m_element_count || i_new<m_new_element_count)
00523         {
00524 
00525         if (i_new>=m_new_element_count || i_old<m_element_count && m_elements[i_old]>new_elements[i_new])
00526         {
00527 
00528             std::set<int>::iterator found = m_deleted_fileindices.find(m_elements[i_old].i);
00529             if (found==m_deleted_fileindices.end())
00530             {
00531                             all_elements[i_all] = m_elements[i_old];
00532                 bytesize += m_elements[i_old].size();
00533                 i_all++;
00534             }
00535 
00536             do {
00537                 i_old++;
00538             } while (i_old<m_element_count && m_elements[i_old]==m_elements[i_old-1]);
00539 
00540         } else {
00541 
00542             while (i_old<m_element_count && m_elements[i_old]==new_elements[i_new])
00543             {
00544                 // Duplikat entfernen
00545                 i_old++;
00546             }
00547 
00548             std::set<int>::iterator found = m_deleted_fileindices.find(new_elements[i_new].i);
00549             if (found==m_deleted_fileindices.end())
00550             {
00551                             all_elements[i_all] = new_elements[i_new];
00552                 bytesize += new_elements[i_new].size();
00553                 i_all++;
00554             }
00555 
00556             do {
00557                 i_new++;
00558             } while (i_new<m_new_element_count && new_elements[i_new]==new_elements[i_new-1]);
00559         
00560         }
00561 
00562         }
00563 
00564     int all_element_count = i_all;
00565 
00566 
00567     // Länge der Liste, Anzahl von Einträgen und ID schreiben    
00568     ofs.write((char*)&m_id,sizeof(long));
00569     ofs.write((char*)&all_element_count,sizeof(long));
00570     ofs.write((char*)&bytesize,sizeof(long));
00571 
00572     m_fileoffset = ofs.tellp();
00573 
00574         // Schreiben von all_elements
00575     for (i_all = 0; i_all<all_element_count; i_all++)
00576         {
00577 
00578                 ofs<<all_elements[i_all];
00579 
00580         };
00581 
00582     m_element_count = all_element_count;
00583     m_new_element_count = 0;
00584 
00585     // belegte Resourcen (Speicher und Dateien) freigeben
00586     delete[] m_elements;
00587         delete[] new_elements;
00588     delete[] all_elements;
00589     m_elements = NULL;
00590 
00591     // Alle ListTupel stehen jetzt in der Indexdatei; die temporäre glist_-Datei
00592     // kann daher gelöscht werden.
00593     ::remove(m_insertion_file_name);
00594 
00595     m_deleted_fileindices.clear();
00596 
00597 }
00598 
00600 template<class Group>
00601 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00602 GInvertedList<Group>::GInvertedList<Group>(const GInvertedList<Group>& glist)
00603 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00604 {
00605     ins_buffer_size = glist.ins_buffer_size;
00606     ins_buffer_pos = glist.ins_buffer_pos;
00607     if (glist.insertion_buffer!=NULL)
00608     {
00609         insertion_buffer = new ListTupel<Group>[ins_buffer_size];
00610         for (int i=0; i<ins_buffer_pos; i++)
00611             insertion_buffer[i] = glist.insertion_buffer[i];
00612     }
00613         else
00614                 insertion_buffer = NULL;
00615         
00616         m_stream = glist.m_stream;
00617         strcpy(m_insertion_file_name,glist.m_insertion_file_name);
00618         m_fileoffset = glist.m_fileoffset;
00619         m_factor = glist.m_factor;
00620         m_factor_inverse = glist.m_factor_inverse;
00621 
00622         m_elements = NULL;
00623         m_element_count = glist.m_element_count;
00624         m_new_element_count = glist.m_new_element_count;
00625 
00626         m_pos_beg = NULL;
00627         m_pos_end = NULL;
00628 
00629     m_id = glist.m_id;
00630 
00631 }
00632 
00634 template<class Group>
00635 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00636 GInvertedList<Group>::GInvertedList<Group>()
00637 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00638 {
00639         m_elements = NULL;
00640     m_stream = NULL;
00641 
00642         m_insertion_file_name[0] = '\0';
00643         m_element_count = 0;
00644         m_new_element_count = 0;
00645 
00646         m_pos_beg = NULL;
00647         m_pos_end = NULL;
00648 
00649     ins_buffer_size = INS_BUFFER_SIZE;
00650     ins_buffer_pos = 0;
00651     insertion_buffer=NULL;
00652         
00653     m_id = -1;
00654 };
00655 
00657 template<class Group>
00658 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00659 GInvertedList<Group>::GInvertedList<Group>(long id)
00660 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00661 {
00662         m_elements = NULL;
00663         m_element_count = 0;
00664         m_new_element_count = 0;
00665 
00666         m_pos_beg = NULL;
00667         m_pos_end = NULL;
00668 
00669     m_id = id;
00670 
00671     ins_buffer_size = INS_BUFFER_SIZE;
00672     ins_buffer_pos = 0;
00673     insertion_buffer=NULL;
00674 
00675     initInsertion();
00676     
00677 };
00678 
00679 template<class Group>
00680 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00681 inline GInvertedList<Group>& GInvertedList<Group>::operator*=(const Group& g)
00682 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00683 {
00684         m_factor = g;
00685         m_factor_inverse = g;
00686         !m_factor_inverse;
00687     return *this;
00688 };
00689 
00690 template<class Group>
00691 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00692 inline GInvertedList<Group>::iterator GInvertedList<Group>::begin()
00693 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00694 {
00695     
00696     if (m_elements==NULL)
00697         readElements();
00698 
00699         return iterator(m_pos_beg, &m_factor);
00700 };
00701 
00702 template<class Group>
00703 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00704 inline GInvertedList<Group>::iterator GInvertedList<Group>::begin(bool dummy)
00705 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00706 {
00707         return begin();
00708 }
00709 
00710 template<class Group>
00711 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00712 inline GInvertedList<Group>::iterator GInvertedList<Group>::end()
00713 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00714 {
00715         return iterator(m_pos_end);
00716 };
00717 
00718 template<class Group>
00719 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00720 inline GInvertedList<Group>::iterator GInvertedList<Group>::end(bool dummy)
00721 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00722 {
00723         return end();
00724 }
00725 
00726 template<class Group>
00727 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00728 inline GInvertedList<Group>::read_iterator GInvertedList<Group>::_begin(void*)
00729 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00730 {
00731         return read_iterator(m_pos_beg);
00732 };
00733 
00734 template<class Group>
00735 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00736 inline GInvertedList<Group>::read_iterator GInvertedList<Group>::_end(void*)
00737 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00738 {
00739         return read_iterator(m_pos_end);
00740 };
00741 
00742 
00746 template<class Group>
00747 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00748 inline int GInvertedList<Group>::size() const
00749 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00750 {
00751         return m_element_count;
00752 };
00753 
00767 template<class Group>
00768 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00769 void GInvertedList<Group>::insert(const Group& g, int i)
00770 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00771 {
00772     
00773     // Falls noch nicht geschehen, wird zunächst die temporäre Datei initialisiert
00774     // initUpdate();
00775 
00776         m_new_element_count++;
00777 
00778     if (insertion_buffer == NULL)
00779         insertion_buffer = new ListTupel<Group>[ins_buffer_size];
00780 
00781     ListTupel<Group> lt(g,i);
00782         if (ins_buffer_pos < ins_buffer_size)
00783     {
00784         insertion_buffer[ins_buffer_pos++] = lt;
00785         return;
00786     }
00787 
00788     if (chdir("list")==-1)
00789         #ifdef VISUALC_INCLUDES
00790         mkdir("list");
00791         #else
00792         mkdir("list",0);
00793         #endif
00794     else
00795         chdir("..");
00796 
00797         std::/*o*/fstream insertion_stream;
00798     insertion_stream.open(m_insertion_file_name, std::ios::app | std::ios::out | std::ios::binary);
00799         if (!insertion_stream)
00800         {
00801         throw IndexingException(IndexingException::FILE_ERROR_OPEN);
00802                 return;
00803         }
00804 
00805     for (int j=0; j<ins_buffer_size; j++)
00806         insertion_stream<<insertion_buffer[j];
00807         insertion_stream<<lt;
00808     ins_buffer_pos = 0;
00809 
00810     insertion_stream.close();
00811 
00812 };
00813 
00825 template<class Group>
00826 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00827 void GInvertedList<Group>::initInsertion()
00828 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00829 {
00830     setFileName(m_id);
00831 };
00832 
00833 
00834 template<class Group>
00835 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00836 inline void GInvertedList<Group>::setFileName(long id)
00837 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00838 {
00839 
00840         char sNum[28];
00841         my_itoa(id, sNum, 16);
00842         strcpy(m_insertion_file_name,"list/glist_");
00843         strcat(m_insertion_file_name,sNum);
00844 
00845     m_stream = NULL;
00846         
00847 }
00848 
00849 
00850 template<class Group>
00851 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00852 void GInvertedList<Group>::initFileRead(std::ifstream& ifs)
00853 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00854 {
00855     
00856     long bytesize;
00857 
00858     // Indexweite eindeutige ID der Liste lesen
00859     ifs.read((char*)&m_id, sizeof(long));
00860     
00861         // Anzahl Einträge lesen
00862     ifs.read((char*)&m_element_count, sizeof(long));
00863 
00864     m_new_element_count = 0;
00865 
00866     // Länge der aktuellen Liste ermitteln
00867         ifs.read((char*)&bytesize, sizeof(long));
00868         if (!ifs)
00869         throw IndexingException(IndexingException::FILE_ERROR_READ);
00870 
00871     // Namen für Einfüge-Datei anhand von m_id festlegen
00872     initInsertion();
00873 
00874         m_stream = &ifs;
00875         //m_fileoffset = offset;
00876         m_fileoffset = ifs.tellg();
00877 
00878 
00879         // stream-Position auf nächste Liste setzen
00880     ifs.seekg(bytesize, std::ios::cur);
00881         if (!ifs)
00882                 throw IndexingException(IndexingException::FILE_ERROR_READ);
00883 
00884 }
00885 
00886 template<class Group>
00887 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00888 void GInvertedList<Group>::initFileRead(std::fstream& ifs)
00889 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00890 {
00891     
00892     long bytesize;
00893 
00894     // Indexweite eindeutige ID der Liste lesen
00895     ifs.read((char*)&m_id, sizeof(long));
00896     
00897         // Anzahl Einträge lesen
00898     ifs.read((char*)&m_element_count, sizeof(long));
00899 
00900     m_new_element_count = 0;
00901 
00902     // Länge der aktuellen Liste ermitteln
00903         ifs.read((char*)&bytesize, sizeof(long));
00904         if (!ifs)
00905         throw IndexingException(IndexingException::FILE_ERROR_READ);
00906 
00907     // Namen für Einfüge-Datei anhand von m_id festlegen
00908     initInsertion();
00909 
00910         m_stream = &ifs;
00911         //m_fileoffset = offset;
00912         m_fileoffset = ifs.tellg();
00913 
00914 
00915         // stream-Position auf nächste Liste setzen
00916     ifs.seekg(bytesize, std::ios::cur);
00917         if (!ifs)
00918                 throw IndexingException(IndexingException::FILE_ERROR_READ);
00919 
00920 }
00921 
00929 template<class Group>
00930 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00931 GInvertedList<Group>::GInvertedList<Group>(std::/*i*/fstream& ifs)
00932 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00933 {
00934 
00935     ins_buffer_size = INS_BUFFER_SIZE;
00936     ins_buffer_pos = 0;
00937     insertion_buffer=NULL;
00938     
00939         m_elements = NULL;
00940     m_pos_beg = NULL;
00941     m_pos_end = NULL;
00942 
00943     initFileRead(ifs);
00944 
00945 }    
00946 
00948 template<class Group>
00949 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00950 void GInvertedList<Group>::readElements()
00951 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00952 {
00953         if (m_elements!=NULL || m_stream==NULL)
00954         // nix zu tun
00955                 return;
00956 
00957         m_elements = new ListTupel<Group>[m_element_count+1];
00958 
00959     // stop-Element für iterator einfügen
00960     m_elements[m_element_count].credit = 0;
00961         readElements(m_elements, 0);
00962     m_pos_beg = &(m_elements[0]);
00963     m_pos_end = &(m_elements[m_element_count]);
00964 };
00965 
00967 template<class Group>
00968 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00969 void GInvertedList<Group>::readElements(int credit)
00970 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00971 {
00972         if (m_elements!=NULL || m_stream==NULL)
00973         // nix zu tun
00974                 return;
00975 
00976         m_elements = new ListTupel<Group>[m_element_count+2];
00977 
00978 
00979     // stop-Element für iterator einfügen
00980     m_elements[m_element_count].credit = 0;
00981         readElements(m_elements, credit);
00982     m_pos_beg = &(m_elements[0]);
00983     m_pos_end = &(m_elements[m_element_count]);
00984 };
00985 
00992 template<class Group>
00993 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00994 void GInvertedList<Group>::readElements(ListTupel<Group>* buffer, int credit) 
00995 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
00996 {
00997         if (m_stream==NULL)
00998         return;
00999 
01000 
01001     (*m_stream).seekg(m_fileoffset, std::ios::beg);
01002     int i;
01003     for (i=0; i<m_element_count; i++)
01004     {
01005         (*m_stream)>>(ListTupel<Group>&)buffer[i];
01006         buffer[i].credit = 0;
01007 /*// BEGIN DEBUG
01008                 Group g = buffer[i].g;
01009                 std::cout << i << ": (" << g << ") -> ";
01010                 g *= m_factor;
01011                 std::cout << "(" << g << ")\n";
01012 // END DEBUG*/
01013     }
01014     //(*m_stream).read((char*)buffer, m_element_count*sizeof(ListTupel<Group>));
01015         if (!(*m_stream))
01016         {
01017                 throw IndexingException(IndexingException::FILE_ERROR_READ);
01018         }
01019 
01020    for (i=0; i<m_element_count; buffer[i++].credit = credit);
01021 
01022 
01023 };
01024 
01026 template<class Group>
01027 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01028 void GInvertedList<Group>::clear()
01029 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01030 {
01031     delete[] m_elements;
01032     m_elements = NULL;
01033 }
01034 
01036 template<class Group>
01037 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01038 void GInvertedList<Group>::remove(int fileindex)
01039 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01040 {
01041     // TODO: anpassen!
01042     // alle ListTupel (sowohl die bereits indexierten als auch die in m_insertion_file_name
01043     // enthaltenen), die nicht Dateinummer fileindex haben, 
01044     // in Datei m_insertion_file_name schreiben, dann m_element_count
01045     // auf 0 setzen und m_new_element_count auf Anzahl der verbliebenen ListTupel setzen.
01046 
01047     m_deleted_fileindices.insert(fileindex);
01048 
01049 /*      ifstream insertion_stream;
01050     insertion_stream.open(m_insertion_file_name,ios::binary);
01051         if (insertion_stream == NULL)
01052         throw IndexingException(IndexingException::FILE_ERROR_OPEN);
01053 
01054     // Bereits indexierte Elemente in m_elements lesen
01055 
01056         ListTupel<Group>* new_elements = new ListTupel<Group>[m_new_element_count+1];
01057     // stop-Element für iterator einfügen
01058     new_elements[m_new_element_count].credit = 0;
01059 
01060         // Alle ListTupel aus glist_-Datei in array lesen
01061         for (int i=0; i<m_new_element_count; i++)
01062         {
01063                 insertion_stream>>new_elements[i];
01064                 if (!insertion_stream)
01065             throw IndexingException(IndexingException::FILE_ERROR_READ);
01066         }
01067 
01068         insertion_stream.close();
01069 
01070     ofstream output_stream;
01071 
01072     char out_file_name[1024];
01073     strcpy(out_file_name, m_insertion_file_name);
01074     strcat(out_file_name, "~");
01075 
01076     output_stream.open(out_file_name,ios::binary | ios::app);
01077 
01078         for (i=1; i<m_new_element_count; i++)
01079         {
01080         if (new_elements[i].i!=fileindex)
01081             output_stream<<new_elements[i];
01082         else 
01083             m_new_element_count--;
01084         };
01085 
01086         delete[] new_elements;
01087 
01088     output_stream.close();
01089 
01090     // Alle ListTupel stehen jetzt in der Indexdatei; die temporäre glist_-Datei
01091     // kann daher gelöscht werden.
01092     if (::remove(m_insertion_file_name)!=0)
01093         throw IndexingException(IndexingException::FILE_ERROR_WRITE);
01094 
01095     if (rename(out_file_name,m_insertion_file_name)!=0)
01096         throw IndexingException(IndexingException::FILE_ERROR_WRITE);
01097   */  
01098 }
01099 
01100 
01101 template<class Group>
01102 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01103 GInvertedList<Group>::read_iterator GInvertedList<Group>::find(const ListTupel<Group>& lt) 
01104 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01105 {
01106         read_iterator found = end();
01107         int left = 0;
01108         int right = size();
01109         int mid = 0;
01110 
01111         ListTupel<Group> l1 = lt;
01112         l1.g *= m_factor_inverse;
01113 
01114         while (left<=right && found==end())
01115         {
01116                 mid = (left+right)/2;
01117 
01118                 ListTupel<Group>* cmp = &m_elements[mid];                       
01119                 if (l1.i==(*cmp).i && !(l1.g!=(*cmp).g))
01120                         found = read_iterator(cmp);
01121                 else if (l1<*cmp)
01122                         left = mid+1;
01123                 else // (current>m_elements2[mid])
01124                         right = mid-1;
01125         }
01126 
01127         return found;
01128 };
01129 
01130 
01131 template<class Group>
01132 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01133 GInvertedList<Group>::read_iterator GInvertedList<Group>::find(const ListTupel<Group>& lt, read_iterator& it)
01134 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01135 {
01136         return find(lt);
01137 };
01138 
01144 template<class Group>
01145 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01146 inline void GInvertedList<Group>::assign(const read_iterator& new_beg, const read_iterator& new_end)
01147 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01148 {
01149         m_pos_beg = &*new_beg;
01150         m_pos_end = &(*new_end);
01151     (*new_end).credit = 0;
01152 };
01153 
01154 template<class Group>
01155 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01156 inline void GInvertedList<Group>::remove(read_iterator& it)
01157 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01158 {
01159     (*it).credit = -1;
01160 }
01161 
01162 template<class Group>
01163 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01164 inline void GInvertedList<Group>::decrease(read_iterator& it)
01165 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01166 {
01167     if ((--((*it).credit))==-1)
01168         m_element_count--;
01169 }
01170 
01180 template<class Group>
01181 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01182 void GInvertedList<Group>::intersect(GInvertedList<Group>& glist2, int& mismatches)
01183 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01184 {
01185     
01186     if (m_elements==NULL)
01187         readElements(mismatches);
01188 
01189     glist2.readElements(mismatches>0 ? mismatches-1 : 0);
01190 
01191     //cout<<*this<<endl<<endl<<glist2<<endl<<endl<<endl;
01192 
01193         // iterator, der auf das nächste zu suchende ListTupel zeigt
01194         read_iterator it = _begin(NULL);
01195 
01196         // iterator, der auf die Position zeigt, an der das nächste Element einzufügen ist.
01197         read_iterator ins = _begin(NULL);
01198         read_iterator last = _end(NULL);
01199 
01200         for (; it != last; it++)
01201         {
01202                 
01203                 ListTupel<Group> l1 = *it;
01204         l1.g *= m_factor;
01205 
01206                 read_iterator found = glist2.find(l1);
01207 
01208                 if (found!=glist2.end())
01209                 {
01210             glist2.remove(found);
01211             *ins = *it;
01212                         ins++;
01213         } else {
01214             // l1 hat einen Mismatch
01215             decrease(it);
01216             if ((*it).credit>=0)
01217             {
01218                 *ins = *it;
01219                 ins++;
01220             }
01221         }
01222 
01223         }
01224         
01225         // neuen Bereich der Liste festlegen auf Bereich vom bisherigen ersten Element bis zur aktuellen Einfügeposition,
01226         // die durch den Iterator ins angezeigt wird;
01227         // die Bedeutung von assign() ist dieselbe wie die des assign() der stl-Container (z.B. list oder vector).
01228     assign(_begin(NULL), ins);
01229 
01230     if (mismatches>0)
01231     {
01232         merge(glist2);
01233         mismatches--;
01234     }
01235 
01236     glist2.clear();
01237 
01238 };
01239 
01240 template<class Group>
01241 bool operator>(const GInvertedList<Group>& l1, const GInvertedList<Group>& l2)
01242 {
01243     return l1.size() > l2.size();
01244 }
01245 
01246 template<class Group>
01247 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01248 void GInvertedList<Group>::merge(GInvertedList<Group>& glist2)
01249 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01250 {
01251 
01252     glist2.readElements();
01253     readElements();
01254 
01255     m_element_count = size()+glist2.size();
01256     ListTupel<Group>* new_elements = new ListTupel<Group>[m_element_count+1];
01257     // stop-Element für iterator einfügen
01258     new_elements[m_element_count].credit = 0;
01259     
01260     read_iterator it1 = _begin(NULL);
01261     read_iterator it2 = glist2._begin(NULL);
01262     int ins_pos = 0;
01263 
01264     while (it1!=(read_iterator)(end()) || it2!=(read_iterator)(glist2.end()))
01265     {
01266         if (it2==(read_iterator)(glist2.end()) || ( it1!=(read_iterator)(end()) && (*it1)<(*it2) ) )
01267         {
01268             new_elements[ins_pos++] = *it1;
01269             it1++;
01270         } else {
01271             (*it2).g *= (glist2.m_factor); 
01272             (*it2).g *= (m_factor_inverse);
01273             new_elements[ins_pos++] = *it2;
01274             it2++;
01275         }
01276     }
01277 
01278     delete[] m_elements;
01279     m_elements = new_elements;
01280     assign(read_iterator(&new_elements[0]),read_iterator(&new_elements[m_element_count]));
01281 
01282 }
01283 
01285 template<class Group>
01286 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01287 GInvertedList<Group>::~GInvertedList<Group>()
01288 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01289 {
01290         if (m_elements != NULL)
01291                 delete[] m_elements;
01292 
01293     ::remove(m_insertion_file_name);
01294 
01295         m_elements = NULL;
01296 
01297     if (insertion_buffer != NULL)
01298         delete[] insertion_buffer;
01299     insertion_buffer = NULL;
01300 
01301 };
01302 
01303 template<class Group>
01304 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01305 std::ofstream& operator<<(std::ofstream& o, GInvertedList<Group>& l)
01306 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01307 {
01308         l.writeToFile(o);
01309         return o;
01310 };
01311 
01312 template<class Group>
01313 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01314 std::ostream& operator<<(std::ostream& o, GInvertedList<Group>& l)
01315 // /////////////////////////////////////////////////////////////////////////////////////////////////////////////
01316 {
01317         o<<l.m_factor<<"*("<<endl;
01318     l.readElements();
01319     GInvertedList<Group>::read_iterator it = l.begin();
01320     GInvertedList<Group>::read_iterator fin = l.end();
01321 
01322     for (; it!=fin; it++)
01323         o<<"  <"<<(*it).g<<", "<<(*it).i<<", "<<(*it).credit<<">"<<endl;
01324     o<<")"<<endl<<endl;
01325 
01326         return o;
01327 };
01328 
01329 }
01330 
01331 #endif
The GroupIndex-Template-Library
Universität Bonn, Institut für Informatik III, 2001