chiark / gitweb /
some maskmap stuff;
[chiark-tcl.git] / maskmap / maskmap.c
1 /*
2  */
3
4 #include "tables.h"
5 #include "hbytes.h"
6
7 typedef struct {
8   int prefixlen; /* there may be some empty slots with prefixlen==-1 at end */
9   Byte *prefix; /* ceil(prefixlen/8) bytes */
10   Tcl_Obj *data;
11 } MaskMap_Entry;
12
13 struct MaskMap_Value {
14   int allocd;
15   MaskMap_Entry *entries;
16 }; /* overlays internalRep */
17
18 int pat_maskmapv(Tcl_Interp *ip, Tcl_Obj *var, MaskMap_Var *agg) {
19   int rc;
20   rc= pat_somethingv(ip,var,&agg->sth,&maskmap_type);  if (rc) return rc;
21   agg->mm= (void*)&agg->sth.obj->internalRep;
22   return TCL_OK;
23 }
24
25 int do_maskmap_amend(ClientData cd, Tcl_Interp *ip,
26                      MaskMap_Var map, HBytes_Value prefix,
27                      int preflen, Tcl_Obj *data) {
28   return TCL_OK;
29 }
30
31 int do_maskmap_lookup(ClientData cd, Tcl_Interp *ip,
32                       MaskMap_Var map, HBytes_Value addr, Tcl_Obj *def,
33                       Tcl_Obj **result) {
34   return TCL_OK;
35 }
36
37 static int prefix_bytes (int prefixlen) {
38   return (prefixlen + 7)/8;
39 }
40
41 static void mme_init(MaskMap_Entry *mme) {
42   mme->prefix= 0;
43   mme->data= 0;
44 }
45
46 static int mm_count(const MaskMap_Value *mm) {
47   int i;
48   for (i=0; i<sm->allocd && sm->entries[i].prefixlen != -1; i++);
49   return i;
50 }
51
52 static void mm_allocentries(MaskMap_Value *mm, int len) {
53   int i;
54   mm->allocd= len;
55   mm->entries= Tcl_Alloc(sizeof(*mm->entries) * len);
56   assert(mm->entries);
57   for (i=0; i < len; i++)
58     mme_init(&mm->entries[i]);
59 }
60   
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]);
66   }
67 }
68
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;
72   int l, i, nbytes;
73
74   assert(so->typePtr == &maskmap_type);
75   objfreeir(do);
76   l= mm_count(&sm);
77
78   mm_allocentries(&dm,l);
79   for (i=0, sme=sm->entries, dme=dm->entries;
80        i<dm->allocd;
81        i++, sme++, dme++) {
82     *dme= *sme;
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);
87   }
88 }
89
90 static void maskmap_t_ustr(Tcl_Obj *so) {
91   MaskMap_Value *sm= (void*)&so->internalRep;
92   Tcl_Obj **mainlobjsl, *mainobj;
93   char *string;
94   int stringl;
95
96   assert(so->typePtr == &maskmap_type);
97   l= mm_count(sm);
98   mainlobjsl= Tcl_Alloc(sizeof(*mainobjsl) * l);  assert(mainlobjsl);
99
100   for (i=0; i<l; i++) {
101     MaskMap_Entry *sme= &sm->entries[i];
102     HBytes_Value hb;
103     Tcl_Obj *subl[3], *sublo;
104
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]);
108     subl[2]= sme->data;
109     
110     sublo= Tcl_NewListObj(3,subl);  assert(sublo);
111     mainlobjsl[i]= sublo;
112   }
113
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 */
117 }
118
119 static int maskmap_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
120   int len, eol;
121   MaskMap_Value mm;
122
123   mm.allocd= 0;
124   mm.entries= 0;
125   
126   rc= Tcl_ListObjLength(ip,o,&len);  if (rc) goto x_rc;
127   mm_allocentries(len);
128   
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;
132     if (eol != 3) {
133       rc= staticerr(ip, "mask-map entry length != 3");
134       goto x_rc;
135     }
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);
140
141     rc= mme_parsekey(&mm.entries[i], prefixo, prefixleno, 1);
142     if (rc) goto rc;
143
144     if (i>0) {
145       if (mme_compare(&mm.entries[i-1], &mm.entries[i]) <= 0) {
146         rc= staticerr(ip, "mask-map entries out of order");
147         goto x_rc;
148       }
149     }
150   }
151
152   /* we commit now */
153   assert(sizeof(mm) <= sizeof(o.internalRep));
154   objfreeir(o);
155   memcpy(&o.internalRep, &mm, sizeof(mm));
156   o.typePtr= &maskmap_type;
157   return TCL_OK;
158
159 x_rc:
160   if (mm.entries) {
161     for (i=0; i<len; i++)
162       mme_free(&mm.entries[i]);
163     Tcl_Free(mm.entries);
164   }
165   return rc;
166 }
167
168     { free(mm.e
169   return rc;
170   rc= Tcl_ConvertToType(ip,o,
171 }
172
173 Tcl_ObjType maskmap_type = {
174   "mask-map",
175   maskmap_t_free, maskmap_t_dup, maskmap_t_ustr, maskmap_t_sfa
176 };