~ubuntu-branches/ubuntu/edgy/lurker/edgy

« back to all changes in this revision

Viewing changes to common/Keys.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Meurer
  • Date: 2004-09-26 16:27:51 UTC
  • Revision ID: james.westby@ubuntu.com-20040926162751-z1ohcjltv7ojtg6z
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $Id: Keys.cpp,v 1.4 2003/06/23 14:38:41 terpstra Exp $
 
2
 *  
 
3
 *  Keys.cpp - Digest a hunk of string into keywords.
 
4
 *  
 
5
 *  Copyright (C) 2002 - Wesley W. Terpstra
 
6
 *  
 
7
 *  License: GPL
 
8
 *  
 
9
 *  Authors: 'Wesley W. Terpstra' <wesley@terpstra.ca>
 
10
 *  
 
11
 *    This program is free software; you can redistribute it and/or modify
 
12
 *    it under the terms of the GNU General Public License as published by
 
13
 *    the Free Software Foundation; version 2.
 
14
 *    
 
15
 *    This program is distributed in the hope that it will be useful,
 
16
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *    GNU General Public License for more details.
 
19
 *    
 
20
 *    You should have received a copy of the GNU General Public License
 
21
 *    along with this program; if not, write to the Free Software
 
22
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
 */
 
24
 
 
25
#define _XOPEN_SOURCE 500
 
26
#define _FILE_OFFSET_BITS 64
 
27
 
 
28
/* #define DEBUG 1 */
 
29
 
 
30
#include "Keys.h"
 
31
 
 
32
#include <cstring>
 
33
 
 
34
/*------------------------------------------------ Private global vars */
 
35
 
 
36
/* These are characters which should be interpretted as both part of the word
 
37
 * and as a word seperator. eg: 'maul.sith.vpn' should be indexed as 'maul',
 
38
 * 'sith', 'vpn', and 'maul.sith.vpn' because '.' is listed here.
 
39
 */
 
40
static const char my_keyword_word_splits[] = "$@./:\\-_~&=%?#+";
 
41
static char my_keyword_is_split[256];
 
42
 
 
43
/* These are characters which should be interpretted as word breaks.
 
44
 * No known language should use these as letters in a word.
 
45
 * All chars 000-037 fall in this category too.
 
46
 */
 
47
static const char my_keyword_word_divs[] = " !\"'()*,;<>[]^`{|}";
 
48
static char my_keyword_is_div[256];
 
49
 
 
50
/* These tables are the conversion for characters being written to keywords.
 
51
 */
 
