plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

sdbuniq.c (1874B)


      1 #include "std.h"
      2 
      3 static char *file;
      4 static char *key[256];
      5 
      6 static int
      7 iskey(char *attr)
      8 {
      9 	ulong i;
     10 
     11 	for (i = 0; key[i]; ++i)
     12 		if (!strcmp(attr, key[i]))
     13 			return 1;
     14 	return 0;
     15 }
     16 
     17 static int
     18 isnew(Sdbr r0, Sdbr r1, char *attr)
     19 {
     20 	String val[2];
     21 
     22 	val[0] = sdbr_val(r0, attr);
     23 	val[1] = sdbr_val(r1, attr);
     24 	if (!val[1].s
     25 		|| (val[0].s && !strcmp(val[0].s, val[1].s))
     26 	)
     27 		return 0;
     28 	return 1;
     29 }
     30 
     31 static void
     32 usage(void)
     33 {
     34 	fprint(2, "sdbuniq: [-f file] [attr]...\n");
     35 	exits("usage");
     36 }
     37 
     38 void
     39 main(int argc, char *argv[])
     40 {
     41 	Sdb db;
     42 	Sdbr r, cr, nr, *sr;
     43 	char *attr;
     44 	ulong i, nk;
     45 
     46 	ARGBEGIN {
     47 	case 'f':
     48 		file = EARGF(usage());
     49 		break;
     50 	default:
     51 		usage();
     52 	} ARGEND;
     53 	for (nk = 0; *argv; ++nk)
     54 		key[nk] = *argv++;
     55 	sdbr_init(&cr);
     56 	sdbr_init(&nr);
     57 	sdbr_init(&r);
     58 	sdb_open(&db, file);
     59 	if (!sdb_next(&db))
     60 		exits(0);
     61 	sdbr_dup(&cr, db.r[db.n]);
     62 	sdbr_dup(&nr, db.r[db.n]);
     63 	for (;sdb_next(&db);) {
     64 		sr = db.r + db.n;
     65 		/* first attribute is always a key, regardless of name */
     66 		if (strcmp(sr->val[0].s, cr.val[0].s)) {
     67 			if (sdbr_n(nr) > nk + 1)
     68 				sdbr_print(nr);
     69 			sdbr_dup(&cr, *sr);
     70 			sdbr_dup(&nr, *sr);
     71 			continue;
     72 		}
     73 		/*
     74 		 * check each key for changes and update internal
     75 		 * current record (cr) state
     76 		 */
     77 		for (i = 0; i < nk; ++i) {
     78 			if (!isnew(cr, *sr, key[i]))
     79 				continue;
     80 			if (sdbr_n(nr) > nk + 1)
     81 				sdbr_print(nr);
     82 			sdbr_zero(&nr);
     83 			sdbr_add(&nr, cr.attr[0], cr.val[0]);
     84 			for (i = 0; i < nk; ++i)
     85 				sdbr_add(&nr, Str(key[i])
     86 					, sdbr_val(*sr, key[i])
     87 				);
     88 			sdbr_edit(&cr, nr);
     89 			break;
     90 		}
     91 		for (i = 1; i < sdbr_n(*sr); ++i) {
     92 			attr = sr->attr[i].s;
     93 			if (iskey(attr) || !isnew(cr, *sr, attr))
     94 				continue;
     95 			sdbr_add(&r, Str(attr), sdbr_val(*sr, attr));
     96 		}
     97 		if (sdbr_n(r)) {
     98 			sdbr_edit(&cr, r);
     99 			sdbr_edit(&nr, r);
    100 			sdbr_zero(&r);
    101 		}
    102 	}
    103 	if (sdbr_n(nr) > nk + 1)
    104 		sdbr_print(nr);
    105 	exits(0);
    106 }