8 int prefixlen; /* there may be some empty slots with prefixlen==-1 at end */
9 Byte *prefix; /* ceil(prefixlen/8) bytes */
13 struct MaskMap_Value {
15 MaskMap_Entry *entries;
16 }; /* overlays internalRep */
18 int pat_maskmapv(Tcl_Interp *ip, Tcl_Obj *var, MaskMap_Var *agg) {
20 rc= pat_somethingv(ip,var,&agg->sth,&maskmap_type); if (rc) return rc;
21 agg->mm= (void*)&agg->sth.obj->internalRep;
25 int do_maskmap_amend(ClientData cd, Tcl_Interp *ip,
26 MaskMap_Var map, HBytes_Value prefix,
27 int preflen, Tcl_Obj *data) {
31 int do_maskmap_lookup(ClientData cd, Tcl_Interp *ip,
32 MaskMap_Var map, HBytes_Value addr, Tcl_Obj *def,
37 static int prefix_bytes (int prefixlen) {
38 return (prefixlen + 7)/8;
41 static void mme_init(MaskMap_Entry *mme) {
46 static int mm_count(const MaskMap_Value *mm) {
48 for (i=0; i<sm->allocd && sm->entries[i].prefixlen != -1; i++);
52 static void mm_allocentries(MaskMap_Value *mm, int len) {
55 mm->entries= Tcl_Alloc(sizeof(*mm->entries) * len);
57 for (i=0; i < len; i++)
58 mme_init(&mm->entries[i]);
61 static void maskmap_t_free(Tcl_Obj *o) {
62 MaskMap_Value *mm= (void*)&o->internalRep;
63 for (i=0; i<mm.allocd; i++) {
64 if (i.prefixlen==-1) break;
65 mme_free(&mm.entries[i]);
69 static void maskmap_t_dup(Tcl_Obj *so, Tcl_Obj *do) {
70 MaskMap_Value *sm= (void*)&so->internalRep;
71 MaskMap_Value *dm= (void*)&do->internalRep;
74 assert(so->typePtr == &maskmap_type);
78 mm_allocentries(&dm,l);
79 for (i=0, sme=sm->entries, dme=dm->entries;
83 nbytes= prefix_bytes(sme->prefixlen);
84 dme->prefix= Tcl_Alloc(nbytes); assert(dme->prefix);
85 memcpy(dme->prefix, sme->prefix, nbytes);
86 Tcl_IncrRefCount(dme->data);
90 static void maskmap_t_ustr(Tcl_Obj *so) {
91 MaskMap_Value *sm= (void*)&so->internalRep;
92 Tcl_Obj **mainlobjsl, *mainobj;
96 assert(so->typePtr == &maskmap_type);
98 mainlobjsl= Tcl_Alloc(sizeof(*mainobjsl) * l); assert(mainlobjsl);
100 for (i=0; i<l; i++) {
101 MaskMap_Entry *sme= &sm->entries[i];
103 Tcl_Obj *subl[3], *sublo;
105 hbytes_array(&hb, sme->prefix, prefix_bytes(sme->prefixlen));
106 subl[0]= ret_hb(ip, &hb); assert(subl[0]);
107 subl[1]= Tcl_NewIntObj(sme->prefixlen); assert(subl[1]);
110 sublo= Tcl_NewListObj(3,subl); assert(sublo);
111 mainlobjsl[i]= sublo;
114 mainobj= Tcl_NewListObj(l,mainlobjsl); assert(mainobj);
115 so->bytes= Tcl_GetStringFromObj(mainobj, &so->length); assert(so->bytes);
116 mainobj->bytes= 0; mainobj->length= 0; /* we stole it */
119 static int maskmap_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
126 rc= Tcl_ListObjLength(ip,o,&len); if (rc) goto x_rc;
127 mm_allocentries(len);
129 for (i=0; i<len; i++) {
130 rc= Tcl_ListObjIndex(ip,o,i,&eo); if (rc) goto x_rc;
131 rc= Tcl_ListObjLength(ip,eo,&eol); if (rc) goto x_rc;
133 rc= staticerr(ip, "mask-map entry length != 3");
136 rc= Tcl_ListObjIndex(ip,eo,0,&prefixo); if (rc) goto rc;
137 rc= Tcl_ListObjIndex(ip,eo,1,&prefixleno); if (rc) goto rc;
138 rc= Tcl_ListObjIndex(ip,eo,2,&mm.entries[i].data); if (rc) goto x_rc;
139 Tcl_IncrRefCount(mm.entries[i].data);
141 rc= mme_parsekey(&mm.entries[i], prefixo, prefixleno, 1);
145 if (mme_compare(&mm.entries[i-1], &mm.entries[i]) <= 0) {
146 rc= staticerr(ip, "mask-map entries out of order");
153 assert(sizeof(mm) <= sizeof(o.internalRep));
155 memcpy(&o.internalRep, &mm, sizeof(mm));
156 o.typePtr= &maskmap_type;
161 for (i=0; i<len; i++)
162 mme_free(&mm.entries[i]);
163 Tcl_Free(mm.entries);
170 rc= Tcl_ConvertToType(ip,o,
173 Tcl_ObjType maskmap_type = {
175 maskmap_t_free, maskmap_t_dup, maskmap_t_ustr, maskmap_t_sfa