Пример #1
0
static void rxml_free_node(struct rxml_node *node)
{
   struct rxml_node *head;
   for (head = node->children; head; )
   {
      struct rxml_node *next_node = head->next;
      rxml_free_node(head);
      head = next_node;
   }

   struct rxml_attrib_node *attrib_node_head;
   for (attrib_node_head = node->attrib; attrib_node_head; )
   {
      struct rxml_attrib_node *next_attrib = attrib_node_head->next;

      free(attrib_node_head->attrib);
      free(attrib_node_head->value);
      free(attrib_node_head);

      attrib_node_head = next_attrib;
   }

   free(node->name);
   free(node->data);
   free(node);
}
Пример #2
0
void rxml_free_document(rxml_document_t *doc)
{
   if (!doc)
      return;

   if (doc->root_node)
      rxml_free_node(doc->root_node);

   free(doc);
}
Пример #3
0
static void rxml_free_node(struct rxml_node *node)
{
   struct rxml_node *head = NULL;
   struct rxml_attrib_node *attrib_node_head = NULL;

   if (!node)
      return;

   for (head = node->children; head; )
   {
      struct rxml_node *next_node = (struct rxml_node*)head->next;
      rxml_free_node(head);
      head = next_node;
   }

   for (attrib_node_head = node->attrib; attrib_node_head; )
   {
      struct rxml_attrib_node *next_attrib = NULL;

      if (!attrib_node_head)
         continue;

      next_attrib = (struct rxml_attrib_node*)attrib_node_head->next;

      if (!next_attrib)
         continue;

      if (attrib_node_head->attrib)
         free(attrib_node_head->attrib);
      if (attrib_node_head->value)
         free(attrib_node_head->value);
      if (attrib_node_head)
         free(attrib_node_head);

      attrib_node_head = next_attrib;
   }

   if (node->name)
      free(node->name);
   if (node->data)
      free(node->data);
   if (node)
      free(node);
}
Пример #4
0
static struct rxml_node *rxml_parse_node(const char **ptr_)
{
   const char *ptr     = NULL;
   const char *closing = NULL;
   char *str           = NULL;
   bool is_closing     = false;

   struct rxml_node *node = (struct rxml_node*)calloc(1, sizeof(*node));
   if (!node)
      return NULL;

   skip_spaces(ptr_);

   ptr = *ptr_;
   if (*ptr != '<')
      goto error;

   closing = strchr(ptr, '>');
   if (!closing)
      goto error;

   str = strdup_range(ptr + 1, closing);
   if (!str)
      goto error;

   if (!rxml_parse_tag(node, str))
      goto error;

   is_closing = strstr(ptr, "/>") + 1 == closing; // Are spaces between / and > allowed?

   // Look for more data. Either child nodes or data.
   if (!is_closing)
   {
      size_t closing_tag_size = strlen(node->name) + 4;
      char *closing_tag = (char*)malloc(closing_tag_size);

      const char *cdata_start = NULL;
      const char *child_start = NULL;
      const char *closing_start = NULL;

      if (!closing_tag)
      {
         free(closing_tag);
         goto error;
      }

      snprintf(closing_tag, closing_tag_size, "</%s>", node->name);

      cdata_start   = strstr(closing + 1, "<![CDATA[");
      child_start   = strchr(closing + 1, '<');
      closing_start = strstr(closing + 1, closing_tag);

      if (!closing_start)
      {
         free(closing_tag);
         goto error;
      }

      if (cdata_start && range_is_space(closing + 1, cdata_start)) // CDATA section
      {
         const char *cdata_end = strstr(cdata_start, "]]>");
         if (!cdata_end)
         {
            free(closing_tag);
            goto error;
         }

         node->data = strdup_range(cdata_start + strlen("<![CDATA["), cdata_end);
      }
      else if (closing_start && closing_start == child_start) // Simple Data
         node->data = strdup_range(closing + 1, closing_start);
      else // Parse all child nodes.
      {
         struct rxml_node *list = NULL;
         struct rxml_node *tail = NULL;

         const char *ptr = child_start;

         const char *first_start   = strchr(ptr, '<');
         const char *first_closing = strstr(ptr, "</");
         while (first_start && first_closing && first_start < first_closing)
         {
            struct rxml_node *new_node = rxml_parse_node(&ptr);
            if (!new_node)
            {
               free(closing_tag);
               goto error;
            }

            if (tail)
            {
               tail->next = new_node;
               tail = new_node;
            }
            else
               list = tail = new_node;

            first_start   = strchr(ptr, '<');
            first_closing = strstr(ptr, "</");
         }

         node->children = list;

         closing_start = strstr(ptr, closing_tag);
         if (!closing_start)
         {
            free(closing_tag);
            goto error;
         }
      }

      *ptr_ = closing_start + strlen(closing_tag);
      free(closing_tag);
   }
   else
      *ptr_ = closing + 1;

   free(str);
   return node;

error:
   free(str);
   rxml_free_node(node);
   return NULL;
}