return TCL_OK;
}
-static void maskmap_t_free(Tcl_Obj *o) { }
-static void maskmap_t_dup(Tcl_Obj *src, Tcl_Obj *dup) { }
-static void maskmap_t_ustr(Tcl_Obj *o) { }
-static int maskmap_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) { return TCL_ERROR; }
+static int prefix_bytes (int prefixlen) {
+ return (prefixlen + 7)/8;
+}
+
+static void mme_init(MaskMap_Entry *mme) {
+ mme->prefix= 0;
+ mme->data= 0;
+}
+
+static int mm_count(const MaskMap_Value *mm) {
+ int i;
+ for (i=0; i<sm->allocd && sm->entries[i].prefixlen != -1; i++);
+ return i;
+}
+
+static void mm_allocentries(MaskMap_Value *mm, int len) {
+ int i;
+ mm->allocd= len;
+ mm->entries= Tcl_Alloc(sizeof(*mm->entries) * len);
+ assert(mm->entries);
+ for (i=0; i < len; i++)
+ mme_init(&mm->entries[i]);
+}
+
+static void maskmap_t_free(Tcl_Obj *o) {
+ MaskMap_Value *mm= (void*)&o->internalRep;
+ for (i=0; i<mm.allocd; i++) {
+ if (i.prefixlen==-1) break;
+ mme_free(&mm.entries[i]);
+ }
+}
+
+static void maskmap_t_dup(Tcl_Obj *so, Tcl_Obj *do) {
+ MaskMap_Value *sm= (void*)&so->internalRep;
+ MaskMap_Value *dm= (void*)&do->internalRep;
+ int l, i, nbytes;
+
+ assert(so->typePtr == &maskmap_type);
+ objfreeir(do);
+ l= mm_count(&sm);
+
+ mm_allocentries(&dm,l);
+ for (i=0, sme=sm->entries, dme=dm->entries;
+ i<dm->allocd;
+ i++, sme++, dme++) {
+ *dme= *sme;
+ nbytes= prefix_bytes(sme->prefixlen);
+ dme->prefix= Tcl_Alloc(nbytes); assert(dme->prefix);
+ memcpy(dme->prefix, sme->prefix, nbytes);
+ Tcl_IncrRefCount(dme->data);
+ }
+}
+
+static void maskmap_t_ustr(Tcl_Obj *so) {
+ MaskMap_Value *sm= (void*)&so->internalRep;
+ Tcl_Obj **mainlobjsl, *mainobj;
+ char *string;
+ int stringl;
+
+ assert(so->typePtr == &maskmap_type);
+ l= mm_count(sm);
+ mainlobjsl= Tcl_Alloc(sizeof(*mainobjsl) * l); assert(mainlobjsl);
+
+ for (i=0; i<l; i++) {
+ MaskMap_Entry *sme= &sm->entries[i];
+ HBytes_Value hb;
+ Tcl_Obj *subl[3], *sublo;
+
+ hbytes_array(&hb, sme->prefix, prefix_bytes(sme->prefixlen));
+ subl[0]= ret_hb(ip, &hb); assert(subl[0]);
+ subl[1]= Tcl_NewIntObj(sme->prefixlen); assert(subl[1]);
+ subl[2]= sme->data;
+
+ sublo= Tcl_NewListObj(3,subl); assert(sublo);
+ mainlobjsl[i]= sublo;
+ }
+
+ mainobj= Tcl_NewListObj(l,mainlobjsl); assert(mainobj);
+ so->bytes= Tcl_GetStringFromObj(mainobj, &so->length); assert(so->bytes);
+ mainobj->bytes= 0; mainobj->length= 0; /* we stole it */
+}
+
+static int maskmap_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
+ int len, eol;
+ MaskMap_Value mm;
+
+ mm.allocd= 0;
+ mm.entries= 0;
+
+ rc= Tcl_ListObjLength(ip,o,&len); if (rc) goto x_rc;
+ mm_allocentries(len);
+
+ for (i=0; i<len; i++) {
+ rc= Tcl_ListObjIndex(ip,o,i,&eo); if (rc) goto x_rc;
+ rc= Tcl_ListObjLength(ip,eo,&eol); if (rc) goto x_rc;
+ if (eol != 3) {
+ rc= staticerr(ip, "mask-map entry length != 3");
+ goto x_rc;
+ }
+ rc= Tcl_ListObjIndex(ip,eo,0,&prefixo); if (rc) goto rc;
+ rc= Tcl_ListObjIndex(ip,eo,1,&prefixleno); if (rc) goto rc;
+ rc= Tcl_ListObjIndex(ip,eo,2,&mm.entries[i].data); if (rc) goto x_rc;
+ Tcl_IncrRefCount(mm.entries[i].data);
+
+ rc= mme_parsekey(&mm.entries[i], prefixo, prefixleno, 1);
+ if (rc) goto rc;
+
+ if (i>0) {
+ if (mme_compare(&mm.entries[i-1], &mm.entries[i]) <= 0) {
+ rc= staticerr(ip, "mask-map entries out of order");
+ goto x_rc;
+ }
+ }
+ }
+
+ /* we commit now */
+ assert(sizeof(mm) <= sizeof(o.internalRep));
+ objfreeir(o);
+ memcpy(&o.internalRep, &mm, sizeof(mm));
+ o.typePtr= &maskmap_type;
+ return TCL_OK;
+
+x_rc:
+ if (mm.entries) {
+ for (i=0; i<len; i++)
+ mme_free(&mm.entries[i]);
+ Tcl_Free(mm.entries);
+ }
+ return rc;
+}
+
+ { free(mm.e
+ return rc;
+ rc= Tcl_ConvertToType(ip,o,
+}
Tcl_ObjType maskmap_type = {
"mask-map",