chiark / gitweb /
mask-map amend implemented, but untested
authorian <ian>
Thu, 25 Nov 2004 01:18:14 +0000 (01:18 +0000)
committerian <ian>
Thu, 25 Nov 2004 01:18:14 +0000 (01:18 +0000)
base/chiark-tcl.h
base/tables-examples.tct
hbytes/hbytes.h
maskmap/maskmap.c

index 48ee798..17a0594 100644 (file)
@@ -390,5 +390,6 @@ int setnonblock(int fd, int isnonblock);
 
 #define TALLOC(s) ((void*)Tcl_Alloc((s)))
 #define TFREE(f) (Tcl_Free((void*)(f)))
+#define TREALLOC(p,l) ((void*)Tcl_Realloc((void*)(p),(l)))
 
 #endif /*HBYTES_H*/
index 267b88c..9165827 100644 (file)
@@ -45,8 +45,8 @@ Table maskmap MaskMap_SubCommand
                =>      obj
        amend
                map     maskmapv
-               prefix  hb
-               preflen int
+               prefix  obj
+               preflen obj
                data    obj
 
 Table ulong ULong_SubCommand
index 48ee798..17a0594 100644 (file)
@@ -390,5 +390,6 @@ int setnonblock(int fd, int isnonblock);
 
 #define TALLOC(s) ((void*)Tcl_Alloc((s)))
 #define TFREE(f) (Tcl_Free((void*)(f)))
+#define TREALLOC(p,l) ((void*)Tcl_Realloc((void*)(p),(l)))
 
 #endif /*HBYTES_H*/
index 1f122e9..77c677f 100644 (file)
@@ -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;
        i<dm->allocd;
        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<len; i++) {
     rc= Tcl_ListObjIndex(ip,o,i,&eo);  if (rc) goto x_rc;