#include <stdlib.h>
#include <string.h>
#include "Ancestor.h"
Ancestor::Ancestor(Str field, fru_tag_t t, const fru_regdef_t *d)
: field_name(field),
tag(t),
def(d),
numInstances(0),
numBufs(1),
next(NULL)
{
offsets = (uint32_t *)malloc(sizeof (uint32_t)
* ANCESTOR_INST_BUF_SIZE);
paths = (char **)malloc(sizeof (char *)
* ANCESTOR_INST_BUF_SIZE);
}
Ancestor::~Ancestor()
{
free(offsets);
if (paths != NULL) {
for (int i = 0; i < numInstances; i++) {
free(paths[i]);
}
}
free(paths);
delete next;
}
void
Ancestor::addInstance(const char *path, uint32_t offset)
{
if (numInstances >= ANCESTOR_INST_BUF_SIZE) {
numBufs++;
offsets = (uint32_t *)realloc(offsets,
(sizeof (uint32_t) *
(ANCESTOR_INST_BUF_SIZE * numBufs)));
paths = (char **)realloc(offsets,
(sizeof (char *) *
(ANCESTOR_INST_BUF_SIZE * numBufs)));
}
offsets[numInstances] = offset;
paths[numInstances++] = strdup(path);
}
Str
Ancestor::getFieldName(void)
{
return (field_name);
}
fru_tag_t
Ancestor::getTag(void)
{
return (tag);
}
const fru_regdef_t *
Ancestor::getDef(void)
{
return (def);
}
int
Ancestor::getNumInstances(void)
{
return (numInstances);
}
uint32_t
Ancestor::getInstOffset(int num)
{
if (num < numInstances)
return (offsets[num]);
else
return (offsets[numInstances]);
}
const char *
Ancestor::getPath(int num)
{
if (num < numInstances)
return (paths[num]);
else
return (paths[numInstances]);
}
Ancestor *
Ancestor::listTaggedAncestors(char *element)
{
Ancestor *rc = NULL;
fru_regdef_t *def = NULL;
int i = 0;
unsigned int number = 0;
char **data_elems = fru_reg_list_entries(&number);
if (data_elems == NULL) {
return (NULL);
}
for (i = 0; i < number; i++) {
def = (fru_regdef_t *)
fru_reg_lookup_def_by_name(data_elems[i]);
Ancestor *ant = createTaggedAncestor(def, element);
if (ant != NULL) {
if (rc == NULL) {
rc = ant;
} else {
Ancestor *tmp = rc;
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = ant;
}
}
}
for (i = 0; i < number; i++) {
free(data_elems[i]);
}
free(data_elems);
return (rc);
}
Ancestor *
Ancestor::createTaggedAncestor(const fru_regdef_t *def, Str element)
{
if (def->tagType == FRU_X)
return (NULL);
fru_tag_t tag;
mk_tag(def->tagType, def->tagDense, def->payloadLen, &tag);
Ancestor *rc = new Ancestor(element, tag, def);
if (element.compare(def->name) == 0) {
rc->addInstance("", 0);
return (rc);
}
int found = 0;
if (def->dataType == FDTYPE_Record) {
uint32_t offset = 0;
for (int i = 0; i < def->enumCount; i++) {
const fru_regdef_t *tmp
= fru_reg_lookup_def_by_name
((char *)def->enumTable[i].text);
Str path = "/";
path << def->name;
int f = definitionContains(tmp, def, element,
offset, rc, path);
if (f == 1) found = 1;
offset += tmp->payloadLen;
}
}
if (!found) {
delete rc;
return (NULL);
}
return (rc);
}
int
Ancestor::definitionContains(const fru_regdef_t *def,
const fru_regdef_t *parent_def,
Str element,
uint32_t offset,
Ancestor *ant,
Str path)
{
if (element.compare(def->name) == 0) {
if (parent_def->iterationType != FRU_NOT_ITERATED) {
offset += 4;
for (int i = 0; i < parent_def->iterationCount; i++) {
Str tmp = path;
tmp << "[" << i << "]/";
ant->addInstance(tmp.peak(), offset);
offset += (parent_def->payloadLen - 4) /
parent_def->iterationCount;
}
} else {
path << "/";
ant->addInstance(path.peak(), offset);
}
return (1);
}
int found = 0;
if (def->dataType == FDTYPE_Record) {
for (int i = 0; i < def->enumCount; i++) {
const fru_regdef_t *tmp
= fru_reg_lookup_def_by_name
((char *)def->enumTable[i].text);
Str newPath = path;
newPath << "/" << def->name;
int f = definitionContains(tmp, def, element,
offset, ant, newPath);
if (f == 1) found = 1;
offset += tmp->payloadLen;
}
}
return (found);
}