Selaa lähdekoodia

rework Pattern application

instead of creating three lists of mailboxes (common, master, slave)
and deriving the mailbox presence from the list being processed, create
a single joined list which contains the presence information.
additionally, the list is sorted alphabetically (with INBOX first),
which is neater.
Oswald Buddenhagen 10 vuotta sitten
vanhempi
sitoutus
05deb008db
1 muutettua tiedostoa jossa 100 lisäystä ja 53 poistoa
  1. 100 53
      src/main.c

+ 100 - 53
src/main.c

@@ -153,12 +153,33 @@ matches( const char *t, const char *p )
 	}
 }
 
-static string_list_t *
+
+static int
+is_inbox( const char *name )
+{
+	return starts_with( name, -1, "INBOX", 5 ) && (!name[5] || name[5] == '/');
+}
+
+static int
+cmp_box_names( const void *a, const void *b )
+{
+	const char *as = *(const char **)a;
+	const char *bs = *(const char **)b;
+	int ai = is_inbox( as );
+	int bi = is_inbox( bs );
+	int di = bi - ai;
+	if (di)
+		return di;
+	return strcmp( as, bs );
+}
+
+static char **
 filter_boxes( string_list_t *boxes, const char *prefix, string_list_t *patterns )
 {
-	string_list_t *nboxes = 0, *cpat;
+	string_list_t *cpat;
+	char **boxarr = 0;
 	const char *ps;
-	int not, fnot, pfxl;
+	int not, fnot, pfxl, num = 0, rnum = 0;
 
 	pfxl = prefix ? strlen( prefix ) : 0;
 	for (; boxes; boxes = boxes->next) {
@@ -177,10 +198,15 @@ filter_boxes( string_list_t *boxes, const char *prefix, string_list_t *patterns
 				break;
 			}
 		}
-		if (!fnot)
-			add_string_list( &nboxes, boxes->string + pfxl );
+		if (!fnot) {
+			if (num + 1 >= rnum)
+				boxarr = nfrealloc( boxarr, (rnum = (rnum + 10) * 2) * sizeof(*boxarr) );
+			boxarr[num++] = nfstrdup( boxes->string + pfxl );
+			boxarr[num] = 0;
+		}
 	}
-	return nboxes;
+	qsort( boxarr, num, sizeof(*boxarr), cmp_box_names );
+	return boxarr;
 }
 
 static void
@@ -202,12 +228,19 @@ merge_actions( channel_conf_t *chan, int ops[], int have, int mask, int def )
 	}
 }
 