52
static const char my_keyword_orig[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
53
static const char my_keyword_dest[] = "abcdefghijklmnopqrstuvwxyz";
 
54
static char my_keyword_conv[256];
 
55
 
 
56
/* We need to be initd */
 
57
static int my_keyword_initd = 1;
 
58
 
 
59
/*------------------------------------------------ Private helper methods */
 
60
 
 
61
/* Combine the prefix with the substring */
 
62
static int my_keyword_index_hunk(
 
63
        const unsigned char* buf,
 
64
        const unsigned char* eos,
 
65
        const char* prefix,
 
66
        int (*writefn)(const char* keyword, void* arg),
 
67
        void* arg)
 
68
{
 
69
        char out[LU_KEYWORD_LEN+1];
 
70
        char* w;
 
71
        char* e;
 
72
        
 
73
        if (buf == eos)
 
74
        {       /* Don't index nothing */
 
75
                return 0;
 
76
        }
 
77
        
 
78
        /* A quick check to avoid function calls */
 
79
        if (prefix[0])
 
80
        {
 
81
                strcpy(&out[0], prefix);
 
82
                w = &out[strlen(prefix)];
 
83
        }
 
84
        else
 
85
        {
 
86
                w = &out[0];
 
87
        }
 
88
        
 
89
        e = &out[sizeof(out) - 1];
 
90
        
 
91
        /* Copy the range into the buffer while converting it */
 
92
        while (w != e && buf != eos)
 
93
        {
 
94
                *w++ = my_keyword_conv[*buf++];
 
95
        }
 
96
        
 
97
        *w = 0;
 
98
        if (!out[0])
 
99
        {
 
100
                /* Ignore this keyword */
 
101
                return 0;
 
102
        }
 
103
        
 
104
        return writefn(&out[0], arg);
 
105
}
 
106
 
 
107
/* Look at a section of non-whitespace chars and decide what to do with it. */
 
108
static int my_keyword_digest_hunk(
 
109
        const unsigned char* buf, 
 
110
        const unsigned char* eos, 
 
111
        const char* prefix,
 
112
        int       (*writefn)(const char* keyword, void* arg),
 
113
        void*       arg,
 
114
        int         do_div)
 
115
{
 
116
        const unsigned char* start;
 
117
        const unsigned char* scan;
 
118
        
 
119
        /*!!! Make me work with non-romanian languages (eg. japanese) */
 
120
        /* Japanese has no spaces to delineate words */
 
121
        
 
122
        /* Don't index vapour.
 
123
         */
 
124
        if (buf == eos)
 
125
                return 0;
 
126
        
 
127
        /* Firstly, index the entire chunk, with leading and trailing chars.
 
128
         */
 
129
        
 
130
        /* Index the entire hunk. */
 
131
        if (my_keyword_index_hunk(buf, eos, prefix, writefn, arg) != 0)
 
132
                return -1;
 
133
        
 
134
        if (!do_div) return 0;
 
135
        
 
136
        /* Now, divide the chunk into bits which we will keyword index */
 
137
        start = 0;
 
138
        for (scan = buf; scan != eos; scan++)
 
139
        {
 
140
                if (my_keyword_is_split[*scan])
 
141
                {
 
142
                        if (start)
 
143
                        {
 
144
                                if (my_keyword_index_hunk(start, scan, 
 
145
                                        prefix, writefn, arg) != 0)
 
146
                                        return -1;
 
147
                                start = 0;
 
148
                        }
 
149
                }
 
150
                else
 
151
                {
 
152
                        if (!start)
 
153
                        {
 
154
                                start = scan;
 
155
                        }
 
156
                }
 
157
        }
 
158
        
 
159
        if (start)
 
160
        {
 
161
                if (my_keyword_index_hunk(start, eos, prefix, writefn, arg) != 0)
 
162
                        return -1;
 
163
        }
 
164
        
 
165
        return 0;
 
166
}
 
167
 
 
168
static void my_keyword_init(void)
 
169
{
 
170
        unsigned int i;
 
171
        
 
172
        /* Clear the lookup tables */
 
173
        memset(&my_keyword_is_split[0], 0, sizeof(my_keyword_is_split));
 
174
        memset(&my_keyword_is_div  [0], 0, sizeof(my_keyword_is_div));
 
175
        
 
176
        /* Bootstrap the lookup tables */
 
177
        for (i = 0; i < sizeof(my_keyword_word_splits)-1; i++)
 
178
                my_keyword_is_split[((int)my_keyword_word_splits[i])] = 1;
 
179
        for (i = 0; i < sizeof(my_keyword_word_divs)-1; i++)
 
180
                my_keyword_is_div[((int)my_keyword_word_divs[i])] = 1;
 
181
        
 
182
        /* All control characters divide words */
 
183
        for (i = 0; i < 040; i++)
 
184
                my_keyword_is_div[i] = 1;
 
185
        
 
186
        /* Initialize conversion table */
 
187
        for (i = 0; i < 256; i++)
 
188
                my_keyword_conv[i] = i;
 
189
        
 
190
        /* Fill the conversion entries */
 
191
        for (i = 0; i < sizeof(my_keyword_orig)-1; i++)
 
192
                my_keyword_conv[((int)my_keyword_orig[i])] = 
 
193
                        my_keyword_dest[i];
 
194
        
 
195
        my_keyword_initd = 0;
 
196
}
 
197
 
 
198
/*------------------------------------------------- Public component methods */
 
199
 
 
200
/* Run through a buffer looking for segments of non-divide characters.
 
201
 */
 
202
int my_keyword_digest_string(
 
203
        const char* buf, 
 
204
        int         len, 
 
205
        const char* prefix,
 
206
        int       (*writefn)(const char* keyword, void* arg),
 
207
        void*       arg,
 
208
        int         do_div)
 
209
{
 
210
        const unsigned char* start;
 
211
        const unsigned char* scan;
 
212
        const unsigned char* eos = (const unsigned char*)buf + len;
 
213
        
 
214
        if (my_keyword_initd)
 
215
                my_keyword_init();
 
216
        
 
217
        start = 0;
 
218
        for (scan = (const unsigned char*)buf; scan != eos; scan++)
 
219
        {
 
220
                if (my_keyword_is_div[*scan])
 
221
                {
 
222
                        if (start)
 
223
                        {
 
224
                                my_keyword_digest_hunk(start, scan, 
 
225
                                        prefix, writefn, arg, do_div);
 
226
                                start = 0;
 
227
                        }
 
228
                }
 
229
                else
 
230
                {
 
231
                        if (!start)
 
232
                        {
 
233
                                start = scan;
 
234
                        }
 
235
                }
 
236
        }
 
237
        
 
238
        if (start)
 
239
        {
 
240
                my_keyword_digest_hunk(start, eos, prefix, writefn, arg, do_div);
 
241
        }
 
242
        
 
243
        return 0;
 
244
}