LZ index support
[SXSI/TextCollection.git] / TextStorage.cpp
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 #include "TextStorage.h"
22
23 #undef W
24 #undef bitsW
25 #undef bitset
26 #undef bits
27
28 #include "lzindex/lztrie.h"
29
30 // Re-define word size to ulong:
31 #undef W
32 #if __WORDSIZE == 64
33 #   define W 64
34 #else
35 #   define W 32
36 #endif
37 #undef bitset
38 #undef bitget
39 #undef bits
40
41
42 namespace SXSI
43 {
44
45 /******************************************************************
46  * Class TextStorage
47  */
48
49 TextStorage * TextStorage::Load(std::FILE *file)
50 {
51     char type = 0;
52     if (std::fread(&type, sizeof(char), 1, file) != 1)
53         throw std::runtime_error("TextStorage::Load(): file read error (type).");
54
55     switch(type)
56     {
57     case (TYPE_PLAIN_TEXT):
58         return new TextStoragePlainText(file);
59     case (TYPE_LZ_INDEX):
60         return new TextStorageLzIndex(file);
61     default:
62         std::cerr << "TextStorage::Load(): Unknown type in save file!" << std::endl;
63         exit(1);
64     }
65 }
66
67 TextStorage::TextStorage(std::FILE * file)
68     : n_(0), offsets_(0), numberOfTexts_(0)
69 {
70    if (std::fread(&(this->n_), sizeof(TextPosition), 1, file) != 1)
71         throw std::runtime_error("TextStorage::Load(): file read error (n_).");
72
73     if (std::fread(&(this->numberOfTexts_), sizeof(TextPosition), 1, file) != 1)
74         throw std::runtime_error("TextStorage::Load(): file read error (numberOfTexts_).");
75
76     offsets_ = new CSA::DeltaVector(file);   
77 }
78
79 void TextStorage::Save(FILE *file, char type) const
80 {
81     if (std::fwrite(&type, sizeof(char), 1, file) != 1)
82         throw std::runtime_error("TextStorage::Save(): file write error (type).");
83         
84     if (std::fwrite(&(this->n_), sizeof(TextPosition), 1, file) != 1)
85         throw std::runtime_error("TextStorage::Save(): file write error (n_).");
86     
87     if (std::fwrite(&(this->numberOfTexts_), sizeof(TextPosition), 1, file) != 1)
88         throw std::runtime_error("TextStorage::Save(): file write error (n_).");
89
90     offsets_->writeTo(file);
91 }
92
93
94 /******************************************************************
95  * Class TextStorageLzIndex
96  */
97
98 // Hide the lztrie declaration
99 struct LzTriePimpl 
100 {
101     lztrie lz;
102     
103     LzTriePimpl()
104         : lz(0)
105     { }
106 };    
107
108 TextStorageLzIndex::TextStorageLzIndex(uchar *text, TextPosition n)
109     : TextStorage(text, n), p_(new struct LzTriePimpl)
110
111     for (ulong i = 0; i < n_ - 1; ++i)
112         if (text[i] == 0)
113             text[i] = 1; // '\0' can appear only once.
114     text[n_ - 1] = 0;
115
116     p_->lz = buildLZTrie(text, (uchar)0, n_);
117     delete [] text;
118 }
119
120 TextStorageLzIndex::TextStorageLzIndex(FILE *file)
121     : TextStorage(file), p_(new struct LzTriePimpl)
122 {
123     p_->lz = loadLZTrie(file);
124 }
125
126 void TextStorageLzIndex::Save(FILE *file) const
127 {
128     TextStorage::Save(file, TYPE_LZ_INDEX);
129
130     saveLZTrie(p_->lz, file);
131 }
132
133 TextStorageLzIndex::~TextStorageLzIndex()
134 {
135     destroyLZTrie(p_->lz);
136     delete p_;
137     p_ = 0;
138     n_ = 0;
139 }
140
141 uchar * TextStorageLzIndex::GetText(TextCollection::DocId docId) const
142 {
143     assert(docId < (TextCollection::DocId)numberOfTexts_);
144
145     TextPosition from = offsets_->select(docId);
146     TextPosition to = 0;
147     if (docId < (TextCollection::DocId)numberOfTexts_ - 1)
148         to = offsets_->select(docId + 1) - 1;
149     else
150         to = n_-1;
151
152     uchar *text = 0;
153     ulong l = 0;
154     extract(p_->lz, from, to, &text, &l);
155
156     text[l-1] = 0;
157     return text;
158 }
159
160 uchar * TextStorageLzIndex::GetText(TextCollection::DocId i, TextCollection::DocId j) const
161 {
162     assert(i < (TextCollection::DocId)numberOfTexts_);
163     assert(j < (TextCollection::DocId)numberOfTexts_);
164
165     TextPosition from = offsets_->select(i);
166     TextPosition to = 0;
167     if (j < (TextCollection::DocId)numberOfTexts_ - 1)
168         to = offsets_->select(j + 1) - 1;
169     else
170         to = n_-1;
171
172     uchar *text = 0;
173     ulong l = 0;
174     extract(p_->lz, from, to, &text, &l);
175
176     // Put '\0' bytes back in place
177     while (i < j && i < (TextCollection::DocId)numberOfTexts_)
178     {        
179         ++i;
180         text[offsets_->select(i) - 1 - from] = 0;
181     }
182     text[l-1] = 0;
183     return text;
184 }
185
186 } // namespace SXSI
187