"Fossies" - the Fresh Open Source Software Archive 
Member "postal-0.76/expand.cpp" (10 Apr 2008, 5421 Bytes) of package /linux/privat/postal-0.76.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "expand.cpp" see the
Fossies "Dox" file reference documentation.
1 #include "expand.h"
2 // for strdup() and strtok()
3 #include <cstring>
4 // for random()
5 #include <cstdlib>
6 #include <stdio.h>
7
8 typedef char * PCHAR;
9
10 NamePattern::NamePattern(const char *match, const char *replace)
11 : m_match(strdup(match))
12 , m_replace(strdup(replace))
13 , m_conv_len(strlen(m_replace))
14 , m_convert(new PCHAR[m_conv_len])
15 , m_conv_item_len(new int[m_conv_len])
16 , m_next_value(new int[m_conv_len])
17 , m_no_seq(false)
18 , m_next(NULL)
19 {
20 regcomp(&m_match_regex, m_match, REG_NOSUB);
21 int i;
22 for(i = 0; i < m_conv_len; i++)
23 m_next_value[i] = 0;
24 int pos = 0;
25 bool paren = false;
26 bool escape = false;
27 bool hyphen = false;
28
29 char buf[1024];
30 int buf_pos = 0;
31
32 for(i = 0; replace[i]; i++)
33 {
34 switch(replace[i])
35 {
36 case '.':
37 if(!paren)
38 {
39 m_convert[pos] = NULL;
40 m_conv_item_len[pos] = 0;
41 pos++;
42 }
43 else
44 {
45 buf[buf_pos] = '.';
46 buf_pos++;
47 }
48 break;
49 case '[':
50 if(paren)
51 {
52 if(!escape)
53 {
54 printf("Unmatched brackets in \"%s\".\n", replace);
55 exit(1);
56 }
57 else
58 {
59 buf[buf_pos] = '[';
60 buf_pos++;
61 }
62 }
63 else
64 {
65 paren = true;
66 }
67 break;
68 case ']':
69 if(!paren)
70 {
71 printf("Unmatched brackets in \"%s\".\n", replace);
72 exit(1);
73 }
74 if(!escape)
75 {
76 if(hyphen)
77 {
78 printf("Unfinished hyphen in \"%s\".\n", replace);
79 exit(1);
80 }
81 buf[buf_pos] = '\0';
82 m_convert[pos] = strdup(buf);
83 m_conv_item_len[pos] = strlen(m_convert[pos]);
84 pos++;
85 buf_pos = 0;
86 paren = false;
87 break;
88 } // if escape then fall-through
89 case '-':
90 if(!paren)
91 {
92 printf("Misplaced hyphen in \"%s\".\n", replace);
93 exit(1);
94 }
95 hyphen = true;
96 break;
97 default:
98 if(paren)
99 {
100 if(!hyphen)
101 {
102 buf[buf_pos] = replace[i];
103 buf_pos++;
104 if(buf_pos == sizeof(buf))
105 {
106 printf("Out of buffer space for \"%s\".\n", replace);
107 exit(1);
108 }
109 }
110 else
111 {
112 for(char c = buf[buf_pos - 1] + 1; c <= replace[i] && c < 127; c++)
113 {
114 buf[buf_pos] = c;
115 buf_pos++;
116 if(buf_pos == sizeof(buf))
117 {
118 printf("Out of buffer space for \"%s\".\n", replace);
119 exit(1);
120 }
121 }
122 hyphen = false;
123 }
124 }
125 else
126 {
127 printf("Can't parse replace string \"%s\".\n", replace);
128 exit(1);
129 }
130 } // end switch
131 } // end for
132 m_conv_len = pos;
133 }
134
135 NamePattern::~NamePattern()
136 {
137 for(int i = 0; i < m_conv_len; i++)
138 delete m_convert[i];
139 delete m_convert;
140 delete m_conv_item_len;
141 delete m_next_value;
142 regfree(&m_match_regex);
143 delete m_match;
144 delete m_replace;
145 }
146
147 int NamePattern::expand(string &output, const string &input, bool sequential)
148 {
149 int i;
150 if(sequential && m_no_seq)
151 {
152 for(i = 0; i < m_conv_len; i++)
153 m_next_value[i] = 0;
154 m_no_seq = false;
155 return 1;
156 }
157 if(regexec(&m_match_regex, input.c_str(), 0, NULL, 0))
158 {
159 if(m_next)
160 return m_next->expand(output, input, sequential);
161 else
162 return 1;
163 }
164 output = input;
165 for(i = 0; i < m_conv_len; i++)
166 {
167 if(m_convert[i])
168 {
169 if(!sequential)
170 {
171 output[i] = m_convert[i][random()%m_conv_item_len[i]];
172 }
173 else
174 {
175 output[i] = m_convert[i][m_next_value[i]];
176 }
177 }
178 }
179 if(sequential)
180 {
181 for(i = m_conv_len - 1; i >= 0; i--)
182 {
183 if(m_convert[i])
184 {
185 m_next_value[i]++;
186 if(m_next_value[i] >= m_conv_item_len[i])
187 m_next_value[i] = 0;
188 else
189 return 0;
190 }
191 }
192 m_no_seq = true;
193 }
194 return 0;
195 }
196
197 NameExpand::NameExpand(const char *filename)
198 : m_no_seq(true)
199 , m_names(NULL)
200 {
201 if(!filename || strcmp(filename, "-") == 0)
202 {
203 return;
204 }
205 FILE *fp = fopen(filename, "r");
206 if(!fp)
207 {
208 printf("Can't open config file \"%s\". Doing no expansion.\n", filename);
209 return;
210 }
211 char match[1024];
212 NamePattern *np = NULL, *old_np = NULL;
213 while(fgets(match, sizeof(match), fp))
214 {
215 match[sizeof(match) - 1] = '\0';
216 strtok(match, "\n");
217 unsigned int i;
218 int blank_pos = -1;
219 for(i = 0; match[i]; i++)
220 {
221 if(match[i] == ' ')
222 {
223 if(blank_pos != -1)
224 {
225 printf("Can't parse pattern line \"%s\".\n", match);
226 exit(1);
227 }
228 blank_pos = i;
229 }
230 }
231 if(blank_pos == -1)
232 {
233 printf("Can't parse pattern line \"%s\".\n", match);
234 exit(1);
235 }
236 char *replace = &match[blank_pos + 1];
237 match[blank_pos] = '\0';
238 np = new NamePattern(match, replace);
239 if(!m_names)
240 m_names = np;
241 if(old_np)
242 old_np->AddNext(np);
243 old_np = np;
244 }
245 fclose(fp);
246 }
247
248 int NameExpand::expand(string &output, const string &input, bool sequential)
249 {
250 if(!m_names)
251 {
252 if(sequential)
253 {
254 if(m_no_seq)
255 {
256 m_no_seq = false;
257 return 1;
258 }
259 else
260 {
261 output = input;
262 m_no_seq = true;
263 return 0;
264 }
265 }
266 output = input;
267 return 1;
268 }
269 return m_names->expand(output, input, sequential);
270 }