ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/Search/trunk/Outputter.cpp
Revision: 334
Committed: 2004-04-05T16:37:41-07:00 (21 years, 2 months ago) by Douglas Thrift
Original Path: trunk/Search/Outputer.cpp
File size: 12540 byte(s)
Log Message:
Ah, I just love Subversion!

File Contents

# User Rev Content
1 douglas 1 /* ============================================================================
2     * Douglas Thrift's Search Engine License
3     *
4 douglas 312 * Copyright (C) 2002-2004, Douglas Thrift. All Rights Reserved.
5 douglas 1 * Redistribution and use in source and binary forms, with or without
6     * modification, are permitted provided that the following conditions are met:
7     *
8     * 1. Redistributions of source code must retain the above copyright notice,
9     * this list of conditions and the following disclaimer.
10     *
11     * 2. Redistributions in binary form must reproduce the above copyright notice,
12     * this list of conditions and the following disclaimer in the documentation
13     * and/or other materials provided with the distribution.
14     *
15     * 3. The end-user documentation included with the redistribution, if any, must
16     * include the following acknowledgment:
17     *
18     * "This product includes software developed by Douglas Thrift
19     * (http://computers.douglasthrift.net/searchengine/)."
20     *
21     * Alternately, this acknowledgment may appear in the software itself, if
22     * and wherever such third-party acknowledgments normally appear.
23     *
24     * 4. The names "Douglas Thrift" and "Douglas Thrift's Search Engine" must not
25     * be used to endorse or promote products derived from this software without
26     * specific prior written permission. For written permission, please visit
27     * http://www.douglasthrift.net/contact.cgi for contact information.
28     *
29     * 5. Products derived from this software may not be called "Douglas Thrift's
30     * Search Engine", nor may "Douglas Thrift's Search Engine" appear in their
31     * name, without prior written permission.
32     *
33     * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
34     * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35     * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
36     * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
37     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
39     * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40     * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41     * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43     * ============================================================================
44     */
45     // Douglas Thrift's Search Engine Outputer
46     //
47     // Douglas Thrift
48     //
49 Douglas Thrift 331 // $Id$
50 douglas 1
51 Douglas Thrift 334 #include "Outputer.hpp"
52 douglas 1
53 douglas 28 Outputer::Outputer(const string& headerFile, const string& bodyFile, const
54 douglas 15 string& footerFile, const string& notfoundFile, const string& pagesFile)
55 douglas 1 {
56     this->headerFile = headerFile;
57     this->bodyFile = bodyFile;
58     this->footerFile = footerFile;
59     this->notfoundFile = notfoundFile;
60     this->pagesFile = pagesFile;
61     }
62    
63     void Outputer::output(Searcher& searcher, unsigned page)
64     {
65     MultiSet pagesSet = searcher.getPages();
66     numWebpages = pagesSet.size();
67     numPages = (numWebpages + 9) / 10;
68     string query = searcher.getQueryString();
69     vector<string> common = searcher.getCommonUsed();
70    
71     MultiSetIterator itor = pagesSet.begin();
72    
73     for (int count = 0; count < page * 10 && itor != pagesSet.end(); count++)
74     {
75     itor++;
76     }
77    
78     for (int index = 0; index < 10 && itor != pagesSet.end(); index++, itor++)
79     {
80     webpages.push_back(*itor);
81     }
82    
83     this->query = searcher.getQuery().size() > 0;
84     results = webpages.size() > 0;
85     time = searcher.time();
86    
87     if (debug)
88     {
89 douglas 183 cerr << "query = " << this->query << "\n"
90     << "results = " << results << "\n"
91 douglas 1 << "time = " << duration() << "\n";
92     }
93    
94     entities(query, '&', "&amp;");
95     entities(query, '\"', "&quot;");
96     entities(query, '<', "&lt;");
97     entities(query, '>', "&gt;");
98    
99     string ignore = searcher.getIgnore();
100    
101     header(query, page, common, searcher.getAnd(), searcher.getOr(),
102     ignore);
103    
104     if (results)
105     {
106     body();
107     }
108     else if (this->query)
109     {
110     notfound(query, searcher.getQuery().size());
111     }
112    
113     footer(query, page, common, searcher.getAnd(), searcher.getOr(),
114     ignore);
115     }
116    
117 douglas 15 void Outputer::header(const string& query, unsigned page, vector<string>
118     common, bool and_, bool or_, const string& ignore)
119 douglas 1 {
120     ifstream fin(headerFile.c_str());
121    
122     string line;
123     while (fin.good())
124     {
125     getline(fin, line);
126    
127     conditional(line, fin, "<?ifquery?>", this->query);
128     conditional(line, fin, "<?ifresults?>", results);
129     conditional(line, fin, "<?ifor?>", or_);
130     conditional(line, fin, "<?ifand?>", and_);
131     conditional(line, fin, "<?ifignore?>", ignore != "");
132     conditional(line, fin, "<?ifcommon?>", common.size() == 1);
133     conditional(line, fin, "<?ifmanycommon?>", common.size() > 1);
134    
135 douglas 206 #ifndef _OpenSSL_
136 douglas 43 tag(line, "<?version?>", programName + ' ' + programVersion + ' ' +
137     platform());
138 douglas 206 #else
139     tag(line, "<?version?>", programName + ' ' + programVersion + ' ' +
140 douglas 207 platform() + ' ' + openssl());
141 douglas 206 #endif
142 douglas 1 tag(line, "<?query?>", query);
143 douglas 15 tag(line, "<?range?>", range(page));
144     tag(line, "<?total?>", total());
145     tag(line, "<?time?>", duration());
146     tag(line, "<?pages?>", pages(query, page));
147 douglas 1 tag(line, "<?ignore?>", ignore);
148     tag(line, "<?common?>", common[0]);
149 douglas 15 tag(line, "<?manycommon?>", manycommon(common));
150 douglas 1
151 douglas 30 cout << line << (fin.good() ? "\n" : "");
152 douglas 1 }
153    
154     fin.close();
155     }
156    
157     void Outputer::body()
158     {
159     for (int index = 0; index < webpages.size(); index++)
160     {
161     Ranker webpage = webpages[index];
162     string title = webpage.getTitle();
163     if (title == "")
164     {
165     title = webpage.getURL();
166     entities(title, '&', "&amp;");
167     entities(title, '\"', "&quot;");
168     entities(title, '<', "&lt;");
169     entities(title, '>', "&gt;");
170     }
171     string address = webpage.getURL();
172     string sample = webpage.getSample();
173     string description = webpage.getDescription();
174 douglas 207 ostringstream size;
175 douglas 1
176 douglas 211 size.precision(0);
177     size.setf(ios_base::fixed, ios_base::floatfield);
178 douglas 207 size << double(webpage.getSize()) / double(1024) << "k";
179 douglas 1
180     entities(address, '&', "&amp;");
181     entities(address, '\"', "&quot;");
182     entities(address, '<', "&lt;");
183     entities(address, '>', "&gt;");
184    
185     ifstream fin(bodyFile.c_str());
186    
187     string line;
188     while (fin.good())
189     {
190     getline(fin, line);
191    
192     conditional(line, fin, "<?ifdescription?>", description != "");
193    
194     tag(line, "<?address?>", address);
195     tag(line, "<?title?>", title);
196     tag(line, "<?sample?>", sample);
197     tag(line, "<?description?>", description);
198 douglas 207 tag(line, "<?size?>", size.str());
199 douglas 1
200 douglas 30 cout << line << (fin.good() ? "\n" : "");
201 douglas 1 }
202    
203     fin.close();
204     }
205     }
206    
207 douglas 15 void Outputer::footer(const string& query, unsigned page, vector<string>
208     common, bool and_, bool or_, const string& ignore)
209 douglas 1 {
210     ifstream fin(footerFile.c_str());
211    
212     string line;
213     while (fin.good())
214     {
215     getline(fin, line);
216    
217     conditional(line, fin, "<?ifquery?>", this->query);
218     conditional(line, fin, "<?ifresults?>", results);
219     conditional(line, fin, "<?ifor?>", or_);
220     conditional(line, fin, "<?ifand?>", and_);
221     conditional(line, fin, "<?ifignore?>", ignore != "");
222     conditional(line, fin, "<?ifcommon?>", common.size() == 1);
223     conditional(line, fin, "<?ifmanycommon?>", common.size() > 1);
224    
225 douglas 205 #ifndef _OpenSSL_
226 douglas 43 tag(line, "<?version?>", programName + ' ' + programVersion + ' ' +
227     platform());
228 douglas 205 #else
229     tag(line, "<?version?>", programName + ' ' + programVersion + ' ' +
230 douglas 207 platform() + ' ' + openssl());
231 douglas 205 #endif
232 douglas 1 tag(line, "<?query?>", query);
233 douglas 15 tag(line, "<?range?>", range(page));
234     tag(line, "<?total?>", total());
235     tag(line, "<?time?>", duration());
236     tag(line, "<?pages?>", pages(query, page));
237 douglas 1 tag(line, "<?ignore?>", ignore);
238     tag(line, "<?common?>", common[0]);
239 douglas 15 tag(line, "<?manycommon?>", manycommon(common));
240 douglas 1
241 douglas 30 cout << line << (fin.good() ? "\n" : "");
242 douglas 1 }
243    
244     fin.close();
245     }
246    
247 douglas 15 void Outputer::notfound(const string& query, unsigned keywords)
248 douglas 1 {
249     ifstream fin(notfoundFile.c_str());
250    
251     string line;
252     while (fin.good())
253     {
254     getline(fin, line);
255    
256     conditional(line, fin, "<?ifmany?>", keywords > 1);
257    
258     tag(line, "<?query?>", query);
259    
260 douglas 30 cout << line << (fin.good() ? "\n" : "");
261 douglas 1 }
262    
263     fin.close();
264     }
265    
266     string Outputer::pages(string query, unsigned page)
267     {
268     entities(query, "&lt;", '<');
269     entities(query, "&gt;", '>');
270     entities(query, "&quot;", '\"');
271     entities(query, "&amp;", '&');
272    
273     entities(query, '%', "%25");
274     entities(query, '\t', "%09");
275     entities(query, ' ', "%20");
276     entities(query, '\"', "%22");
277     entities(query, '#', "%23");
278     entities(query, '$', "%24");
279     entities(query, '&', "%26");
280     entities(query, '\'', "%27");
281     entities(query, '+', "%2B");
282     entities(query, ',', "%2C");
283     entities(query, '/', "%2F");
284     entities(query, ':', "%3A");
285     entities(query, ';', "%3B");
286     entities(query, '<', "%3C");
287     entities(query, '=', "%3D");
288     entities(query, '>', "%3E");
289     entities(query, '?', "%3F");
290     entities(query, '@', "%40");
291     entities(query, '[', "%5B");
292     entities(query, ']', "%5D");
293     entities(query, '\\', "%5C");
294     entities(query, '^', "%5E");
295     entities(query, '`', "%60");
296     entities(query, '{', "%7B");
297     entities(query, '|', "%7C");
298     entities(query, '}', "%7D");
299     entities(query, '~', "%7E");
300    
301     string lines;
302    
303     ifstream fin(pagesFile.c_str());
304    
305     string line;
306     while (fin.good())
307     {
308     getline(fin, line);
309     conditional(line, fin, "<?ifprevious?>", page >= 1);
310     conditional(line, fin, "<?ifpage?>", false);
311     conditional(line, fin, "<?ifnum?>", false);
312     conditional(line, fin, "<?ifnext?>", false);
313    
314 douglas 207 ostringstream previous;
315 douglas 1
316 douglas 207 previous << page;
317 douglas 1
318     tag(line, "<?query?>", query);
319 douglas 207 tag(line, "<?previous?>", previous.str());
320 douglas 1
321 douglas 30 lines += line + (fin.good() ? "\n" : "");
322 douglas 1 }
323    
324     fin.close();
325     fin.clear();
326    
327     for (int index = 0; index < numPages; index++)
328     {
329     fin.open(pagesFile.c_str());
330    
331     while (fin.good())
332     {
333     getline(fin, line);
334     if (index == page)
335     {
336     conditional(line, fin, "<?ifprevious?>", false);
337     conditional(line, fin, "<?ifpage?>", true);
338     conditional(line, fin, "<?ifnum?>", false);
339     conditional(line, fin, "<?ifnext?>", false);
340    
341 douglas 207 ostringstream current;
342 douglas 1
343 douglas 207 current << index + 1;
344 douglas 1
345 douglas 207 tag(line, "<?page?>", current.str());
346 douglas 1 }
347     else
348     {
349     conditional(line, fin, "<?ifprevious?>", false);
350     conditional(line, fin, "<?ifpage?>", false);
351     conditional(line, fin, "<?ifnum?>", true);
352     conditional(line, fin, "<?ifnext?>", false);
353    
354 douglas 207 ostringstream num;
355 douglas 1
356 douglas 207 num << index + 1;
357 douglas 1
358     tag(line, "<?query?>", query);
359 douglas 207 tag(line, "<?num?>", num.str());
360 douglas 1 }
361    
362 douglas 30 lines += line + (fin.good() ? "\n" : "");
363 douglas 1 }
364    
365     fin.close();
366     fin.clear();
367     }
368    
369     fin.open(pagesFile.c_str());
370    
371     while (fin.good())
372     {
373     getline(fin, line);
374     conditional(line, fin, "<?ifprevious?>", false);
375     conditional(line, fin, "<?ifpage?>", false);
376     conditional(line, fin, "<?ifnum?>", false);
377     conditional(line, fin, "<?ifnext?>", page + 2 <= numPages);
378    
379 douglas 207 ostringstream next;
380 douglas 1
381 douglas 207 next << page + 2;
382 douglas 1
383     tag(line, "<?query?>", query);
384 douglas 207 tag(line, "<?next?>", next.str());
385 douglas 1
386 douglas 30 lines += line + (fin.good() ? "\n" : "");
387 douglas 1 }
388    
389     fin.close();
390    
391     return lines;
392     }
393    
394     string Outputer::range(unsigned page)
395     {
396     unsigned bottom = page * 10 + 1;
397     unsigned top = numWebpages > page * 10 + 10 ? page * 10 + 10 : numWebpages;
398 douglas 207 ostringstream range;
399 douglas 1
400 douglas 207 range << bottom << " - " << top;
401 douglas 1
402 douglas 207 return range.str();
403 douglas 1 }
404    
405     string Outputer::total()
406     {
407 douglas 207 ostringstream total;
408 douglas 1
409 douglas 207 total << numWebpages;
410 douglas 1
411 douglas 207 return total.str();
412 douglas 1 }
413    
414     string Outputer::duration()
415     {
416 douglas 207 ostringstream duration;
417 douglas 1
418 douglas 207 duration.precision(2);
419 douglas 212 duration.setf(ios_base::fixed, ios_base::floatfield);
420 douglas 207 duration << time;
421 douglas 1
422 douglas 207 return duration.str();
423 douglas 1 }
424    
425     string Outputer::manycommon(vector<string> common)
426     {
427     string line;
428    
429     for (int index = 0; index < common.size(); index++)
430     {
431     line += common[index];
432    
433     if (index != common.size() - 1) line += ' ';
434     }
435    
436     return line;
437     }
438    
439 douglas 15 void Outputer::tag(string& line, char* tag, const string& replacement)
440 douglas 1 {
441     int begin = 0;
442     while (begin < line.length())
443     {
444     int spot = line.find(tag, begin);
445    
446     if (spot != string::npos)
447     {
448     line.replace(spot, strlen(tag), replacement);
449     }
450     else
451     {
452     break;
453     }
454    
455     begin = spot + replacement.length();
456     }
457     }
458    
459     void Outputer::conditional(string& line, ifstream& fin, char* tag, bool
460     condition)
461     {
462     unsigned begin = 0;
463     while (begin < line.length())
464     {
465     unsigned start = line.find(tag, begin);
466     unsigned finish = line.find("<?endif?>", start);
467    
468     if (start == string::npos) break;
469    
470     string next;
471     while (finish == string::npos)
472     {
473     getline(fin, next);
474     line += '\n' + next;
475     finish = line.find("<?endif?>", start);
476     }
477    
478     if (condition)
479     {
480     line.erase(start, strlen(tag));
481     line.erase(finish - strlen(tag), 9);
482    
483     begin = finish - strlen(tag) - 9;
484     }
485     else
486     {
487     line.erase(start, finish - start + 9);
488    
489     begin = start;
490     }
491     }
492     }

Properties

Name Value
svn:eol-style native
svn:keywords Id