Re: [xml] libxml2 API crazy?



OK, so this is really guaranteed by the standard, good. But how libxml2
uses that is still insane. In GTK+, I can always expect a GtkWidget * to
point to a GtkWidget or a descendant (like GtkButton), so I can be sure
that all of its stucture fields don't contain garbage or point outside
the structure (I'm sure that the last field of xmlDoc (int properties)
points outside xmlNode's last element (int extra) and if I accidentally
try to access it in the xmlNodePtr that really points to an xmlDoc, my
program will end up with corrupted memory or crash). I'd expect libxml2
to have a common structure that only contains the common part, like
this:

/* this only contains the common part */
typedef strcut xmlNode {
       void            *_private;  /* application data */
       xmlElementType   type;      /* type number */
       const xmlChar   *name;      /* used differently  */
       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 */
};

typedef struct xmlDoc {
       void            *_private;  /* application data */
       xmlElementType   type;      /* type number */
       const xmlChar   *name;      /* used differently  */
       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 */

  /* document specific stuff */
};

/* what the current xmlNode seems to be */
typedef struct xmlTagOrText {
       void            *_private;  /* application data */
       xmlElementType   type;      /* type number */
       const xmlChar   *name;      /* used differently  */
       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 */

  /* tag-or-text specific stuff */
};

/* useful help functions */

xmlDocPtr xmlToDoc(xmlNodePtr node) {
  if (node->type == XML_DOCUMENT_NODE)
    return (xmlDocPtr)node;
  else
    return NULL;
}

xmlTagOrTextPtr xmlToTagOrText(xmlNodePtr node) {
  if (node->type == XML_ELEMENT_NODE
      || node->type == XML_TEXT_NODE
      || node->type == XML_CDATA_SECTION_NODE)
    return (xmlTextOrTagPtr)node;
  else
    return NULL;
}

On Mon, 2013-04-29 at 01:06 -0400, Liam R E Quin wrote:
On Mon, 2013-04-29 at 08:32 +0400, Nikita Churaev wrote:
It doesn't have anything to do with C standard.

It does. Take for example:

struct A {
  int q;
  int w;
  /* end of common part */

  float x;
};

struct B {
  int q;
  int w;
  /* end of common part */

  double x;
};

What if the C standard allows the compiler to place q and w further
apart in struct A than in struct B?

Then every kernel or device driver on the planet would break, as would
large amount of application code. But it doesn't allow the compiler that
freedom.

C specifies the behaviour very precisely and carefully exactly so you
can do this. See "structure padding"...

Liam





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]