ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/Search/trunk/Outputter.cpp
Revision: 385
Committed: 2010-05-07T18:00:35-07:00 (15 years, 1 month ago) by douglas
File size: 12210 byte(s)
Log Message:
Grr! Oops!

File Contents

# User Rev Content
1 douglas 1 /* ============================================================================
2     * Douglas Thrift's Search Engine License
3     *
4 douglas 372 * Copyright (C) 2002-2004, 2008, 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 351 // Douglas Thrift's Search Engine Outputter
46 douglas 1 //
47     // Douglas Thrift
48     //
49 Douglas Thrift 331 // $Id$
50 douglas 1
51 Douglas Thrift 351 #include "Outputter.hpp"
52 douglas 1
53 douglas 365 void Outputter::output(Searcher& searcher, size_t page)
54 douglas 1 {
55 Douglas Thrift 348 MultiSet pagesSet(searcher.getPages());
56 douglas 365
57 douglas 1 numWebpages = pagesSet.size();
58     numPages = (numWebpages + 9) / 10;
59    
60 Douglas Thrift 348 string query(searcher.getQueryString());
61     vector<string> common(searcher.getCommonUsed());
62 douglas 1
63 Douglas Thrift 348 MultiSetIterator itor(pagesSet.begin());
64    
65     for (size_t count(0); count < page * 10 && itor != pagesSet.end(); count++)
66 douglas 1 {
67     itor++;
68     }
69    
70 Douglas Thrift 348 for (short index(0); index < 10 && itor != pagesSet.end(); index++, itor++)
71 douglas 1 {
72     webpages.push_back(*itor);
73     }
74    
75     this->query = searcher.getQuery().size() > 0;
76     results = webpages.size() > 0;
77     time = searcher.time();
78    
79     if (debug)
80     {
81 douglas 183 cerr << "query = " << this->query << "\n"
82     << "results = " << results << "\n"
83 douglas 1 << "time = " << duration() << "\n";
84     }
85    
86     entities(query, '&', "&amp;");
87     entities(query, '\"', "&quot;");
88     entities(query, '<', "&lt;");
89     entities(query, '>', "&gt;");
90    
91 Douglas Thrift 348 string ignore(searcher.getIgnore());
92 douglas 1
93 Douglas Thrift 348 header(query, page, common, searcher.getAnd(), searcher.getOr(), ignore);
94 douglas 1
95 Douglas Thrift 348 if (results) body(); else if (this->query)
96 douglas 1 {
97     notfound(query, searcher.getQuery().size());
98     }
99    
100 Douglas Thrift 348 footer(query, page, common, searcher.getAnd(), searcher.getOr(), ignore);
101 douglas 1 }
102    
103 douglas 365 void Outputter::header(const string& query, size_t page, const vector<string>&
104 douglas 15 common, bool and_, bool or_, const string& ignore)
105 douglas 1 {
106     ifstream fin(headerFile.c_str());
107 Douglas Thrift 348 string line;
108 douglas 1
109     while (fin.good())
110     {
111     getline(fin, line);
112     conditional(line, fin, "<?ifquery?>", this->query);
113     conditional(line, fin, "<?ifresults?>", results);
114     conditional(line, fin, "<?ifor?>", or_);
115     conditional(line, fin, "<?ifand?>", and_);
116     conditional(line, fin, "<?ifignore?>", ignore != "");
117     conditional(line, fin, "<?ifcommon?>", common.size() == 1);
118     conditional(line, fin, "<?ifmanycommon?>", common.size() > 1);
119 douglas 206 #ifndef _OpenSSL_
120 douglas 43 tag(line, "<?version?>", programName + ' ' + programVersion + ' ' +
121     platform());
122 douglas 206 #else
123     tag(line, "<?version?>", programName + ' ' + programVersion + ' ' +
124 douglas 207 platform() + ' ' + openssl());
125 douglas 206 #endif
126 douglas 1 tag(line, "<?query?>", query);
127 douglas 15 tag(line, "<?range?>", range(page));
128     tag(line, "<?total?>", total());
129     tag(line, "<?time?>", duration());
130     tag(line, "<?pages?>", pages(query, page));
131 douglas 1 tag(line, "<?ignore?>", ignore);
132     tag(line, "<?common?>", common[0]);
133 douglas 15 tag(line, "<?manycommon?>", manycommon(common));
134 douglas 1
135 douglas 30 cout << line << (fin.good() ? "\n" : "");
136 douglas 1 }
137    
138     fin.close();
139     }
140    
141 Douglas Thrift 351 void Outputter::body()
142 douglas 1 {
143 Douglas Thrift 348 for (size_t index = 0; index < webpages.size(); index++)
144 douglas 1 {
145 Douglas Thrift 348 Ranker webpage(webpages[index]);
146     string title(webpage.getTitle());
147    
148 douglas 1 if (title == "")
149     {
150     title = webpage.getURL();
151 Douglas Thrift 348
152 douglas 1 entities(title, '&', "&amp;");
153     entities(title, '\"', "&quot;");
154     entities(title, '<', "&lt;");
155     entities(title, '>', "&gt;");
156     }
157 Douglas Thrift 348
158     string address(webpage.getURL()), sample(webpage.getSample()),
159     description(webpage.getDescription());
160 douglas 207 ostringstream size;
161 douglas 1
162 douglas 211 size.precision(0);
163     size.setf(ios_base::fixed, ios_base::floatfield);
164 Douglas Thrift 348
165 douglas 207 size << double(webpage.getSize()) / double(1024) << "k";
166 douglas 1
167     entities(address, '&', "&amp;");
168     entities(address, '\"', "&quot;");
169     entities(address, '<', "&lt;");
170     entities(address, '>', "&gt;");
171    
172     ifstream fin(bodyFile.c_str());
173 Douglas Thrift 348 string line;
174 douglas 1
175     while (fin.good())
176     {
177     getline(fin, line);
178     conditional(line, fin, "<?ifdescription?>", description != "");
179     tag(line, "<?address?>", address);
180     tag(line, "<?title?>", title);
181     tag(line, "<?sample?>", sample);
182     tag(line, "<?description?>", description);
183 douglas 207 tag(line, "<?size?>", size.str());
184 douglas 1
185 douglas 30 cout << line << (fin.good() ? "\n" : "");
186 douglas 1 }
187    
188     fin.close();
189     }
190     }
191    
192 douglas 365 void Outputter::footer(const string& query, size_t page, const vector<string>&
193 douglas 15 common, bool and_, bool or_, const string& ignore)
194 douglas 1 {
195     ifstream fin(footerFile.c_str());
196 Douglas Thrift 348 string line;
197 douglas 1
198     while (fin.good())
199     {
200     getline(fin, line);
201     conditional(line, fin, "<?ifquery?>", this->query);
202     conditional(line, fin, "<?ifresults?>", results);
203     conditional(line, fin, "<?ifor?>", or_);
204     conditional(line, fin, "<?ifand?>", and_);
205     conditional(line, fin, "<?ifignore?>", ignore != "");
206     conditional(line, fin, "<?ifcommon?>", common.size() == 1);
207     conditional(line, fin, "<?ifmanycommon?>", common.size() > 1);
208 douglas 205 #ifndef _OpenSSL_
209 douglas 43 tag(line, "<?version?>", programName + ' ' + programVersion + ' ' +
210     platform());
211 douglas 205 #else
212     tag(line, "<?version?>", programName + ' ' + programVersion + ' ' +
213 douglas 207 platform() + ' ' + openssl());
214 douglas 205 #endif
215 douglas 1 tag(line, "<?query?>", query);
216 douglas 15 tag(line, "<?range?>", range(page));
217     tag(line, "<?total?>", total());
218     tag(line, "<?time?>", duration());
219     tag(line, "<?pages?>", pages(query, page));
220 douglas 1 tag(line, "<?ignore?>", ignore);
221     tag(line, "<?common?>", common[0]);
222 douglas 15 tag(line, "<?manycommon?>", manycommon(common));
223 douglas 1
224 douglas 30 cout << line << (fin.good() ? "\n" : "");
225 douglas 1 }
226    
227     fin.close();
228     }
229    
230 douglas 365 void Outputter::notfound(const string& query, size_t keywords)
231 douglas 1 {
232     ifstream fin(notfoundFile.c_str());
233 Douglas Thrift 348 string line;
234 douglas 1
235     while (fin.good())
236     {
237     getline(fin, line);
238     conditional(line, fin, "<?ifmany?>", keywords > 1);
239     tag(line, "<?query?>", query);
240    
241 douglas 30 cout << line << (fin.good() ? "\n" : "");
242 douglas 1 }
243    
244     fin.close();
245     }
246    
247 douglas 365 string Outputter::pages(string query, size_t page)
248 douglas 1 {
249     entities(query, "&lt;", '<');
250     entities(query, "&gt;", '>');
251     entities(query, "&quot;", '\"');
252     entities(query, "&amp;", '&');
253     entities(query, '%', "%25");
254     entities(query, '\t', "%09");
255     entities(query, ' ', "%20");
256     entities(query, '\"', "%22");
257     entities(query, '#', "%23");
258     entities(query, '$', "%24");
259     entities(query, '&', "%26");
260     entities(query, '\'', "%27");
261     entities(query, '+', "%2B");
262     entities(query, ',', "%2C");
263     entities(query, '/', "%2F");
264     entities(query, ':', "%3A");
265     entities(query, ';', "%3B");
266     entities(query, '<', "%3C");
267     entities(query, '=', "%3D");
268     entities(query, '>', "%3E");
269     entities(query, '?', "%3F");
270     entities(query, '@', "%40");
271     entities(query, '[', "%5B");
272     entities(query, ']', "%5D");
273     entities(query, '\\', "%5C");
274     entities(query, '^', "%5E");
275     entities(query, '`', "%60");
276     entities(query, '{', "%7B");
277     entities(query, '|', "%7C");
278     entities(query, '}', "%7D");
279     entities(query, '~', "%7E");
280    
281     ifstream fin(pagesFile.c_str());
282 Douglas Thrift 348 string lines, line;
283 douglas 1
284     while (fin.good())
285     {
286     getline(fin, line);
287     conditional(line, fin, "<?ifprevious?>", page >= 1);
288     conditional(line, fin, "<?ifpage?>", false);
289     conditional(line, fin, "<?ifnum?>", false);
290     conditional(line, fin, "<?ifnext?>", false);
291    
292 douglas 207 ostringstream previous;
293 douglas 1
294 douglas 207 previous << page;
295 douglas 1
296     tag(line, "<?query?>", query);
297 douglas 207 tag(line, "<?previous?>", previous.str());
298 douglas 1
299 douglas 30 lines += line + (fin.good() ? "\n" : "");
300 douglas 1 }
301    
302     fin.close();
303     fin.clear();
304    
305 douglas 365 for (size_t index(0); index < numPages; index++)
306 douglas 1 {
307     fin.open(pagesFile.c_str());
308    
309     while (fin.good())
310     {
311     getline(fin, line);
312 Douglas Thrift 348
313 douglas 1 if (index == page)
314     {
315     conditional(line, fin, "<?ifprevious?>", false);
316     conditional(line, fin, "<?ifpage?>", true);
317     conditional(line, fin, "<?ifnum?>", false);
318     conditional(line, fin, "<?ifnext?>", false);
319    
320 douglas 207 ostringstream current;
321 douglas 1
322 douglas 207 current << index + 1;
323 douglas 1
324 douglas 207 tag(line, "<?page?>", current.str());
325 douglas 1 }
326     else
327     {
328     conditional(line, fin, "<?ifprevious?>", false);
329     conditional(line, fin, "<?ifpage?>", false);
330     conditional(line, fin, "<?ifnum?>", true);
331     conditional(line, fin, "<?ifnext?>", false);
332    
333 douglas 207 ostringstream num;
334 douglas 1
335 douglas 207 num << index + 1;
336 douglas 1
337     tag(line, "<?query?>", query);
338 douglas 207 tag(line, "<?num?>", num.str());
339 douglas 1 }
340    
341 douglas 30 lines += line + (fin.good() ? "\n" : "");
342 douglas 1 }
343    
344     fin.close();
345     fin.clear();
346     }
347    
348     fin.open(pagesFile.c_str());
349    
350     while (fin.good())
351     {
352     getline(fin, line);
353     conditional(line, fin, "<?ifprevious?>", false);
354     conditional(line, fin, "<?ifpage?>", false);
355     conditional(line, fin, "<?ifnum?>", false);
356     conditional(line, fin, "<?ifnext?>", page + 2 <= numPages);
357    
358 douglas 207 ostringstream next;
359 douglas 1
360 douglas 207 next << page + 2;
361 douglas 1
362     tag(line, "<?query?>", query);
363 douglas 207 tag(line, "<?next?>", next.str());
364 douglas 1
365 douglas 30 lines += line + (fin.good() ? "\n" : "");
366 douglas 1 }
367    
368     fin.close();
369    
370     return lines;
371     }
372    
373 douglas 365 string Outputter::range(size_t page)
374 douglas 1 {
375 douglas 365 size_t bottom(page * 10 + 1), top(numWebpages > page * 10 + 10 ? page *
376 Douglas Thrift 348 10 + 10 : numWebpages);
377 douglas 207 ostringstream range;
378 douglas 1
379 douglas 207 range << bottom << " - " << top;
380 douglas 1
381 douglas 207 return range.str();
382 douglas 1 }
383    
384 Douglas Thrift 351 string Outputter::total()
385 douglas 1 {
386 douglas 207 ostringstream total;
387 douglas 1
388 douglas 207 total << numWebpages;
389 douglas 1
390 douglas 207 return total.str();
391 douglas 1 }
392    
393 Douglas Thrift 351 string Outputter::duration()
394 douglas 1 {
395 douglas 207 ostringstream duration;
396 douglas 1
397 douglas 207 duration.precision(2);
398 douglas 212 duration.setf(ios_base::fixed, ios_base::floatfield);
399 Douglas Thrift 348
400 douglas 207 duration << time;
401 douglas 1
402 douglas 207 return duration.str();
403 douglas 1 }
404    
405 Douglas Thrift 351 string Outputter::manycommon(const vector<string>& common)
406 douglas 1 {
407     string line;
408    
409 Douglas Thrift 348 for (size_t index = 0; index < common.size(); index++)
410 douglas 1 {
411     line += common[index];
412    
413     if (index != common.size() - 1) line += ' ';
414     }
415    
416     return line;
417     }
418    
419 douglas 365 void Outputter::tag(string& line, const char* tag, const string& replacement)
420 douglas 1 {
421 Douglas Thrift 348 size_t begin(0);
422    
423 douglas 1 while (begin < line.length())
424     {
425 Douglas Thrift 348 int spot(line.find(tag, begin));
426 douglas 1
427     if (spot != string::npos)
428     {
429     line.replace(spot, strlen(tag), replacement);
430     }
431 Douglas Thrift 348 else break;
432 douglas 1
433     begin = spot + replacement.length();
434     }
435     }
436    
437 douglas 365 void Outputter::conditional(string& line, ifstream& fin, const char* tag, bool
438 douglas 1 condition)
439     {
440 douglas 365 size_t begin(0);
441 Douglas Thrift 348
442 douglas 1 while (begin < line.length())
443     {
444 douglas 365 size_t start(line.find(tag, begin)), finish(line.find("<?endif?>",
445 Douglas Thrift 348 start));
446 douglas 1
447     if (start == string::npos) break;
448    
449     string next;
450 Douglas Thrift 348
451 douglas 1 while (finish == string::npos)
452     {
453     getline(fin, next);
454 Douglas Thrift 348
455 douglas 1 line += '\n' + next;
456 Douglas Thrift 348
457 douglas 1 finish = line.find("<?endif?>", start);
458     }
459    
460     if (condition)
461     {
462 douglas 385 line.erase(start, std::strlen(tag));
463     line.erase(finish - std::strlen(tag), 9);
464 douglas 1
465     begin = finish - strlen(tag) - 9;
466     }
467     else
468     {
469     line.erase(start, finish - start + 9);
470    
471     begin = start;
472     }
473     }
474     }

Properties

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