X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=maskmap%2Fmaskmap.c;h=77c677fba4314558887ae45ebbe9c06b3c8f2efc;hp=1f122e9f114e53a85749cde15a7227a3774f0fc4;hb=4149293c485d766e446f1a841892420059755347;hpb=6235da689cb928ce3b4f9e6deb4a50a5b9c841fb diff --git a/maskmap/maskmap.c b/maskmap/maskmap.c index 1f122e9..77c677f 100644 --- a/maskmap/maskmap.c +++ b/maskmap/maskmap.c @@ -97,22 +97,72 @@ static int mm_count(const MaskMap_Value *mm) { return i; } -static void mm_allocentries(MaskMap_Value *mm, int len) { +static void mm_init(MaskMap_Value *mm) { + mm->allocd= 0; + mm->entries= 0; +} + +static void mm_reallocentries(MaskMap_Value *mm, int len) { int i; + MaskMap_Entry *newentries, *clear; + + newentries= TREALLOC(mm->entries, sizeof(*newentries)*len); + assert(!len || newentries); + + for (i=mm->allocd, clear=&mm->entries[mm->allocd]; + i < len; + i++, clear++) + mme_init(clear); + mm->allocd= len; - mm->entries= TALLOC(sizeof(*mm->entries) * len); - assert(mm->entries); - for (i=0; i < len; i++) - mme_init(&mm->entries[i]); + mm->entries= newentries; } /*---------- substantial operations on mask maps ----------*/ int do_maskmap_amend(ClientData cd, Tcl_Interp *ip, - MaskMap_Var map, HBytes_Value prefix, - int preflen, Tcl_Obj *data) { + MaskMap_Var map, Tcl_Obj *prefix, + Tcl_Obj *preflen, Tcl_Obj *data) { + MaskMap_Value *mm= map.mm; + MaskMap_Entry mme, *search; + int rc, insertat, findend, cmp; + + mme_init(&mme); + rc= mme_parsekey(ip,&mme,prefix,preflen,0); if (rc) goto x_rc; + + for (insertat=0, search=mm->entries; + insertat < mm->allocd && + search->prefixlen != -1; + insertat++, search++) { + cmp= mme_ordercompare(&mme,search); + if (!cmp) { + mme_free(&mme); + Tcl_DecrRefCount(search->data); + goto put_here; + } + if (cmp>0) + /* the new one sorts later, insert it here */ + break; + } + + /* we're adding an entry, make room for it */ + findend= mm_count(mm); + if (findend == mm->allocd) mm_reallocentries(mm, mm->allocd*2 + 1); + if (findend > insertat) + memmove(&mm->entries[insertat+1], + &mm->entries[insertat], + sizeof(mm->entries[0]) * (findend - insertat)); + *search= mme; + + put_here: + Tcl_IncrRefCount(data); + search->data= data; return TCL_OK; + + x_rc: + mme_free(&mme); + return rc; } int do_maskmap_lookup(ClientData cd, Tcl_Interp *ip, @@ -153,7 +203,8 @@ static void maskmap_t_dup(Tcl_Obj *sob, Tcl_Obj *dob) { objfreeir(dob); l= mm_count(sm); - mm_allocentries(dm,l); + mm_init(dm); + mm_reallocentries(dm,l); for (i=0, sme=sm->entries, dme=dm->entries; iallocd; i++, sme++, dme++) { @@ -199,11 +250,10 @@ static int maskmap_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) { MaskMap_Value mm; Tcl_Obj *eo, *prefixo, *prefixleno; - mm.allocd= 0; - mm.entries= 0; + mm_init(&mm); rc= Tcl_ListObjLength(ip,o,&len); if (rc) goto x_rc; - mm_allocentries(&mm, len); + mm_reallocentries(&mm, len); for (i=0; i