nullptr checking for linked member pointer access

69 Views Asked by At
typedef struct _xmlNode xmlNode;
typedef xmlNode *xmlNodePtr;
struct _xmlNode {
    void           *_private;   /* application data */
    xmlElementType   type;  /* type number, must be second ! */
    const xmlChar   *name;      /* the name of the node, or the entity */
    struct _xmlNode *children;  /* parent->childs link */
    struct _xmlNode *last;  /* last child link */
    struct _xmlNode *parent;    /* child->parent link */
    struct _xmlNode *next;  /* next sibling link  */
    struct _xmlNode *prev;  /* previous sibling link  */
    struct _xmlDoc  *doc;   /* the containing document */

    /* End of common part */
    xmlNs           *ns;        /* pointer to the associated namespace */
    xmlChar         *content;   /* the content */
...
}

There's a node like above, and suppose that one have xmlNode node(not NULL).
One wants to access
node->next->children->next->next->content
but since each pointer can be NULL, one have to check all of them.

if(node == NULL || node->next == NULL || node->next->children == NULL ...)
  fprintf(stderr, "err");

Is there a method to check if the pointer is NULL automatically? Such as

#define CHECK(ptr) BOOST_PP_????(...) ??

if (CHECK(node->next->children->next->next->content))
 ...

_xmlNode is from libxml2 and since I'm accessing members in HTML parsed data to get specific element for crawling website, accessing cannot be regular like below.

bool go_next(xmlNode n, int num) {
  for(; num; --num) {
    if(n==NULL) return false;
    n = n->next;
  }
  return true;
}
1

There are 1 best solutions below

0
David Ranieri On

Is trivial using an enum and a compound literal, something like:

enum {END, PREV, NEXT, CHILDREN, CONTENTS};

int check_node(xmlNode node, int test[])
{
    while ((node != NULL) && (*test != END))
    {
        switch (*test)
        {
            case PREV:
                node = node->prev;
                break;
            case NEXT:
                node = node->next;
                break;
            case CHILDREN:
                node = node->children;
                break;
            case CONTENTS:
                node = node->contents;
                break;
            default:
                return 0;
        }
        test++;
    }
    return (node != NULL);
}

if (!check_node(node, (int []){NEXT, CHILDREN, NEXT, NEXT, CONTENTS, END}))
{
    fprintf(stderr, "err");
}