* ulong VARNAME/VALUE VALUE if bitfields2ul)
*
* hbytes mask-map lookup MAP-VAR ADDRESS [DEFAULT] => DATA
- * error on missing default or if address too short
+ * error on missing default or if any prefix longer than address
* hbytes mask-map amend MAP-VAR PREFIX PREFIX-LENGTH DATA
* a maskmap MAP is [list [list PREFIX PREFIX-LENGTH DATA]] sorted
* first by descending PREFIX-LENGTH and then by ascending PREFIX
* HBYTES LENGTH MISMATCH when blocks must be exactly same length
* HBYTES SYNTAX supposed hex block had wrong syntax
* HBYTES VALUE OVERFLOW value to be conv'd to hex too big/long
+ * HBYTES MASKMAP NOMATCH no addr/mask matches address for lookup
+ * HBYTES MASKMAP UNDERRUN addr value for lookup is too short
* HBYTES MASKMAP SYNTAX LLENGTH value for mask-map entry not llength==3
* HBYTES MASKMAP SYNTAX UNDERRUN value for mask-map entry hex too short
* HBYTES MASKMAP SYNTAX OVERRUN actual mask-map entry hex too short
* ulong VARNAME/VALUE VALUE if bitfields2ul)
*
* hbytes mask-map lookup MAP-VAR ADDRESS [DEFAULT] => DATA
- * error on missing default or if address too short
+ * error on missing default or if any prefix longer than address
* hbytes mask-map amend MAP-VAR PREFIX PREFIX-LENGTH DATA
* a maskmap MAP is [list [list PREFIX PREFIX-LENGTH DATA]] sorted
* first by descending PREFIX-LENGTH and then by ascending PREFIX
* HBYTES LENGTH MISMATCH when blocks must be exactly same length
* HBYTES SYNTAX supposed hex block had wrong syntax
* HBYTES VALUE OVERFLOW value to be conv'd to hex too big/long
+ * HBYTES MASKMAP NOMATCH no addr/mask matches address for lookup
+ * HBYTES MASKMAP UNDERRUN addr value for lookup is too short
* HBYTES MASKMAP SYNTAX LLENGTH value for mask-map entry not llength==3
* HBYTES MASKMAP SYNTAX UNDERRUN value for mask-map entry hex too short
* HBYTES MASKMAP SYNTAX OVERRUN actual mask-map entry hex too short
}
int do_maskmap_lookup(ClientData cd, Tcl_Interp *ip,
- Tcl_Obj *mapo, HBytes_Value addr, Tcl_Obj *def,
+ Tcl_Obj *mapo, HBytes_Value addrhb, Tcl_Obj *def,
Tcl_Obj **result) {
- /*MaskMap_Var *map= (void*)&mapo->internalRep;*/
- *result= Tcl_NewIntObj(42);
- return TCL_OK; /*fixme*/
+ MaskMap_Value *mm= (void*)&mapo->internalRep;
+ MaskMap_Entry *search;
+ const Byte *addr= hbytes_data(&addrhb);
+ int addrbytes= hbytes_len(&addrhb);
+ int i, directbytes, leftoverbits;
+
+ search= mm->entries;
+ if (!search || search->prefixlen==-1) goto not_found;
+
+ /* longest masks are first, so we can test this once */
+ if (addrbytes < prefix_bytes(search->prefixlen))
+ return staticerr(ip, "address shorter than mask(s) in map",
+ "HBYTES MASKMAP UNDERRUN");
+
+ for (i=0;
+ i < mm->allocd && search->prefixlen != -1;
+ i++, search++) {
+ directbytes= search->prefixlen / 8;
+ if (memcmp(search->prefix, addr, directbytes)) continue;
+
+ leftoverbits= search->prefixlen % 8;
+ if (leftoverbits)
+ if ((addr[directbytes] & (0xffu << leftoverbits))
+ != search->prefix[directbytes])
+ continue;
+
+ /*found*/
+ *result= search->data;
+ return TCL_OK;
+ }
+
+ not_found:
+ if (!def)
+ return staticerr(ip, "address not found in mask-map",
+ "HBYTES MASKMAP NOMATCH");
+ *result= def;
+ return TCL_OK;
}
/*---------- Tcl type and arg parsing functions ----------*/