#include <stdio.h>
#include <string.h>
#include <libnvpair.h>
#include "evnv.h"
#include "out.h"
#define min(a, b) (((a) <= (b)) ? (a) : (b))
extern nv_alloc_t Eft_nv_hdl;
static void
outindent(int depth)
{
while (depth-- > 0)
out(O_ALTFP|O_VERB3|O_NONL, " ");
}
int
evnv_cmpnvl(nvlist_t *nvl1, nvlist_t *nvl2, int depth)
{
data_type_t t1, t2;
nvlist_t **la1 = NULL;
nvlist_t **la2 = NULL;
nvlist_t *l1 = NULL;
nvlist_t *l2 = NULL;
nvpair_t *p1 = NULL;
nvpair_t *p2 = NULL;
uint64_t lv1, lv2;
uint_t m, na1, na2;
char *s1, *s2;
int ret, i;
for (;;) {
p1 = nvlist_next_nvpair(nvl1, p1);
p2 = nvlist_next_nvpair(nvl2, p2);
if (p1 == NULL && p2 == NULL) {
outindent(depth);
out(O_ALTFP|O_VERB3, "equal nvls\n");
return (0);
}
if (p1 == NULL)
return (-1);
if (p2 == NULL)
return (1);
s1 = nvpair_name(p1);
s2 = nvpair_name(p2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: pair %s vs %s", s1, s2);
if ((ret = strcmp(s1, s2)) != 0)
return (ret);
t1 = nvpair_type(p1);
t2 = nvpair_type(p2);
if (t1 != t2)
return (t1 - t2);
switch (t1) {
case DATA_TYPE_NVLIST:
(void) nvpair_value_nvlist(p1, &l1);
(void) nvpair_value_nvlist(p2, &l2);
if ((ret = evnv_cmpnvl(l1, l2, depth + 1)) != 0)
return (ret);
break;
case DATA_TYPE_NVLIST_ARRAY:
(void) nvpair_value_nvlist_array(p1, &la1, &na1);
(void) nvpair_value_nvlist_array(p2, &la2, &na2);
m = min(na1, na2);
for (i = 0; i < m; i++) {
if ((ret =
evnv_cmpnvl(*la1, *la2, depth + 1)) != 0)
return (ret);
la1++;
la2++;
}
if (na1 < na2)
return (-1);
else if (na2 < na1)
return (1);
break;
case DATA_TYPE_STRING:
(void) nvpair_value_string(p1, &s1);
(void) nvpair_value_string(p2, &s2);
if ((ret = strcmp(s1, s2)) != 0) {
outindent(depth);
if (ret < 0)
out(O_ALTFP|O_VERB3,
"cmpnvl: %s < %s", s1, s2);
else
out(O_ALTFP|O_VERB3,
"cmpnvl: %s > %s", s1, s2);
return (ret);
}
break;
case DATA_TYPE_UINT64:
lv1 = lv2 = 0;
(void) nvpair_value_uint64(p1, &lv1);
(void) nvpair_value_uint64(p2, &lv2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: %llu vs %llu", lv1, lv2);
if (lv1 > lv2)
return (1);
else if (lv2 > lv1)
return (-1);
break;
case DATA_TYPE_INT64:
lv1 = lv2 = 0;
(void) nvpair_value_int64(p1, (int64_t *)&lv1);
(void) nvpair_value_int64(p2, (int64_t *)&lv2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: %lld vs %lld", lv1, lv2);
if (lv1 > lv2)
return (1);
else if (lv2 > lv1)
return (-1);
break;
case DATA_TYPE_UINT32:
lv1 = lv2 = 0;
(void) nvpair_value_uint32(p1, (uint32_t *)&lv1);
(void) nvpair_value_uint32(p2, (uint32_t *)&lv2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: %u vs %u",
*(uint32_t *)&lv1, *(uint32_t *)&lv2);
if (lv1 > lv2)
return (1);
else if (lv2 > lv1)
return (-1);
break;
case DATA_TYPE_INT32:
lv1 = lv2 = 0;
(void) nvpair_value_int32(p1, (int32_t *)&lv1);
(void) nvpair_value_int32(p2, (int32_t *)&lv2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: %d vs %d",
*(int32_t *)&lv1, *(int32_t *)&lv2);
if (lv1 > lv2)
return (1);
else if (lv2 > lv1)
return (-1);
break;
case DATA_TYPE_UINT16:
lv1 = lv2 = 0;
(void) nvpair_value_uint16(p1, (uint16_t *)&lv1);
(void) nvpair_value_uint16(p2, (uint16_t *)&lv2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: %u vs %u",
*(uint16_t *)&lv1, *(uint16_t *)&lv2);
if (lv1 > lv2)
return (1);
else if (lv2 > lv1)
return (-1);
break;
case DATA_TYPE_INT16:
lv1 = lv2 = 0;
(void) nvpair_value_int16(p1, (int16_t *)&lv1);
(void) nvpair_value_int16(p2, (int16_t *)&lv2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: %d vs %d",
*(int16_t *)&lv1, *(int16_t *)&lv2);
if (lv1 > lv2)
return (1);
else if (lv2 > lv1)
return (-1);
break;
case DATA_TYPE_UINT8:
lv1 = lv2 = 0;
(void) nvpair_value_uint8(p1, (uint8_t *)&lv1);
(void) nvpair_value_uint8(p2, (uint8_t *)&lv2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: %u vs %u",
*(uint8_t *)&lv1, *(uint8_t *)&lv2);
if (lv1 > lv2)
return (1);
else if (lv2 > lv1)
return (-1);
break;
case DATA_TYPE_INT8:
lv1 = lv2 = 0;
(void) nvpair_value_int8(p1, (int8_t *)&lv1);
(void) nvpair_value_int8(p2, (int8_t *)&lv2);
outindent(depth);
out(O_ALTFP|O_VERB3, "cmpnvl: %d vs %d",
*(int8_t *)&lv1, *(int8_t *)&lv2);
if (lv1 > lv2)
return (1);
else if (lv2 > lv1)
return (-1);
break;
}
}
}
nvlist_t *
evnv_dupnvl(nvlist_t *nvp)
{
nvlist_t *retval = NULL;
int nvret;
if (nvp == NULL)
return (NULL);
if ((nvret = nvlist_xdup(nvp, &retval, &Eft_nv_hdl)) != 0)
out(O_DIE, "dupnvl: dup failed: %d", nvret);
return (retval);
}