1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
93
  
94
  
95
  
96
  
97
  
98
  
99
  
100
  
101
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
116
  
117
  
118
  
119
  
120
  
121
  
122
  
123
  
124
  
125
  
126
  
127
  
128
  
129
  
130
  
131
  
132
  
133
  
134
  
135
  
136
  
137
  
138
  
139
  
140
  
141
  
142
  
143
  
144
  
145
  
146
  
147
  
148
  
149
  
150
  
151
  
152
  
153
  
154
  
155
  
156
  
157
  
158
  
159
  
160
  
161
  
162
  
163
  
164
  
165
  
166
  
167
  
168
  
169
  
170
  
171
  
/* vim:syntax=c 
 */ 
#include "common.h" 
 
#include "critbit/int2svalue.h" 
#define CB_PRINT_KEY(buf, key)          do \ 
    { string_builder_sprintf((buf), "%"PRINTPIKEINT"d", CB_UINT2INT((key).str)); } while(0) 
#define CB_LOW_ASSIGN_SVALUE_KEY(key, s)        do {                    \ 
    struct svalue * __ = (s);                                           \ 
    SET_SVAL(*__, PIKE_T_INT, 0, integer, CB_UINT2INT((key).str));      \ 
} while(0) 
#define CB_PUSH_KEY(key)        push_int(CB_UINT2INT((key).str)); 
#define CB_STRING_FROM_SVALUE(v)        CB_INT2UINT((v)->u.integer) 
#define CB_LOW_KEY_FROM_SVALUE(x) CB_KEY_FROM_STRING(CB_STRING_FROM_SVALUE(x)) 
#include "tree_high.c" 
 
#define DEFAULT_CMOD_STORAGE static 
 
DECLARATIONS 
 
/*! @module ADT */ 
/*! @module CritBit */ 
 
PIKECLASS IntTree { 
#cmod_define iterator_class Iterator 
#cmod_define tree_class IntTree 
#cmod_define cmod_OBJ2_TREE OBJ2_INTTREE 
#cmod_define T_KEY BIT_INT 
#cmod_define key_ptype int 
#cmod_define sval_type integer 
#cmod_define sample_key 12 
#cmod_define sample_keys ({ 1025, 15000, 3 }) 
#cmod_define ordered_keys 3, 1025 and 15000 
#cmod_define reverse_ordered_keys 15000, 1025 and 3 
#cmod_define sample_value ({ 1, 2 ,3 }) 
#cmod_define extra_doc 
#cmod_include "redefine.H" 
 
#cmod_include "tree_header.H" 
#cmod_include "iterator_source.H" 
#undef THIS 
#define THIS THIS_INTTREE 
#cmod_include "tree_source.H" 
} 
 
#define WASTED_BITS (8*(sizeof(INT_TYPE)-4)) 
 
cb_key cb_key_from_ptype_ipv4(struct pike_string * s) { 
    cb_key key; 
    unsigned int a, b, c, d, e; 
 
    key.len.chars = 1; 
    key.len.bits = 0; 
 
    if (s->size_shift || s->len > 18) Pike_error("Malformed ip.\n"); 
 
    switch (sscanf((char *)STR0(s), "%3u.%3u.%3u.%3u/%2u", &a, &b, &c, &d, &e)) 
    { 
    case 5: 
        if (e > 32) Pike_error("Mask is too big!"); 
        key.len.chars = 0; 
        key.len.bits = WASTED_BITS + e; 
    case 4: 
        if (a > 255 || b > 255 || c > 255 || d > 255) 
            Pike_error("Bad ip.\n"); 
        key.str = (INT_TYPE)(a << 24 | b << 16 | c << 8 | d); 
        break; 
    default: 
        Pike_error("Malformed ip.\n"); 
    } 
 
    return key; 
} 
 
struct pike_string * cb_ptype_from_key_ipv4(cb_key key) { 
    char buf[19]; 
    size_t len; 
 
    unsigned INT32 ip = (unsigned INT32)key.str; 
 
