which is now a pointer to the vendor definition.
*/
union {
struct {
+ fr_dict_attr_t const *vendor; //!< ancestor which has type FR_TYPE_VENDOR
fr_dict_attr_t const **children; //!< Children of this attribute.
};
struct {
*/
static inline uint32_t fr_dict_vendor_num_by_da(fr_dict_attr_t const *da)
{
- fr_dict_attr_t const *da_p = da;
+ if (!da->vendor) return 0;
- while (da_p->parent) {
- if (da_p->type == FR_TYPE_VENDOR) break;
- da_p = da_p->parent;
- }
- if (da_p->type != FR_TYPE_VENDOR) return 0;
-
- return da_p->attr;
+ return da->vendor->attr;
}
fr_dict_vendor_t const *fr_dict_vendor_by_da(fr_dict_attr_t const *da);
if (dict_gctx_push(ctx, da) < 0) return -1;
}
+ /*
+ * Point to the vendor definition. Since ~90% of
+ * attributes are VSAs, caching this pointer will help.
+ */
+ if (parent->type == FR_TYPE_VENDOR) {
+ fr_dict_attr_t *self;
+
+ memcpy(&self, &da, sizeof(self)); /* const issues */
+ self->vendor = parent;
+
+ } else if (parent->vendor) {
+ fr_dict_attr_t *self;
+
+ memcpy(&self, &da, sizeof(self)); /* const issues */
+ self->vendor = parent->vendor;
+ }
+
return 0;
}