dav/sync.c

changeset 395
b491d207ee16
parent 394
4826f5fdd865
child 396
1490c24c6077
equal deleted inserted replaced
394:4826f5fdd865 395:b491d207ee16
255 } 255 }
256 return 1; 256 return 1;
257 } 257 }
258 258
259 // TODO: use scstr_t after update to UCX 2.0 259 // TODO: use scstr_t after update to UCX 2.0
260 static sstr_t rtrimskip(sstr_t str, size_t skip) { 260 static size_t rtrimskip(sstr_t str, size_t skip) {
261 while (skip < str.length && isspace(str.ptr[skip])) skip++; 261 while (skip < str.length && isspace(str.ptr[skip])) skip++;
262 return sstrsubs(str, skip); 262 return skip;
263 } 263 }
264 264
265 static size_t parse_tagfilter_taglist(sstr_t fs, SyncTagFilter* tagfilter) { 265 static size_t parse_tagfilter_taglist(sstr_t fs, SyncTagFilter* tagfilter) {
266 size_t csvlen; 266 size_t csvlen;
267 for (csvlen = 0 ; csvlen < fs.length ; ++csvlen) { 267 for (csvlen = 0 ; csvlen < fs.length ; ++csvlen) {
270 fs.length = csvlen; 270 fs.length = csvlen;
271 271
272 tagfilter->tags = parse_csv_taglist(fs.ptr, fs.length); 272 tagfilter->tags = parse_csv_taglist(fs.ptr, fs.length);
273 273
274 return csvlen; 274 return csvlen;
275 }
276
277 static size_t parse_tagfilter_subfilters(sstr_t fs, SyncTagFilter* tagfilter);
278
279 static size_t parse_tagfilter_filter(sstr_t fs, SyncTagFilter* tagfilter) {
280
281 size_t consumed = rtrimskip(fs, 0);
282 fs = sstrsubs(fs, consumed);
283
284 if (fs.length == 0) {
285 memset(tagfilter, 0, sizeof(SyncTagFilter));
286 return consumed;
287 } else {
288
289 // optional operator
290 int hasop = 0;
291 if (fs.ptr[0] == '&') {
292 tagfilter->mode = DAV_SYNC_TAGFILTER_AND;
293 hasop = 1;
294 } else if (fs.ptr[0] == '|') {
295 tagfilter->mode = DAV_SYNC_TAGFILTER_OR;
296 hasop = 1;
297 } else if (fs.ptr[0] == '0') {
298 tagfilter->mode = DAV_SYNC_TAGFILTER_NONE;
299 hasop = 1;
300 } else if (fs.ptr[0] == '1') {
301 tagfilter->mode = DAV_SYNC_TAGFILTER_ONE;
302 hasop = 1;
303 } else {
304 // default operator is AND
305 tagfilter->mode = DAV_SYNC_TAGFILTER_AND;
306 }
307
308 if (hasop) {
309 size_t skip = rtrimskip(fs, 1);
310 consumed += skip;
311 fs = sstrsubs(fs, skip);
312 }
313
314 if (fs.length > 0 && fs.ptr[0] == '(') {
315 consumed += parse_tagfilter_subfilters(fs, tagfilter);
316 } else {
317 tagfilter->subfilter_count = 0;
318 tagfilter->subfilters = NULL;
319 consumed += parse_tagfilter_taglist(fs, tagfilter);
320 }
321
322 return consumed;
323 }
275 } 324 }
276 325
277 /* 326 /*
278 * Parses: ( "(" , filter , ")" )+ 327 * Parses: ( "(" , filter , ")" )+
279 */ 328 */
291 memset(tagfilter, 0, sizeof(SyncTagFilter)); 340 memset(tagfilter, 0, sizeof(SyncTagFilter));
292 return tagfilter; 341 return tagfilter;
293 } 342 }
294 343
295 // TODO: use scstr_t after update to UCX 2.0 344 // TODO: use scstr_t after update to UCX 2.0
296 sstr_t fs = sstrtrim(sstr((char*) filterstring)); 345 sstr_t fs = sstr((char*) filterstring);
297 346 size_t consumed = parse_tagfilter_filter(fs, tagfilter);
298 if (fs.length == 0) { 347
299 memset(tagfilter, 0, sizeof(SyncTagFilter)); 348 // consume trailing white spaces
300 return tagfilter; 349 consumed = rtrimskip(fs, consumed);
301 } else { 350
302 351 // sanity check: have we consumed the whole string?
303 // optional operator 352 if (consumed != fs.length) {
304 if (fs.ptr[0] == '&') { 353 free_tagfilter(tagfilter);
305 tagfilter->mode = DAV_SYNC_TAGFILTER_AND; 354 return NULL;
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 } 355 }
336 356
337 return tagfilter; 357 return tagfilter;
358 }
359
360 void free_tagfilter(SyncTagFilter* filter) {
361 for (size_t i = 0 ; i < filter->subfilter_count ; i++) {
362 free_tagfilter(filter->subfilters[i]);
363 }
364 free(filter->subfilters);
365 free(filter);
338 } 366 }
339 367
340 static int matches_tags_and(UcxList *dav_tags, UcxList *tags, int ignorecase) { 368 static int matches_tags_and(UcxList *dav_tags, UcxList *tags, int ignorecase) {
341 UCX_FOREACH(e, tags) { 369 UCX_FOREACH(e, tags) {
342 if (!ucx_list_contains(dav_tags, e->data, 370 if (!ucx_list_contains(dav_tags, e->data,
385 static int matches_tags(UcxList *dav_tags, SyncTagFilter *tagfilter) { 413 static int matches_tags(UcxList *dav_tags, SyncTagFilter *tagfilter) {
386 414
387 if (tagfilter->subfilter_count > 0) { 415 if (tagfilter->subfilter_count > 0) {
388 int ret = 1; 416 int ret = 1;
389 for (size_t i = 0 ; i < tagfilter->subfilter_count ; i++) { 417 for (size_t i = 0 ; i < tagfilter->subfilter_count ; i++) {
390 ret &= matches_tags(dav_tags, &(tagfilter->subfilters[i])); 418 ret &= matches_tags(dav_tags, tagfilter->subfilters[i]);
391 } 419 }
392 return ret; 420 return ret;
393 } else { 421 } else {
394 int ignorecase = 0; // TODO: maybe add support later 422 int ignorecase = 0; // TODO: maybe add support later
395 switch (tagfilter->mode) { 423 switch (tagfilter->mode) {
487 SyncTagFilter* tagfilter = parse_tagfilter_string(cmd_getoption(a, "tags")); 515 SyncTagFilter* tagfilter = parse_tagfilter_string(cmd_getoption(a, "tags"));
488 if (!tagfilter) { 516 if (!tagfilter) {
489 fprintf(stderr, "Malformed tag filter\n"); 517 fprintf(stderr, "Malformed tag filter\n");
490 return -1; 518 return -1;
491 } 519 }
520 // TODO: tons of memory leaks...
521 // call free_tagfilter() before each return
492 522
493 SyncDirectory *dir = scfg_get_dir(a->argv[0]); 523 SyncDirectory *dir = scfg_get_dir(a->argv[0]);
494 if(!dir) { 524 if(!dir) {
495 fprintf(stderr, "Unknown sync dir: %s\n", a->argv[0]); 525 fprintf(stderr, "Unknown sync dir: %s\n", a->argv[0]);
496 return -1; 526 return -1;

mercurial