253 } |
254 } |
254 } |
255 } |
255 return 1; |
256 return 1; |
256 } |
257 } |
257 |
258 |
|
259 // TODO: use scstr_t after update to UCX 2.0 |
|
260 static sstr_t rtrimskip(sstr_t str, size_t skip) { |
|
261 while (skip < str.length && isspace(str.ptr[skip])) skip++; |
|
262 return sstrsubs(str, skip); |
|
263 } |
|
264 |
|
265 static size_t parse_tagfilter_taglist(sstr_t fs, SyncTagFilter* tagfilter) { |
|
266 size_t csvlen; |
|
267 for (csvlen = 0 ; csvlen < fs.length ; ++csvlen) { |
|
268 if (fs.ptr[csvlen] == ')') break; |
|
269 } |
|
270 fs.length = csvlen; |
|
271 |
|
272 tagfilter->tags = parse_csv_taglist(fs.ptr, fs.length); |
|
273 |
|
274 return csvlen; |
|
275 } |
|
276 |
|
277 /* |
|
278 * Parses: ( "(" , filter , ")" )+ |
|
279 */ |
|
280 static size_t parse_tagfilter_subfilters(sstr_t fs, SyncTagFilter* tagfilter) { |
|
281 // TODO: implement |
|
282 tagfilter->subfilter_count = 0; |
|
283 tagfilter->subfilters = NULL; |
|
284 |
|
285 return 0; |
|
286 } |
|
287 |
258 SyncTagFilter* parse_tagfilter_string(const char* filterstring) { |
288 SyncTagFilter* parse_tagfilter_string(const char* filterstring) { |
259 SyncTagFilter* tagfilter = malloc(sizeof(SyncTagFilter)); |
289 SyncTagFilter* tagfilter = malloc(sizeof(SyncTagFilter)); |
260 if (!filterstring) { |
290 if (!filterstring) { |
261 memset(tagfilter, 0, sizeof(SyncTagFilter)); |
291 memset(tagfilter, 0, sizeof(SyncTagFilter)); |
262 return tagfilter; |
292 return tagfilter; |
263 } |
293 } |
264 |
294 |
265 tagfilter->mode = DAV_SYNC_TAGFILTER_AND; |
295 // TODO: use scstr_t after update to UCX 2.0 |
266 tagfilter->subfilter_count = 0; |
296 sstr_t fs = sstrtrim(sstr((char*) filterstring)); |
267 tagfilter->tags = parse_csv_taglist(filterstring, strlen(filterstring)); |
297 |
268 |
298 if (fs.length == 0) { |
|
299 memset(tagfilter, 0, sizeof(SyncTagFilter)); |
|
300 return tagfilter; |
|
301 } else { |
|
302 |
|
303 // optional operator |
|
304 if (fs.ptr[0] == '&') { |
|
305 tagfilter->mode = DAV_SYNC_TAGFILTER_AND; |
|
306 fs = rtrimskip(fs, 1); |
|
307 } else if (fs.ptr[0] == '|') { |
|
308 tagfilter->mode = DAV_SYNC_TAGFILTER_OR; |
|
309 fs = rtrimskip(fs, 1); |
|
310 } else if (fs.ptr[0] == '0') { |
|
311 tagfilter->mode = DAV_SYNC_TAGFILTER_NONE; |
|
312 fs = rtrimskip(fs, 1); |
|
313 } else if (fs.ptr[0] == '1') { |
|
314 tagfilter->mode = DAV_SYNC_TAGFILTER_ONE; |
|
315 fs = rtrimskip(fs, 1); |
|
316 } else { |
|
317 // default operator is AND |
|
318 tagfilter->mode = DAV_SYNC_TAGFILTER_AND; |
|
319 } |
|
320 |
|
321 size_t consumed; |
|
322 if (fs.length > 0 && fs.ptr[0] == '(') { |
|
323 consumed = parse_tagfilter_subfilters(fs, tagfilter); |
|
324 } else { |
|
325 tagfilter->subfilter_count = 0; |
|
326 tagfilter->subfilters = NULL; |
|
327 consumed = parse_tagfilter_taglist(fs, tagfilter); |
|
328 } |
|
329 |
|
330 if (consumed != fs.length) { |
|
331 free(tagfilter->subfilters); |
|
332 free(tagfilter); |
|
333 return NULL; |
|
334 } |
|
335 } |
|
336 |
269 return tagfilter; |
337 return tagfilter; |
270 } |
338 } |
271 |
339 |
272 static int matches_tags_and(UcxList *dav_tags, UcxList *tags, int ignorecase) { |
340 static int matches_tags_and(UcxList *dav_tags, UcxList *tags, int ignorecase) { |
273 UCX_FOREACH(e, tags) { |
341 UCX_FOREACH(e, tags) { |