12154b58da04b4ac509e60ab459eb81b50a36174
[rrq/rrqmisc.git] / pvector / example-pvector.c
1 #include <arpa/inet.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 #include <unistd.h>
10 #include "pvector.h"
11
12 typedef struct _ipslot {
13     char data[16];
14     unsigned int bits;
15 } ipslot;
16
17 static struct {
18     pvector data;
19     int fill;
20 } table;
21
22 #define BUFSZ 10000
23 static struct {
24     char data[ BUFSZ ];
25     int cur;
26     int end;
27 } stream;
28
29 static int readline(int fd,char **outp) {
30     for ( ;; ) {
31         char *curp = stream.data + stream.cur;
32         char *endp = stream.data + stream.end;
33         char *top = curp;
34         while  ( curp < endp ) {
35             if ( *(curp++) == '\n' ) {
36                 stream.cur = curp - stream.data;
37                 (*outp) = top;
38                 return curp - top;
39             }
40         }
41         if ( top != stream.data ) {
42             curp = stream.data;
43             while ( top < endp ) {
44                 *(curp++) = *(top++);
45             }
46             endp = curp;
47             stream.end = endp - stream.data;
48         }
49         stream.cur = 0;
50         ssize_t n = read( fd, endp, BUFSZ - stream.end );
51         if ( n <= 0 ) {
52             if ( stream.end == 0 ) {
53                 return -1; // No more data
54             }
55             (*outp) = stream.data;
56             return stream.end;
57         }
58         stream.end += n;
59     }
60     //unreachable
61 }
62
63 // Scan to NUL, CR or c. Return pointer not including character.
64 static char *scanto(char *p, char c) {
65     while ( *p && *p != '\n' && *p != c ) {
66         p++;
67     }
68     return p;
69 }
70
71 static int parse_addr(char *line,ipslot *addr) {
72     char *end = scanto( line, '\n' );
73     char *slash = scanto( line, '/' );
74     *slash = 0;
75     if ( inet_pton( AF_INET, line, addr->data ) == 0 ) {
76         addr->bits = 32;
77     } if ( inet_pton( AF_INET6, line, addr->data ) == 0 ) {
78         addr->bits = 128;
79     } else {
80         return 1;
81     }
82     if ( slash != end && sscanf( slash+1, "%u", &addr->bits ) != 1 ) {
83         return 1;
84     }
85     return 0;
86 }
87
88 static void add_entry(ipslot *tmp) {
89     ipslot *p = (ipslot *) malloc( sizeof( ipslot ) );
90     memmove( p, tmp, sizeof( ipslot ) );
91     if ( table.data.size == table.fill ) {
92         (void) pvector_resize( &table.data, table.fill + 256, 0, 0 );
93     }
94     pvector_set( &table.data, table.fill++, p );
95 }
96
97 static void load_file(const char *filename) {
98     int fd = open( filename, O_RDONLY );
99     if ( fd < 0 ) {
100         perror( filename );
101         exit( errno );
102     }
103     char *line;
104     int n;
105     while ( ( n = readline( fd, &line ) ) >= 0 ) {
106         ipslot addr;
107         if ( parse_addr( line, &addr ) ) {
108             fprintf( stderr, "Bad address: %s\n", line );
109             continue;
110         }
111         add_entry( &addr );
112     }
113 }
114
115 static int int_reclaim(pvector *pv,unsigned long index,void *item,void *data) {
116     return 0;
117 }
118
119 static int dumpitem(unsigned long index,void *item) {
120     fprintf( stdout, "[%ld] %p\n", index, item );
121     return 0;
122 }
123
124 static int dump_ipslot(unsigned long index,void *item) {
125     static char buffer[100];
126     ipslot *ip = (ipslot*) item;
127     const char *p = inet_ntop( (ip->bits <= 32)? AF_INET : AF_INET6,
128                          ip->data, buffer, 100 );
129     
130     fprintf( stdout, "[%ld] %s/%d\n", index, p, ip->bits );
131     return 0;
132 }
133
134 int main(int argc,char **argv) {
135     pvector test = { 0 };
136     pvector_resize( &test, 100, 0, 0 );
137     pvector_set( &test, 5, (void*) 500 );
138     pvector_set( &test, 55, (void*) 600 );
139     //pvector_set( &test, 550, (void*) 800 );
140     pvector_resize( &test, 300, 0, 0 );
141     pvector_set( &test, 55, (void*) 650 );
142     pvector_resize( &test, 30000, 0, 0 );
143     pvector_set( &test, 22255, (void*) 26 );
144     pvector_dump( &test, dumpitem );
145     pvector_resize( &test, 100, int_reclaim, 0 );
146     pvector_set( &test, 5, (void*) 2 );
147     pvector_dump( &test, dumpitem );
148
149     int i;
150     for ( i = 1; i < argc; i++ ) {
151         load_file( argv[ i ] );
152     }
153     pvector_dump( &table.data, dump_ipslot );
154
155     return 0;
156 }