    if (key.len.bits || !key.len.chars) { 
        ip &= (~0U) << (32 - (int)(key.len.bits - WASTED_BITS)); 
        len = snprintf(buf, 19, "%u.%u.%u.%u/%u", 
                       (unsigned int)(ip>>24), (unsigned int)((ip>>16)&0xff), 
                       (unsigned int)((ip>>8)&0xff), (unsigned int)(ip&0xff), 
                       (unsigned int)(key.len.bits - WASTED_BITS)); 
    } else { 
        len = snprintf(buf, 19, "%u.%u.%u.%u", 
                       (unsigned int)(ip>>24), (unsigned int)((ip>>16)&0xff), 
                       (unsigned int)((ip>>8)&0xff), (unsigned int)(ip&0xff)); 
    } 
 
    return make_shared_binary_string(buf, MINIMUM(19, len)); 
} 
 
PIKECLASS IPv4Tree { 
#cmod_define iterator_class Iterator 
#cmod_define tree_class IPv4Tree 
#cmod_define cmod_OBJ2_TREE OBJ2_IPV4TREE 
#cmod_define T_KEY BIT_STRING 
#cmod_define key_ptype string 
#cmod_define sval_type string 
#cmod_define sample_key "127.0.0.0/8" 
#cmod_define sample_keys ({ "10.243.7.1", "127.0.0.1/8", "172.16.5.2" }) 
#cmod_define ordered_keys "10.243.7.1", "127.0.0.1/8" and "172.16.5.2" 
#cmod_define reverse_ordered_keys "172.16.5.2", "127.0.0.1/8" and "10.243.7.1" 
#cmod_define sample_value "reject" 
#cmod_define extra_doc 
 
#undef CB_INT2UINT 
#undef CB_UINT2INT 
#define CB_INT2UNIT(x) (x) 
#define CB_UINT2INT(x) (x) 
#undef CB_PUSH_KEY 
#define CB_PUSH_KEY(key)    push_string(cb_ptype_from_key_ipv4(key)) 
#undef CB_KEY_FROM_PTYPE 
#define CB_KEY_FROM_PTYPE(x)    cb_key_from_ptype_ipv4(x) 
#undef CB_STRING_FROM_SVALUE 
#undef CB_LOW_KEY_FROM_SVALUE 
#undef CB_KEY_FROM_SVALUE 
#define CB_LOW_KEY_FROM_SVALUE(x)   CB_KEY_FROM_PTYPE((x)->u.string) 
#undef CB_LOW_ASSIGN_SVALUE_KEY 
#define CB_LOW_ASSIGN_SVALUE_KEY(key, s) do {                             \ 
    struct svalue * __ = s;                                               \ 
    SET_SVAL(*__, PIKE_T_STRING, 0, string, cb_ptype_from_key_ipv4(key)); \ 
} while (0) 
 
#cmod_include "redefine.H" 
 
#cmod_include "tree_header.H" 
#cmod_include "iterator_source.H" 
#undef THIS 
#define THIS THIS_IPV4TREE 
#cmod_include "prefix.H" 
#cmod_include "tree_source.H" 
 
    PIKEFUN int mask(int n) { 
        RETURN MASK(INT_TYPE, n); 
    } 
 
    PIKEFUN int umask(int n) { 
        RETURN MASK(unsigned INT64, n); 
    } 
 
    PIKEFUN int cmp_key(mixed a, mixed b) { 
        cb_key k1 = CB_KEY_FROM_SVALUE(a); 
        cb_key k2 = CB_KEY_FROM_SVALUE(b); 
        INT_TYPE ret; 
        if (CB_KEY_LT(k1, k2)) { 
            ret = -1; 
        } else if (CB_KEY_MATCH(k1, k2)) { 
            ret = 0; 
        } else { 
            ret = 1; 
        } 
        pop_n_elems(args); 
        push_int(ret); 
    } 
} 
 
/*! @endmodule */ 
/*! @endmodule */ 
 
void pike_init_inttree_module(void) { 
    INIT 
} 
 
void pike_exit_inttree_module(void) { 
    EXIT 
}