📄 doxysearch.cpp
字号:
/****************************************************************************** * * $Id: doxysearch.cpp,v 1.12 2001/03/19 19:27:40 root Exp $ * * Copyright (C) 1997-2001 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */// includes#include <stdio.h>#include <string.h>#include <stdarg.h>#include <stdlib.h>#include <ctype.h>#include <sys/stat.h>#ifdef PROFILING#include <sys/time.h>#include <unistd.h>#endif// defines#ifndef bool#define bool int#endif#define MAXSTRLEN 1024#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif#define NORMAL 1 // OR search results#define INCLUDE 2 // AND search results#define EXCLUDE 3 // AND NOT search results#define TERMMASK (1<<31)#define OFFSETMASK (~TERMMASK)// structs//----------------------------------------------------------------------------struct FileInfo{ FileInfo() { name[0]='\0'; f=0; url=0; } ~FileInfo() { if (f) fclose(f); delete[] url; } FILE *f; char name[MAXSTRLEN]; int index; int refOffset; char *url; FileInfo *next;};//----------------------------------------------------------------------------struct FileList{ FileList() { first=0; last=0; index=0; } ~FileList() { FileInfo *fi=first; while (fi) { FileInfo *ofi=fi; fi=fi->next; delete ofi; } } FileInfo *add() { FileInfo *nf=new FileInfo; nf->next=0; nf->index=index++; if (last) { last->next=nf; last=nf; } else { first=nf; last=nf; } return nf; } FileInfo *first; FileInfo *last; int index;};//----------------------------------------------------------------------------struct WordInfo{ WordInfo() { word=0; } ~WordInfo() { delete[] word; } char *word; int freq; WordInfo *next;};//----------------------------------------------------------------------------struct WordList{ WordList() { first=0; last=0; } ~WordList() { WordInfo *wi=first; while (wi) { WordInfo *owi=wi; wi=wi->next; delete owi; } } void add(const char *word,int freq) { WordInfo *nw=new WordInfo; nw->word = new char[strlen(word)+1]; strcpy(nw->word,word); nw->freq=freq; nw->next=0; if (last) { last->next=nw; last=nw; } else { first=nw; last=nw; } } WordInfo *first; WordInfo *last;};//----------------------------------------------------------------------------struct SearchDoc{ FileInfo *fileInfo; int index; int freq; double rank; SearchDoc *next;};//----------------------------------------------------------------------------struct SearchResults{ SearchResults() { totalFreq=0; docList=0; last=0; } ~SearchResults() { SearchDoc *d=docList; while (d) { SearchDoc *od=d; d=d->next; delete od; } } void add(FileInfo *fi,int index,int freq) { SearchDoc *nd=new SearchDoc; nd->fileInfo=fi; nd->index=index; nd->freq=freq; nd->next=0; if (last) { last->next=nd; last=nd; } else { docList=nd; last=nd; } } SearchDoc *docList; SearchDoc *last; int totalFreq;};//----------------------------------------------------------------------------// global varsstatic WordList wordList;static FileList fileList;static char cgiBin[MAXSTRLEN];static char queryInput[MAXSTRLEN];static char encQueryInput[MAXSTRLEN];static char firstDocUrl[MAXSTRLEN];static bool nameOnly;static bool wordOnly;static bool helpOnly;static int page;static char *headerBuf=0;static char *footerBuf=0;//----------------------------------------------------------------------------// functionsvoid printHeader(){ if (headerBuf) { printf("Content-Type: text/html\r\n\r\n%s",headerBuf); } else { printf("Content-Type: text/html\r\n\r\n"); printf("<html><head><title>Search the documentation</title></head>\n" "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#0000ee\" \n" "vlink=\"#551a8b\" alink=\"#ff0000\">\n"); }}//----------------------------------------------------------------------------void printFooter(){ if (footerBuf) { printf("%s",footerBuf); } else { printf("</body></html>\n"); }}//----------------------------------------------------------------------------void message(const char *fmt,...){ printHeader(); printf("<h2>"); va_list args; va_start(args, fmt); vfprintf(stdout, fmt, args); va_end(args); printf("</h2>"); printFooter();}//----------------------------------------------------------------------------void printSearchPage(bool open=FALSE){ printf("<form name=doxyform method=GET action=\"%s\">\n" "<center>\n" "<input type=hidden name=page value=0>\n" "<table border=0 bgcolor=\"#ffffcc\" cellspacing=0 cellpadding=4>\n" " <tr>\n" " <td valign=top><font size=-1 face=\"arial, helvetica\"><b>" " Search for\n" " <select name=which>\n" " <option value=string %s>strings\n" " <option value=word %s>words\n" " </select>\n" " in function and class\n" " <select name=what>\n" " <option value=doc %s>documentation\n" " <option value=name %s>names</select></b></font>\n" " </td>\n" " <td valign=top align=right>\n" " <a href=\"%s?help=on\"><font size=-1>Help</font></a>\n" " </td>\n" " </tr>\n" " <tr>\n" " <td><input name=query size=44 wrap=virtual maxlength=1000 value=\"%s\">\n" " </td>\n" " <td><input type=image src=\"%s/search.gif\" height=26 width=120 border=0 name=\"search\">\n" " </td>\n" " </tr>\n", cgiBin, (wordOnly?"":"selected"),(wordOnly?"selected":""), (nameOnly?"":"selected"),(nameOnly?"selected":""), cgiBin,queryInput,firstDocUrl); if (!open) { printf("</table>\n</center></form>\n"); }}//----------------------------------------------------------------------------int readInt(FILE *f){ unsigned char c_24 = fgetc(f); unsigned char c_16 = fgetc(f); unsigned char c_08 = fgetc(f); unsigned char c_00 = fgetc(f); return ((unsigned int)c_24<<24)+ ((unsigned int)c_16<<16)+ ((unsigned int)c_08<<8)+ c_00; //return (fgetc(f)<<24)+(fgetc(f)<<16)+(fgetc(f)<<8)+fgetc(f);}//----------------------------------------------------------------------------int readEncodedNumber(FILE *f){ int n=0,b,s=0; do { b=fgetc(f); n|=(b&0x7f)<<s; s+=7; } while (b&0x80); return n;}void readString(FILE *f,char *s,int n){ int i=0,b; if (n<=0) return; while (i<n-1 && (b=fgetc(f))!=0) s[i++]=b; s[i]='\0';}//----------------------------------------------------------------------------bool searchRecursive(SearchResults *sr,FileInfo *fi,const char *word){ char entry[MAXSTRLEN]; readString(fi->f,entry,MAXSTRLEN); while (entry[0]!='\0') { //printf("Found entry `%s'\n",entry); int i=0, w=word[0], e=entry[0]; while (w!=0 && e!=0 && w==e) { i++; w=word[i]; e=entry[i]; } if (w==0 && e!=0) // word is a substring of entry { if (wordOnly) return FALSE; // no full word match //printf("Word found as substring of `%s%s'\n",&word[-index],&entry[i]); int offset=readInt(fi->f); // <= follow for extensions if (!(offset&TERMMASK)) // extra info available { int tfreq=readEncodedNumber(fi->f); sr->totalFreq+=tfreq; //printf("Total frequency %d\n",tfreq); int s=-1,k; while ((k=readEncodedNumber(fi->f))!=0) { bool inName = (k&2)==2; s+=(k>>3); int freq=readEncodedNumber(fi->f); //printf("Doc index %d frequency %d\n",s,freq); if (!nameOnly || inName) //addResult(fi,sr,s,freq); sr->add(fi,s,freq); } } return TRUE; } else if (e==0) // entry is a substring of word { if (w==0) // word is equal to entry => exact match found { int offset=readInt(fi->f); // <= follow for extensions if (!(offset&TERMMASK)) // extra info available { //printf("Match found\n"); int tfreq=readEncodedNumber(fi->f); sr->totalFreq+=tfreq; //printf("Total frequency %d\n",tfreq); int s=-1,k; while ((k=readEncodedNumber(fi->f))!=0) { bool fullWord = (k&1)==1; bool inName = (k&2)==2; bool wordInName = (k&4)==4; s+=(k>>3); int freq=readEncodedNumber(fi->f); if (nameOnly && wordOnly) { if (wordInName) sr->add(fi,s,freq); } else if (!nameOnly && wordOnly) { if (fullWord) sr->add(fi,s,freq); } else if (nameOnly && !wordOnly) { if (inName) sr->add(fi,s,freq); } else // !nameOnly && !wordOnly { sr->add(fi,s,freq); } } } return TRUE; } else // follow branch to next entry { int offset=readInt(fi->f); if ((offset&OFFSETMASK)==0) // no next entry (leaf node) { return FALSE; } else // follow branch { fseek(fi->f,offset&OFFSETMASK,SEEK_SET); //printf("Recursive call; jump to %lx\n",ftell(f)); return searchRecursive(sr,fi,&word[i]); } } } else // skip rest of the entry { int offset=readInt(fi->f); if (!(offset&TERMMASK)) while (readEncodedNumber(fi->f)!=0); } readString(fi->f,entry,MAXSTRLEN); } //printf("Sorry no match found\n"); return FALSE;}//----------------------------------------------------------------------------void searchIndex(const char *word,SearchResults *results){ FileInfo *fi=fileList.first; while (fi) { fi->f = fopen(fi->name, "rb"); fseek(fi->f,8,SEEK_SET); searchRecursive(results,fi,word); fclose(fi->f); fi->f=0; fi=fi->next; } SearchDoc *ds = results->docList; while (ds) { ds->rank = ds->freq/(double)results->totalFreq; ds = ds->next; } wordList.add(word,results->totalFreq);}//----------------------------------------------------------------------------extern "C" int sortResults(const void *a1,const void *a2){ SearchDoc **d1=(SearchDoc **)a1; SearchDoc **d2=(SearchDoc **)a2; if ((*d1)->rank > (*d2)->rank) return -1; else if ((*d1)->rank == (*d2)->rank) return 0; else return 1;}//----------------------------------------------------------------------------void generateResults(SearchResults *sr){ // compute the maximum rank SearchDoc *ds = sr->docList; double maxRank = 0.00000001; int resultCount=0; if (ds) { while (ds) { if (ds->rank>maxRank) maxRank = ds->rank; ds = ds->next; } // scale ranks, so the highest is 1 and count the number of links double oneOverMaxRank = 1.0/maxRank; ds = sr->docList; while (ds) { ds->rank *= oneOverMaxRank; resultCount++; ds = ds->next; } } SearchDoc **docPtrArray=0; if (resultCount>0) { docPtrArray=(SearchDoc **)calloc(resultCount,sizeof(SearchDoc *)); int offset=0; ds = sr->docList; while (ds) { docPtrArray[offset++]=ds; ds = ds->next; } qsort(docPtrArray,resultCount,sizeof(SearchDoc *),sortResults); } // start generating output printHeader(); printSearchPage(TRUE); printf(" <tr bgcolor=#ffffff>\n" " <td colspan=2>" "<br><h3>Search results</h3>\n" " </td>\n" " </tr>\n"); if (resultCount==0) // nothing found { printf(" <tr bgcolor=#ffffff>\n" " <td colspan=2>Sorry, no documents matching your query.\n" " </td>\n" " </tr>\n"); } else // something found { printf(" <tr bgcolor=#ffffff>\n" " <td colspan=2>" "Found <b>%d</b> document%s matching your query. ", resultCount,resultCount==1?"":"s"); if (resultCount>1) printf("Showing best matches first.\n"); printf(" <br><br>\n"); printf(" </td>\n" " </tr>\n"); const int lpp=20; int numPages = (resultCount+lpp-1)/lpp; // clip page if (page<0) page=0; if (page>=numPages) page=numPages-1; int skipEntries = page * lpp; int pageEntries = lpp; printf(" <tr><td colspan=2 bgcolor=\"#4040c0\">" "<center><b><font color=\"#ffffff\">Page %d / %d</font></b>" "</center></td></tr>\n",page+1,numPages); printf(" <tr bgcolor=#ffffff>\n" " <td colspan=2>\n" " <table border=\"0\" cellspacing=\"2\" cellpadding=\"2\">\n"); int i; for (i=0 ; i < resultCount && pageEntries > 0; i++) { if (skipEntries == 0) { SearchDoc *d=docPtrArray[i]; if (d->fileInfo->f == 0) { d->fileInfo->f = fopen(d->fileInfo->name, "rb"); } FILE *f=d->fileInfo->f; fseek(f,d->fileInfo->refOffset+d->index*4,SEEK_SET); int offset=readInt(f); fseek(f,offset,SEEK_SET); char linkName[MAXSTRLEN]; char htmlName[MAXSTRLEN]; readString(f,linkName,MAXSTRLEN); readString(f,htmlName,MAXSTRLEN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -