gwenhywfar
4.6.0beta
Main Page
Related Pages
Modules
Data Structures
Files
File List
Globals
src
parser
path.c
Go to the documentation of this file.
1
/***************************************************************************
2
begin : Tue Sep 09 2003
3
copyright : (C) 2003 by Martin Preuss
4
email : martin@libchipcard.de
5
6
***************************************************************************
7
* *
8
* This library is free software; you can redistribute it and/or *
9
* modify it under the terms of the GNU Lesser General Public *
10
* License as published by the Free Software Foundation; either *
11
* version 2.1 of the License, or (at your option) any later version. *
12
* *
13
* This library is distributed in the hope that it will be useful, *
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16
* Lesser General Public License for more details. *
17
* *
18
* You should have received a copy of the GNU Lesser General Public *
19
* License along with this library; if not, write to the Free Software *
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21
* MA 02111-1307 USA *
22
* *
23
***************************************************************************/
24
25
#ifdef HAVE_CONFIG_H
26
# include <config.h>
27
#endif
28
29
#define DISABLE_DEBUGLOG
30
31
#include "
path.h
"
32
#include "gwenhywfar/debug.h"
33
#include "gwenhywfar/misc.h"
34
#include "gwenhywfar/text.h"
35
#include <ctype.h>
36
37
38
39
void
*
GWEN_Path_Handle
(
const
char
*path,
40
void
*data,
41
uint32_t flags,
42
GWEN_PATHHANDLERPTR
elementFunction) {
43
GWEN_BUFFER
*buf1;
44
int
i;
45
unsigned
int
origflags;
46
int
startAtRoot;
47
48
origflags=flags;
49
50
buf1=
GWEN_Buffer_new
(0, 128, 0, 1);
51
52
/* skip leading blanks */
53
while
(*path && isspace((
int
)*path))
54
path++;
55
56
/* skip leading slashes */
57
startAtRoot=0;
58
while
(*path && (*path==
'/'
|| *path==
'\\'
)) {
59
if
(origflags &
GWEN_PATH_FLAGS_CHECKROOT
)
60
startAtRoot=1;
61
path++;
62
}
/* while */
63
64
while
(*path) {
65
GWEN_Buffer_Reset
(buf1);
66
67
flags=origflags &
68
~
GWEN_PATH_FLAGS_INTERNAL
&
69
~
GWEN_PATH_FLAGS_VARIABLE
;
70
71
/* copy element into buffer */
72
i=0;
73
if
(startAtRoot) {
74
GWEN_Buffer_AppendByte
(buf1,
'/'
);
75
flags|=
GWEN_PATH_FLAGS_ROOT
;
76
}
77
while
(*path && !(*path==
'/'
|| *path==
'\\'
))
78
GWEN_Buffer_AppendByte
(buf1, *(path++));
79
80
/* check for group or entry */
81
if
(*path) {
82
/* skip slashes */
83
path++;
84
while
(*path && (*path==
'/'
|| *path==
'\\'
))
85
path++;
86
87
/* check if delimiter is followed by #0 */
88
if
(!*path) {
89
/* it is so do some more tests */
90
if
(origflags &
GWEN_PATH_FLAGS_VARIABLE
) {
91
/* a trailing slash indicates that the current entry is
92
* supposed to be a group. If the flags indicate that an entry
93
* is to be found then this would be an error, because the path
94
* ends in a group instead of an entry */
95
DBG_DEBUG
(
GWEN_LOGDOMAIN
,
"Path ends with a group while an entry is wanted"
);
96
return
0;
97
}
98
/* other wise simply mark this element as the last one */
99
flags|=
GWEN_PATH_FLAGS_LAST
;
100
}
101
}
/* if *path */
102
else
{
103
/* path ends here with #0 */
104
flags|=
GWEN_PATH_FLAGS_LAST
;
105
if
(origflags &
GWEN_PATH_FLAGS_VARIABLE
) {
106
/* path ends with #0, caller wants a variable so this
107
* last element is one */
108
flags|=
GWEN_PATH_FLAGS_VARIABLE
;
109
}
110
}
111
112
/* escape or unescape if wanted */
113
if
(!(flags &
GWEN_PATH_FLAGS_LAST
) ||
114
((flags & GWEN_PATH_FLAGS_LAST) &&
115
(flags &
GWEN_PATH_FLAGS_CONVERT_LAST
))) {
116
if
(flags &
GWEN_PATH_FLAGS_ESCAPE
) {
117
GWEN_BUFFER
*buf2;
118
const
char
*p;
119
int
rv;
120
121
buf2=
GWEN_Buffer_new
(0, 64, 0, 1);
122
GWEN_Buffer_SetStep
(buf2, 128);
123
p=
GWEN_Buffer_GetStart
(buf1);
124
if
(startAtRoot) {
125
p++;
126
GWEN_Buffer_AppendByte
(buf2,
'/'
);
127
}
128
if
(flags &
GWEN_PATH_FLAGS_TOLERANT_ESCAPE
)
129
rv=
GWEN_Text_EscapeToBufferTolerant
(p, buf2);
130
else
131
rv=
GWEN_Text_EscapeToBuffer
(p, buf2);
132
if
(rv) {
133
DBG_ERROR
(
GWEN_LOGDOMAIN
,
"Could not escape path element"
);
134
GWEN_Buffer_free
(buf2);
135
GWEN_Buffer_free
(buf1);
136
return
0;
137
}
138
GWEN_Buffer_free
(buf1);
139
buf1=buf2;
140
}
141
else
if
(flags &
GWEN_PATH_FLAGS_UNESCAPE
) {
142
GWEN_BUFFER
*buf2;
143
const
char
*p;
144
int
rv;
145
146
buf2=
GWEN_Buffer_new
(0, 64, 0, 1);
147
GWEN_Buffer_SetStep
(buf2, 128);
148
p=
GWEN_Buffer_GetStart
(buf1);
149
if
(startAtRoot) {
150
p++;
151
GWEN_Buffer_AppendByte
(buf2,
'/'
);
152
}
153
if
(flags &
GWEN_PATH_FLAGS_TOLERANT_ESCAPE
)
154
rv=
GWEN_Text_UnescapeToBufferTolerant
(p, buf2);
155
else
156
rv=
GWEN_Text_UnescapeToBuffer
(p, buf2);
157
if
(rv) {
158
DBG_ERROR
(
GWEN_LOGDOMAIN
,
"Could not unescape path element"
);
159
GWEN_Buffer_free
(buf2);
160
GWEN_Buffer_free
(buf1);
161
return
0;
162
}
163
GWEN_Buffer_free
(buf1);
164
buf1=buf2;
165
}
166
}
167
168
/* call function */
169
if
(elementFunction) {
170
data=(elementFunction)(
GWEN_Buffer_GetStart
(buf1), data, flags);
171
if
(!data) {
172
DBG_DEBUG
(
GWEN_LOGDOMAIN
,
"Error on path element \"%s\""
,
173
GWEN_Buffer_GetStart
(buf1));
174
GWEN_Buffer_free
(buf1);
175
return
0;
176
}
177
}
178
DBG_DEBUG
(
GWEN_LOGDOMAIN
,
"Successfully handled element \"%s\""
,
179
GWEN_Buffer_GetStart
(buf1));
180
if
(startAtRoot)
181
startAtRoot=0;
182
}
/* while (*path) */
183
184
GWEN_Buffer_free
(buf1);
185
return
data;
186
}
187
188
189
190
void
*
GWEN_Path_HandleWithIdx
(
const
char
*path,
191
void
*data,
192
uint32_t flags,
193
GWEN_PATHIDXHANDLERPTR
elementFunction) {
194
GWEN_BUFFER
*buf1;
195
int
i;
196
unsigned
int
origflags;
197
int
startAtRoot;
198
199
origflags=flags;
200
201
buf1=
GWEN_Buffer_new
(0, 128, 0, 1);
202
203
/* skip leading blanks */
204
while
(*path && isspace((
int
)*path))
205
path++;
206
207
/* skip leading slashes */
208
startAtRoot=0;
209
while
(*path && (*path==
'/'
|| *path==
'\\'
)) {
210
if
(origflags &
GWEN_PATH_FLAGS_CHECKROOT
)
211
startAtRoot=1;
212
path++;
213
}
/* while */
214
215
while
(*path) {
216
char
*p;
217
int
idx;
218
219
idx=0;
220
GWEN_Buffer_Reset
(buf1);
221
222
flags=origflags &
223
~
GWEN_PATH_FLAGS_INTERNAL
&
224
~
GWEN_PATH_FLAGS_VARIABLE
;
225
226
/* copy element into buffer */
227
i=0;
228
if
(startAtRoot) {
229
GWEN_Buffer_AppendByte
(buf1,
'/'
);
230
flags|=
GWEN_PATH_FLAGS_ROOT
;
231
}
232
while
(*path && !(*path==
'/'
|| *path==
'\\'
))
233
GWEN_Buffer_AppendByte
(buf1, *(path++));
234
235
/* now buffer contains the element, check for index */
236
if
(!(flags &
GWEN_PATH_FLAGS_NO_IDX
)) {
237
p=strchr(
GWEN_Buffer_GetStart
(buf1),
'['
);
238
if
(p) {
239
char
*p2;
240
int
x;
241
242
*p=0;
243
p++;
244
p2=strchr(p,
']'
);
245
if
(!p2) {
246
DBG_ERROR
(
GWEN_LOGDOMAIN
,
"Closing bracket missing"
);
247
GWEN_Buffer_free
(buf1);
248
return
0;
249
}
250
*p2=0;
251
if
(sscanf(p,
"%d"
, &x)!=1) {
252
DBG_ERROR
(
GWEN_LOGDOMAIN
,
"Bad or missing index in element (%s)"
,
253
p);
254
GWEN_Buffer_free
(buf1);
255
return
0;
256
}
257
idx=x;
258
}
259
}
260
261
/* check for group or entry */
262
if
(*path) {
263
/* skip slashes */
264
path++;
265
while
(*path && (*path==
'/'
|| *path==
'\\'
))
266
path++;
267
268
/* check if delimiter is followed by #0 */
269
if
(!*path) {
270
/* it is so do some more tests */
271
if
(origflags &
GWEN_PATH_FLAGS_VARIABLE
) {
272
/* a trailing slash indicates that the current entry is
273
* supposed to be a group. If the flags indicate that an entry
274
* is to be found then this would be an error, because the path
275
* ends in a group instead of an entry */
276
DBG_DEBUG
(
GWEN_LOGDOMAIN
,
"Path ends with a group while an entry is wanted"
);
277
return
0;
278
}
279
/* other wise simply mark this element as the last one */
280
flags|=
GWEN_PATH_FLAGS_LAST
;
281
}
282
}
/* if *path */
283
else
{
284
/* path ends here with #0 */
285
flags|=
GWEN_PATH_FLAGS_LAST
;
286
if
(origflags &
GWEN_PATH_FLAGS_VARIABLE
) {
287
/* path ends with #0, caller wants a variable so this
288
* last element is one */
289
flags|=
GWEN_PATH_FLAGS_VARIABLE
;
290
}
291
}
292
293
/* escape or unescape if wanted */
294
if
(!(flags &
GWEN_PATH_FLAGS_LAST
) ||
295
((flags & GWEN_PATH_FLAGS_LAST) &&
296
(flags &
GWEN_PATH_FLAGS_CONVERT_LAST
))) {
297
if
(flags &
GWEN_PATH_FLAGS_ESCAPE
) {
298
GWEN_BUFFER
*buf2;
299
const
char
*p;
300
int
rv;
301
302
buf2=
GWEN_Buffer_new
(0, 64, 0, 1);
303
GWEN_Buffer_SetStep
(buf2, 128);
304
p=
GWEN_Buffer_GetStart
(buf1);
305
if
(startAtRoot) {
306
p++;
307
GWEN_Buffer_AppendByte
(buf2,
'/'
);
308
}
309
if
(flags &
GWEN_PATH_FLAGS_TOLERANT_ESCAPE
)
310
rv=
GWEN_Text_EscapeToBufferTolerant
(p, buf2);
311
else
312
rv=
GWEN_Text_EscapeToBuffer
(p, buf2);
313
if
(rv) {
314
DBG_ERROR
(
GWEN_LOGDOMAIN
,
"Could not escape path element"
);
315
GWEN_Buffer_free
(buf2);
316
GWEN_Buffer_free
(buf1);
317
return
0;
318
}
319
GWEN_Buffer_free
(buf1);
320
buf1=buf2;
321
}
322
else
if
(flags &
GWEN_PATH_FLAGS_UNESCAPE
) {
323
GWEN_BUFFER
*buf2;
324
const
char
*p;
325
int
rv;
326
327
buf2=
GWEN_Buffer_new
(0, 64, 0, 1);
328
GWEN_Buffer_SetStep
(buf2, 128);
329
p=
GWEN_Buffer_GetStart
(buf1);
330
if
(startAtRoot) {
331
p++;
332
GWEN_Buffer_AppendByte
(buf2,
'/'
);
333
}
334
if
(flags &
GWEN_PATH_FLAGS_TOLERANT_ESCAPE
)
335
rv=
GWEN_Text_UnescapeToBufferTolerant
(p, buf2);
336
else
337
rv=
GWEN_Text_UnescapeToBuffer
(p, buf2);
338
if
(rv) {
339
DBG_ERROR
(
GWEN_LOGDOMAIN
,
"Could not unescape path element"
);
340
GWEN_Buffer_free
(buf2);
341
GWEN_Buffer_free
(buf1);
342
return
0;
343
}
344
GWEN_Buffer_free
(buf1);
345
buf1=buf2;
346
}
347
}
348
349
/* call function */
350
if
(elementFunction) {
351
data=(elementFunction)(
GWEN_Buffer_GetStart
(buf1), data, idx, flags);
352
if
(!data) {
353
DBG_DEBUG
(
GWEN_LOGDOMAIN
,
"Error on path element \"%s\""
,
354
GWEN_Buffer_GetStart
(buf1));
355
GWEN_Buffer_free
(buf1);
356
return
0;
357
}
358
}
359
DBG_DEBUG
(
GWEN_LOGDOMAIN
,
"Successfully handled element \"%s\""
,
360
GWEN_Buffer_GetStart
(buf1));
361
if
(startAtRoot)
362
startAtRoot=0;
363
}
/* while (*path) */
364
365
GWEN_Buffer_free
(buf1);
366
return
data;
367
}
368
369
370
371
372
void
*
GWEN_Path_AppendPathElement
(
const
char
*entry,
373
void
*data,
374
unsigned
int
flags){
375
GWEN_BUFFER
*ebuf;
376
377
ebuf=(
GWEN_BUFFER
*)data;
378
379
GWEN_Buffer_AppendString
(ebuf, entry);
380
if
(!(flags &
GWEN_PATH_FLAGS_LAST
) ||
381
!(flags &
GWEN_PATH_FLAGS_VARIABLE
))
382
GWEN_Buffer_AppendByte
(ebuf,
'/'
);
383
GWEN_Buffer_AllocRoom
(ebuf, 1);
384
GWEN_Buffer_GetPosPointer
(ebuf)[0]=0;
385
return
data;
386
}
387
388
389
390
int
GWEN_Path_Convert
(
const
char
*path,
391
GWEN_BUFFER
*buffer,
392
uint32_t flags) {
393
void
*p;
394
395
p=
GWEN_Path_Handle
(path,
396
buffer,
397
flags,
398
GWEN_Path_AppendPathElement
);
399
if
(!p) {
400
return
-1;
401
}
402
return
0;
403
}
404
405
406
407
408
409
410
Generated on Wed May 29 2013 05:31:48 for gwenhywfar by
1.8.3.1