rename max aggregate tool, add strict aggregation tool
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
/plag
|
||||
/plageq
|
||||
/plagmax
|
||||
/*.o
|
||||
|
||||
11
Makefile
11
Makefile
@@ -1,13 +1,16 @@
|
||||
CC=gcc
|
||||
CFLAGS= -O3
|
||||
|
||||
all: plag
|
||||
all: plagmax plageq
|
||||
|
||||
plag: plag.c lib.o lib.h config.h
|
||||
$(CC) $(CFLAGS) -o $@ plag.c lib.o
|
||||
plagmax: plagmax.c lib.o lib.h config.h
|
||||
$(CC) $(CFLAGS) -o $@ plagmax.c lib.o
|
||||
|
||||
plageq: plageq.c lib.o lib.h config.h
|
||||
$(CC) $(CFLAGS) -o $@ plageq.c lib.o
|
||||
|
||||
lib.o: lib.c lib.h
|
||||
$(CC) $(CFLAGS) -o $@ -c lib.c
|
||||
|
||||
clean:
|
||||
rm plag lib.o
|
||||
rm plagmax plageq lib.o
|
||||
|
||||
2
config.h
2
config.h
@@ -8,4 +8,6 @@
|
||||
typedef uint32_t pos_t;
|
||||
typedef int mask_t;
|
||||
|
||||
#define STRICT_MAX_DEPTH 32 // less than 32 is aligned anyway
|
||||
|
||||
#endif /* !CONFIG_H */
|
||||
|
||||
219
plageq.c
Normal file
219
plageq.c
Normal file
@@ -0,0 +1,219 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <error.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "lib.h"
|
||||
|
||||
#define DEPTHB ((int)((STRICT_MAX_DEPTH)+7)/8)
|
||||
#define DEPTHL ((DEPTHB)*8)
|
||||
|
||||
struct node {
|
||||
pos_t a[2];
|
||||
uint8_t b[DEPTHB];
|
||||
};
|
||||
typedef struct node *iptree;
|
||||
typedef void (*bitsfun)(bits, mask_t, mask_t, mask_t);
|
||||
|
||||
pos_t maxpos = 0;
|
||||
|
||||
void clearb(uint8_t *b) {
|
||||
bzero(b, DEPTHB);
|
||||
}
|
||||
|
||||
void setb(uint8_t *b, int n, int i) {
|
||||
int p = n >> 3;
|
||||
if (p >= DEPTHB) return;
|
||||
if (i) {
|
||||
b[p] |= 1 << (n & 0x7);
|
||||
} else {
|
||||
b[p] &= ~(1 << (n & 0x7));
|
||||
}
|
||||
}
|
||||
|
||||
int getb(uint8_t *b, int n) {
|
||||
int p = n >> 3;
|
||||
if (p >= DEPTHB) return 0;
|
||||
int i = b[p] & (1 << (n & 0x7));
|
||||
return i ? 1 : 0;
|
||||
}
|
||||
|
||||
iptree iptree_new(pos_t size) {
|
||||
iptree t = malloc(size * sizeof(struct node));
|
||||
if (t == 0) error(1, errno, "iptree_new: malloc failed");
|
||||
pos_t i;
|
||||
for(i = 0; i < size; ++i) {
|
||||
t[i].a[0] = i + 1;
|
||||
t[i].a[1] = 0;
|
||||
clearb(t[i].b);
|
||||
}
|
||||
t[i].a[0] = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
pos_t iptree_popfree(iptree t) {
|
||||
pos_t f = t[0].a[0];
|
||||
if (f > maxpos) maxpos = f;
|
||||
if (!f) error(1, 0, "iptree_popfree: no free nodes left");
|
||||
t[0].a[0] = t[f].a[0];
|
||||
t[f].a[0] = 0;
|
||||
return f;
|
||||
}
|
||||
|
||||
void iptree_fold(iptree t, pos_t h, mask_t m) {
|
||||
// check if we can fold
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
pos_t j = t[h].a[i];
|
||||
if (!j || !getb(t[j].b, m - 1)) return;
|
||||
}
|
||||
setb(t[h].b, m, 1);
|
||||
}
|
||||
|
||||
void iptree_add_new(iptree t, pos_t h, bits b, mask_t m) {
|
||||
if (m) {
|
||||
// there are bits left
|
||||
int l = b[0]; // our bit is left
|
||||
int r = 1 - l; // sibling bit is right
|
||||
// allocate next node element
|
||||
pos_t jl = iptree_popfree(t);
|
||||
// fill current node
|
||||
t[h].a[l] = jl;
|
||||
// recurse to add other bits
|
||||
iptree_add_new(t, jl, b + 1, m - 1);
|
||||
// check if we can fold
|
||||
iptree_fold(t, h, m);
|
||||
} else {
|
||||
// no bits left, this node is terminal
|
||||
setb(t[h].b, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void iptree_add_rec(iptree t, pos_t h, bits b, mask_t m) {
|
||||
if (m) {
|
||||
// bits to check are left
|
||||
int l = b[0]; // our bit is left
|
||||
pos_t jl = t[h].a[l]; // left subtree head
|
||||
if (jl) {
|
||||
// tree for our bit is not empty, recurse
|
||||
iptree_add_rec(t, jl, b + 1, m - 1);
|
||||
} else {
|
||||
// tree for our bit is missing, fill new subtree
|
||||
iptree_add_new(t, h, b, m);
|
||||
}
|
||||
// check if we can fold
|
||||
iptree_fold(t, h, m);
|
||||
} else {
|
||||
// no bits left, mark this mask
|
||||
setb(t[h].b, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void iptree_traverse_rec(iptree t, bitsfun f, pos_t h, bits ip, bits mask_b, mask_t m) {
|
||||
if (!h) return;
|
||||
|
||||
int l = MIN(IPMAXLEN + 1 - m, DEPTHL);
|
||||
bit_t b[l];
|
||||
if (l < DEPTHL) {
|
||||
if (l > 0) memcpy(b, mask_b, sizeof(b));
|
||||
} else {
|
||||
memcpy(b, mask_b, sizeof(b) - sizeof(bit_t));
|
||||
b[l - 1] = 0;
|
||||
}
|
||||
|
||||
// find sequences of folded masks folded from lower levels
|
||||
for (int c1 = 0; c1 < l; ++c1) {
|
||||
// skip if mask was processed or is missing in tree
|
||||
if (b[c1] || !getb(t[h].b, c1)) continue;
|
||||
// we found first mask to process
|
||||
b[c1] = 1; // mark it as processed
|
||||
// look for the end of the masks interval
|
||||
int c2 = c1 + 1;
|
||||
for (c2 = c1 + 1; c2 < l; ++c2) {
|
||||
// this time check masks in tree only
|
||||
if (!getb(t[h].b, c2)) break;
|
||||
b[c2] = 1; // mark it as processed
|
||||
}
|
||||
// print prefix with found masks interval
|
||||
f(ip, m, m + c1, m + c2 - 1);
|
||||
// jump to the end of the interval
|
||||
// b[c2] is zero anyway, so ++c1 in "for" will not hurt
|
||||
c1 = c2;
|
||||
}
|
||||
|
||||
// traverse subtrees
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
pos_t j = t[h].a[i];
|
||||
// if subtree exists
|
||||
if (j) {
|
||||
ip[m] = i; // set ip bit
|
||||
// recurse
|
||||
iptree_traverse_rec(t, f, j, ip, b + 1, m + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iptree_traverse(iptree t, pos_t h, bitsfun f) {
|
||||
bit_t ip[IPMAXLEN]; // ip bits
|
||||
bit_t b[DEPTHL]; // processed masks bits
|
||||
bzero(b, sizeof(b));
|
||||
// call recursive traversal
|
||||
iptree_traverse_rec(t, f, h, ip, b, 0);
|
||||
}
|
||||
|
||||
void print4(bits b, mask_t m, mask_t m1, mask_t m2) {
|
||||
char s_ip[BUFLEN];
|
||||
bits2ip4(b, m, s_ip, BUFLEN);
|
||||
if (m == m1 && m1 == m2) puts(s_ip);
|
||||
else printf("%s{%d,%d}\n", s_ip, m1, m2);
|
||||
}
|
||||
|
||||
void print6(bits b, mask_t m, mask_t m1, mask_t m2) {
|
||||
char s_ip[BUFLEN];
|
||||
bits2ip6(b, m, s_ip, BUFLEN);
|
||||
if (m == m1 && m1 == m2) puts(s_ip);
|
||||
else printf("%s{%d,%d}\n", s_ip, m1, m2);
|
||||
}
|
||||
|
||||
double nodes2mb(pos_t n) {
|
||||
return sizeof(struct node) * (double)n / (double)(1 << 20);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
bit_t b[IPMAXLEN];
|
||||
mask_t m;
|
||||
char s[BUFLEN];
|
||||
|
||||
iptree t = iptree_new(SIZE);
|
||||
pos_t ip4 = iptree_popfree(t);
|
||||
pos_t ip6 = iptree_popfree(t);
|
||||
|
||||
while (1) {
|
||||
if (!fgets(s, BUFLEN, stdin)) {
|
||||
if (!feof(stdin)) error(1, errno, "input");
|
||||
break;
|
||||
}
|
||||
int l = strlen(s);
|
||||
if (!l) continue;
|
||||
if (s[l - 1] == '\n') s[l - 1] = 0;
|
||||
if (!strchr(s, ':')) {
|
||||
// ipv4
|
||||
ip42bits(s, b, &m);
|
||||
iptree_add_rec(t, ip4, b, m);
|
||||
} else {
|
||||
// ipv6
|
||||
ip62bits(s, b, &m);
|
||||
iptree_add_rec(t, ip6, b, m);
|
||||
}
|
||||
}
|
||||
|
||||
iptree_traverse(t, ip4, print4);
|
||||
iptree_traverse(t, ip6, print6);
|
||||
|
||||
double mb_used = nodes2mb(maxpos);
|
||||
double mb_all = nodes2mb(SIZE);
|
||||
fprintf(stderr, "max nodes: %.2f%%, %d / %d, %.2fMB / %.2fMB\n", maxpos / (double)SIZE * 100.0, maxpos, SIZE, mb_used, mb_all);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user