| | 57 | # ISearchProvider methods |
|---|
| | 58 | |
|---|
| | 59 | def get_search_filters(self, req): |
|---|
| | 60 | yield('doxygen', 'Doxygen') |
|---|
| | 61 | |
|---|
| | 62 | def get_search_results(self, req, query, filters): |
|---|
| | 63 | if not 'doxygen' in filters: |
|---|
| | 64 | return |
|---|
| | 65 | if query[0] == query[-1] == "'" or query[0] == query[-1] == '"': |
|---|
| | 66 | keywords = [query[1:-1]] |
|---|
| | 67 | else: |
|---|
| | 68 | keywords = query.split(' ') |
|---|
| | 69 | |
|---|
| | 70 | path = self.config.get('doxygen', 'path') |
|---|
| | 71 | path = ''.join([path, '/search.idx']) |
|---|
| | 72 | |
|---|
| | 73 | if os.path.exists(path): |
|---|
| | 74 | fd = open(path) |
|---|
| | 75 | |
|---|
| | 76 | results = [] |
|---|
| | 77 | for keyword in keywords: |
|---|
| | 78 | results += self._search(fd, keyword) |
|---|
| | 79 | |
|---|
| | 80 | results.sort(compare_rank) |
|---|
| | 81 | |
|---|
| | 82 | # use the creation time for the search.idx file for all results |
|---|
| | 83 | creation = os.path.getctime(path) |
|---|
| | 84 | |
|---|
| | 85 | for result in results: |
|---|
| | 86 | yield result['url'], result['name'], creation, 'doxygen', None |
|---|
| | 87 | |
|---|
| | 88 | # internal methods |
|---|
| | 89 | |
|---|
| | 90 | def _search(self, fd, word): |
|---|
| | 91 | results = [] |
|---|
| | 92 | index = self._computeIndex(word) |
|---|
| | 93 | if index != -1: |
|---|
| | 94 | fd.seek(index * 4 + 4, 0) |
|---|
| | 95 | index = self._readInt(fd) |
|---|
| | 96 | |
|---|
| | 97 | if index: |
|---|
| | 98 | fd.seek(index) |
|---|
| | 99 | w = self._readString(fd) |
|---|
| | 100 | matches = [] |
|---|
| | 101 | while w != "": |
|---|
| | 102 | statIdx = self._readInt(fd) |
|---|
| | 103 | low = word.lower() |
|---|
| | 104 | if w.find(low) != -1: |
|---|
| | 105 | matches.append({'word' : word, 'match' : w, 'index' : statIdx, 'full' : len(low) == len(w)}) |
|---|
| | 106 | w = self._readString(fd) |
|---|
| | 107 | |
|---|
| | 108 | count = 0 |
|---|
| | 109 | totalHi = 0 |
|---|
| | 110 | totalFreqHi = 0 |
|---|
| | 111 | totalFreqLo = 0 |
|---|
| | 112 | |
|---|
| | 113 | for match in matches: |
|---|
| | 114 | multiplier = 1 |
|---|
| | 115 | if match['full']: |
|---|
| | 116 | multiplier = 2 |
|---|
| | 117 | |
|---|
| | 118 | fd.seek(match['index']) |
|---|
| | 119 | numDocs = self._readInt(fd) |
|---|
| | 120 | |
|---|
| | 121 | for i in range(numDocs): |
|---|
| | 122 | idx = self._readInt(fd) |
|---|
| | 123 | freq = self._readInt(fd) |
|---|
| | 124 | results.append({'idx' : idx, 'freq' : freq >> 1, 'hi' : freq & 1, 'multi' : multiplier}) |
|---|
| | 125 | if freq & 1: |
|---|
| | 126 | totalHi += 1 |
|---|
| | 127 | totalFreqHi += freq * multiplier |
|---|
| | 128 | else: |
|---|
| | 129 | totalFreqLo += freq * multiplier |
|---|
| | 130 | |
|---|
| | 131 | for i in range(numDocs): |
|---|
| | 132 | fd.seek(results[count]['idx']) |
|---|
| | 133 | name = self._readString(fd) |
|---|
| | 134 | url = self._readString(fd) |
|---|
| | 135 | results[count]['name'] = name |
|---|
| | 136 | results[count]['url'] = url |
|---|
| | 137 | count += 1 |
|---|
| | 138 | |
|---|
| | 139 | totalFreq = (totalHi + 1) * totalFreqLo + totalFreqHi |
|---|
| | 140 | for i in range(count): |
|---|
| | 141 | freq = results[i]['freq'] |
|---|
| | 142 | multi = results[i]['multi'] |
|---|
| | 143 | if results[i]['hi']: |
|---|
| | 144 | results[i]['rank'] = float((freq * multi + totalFreqLo)) / float(totalFreq) |
|---|
| | 145 | else: |
|---|
| | 146 | results[i]['rank'] = float((freq * multi)) / float(totalFreq) |
|---|
| | 147 | |
|---|
| | 148 | return results |
|---|
| | 149 | |
|---|
| | 150 | def _computeIndex(self, word): |
|---|
| | 151 | if len(word) < 2: |
|---|
| | 152 | return -1 |
|---|
| | 153 | |
|---|
| | 154 | hi = ord(word[0].lower()) |
|---|
| | 155 | if hi == 0: |
|---|
| | 156 | return -1 |
|---|
| | 157 | |
|---|
| | 158 | lo = ord(word[1].lower()) |
|---|
| | 159 | if lo == 0: |
|---|
| | 160 | return -1 |
|---|
| | 161 | |
|---|
| | 162 | return hi * 256 + lo |
|---|
| | 163 | |
|---|
| | 164 | def _readInt(self, fd): |
|---|
| | 165 | b1 = fd.read(1) |
|---|
| | 166 | b2 = fd.read(1) |
|---|
| | 167 | b3 = fd.read(1) |
|---|
| | 168 | b4 = fd.read(1) |
|---|
| | 169 | |
|---|
| | 170 | return (ord(b1) << 24) | (ord(b2) << 16) | (ord(b3) << 8) | ord(b4) |
|---|
| | 171 | |
|---|
| | 172 | |
|---|
| | 173 | def _readString(self, fd): |
|---|
| | 174 | byte = fd.read(1) |
|---|
| | 175 | if byte == '\0': |
|---|
| | 176 | return "" |
|---|
| | 177 | result = byte |
|---|
| | 178 | while byte != '\0': |
|---|
| | 179 | byte = fd.read(1) |
|---|
| | 180 | result = ''.join([result, byte]) |
|---|
| | 181 | |
|---|
| | 182 | return result |
|---|
| | 183 | |
|---|