3da3a1d551b6ba7b51ed46b691a00787a10b4e7c
[SXSI/TextCollection.git] / TextStorage.h
1 /******************************************************************************
2  *   Copyright (C) 2009 Niko Välimäki                                         *
3  *                                                                            *
4  *                                                                            *
5  *   This program is free software; you can redistribute it and/or modify     *
6  *   it under the terms of the GNU Lesser General Public License as published *
7  *   by the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                      *
9  *                                                                            *
10  *   This program is distributed in the hope that it will be useful,          *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of           *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
13  *   GNU Lesser General Public License for more details.                      *
14  *                                                                            *
15  *   You should have received a copy of the GNU Lesser General Public License *
16  *   along with this program; if not, write to the                            *
17  *   Free Software Foundation, Inc.,                                          *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            *
19  *****************************************************************************/
20
21 #ifndef _TextStorage_H_
22 #define _TextStorage_H_
23
24 #include "incbwt/bits/deltavector.h"
25
26 namespace SXSI 
27 {
28
29 /**
30  * Text collection that supports fast extraction.
31  */
32 class TextStorage
33 {
34 public:
35     // Define a shortcut
36     typedef TextCollection::TextPosition TextPosition;
37     // Block size in DeltaVector
38     const static CSA::usint DV_BLOCK_SIZE = 32;
39
40     TextStorage(uchar *text, TextPosition n)
41         : n_(n), text_(text), offsets_(0), numberOfTexts_(0)
42     { 
43         initOffsets();
44     }
45
46     TextStorage(FILE *file)
47         : n_(0), text_(0), offsets_(0), numberOfTexts_(0)
48     {
49         if (std::fread(&(this->n_), sizeof(TextPosition), 1, file) != 1)
50             throw std::runtime_error("TextStorage::Load(): file read error (n_).");
51         
52         text_ = new uchar[n_];
53         if (std::fread(this->text_, sizeof(uchar), n_, file) != n_)
54             throw std::runtime_error("TextStorage::Load(): file read error (text_).");
55
56         initOffsets();
57     }
58
59     void Save(FILE *file)
60     {
61         if (std::fwrite(&(this->n_), sizeof(TextPosition), 1, file) != 1)
62             throw std::runtime_error("TextStorage::Save(): file write error (n_).");
63
64           if (std::fwrite(this->text_, sizeof(uchar), n_, file) != n_)
65             throw std::runtime_error("TextStorage::Save(): file write error (text_).");
66     }
67
68     ~TextStorage()
69     {
70         delete offsets_;
71         offsets_ = 0;
72         delete [] text_;
73         text_ = 0;
74         n_ = 0;
75     }
76
77     uchar * GetText(TextCollection::DocId docId)
78     {
79         assert(docId < (TextCollection::DocId)numberOfTexts_);
80
81         TextPosition offset = offsets_->select(docId);
82         return &text_[offset];
83     }
84
85     TextCollection::DocId DocIdAtTextPos(TextCollection::TextPosition i)
86     {
87         assert(i < n_);
88         return offsets_->rank(i)-1;
89     }
90
91     TextCollection::TextPosition TextStartPos(TextCollection::DocId i)
92     {
93         assert(i < (TextCollection::DocId)numberOfTexts_);
94         return offsets_->select(i);
95     }
96
97 private:
98     void initOffsets()
99     {
100         // Delta encoded bitvector of text offsets.
101         CSA::DeltaEncoder encoder(DV_BLOCK_SIZE);
102         encoder.setBit(0); // Start of the first text.
103
104         // Read offsets by finding text end positions:
105         for (TextPosition i = 0; i < n_ - 1; ++i)
106             if (text_[i] == '\0')
107                 encoder.setBit(i+1);
108
109         offsets_ = new CSA::DeltaVector(encoder, n_);
110         numberOfTexts_ = offsets_->rank(n_ - 1);
111     }
112
113     TextPosition n_;
114     uchar *text_; // FIXME Replace with a succinct representation.
115     CSA::DeltaVector *offsets_;
116     TextPosition numberOfTexts_;
117 }; // class TextStorage
118
119
120 /**
121  * Builder for TextStorage class
122  */
123 class TextStorageBuilder
124 {
125 public:
126     // Define a shortcut
127     typedef TextCollection::TextPosition TextPosition;
128
129     // Build up simple uchar array
130     explicit TextStorageBuilder(TextPosition n)
131         : n_(n), text_(new uchar [n]), freeText(true)
132     { }
133     
134     ~TextStorageBuilder()
135     {
136         if (freeText)
137             delete [] text_;
138         text_ = 0;
139         n_ = 0;
140     }
141     
142     // Write access to text[]
143     uchar& operator[] (TextPosition i)
144     {
145         return text_[i];
146     }
147
148     // Init TextStorage
149     TextStorage * InitTextStorage()
150     {
151         freeText = false; // Passing text to TextStorage.
152         return new TextStorage(text_, n_);
153     }
154
155 private:
156     TextPosition n_;
157     uchar *text_; // FIXME Replace with a succinct representation.
158     bool freeText;
159 }; // class TextStorageBuilder
160
161 } // namespace SXSI
162
163 #endif // #ifndef _TextStorage_H_