Logo Search packages:      
Sourcecode: uget version File versions  Download package

ug_markup.c

/*
 *
 *   Copyright (C) 2005-2009 by Raymond Huang
 *   plushuang at users.sourceforge.net
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU Lesser General Public License in all respects
 *  for all of the code used other than OpenSSL.  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so.  If you
 *  do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#include <string.h>

#include <ug_stdio.h>
#include <ug_markup.h>


static void ug_markup_skip_start_element (GMarkupParseContext*    context,
                                          const gchar*      element_name,
                                          const gchar**     attr_names,
                                          const gchar**     attr_values,
                                          gpointer          data,
                                          GError**          error);
static void ug_markup_skip_end_element (GMarkupParseContext*      context,
                                        const gchar*  element_name,
                                        gpointer            data,
                                        GError**            error);

GMarkupParser     ug_markup_skip_parser =
{
      ug_markup_skip_start_element, ug_markup_skip_end_element,
      NULL, NULL, NULL
};

UgMarkup*   ug_markup_new ()
{
      UgMarkup*   markup;

      markup = g_malloc0 (sizeof (UgMarkup));
      return markup;
}

void  ug_markup_free (UgMarkup* markup)
{
      if (markup->file)
            fclose (markup->file);

      g_free (markup);
}

// ----------------------------------------------
// input
gboolean ug_markup_input (const gchar* filename, const GMarkupParser* parser, gpointer data)
{
      GMarkupParseContext*    context;
      gchar*            buffer;
      gint        fd;
      gint        size;
      gboolean    result = FALSE;

//    fd = open (filename, O_RDONLY | O_TEXT, S_IREAD);
      fd = ug_fd_open (filename, UG_FD_O_READONLY | UG_FD_O_TEXT, UG_FD_S_IREAD);
      if (fd == -1)
            return FALSE;

      buffer = g_malloc (4096);
      context = g_markup_parse_context_new (parser, 0, data, NULL);

      do {
//          size = read (fd, buffer, 4096);
            size = ug_fd_read (fd, buffer, 4096);
            if (size > 0)
                  result = g_markup_parse_context_parse (context, buffer, size, NULL);
      } while (size > 0 && result);

      result = g_markup_parse_context_end_parse (context, NULL);
      g_markup_parse_context_free (context);
      g_free (buffer);

//    close (fd);
      ug_fd_close (fd);

      return result;
}

// ----------------------------------------------
// output
static gboolean  ug_markup_close_element (UgMarkup* markup, gboolean element_end);

gboolean ug_markup_output_start  (UgMarkup* markup, const gchar* filename, gboolean formating)
{
      markup->output_state = UG_MARKUP_ELEMENT_END;
      markup->formating = TRUE;

      markup->file = ug_fopen (filename, "w");
      if (markup->file) {
            fputs ("<?xml version='1.0' encoding='UTF-8'?>\n", markup->file);
            return TRUE;
      }
      return FALSE;
}

void ug_markup_output_end (UgMarkup* markup)
{
      if (markup->file) {
            fputc ('\n', markup->file);
            fclose (markup->file);
            markup->file = NULL;
      }
}

void ug_markup_output_element_start (UgMarkup* markup, const gchar* printf_format, ...)
{
      FILE*       file = markup->file;
      char*       esc_text;
      va_list           arg_list;

      ug_markup_close_element (markup, FALSE);

      if (markup->formating) {
          if (markup->level > 0)
                  fprintf (file, "\n%*c", markup->level, ' ');
            markup->level++;
      }
      fputc ('<', file);

      va_start (arg_list, printf_format);
      esc_text = g_markup_vprintf_escaped (printf_format, arg_list);
      va_end (arg_list);

      fputs (esc_text, file);
      g_free (esc_text);

      markup->output_state = UG_MARKUP_ELEMENT_START;
}

void ug_markup_output_element_end   (UgMarkup* markup, const gchar* element_name)
{
      FILE*       file = markup->file;
      gboolean    element_end;

      element_end = ug_markup_close_element (markup, TRUE);

      if (markup->formating) {
            markup->level--;
            if (markup->output_state != UG_MARKUP_ELEMENT_TEXT && element_end == FALSE) {
                  fputc ('\n', file);
                  if (markup->level > 0)
                        fprintf (file, "%*c", markup->level, ' ');
            }
      }

      if (element_end == FALSE)
            fprintf (file, "</%s>", element_name);

      markup->output_state = UG_MARKUP_ELEMENT_END;
}

void ug_markup_output_text (UgMarkup* markup, const gchar* text, gint len)
{
      char* esc_text;

      if (text) {
            if (len == -1)
                  len = strlen (text);
            if (len == 0)
                  return;

            ug_markup_close_element (markup, FALSE);

            esc_text = g_markup_escape_text (text, len);
            fputs (esc_text, markup->file);
            markup->output_state = UG_MARKUP_ELEMENT_TEXT;
            g_free (esc_text);
      }
}

static gboolean  ug_markup_close_element (UgMarkup* markup, gboolean element_end)
{
    char*   string;

      if (markup->output_state == UG_MARKUP_ELEMENT_START) {
//          markup->output_state = UG_MARKUP_ELEMENT_END;
            string = (element_end) ? "/>" : ">";
            fputs (string, markup->file);
            return TRUE;
      }

      return FALSE;
}

// ----------------------------------------------
// ug_markup_skip_parser
static guint      ug_markup_skip_count = 0;

static void ug_markup_skip_start_element (GMarkupParseContext*    context,
                                          const gchar*      element_name,
                                          const gchar**     attr_names,
                                          const gchar**     attr_values,
                                          gpointer          data,
                                          GError**          error)
{
      guint limit = GPOINTER_TO_INT (data);

      ug_markup_skip_count++;

      if (ug_markup_skip_count > limit) {
            ug_markup_skip_count = 0;
            g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, "Unknow element");
      }
}

static void ug_markup_skip_end_element (GMarkupParseContext*      context,
                                        const gchar*  element_name,
                                        gpointer            data,
                                        GError**            error)
{
      if (ug_markup_skip_count > 0)
            ug_markup_skip_count--;
      else
            g_markup_parse_context_pop (context);
}


Generated by  Doxygen 1.6.0   Back to index