ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/Search/trunk/Outputter.cpp
Revision: 15
Committed: 2002-12-09T09:46:18-08:00 (22 years, 6 months ago) by douglas
Original Path: trunk/Search/Outputer.cpp
File size: 12443 byte(s)
Log Message:
Figured out and fixed fred problems.

File Contents

# User Rev Content
1 douglas 1 /* ============================================================================
2     * Douglas Thrift's Search Engine License
3     *
4     * Copyright (C) 2002, Douglas Thrift. All Rights Reserved.
5     * 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     // Outputer.cpp
50    
51     #include "Outputer.h"
52    
53 douglas 15 Outputer::Outputer(const string& headerFile, const string& bodyFile, const
54     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     cerr << "query = " << (this->query ? "true" : "false") << "\n"
90     << "results = " << (results ? "true" : "false") << "\n"
91     << "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     tag(line, "<?query?>", query);
136 douglas 15 tag(line, "<?range?>", range(page));
137     tag(line, "<?total?>", total());
138     tag(line, "<?time?>", duration());
139     tag(line, "<?pages?>", pages(query, page));
140 douglas 1 tag(line, "<?ignore?>", ignore);
141     tag(line, "<?common?>", common[0]);
142 douglas 15 tag(line, "<?manycommon?>", manycommon(common));
143 douglas 1
144     cout << line << "\n";
145     }
146    
147     fin.close();
148     }
149    
150     void Outputer::body()
151     {
152     for (int index = 0; index < webpages.size(); index++)
153     {
154     Ranker webpage = webpages[index];
155     string title = webpage.getTitle();
156     if (title == "")
157     {
158     title = webpage.getURL();
159     entities(title, '&', "&amp;");
160     entities(title, '\"', "&quot;");
161     entities(title, '<', "&lt;");
162     entities(title, '>', "&gt;");
163     }
164     string address = webpage.getURL();
165     string sample = webpage.getSample();
166     string description = webpage.getDescription();
167    
168     char* csize = new char[1024];
169     sprintf(csize, "%.0fk", (double(webpage.getSize()) / double(1024)));
170    
171     string size = csize;
172    
173     delete [] csize;
174    
175     entities(address, '&', "&amp;");
176     entities(address, '\"', "&quot;");
177     entities(address, '<', "&lt;");
178     entities(address, '>', "&gt;");
179    
180     ifstream fin(bodyFile.c_str());
181    
182     string line;
183     while (fin.good())
184     {
185     getline(fin, line);
186    
187     conditional(line, fin, "<?ifdescription?>", description != "");
188    
189     tag(line, "<?address?>", address);
190     tag(line, "<?title?>", title);
191     tag(line, "<?sample?>", sample);
192     tag(line, "<?description?>", description);
193     tag(line, "<?size?>", size);
194    
195     cout << line << "\n";
196     }
197    
198     fin.close();
199     }
200     }
201    
202 douglas 15 void Outputer::footer(const string& query, unsigned page, vector<string>
203     common, bool and_, bool or_, const string& ignore)
204 douglas 1 {
205     ifstream fin(footerFile.c_str());
206    
207     string line;
208     while (fin.good())
209     {
210     getline(fin, line);
211    
212     conditional(line, fin, "<?ifquery?>", this->query);
213     conditional(line, fin, "<?ifresults?>", results);
214     conditional(line, fin, "<?ifor?>", or_);
215     conditional(line, fin, "<?ifand?>", and_);
216     conditional(line, fin, "<?ifignore?>", ignore != "");
217     conditional(line, fin, "<?ifcommon?>", common.size() == 1);
218     conditional(line, fin, "<?ifmanycommon?>", common.size() > 1);
219    
220     tag(line, "<?query?>", query);
221 douglas 15 tag(line, "<?range?>", range(page));
222     tag(line, "<?total?>", total());
223     tag(line, "<?time?>", duration());
224     tag(line, "<?pages?>", pages(query, page));
225 douglas 1 tag(line, "<?ignore?>", ignore);
226     tag(line, "<?common?>", common[0]);
227 douglas 15 tag(line, "<?manycommon?>", manycommon(common));
228 douglas 1
229     cout << line << "\n";
230     }
231    
232     fin.close();
233     }
234    
235 douglas 15 void Outputer::notfound(const string& query, unsigned keywords)
236 douglas 1 {
237     ifstream fin(notfoundFile.c_str());
238    
239     string line;
240     while (fin.good())
241     {
242     getline(fin, line);
243    
244     conditional(line, fin, "<?ifmany?>", keywords > 1);
245    
246     tag(line, "<?query?>", query);
247    
248     cout << line << "\n";
249     }
250    
251     fin.close();
252     }
253    
254     string Outputer::pages(string query, unsigned page)
255     {
256     entities(query, "&lt;", '<');
257     entities(query, "&gt;", '>');
258     entities(query, "&quot;", '\"');
259     entities(query, "&amp;", '&');
260    
261     entities(query, '%', "%25");
262     entities(query, '\t', "%09");
263     entities(query, ' ', "%20");
264     entities(query, '\"', "%22");
265     entities(query, '#', "%23");
266     entities(query, '$', "%24");
267     entities(query, '&', "%26");
268     entities(query, '\'', "%27");
269     entities(query, '+', "%2B");
270     entities(query, ',', "%2C");
271     entities(query, '/', "%2F");
272     entities(query, ':', "%3A");
273     entities(query, ';', "%3B");
274     entities(query, '<', "%3C");
275     entities(query, '=', "%3D");
276     entities(query, '>', "%3E");
277     entities(query, '?', "%3F");
278     entities(query, '@', "%40");
279     entities(query, '[', "%5B");
280     entities(query, ']', "%5D");
281     entities(query, '\\', "%5C");
282     entities(query, '^', "%5E");
283     entities(query, '`', "%60");
284     entities(query, '{', "%7B");
285     entities(query, '|', "%7C");
286     entities(query, '}', "%7D");
287     entities(query, '~', "%7E");
288    
289     string lines;
290    
291     ifstream fin(pagesFile.c_str());
292    
293     string line;
294     while (fin.good())
295     {
296     getline(fin, line);
297     conditional(line, fin, "<?ifprevious?>", page >= 1);
298     conditional(line, fin, "<?ifpage?>", false);
299     conditional(line, fin, "<?ifnum?>", false);
300     conditional(line, fin, "<?ifnext?>", false);
301    
302     char* cprevious = new char[1024];
303    
304     sprintf(cprevious, "%u", page);
305    
306     string previous = cprevious;
307    
308     delete [] cprevious;
309    
310     tag(line, "<?query?>", query);
311     tag(line, "<?previous?>", previous);
312    
313     lines += line + "\n";
314     }
315    
316     fin.close();
317     fin.clear();
318    
319     for (int index = 0; index < numPages; index++)
320     {
321     fin.open(pagesFile.c_str());
322    
323     while (fin.good())
324     {
325     getline(fin, line);
326     if (index == page)
327     {
328     conditional(line, fin, "<?ifprevious?>", false);
329     conditional(line, fin, "<?ifpage?>", true);
330     conditional(line, fin, "<?ifnum?>", false);
331     conditional(line, fin, "<?ifnext?>", false);
332    
333     char* cpage = new char[1024];
334    
335     sprintf(cpage, "%u", (index + 1));
336    
337     string spage = cpage;
338    
339     delete [] cpage;
340    
341     tag(line, "<?page?>", spage);
342     }
343     else
344     {
345     conditional(line, fin, "<?ifprevious?>", false);
346     conditional(line, fin, "<?ifpage?>", false);
347     conditional(line, fin, "<?ifnum?>", true);
348     conditional(line, fin, "<?ifnext?>", false);
349    
350     char* cnum = new char[1024];
351    
352     sprintf(cnum, "%u", (index + 1));
353    
354     string num = cnum;
355    
356     delete [] cnum;
357    
358     tag(line, "<?query?>", query);
359     tag(line, "<?num?>", num);
360     }
361    
362     lines += line + "\n";
363     }
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     char* cnext = new char[1024];
380    
381     sprintf(cnext, "%u", (page + 2));
382    
383     string next = cnext;
384    
385     delete [] cnext;
386    
387     tag(line, "<?query?>", query);
388     tag(line, "<?next?>", next);
389    
390     lines += line + "\n";
391     }
392    
393     fin.close();
394    
395     return lines;
396     }
397    
398     string Outputer::range(unsigned page)
399     {
400     unsigned bottom = page * 10 + 1;
401     unsigned top = numWebpages > page * 10 + 10 ? page * 10 + 10 : numWebpages;
402    
403     char* cbottom = new char[1024];
404     char* ctop = new char[1024];
405    
406     sprintf(cbottom, "%u", bottom);
407     sprintf(ctop, "%u", top);
408    
409     string range = string(cbottom) + " - " + ctop;
410    
411     delete [] cbottom;
412     delete [] ctop;
413    
414     return range;
415     }
416    
417     string Outputer::total()
418     {
419     char* ctotal = new char[1024];
420    
421     sprintf(ctotal, "%u", numWebpages);
422    
423     string total = ctotal;
424    
425     delete [] ctotal;
426    
427     return total;
428     }
429    
430     string Outputer::duration()
431     {
432     char* ctime = new char[1024];
433     sprintf(ctime, "%.2f", time);
434    
435     string duration = ctime;
436    
437     delete [] ctime;
438    
439     return duration;
440     }
441    
442     string Outputer::manycommon(vector<string> common)
443     {
444     string line;
445    
446     for (int index = 0; index < common.size(); index++)
447     {
448     line += common[index];
449    
450     if (index != common.size() - 1) line += ' ';
451     }
452    
453     return line;
454     }
455    
456 douglas 15 void Outputer::tag(string& line, char* tag, const string& replacement)
457 douglas 1 {
458     int begin = 0;
459     while (begin < line.length())
460     {
461     int spot = line.find(tag, begin);
462    
463     if (spot != string::npos)
464     {
465     line.replace(spot, strlen(tag), replacement);
466     }
467     else
468     {
469     break;
470     }
471    
472     begin = spot + replacement.length();
473     }
474     }
475    
476     void Outputer::conditional(string& line, ifstream& fin, char* tag, bool
477     condition)
478     {
479     unsigned begin = 0;
480     while (begin < line.length())
481     {
482     unsigned start = line.find(tag, begin);
483     unsigned finish = line.find("<?endif?>", start);
484    
485     if (start == string::npos) break;
486    
487     string next;
488     while (finish == string::npos)
489     {
490     getline(fin, next);
491     line += '\n' + next;
492     finish = line.find("<?endif?>", start);
493     }
494    
495     if (condition)
496     {
497     line.erase(start, strlen(tag));
498     line.erase(finish - strlen(tag), 9);
499    
500     begin = finish - strlen(tag) - 9;
501     }
502     else
503     {
504     line.erase(start, finish - start + 9);
505    
506     begin = start;
507     }
508     }
509     }