+typedef struct box_ent {
+	struct box_ent *next;
+	char *name;
+	int present[2];
+} box_ent_t;
+
 typedef struct {
 	int t[2];
 	channel_conf_t *chan;
 	driver_t *drv[2];
 	store_t *ctx[2];
-	string_list_t *boxes[2], *cboxes, *chanptr;
+	box_ent_t *boxes;
+	string_list_t *chanptr;
 	char *names[2];
 	char **argv;
 	int oind, ret, multiple, all, list, ops[2], state[2];
@@ -524,7 +557,7 @@ main( int argc, char **argv )
 
 static void store_opened( store_t *ctx, void *aux );
 static void store_listed( int sts, void *aux );
-static int sync_listed_boxes( main_vars_t *mvars, string_list_t *mbox, int present[] );
+static int sync_listed_boxes( main_vars_t *mvars, box_ent_t *mbox );
 static void done_sync_dyn( int sts, void *aux );
 static void done_sync_2_dyn( int sts, void *aux );
 static void done_sync( int sts, void *aux );
@@ -536,10 +569,10 @@ sync_chans( main_vars_t *mvars, int ent )
 {
 	group_conf_t *group;
 	channel_conf_t *chan;
-	string_list_t *mbox, *sbox, **mboxp, **sboxp;
-	char *channame, *boxp, *nboxp;
+	box_ent_t *mbox, *nmbox, **mboxapp;
+	char *channame, **boxes[2], *boxp, *nboxp;
 	const char *labels[2];
-	int t;
+	int t, mb, sb, cmp;
 
 	if (!mvars->cben)
 		return;
@@ -549,7 +582,7 @@ sync_chans( main_vars_t *mvars, int ent )
 	}
 	for (;;) {
 		mvars->boxlist = 0;
-		mvars->boxes[M] = mvars->boxes[S] = mvars->cboxes = 0;
+		mvars->boxes = 0;
 		if (!mvars->all) {
 			if (mvars->chanptr)
 				channame = mvars->chanptr->string;
@@ -580,6 +613,7 @@ sync_chans( main_vars_t *mvars, int ent )
 					goto gotnone;
 				}
 				mvars->boxlist = 1;
+				mboxapp = &mvars->boxes;
 				for (;;) {
 					nboxp = strpbrk( boxp, ",\n" );
 					if (nboxp) {
@@ -588,10 +622,15 @@ sync_chans( main_vars_t *mvars, int ent )
 					} else {
 						t = strlen( boxp );
 					}
+					mbox = nfmalloc( sizeof(*mbox) );
 					if (t)
-						add_string_list_n( &mvars->cboxes, boxp, t );
+						mbox->name = nfstrndup( boxp, t );
 					else
-						add_string_list_n( &mvars->cboxes, "INBOX", 5 );
+						mbox->name = nfstrndup( "INBOX", 5 );
+					mbox->present[M] = mbox->present[S] = BOX_POSSIBLE;
+					mbox->next = 0;
+					*mboxapp = mbox;
+					mboxapp = &mbox->next;
 					if (!nboxp)
 						break;
 					boxp = nboxp;
@@ -638,21 +677,34 @@ sync_chans( main_vars_t *mvars, int ent )
 
 		if (!mvars->boxlist && mvars->chan->patterns) {
 			mvars->boxlist = 1;
-			mvars->boxes[M] = filter_boxes( mvars->ctx[M]->boxes, mvars->chan->boxes[M], mvars->chan->patterns );
-			mvars->boxes[S] = filter_boxes( mvars->ctx[S]->boxes, mvars->chan->boxes[S], mvars->chan->patterns );
-			for (mboxp = &mvars->boxes[M]; (mbox = *mboxp); ) {
-				for (sboxp = &mvars->boxes[S]; (sbox = *sboxp); sboxp = &sbox->next)
-					if (!strcmp( sbox->string, mbox->string )) {
-						*sboxp = sbox->next;
-						free( sbox );
-						*mboxp = mbox->next;
-						mbox->next = mvars->cboxes;
-						mvars->cboxes = mbox;
-						goto gotdupe;
-					}
-				mboxp = &mbox->next;
-			  gotdupe: ;
+			boxes[M] = filter_boxes( mvars->ctx[M]->boxes, mvars->chan->boxes[M], mvars->chan->patterns );
+			boxes[S] = filter_boxes( mvars->ctx[S]->boxes, mvars->chan->boxes[S], mvars->chan->patterns );
+			mboxapp = &mvars->boxes;
+			for (mb = sb = 0; boxes[M][mb] || boxes[S][sb]; ) {
+				mbox = nfmalloc( sizeof(*mbox) );
+				if (!(cmp = !boxes[M][mb] - !boxes[S][sb]) && !(cmp = cmp_box_names( boxes[M] + mb, boxes[S] + sb ))) {
+					mbox->name = boxes[M][mb];
+					free( boxes[S][sb] );
+					mbox->present[M] = mbox->present[S] = BOX_PRESENT;
+					mb++;
+					sb++;
+				} else if (cmp < 0) {
+					mbox->name = boxes[M][mb];
+					mbox->present[M] = BOX_PRESENT;
+					mbox->present[S] = BOX_ABSENT;
+					mb++;
+				} else {
+					mbox->name = boxes[S][sb];
+					mbox->present[M] = BOX_ABSENT;
+					mbox->present[S] = BOX_PRESENT;
+					sb++;
+				}
+				mbox->next = 0;
+				*mboxapp = mbox;
+				mboxapp = &mbox->next;
 			}
+			free( boxes[M] );
+			free( boxes[S] );
 		}
 
 		if (mvars->list && mvars->multiple)
@@ -660,21 +712,11 @@ sync_chans( main_vars_t *mvars, int ent )
 	  syncml:
 		mvars->done = mvars->cben = 0;
 		if (mvars->boxlist) {
-			while ((mbox = mvars->cboxes)) {
-				int present[] = { BOX_PRESENT, BOX_PRESENT };
-				mvars->cboxes = mbox->next;
-				if (sync_listed_boxes( mvars, mbox, present ))
+			while ((mbox = mvars->boxes)) {
+				mvars->boxes = mbox->next;
+				if (sync_listed_boxes( mvars, mbox ))
 					goto syncw;
 			}
-			for (t = 0; t < 2; t++)
-				while ((mbox = mvars->boxes[t])) {
-					int present[2];
-					present[t] = BOX_PRESENT;
-					present[1-t] = BOX_ABSENT;
-					mvars->boxes[t] = mbox->next;
-					if (sync_listed_boxes( mvars, mbox, present ))
-						goto syncw;
-				}
 		} else {
 			if (!mvars->list) {
 				int present[] = { BOX_POSSIBLE, BOX_POSSIBLE };
@@ -701,9 +743,11 @@ sync_chans( main_vars_t *mvars, int ent )
 			mvars->skip = mvars->cben = 1;
 			return;
 		}
-		free_string_list( mvars->cboxes );
-		free_string_list( mvars->boxes[M] );
-		free_string_list( mvars->boxes[S] );
+		for (nmbox = mvars->boxes; (mbox = nmbox); ) {
+			nmbox = mbox->next;
+			free( mbox->name );
+			free( mbox );
+		}
 	  next2:
 		if (mvars->all) {
 			if (!(mvars->chan = mvars->chan->next))
@@ -821,27 +865,30 @@ store_listed( int sts, void *aux )
 }
 
 static int
-sync_listed_boxes( main_vars_t *mvars, string_list_t *mbox, int present[] )
+sync_listed_boxes( main_vars_t *mvars, box_ent_t *mbox )
 {
 	if (mvars->chan->boxes[M] || mvars->chan->boxes[S]) {
 		const char *mpfx = nz( mvars->chan->boxes[M], "" );
 		const char *spfx = nz( mvars->chan->boxes[S], "" );
 		if (!mvars->list) {
-			nfasprintf( &mvars->names[M], "%s%s", mpfx, mbox->string );
-			nfasprintf( &mvars->names[S], "%s%s", spfx, mbox->string );
+			nfasprintf( &mvars->names[M], "%s%s", mpfx, mbox->name );
+			nfasprintf( &mvars->names[S], "%s%s", spfx, mbox->name );
+			free( mbox->name );
+			sync_boxes( mvars->ctx, (const char **)mvars->names, mbox->present, mvars->chan, done_sync_2_dyn, mvars );
 			free( mbox );
-			sync_boxes( mvars->ctx, (const char **)mvars->names, present, mvars->chan, done_sync_2_dyn, mvars );
 			return 1;
 		}
-		printf( "%s%s <=> %s%s\n", mpfx, mbox->string, spfx, mbox->string );
+		printf( "%s%s <=> %s%s\n", mpfx, mbox->name, spfx, mbox->name );
 	} else {
 		if (!mvars->list) {
-			mvars->names[M] = mvars->names[S] = mbox->string;
-			sync_boxes( mvars->ctx, (const char **)mvars->names, present, mvars->chan, done_sync_dyn, mvars );
+			mvars->names[M] = mvars->names[S] = mbox->name;
+			sync_boxes( mvars->ctx, (const char **)mvars->names, mbox->present, mvars->chan, done_sync_dyn, mvars );
+			free( mbox );
 			return 1;
 		}
-		puts( mbox->string );
+		puts( mbox->name );
 	}
+	free( mbox->name );
 	free( mbox );
 	return 0;
 }
@@ -851,7 +898,7 @@ done_sync_dyn( int sts, void *aux )
 {
 	main_vars_t *mvars = (main_vars_t *)aux;
 
-	free( ((char *)mvars->names[S]) - offsetof(string_list_t, string) );
+	free( mvars->names[M] );
 	done_sync( sts, aux );
 }