⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sflxmll.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  ----------------------------------------------------------------<Prolog>-
    Name:       sflxmll.c
    Title:      XML serialisation functions
    Package:    Standard Function Library (SFL)

    Written:    1996/06/08  iMatix SFL project team <sfl@imatix.com>
    Revised:    2000/02/02

    Synopsis:   Loads XML file into memory, to/from disk files.

    Copyright:  Copyright (c) 1991-2000 iMatix Corporation
    License:    This is free software; you can redistribute it and/or modify
                it under the terms of the SFL License Agreement as provided
                in the file LICENSE.TXT.  This software is distributed in
                the hope that it will be useful, but without any warranty.
 ------------------------------------------------------------------</Prolog>-*/

#include "prelude.h"                    /*  Universal include file           */
#include "sfldate.h"                    /*  Date and time functions          */
#include "sflfile.h"                    /*  File access functions            */
#include "sfllist.h"                    /*  List access functions            */
#include "sflmem.h"                     /*  Memory allocation functions      */
#include "sflstr.h"                     /*  String access functions          */
#include "sflxml.h"                     /*  XML definitions                  */
#include "sflsymb.h"
#include "sflhttp.h"                    /*  Meta-char encoding/decoding      */
#include "sflxmll.h"                    /*  Include prototype data           */
#include "sflxmll.d"                    /*  Include dialog data              */

/*  Function prototypes                                                      */

static int       xml_save_file_item      (FILE *xmlfile, XML_ITEM *item,
                                          int generation);
static void      xml_save_string_item    (char *xml_string, XML_ITEM *item);
static size_t    xml_item_size           (XML_ITEM *item);
static void      init_charmaps           (void);
static void      build_charmap           (byte flag, char *chars);
static int       xml_start_dialog        (void);
static void      expect_token            (char expect);
static char      get_next_char           (void);
static char      get_next_non_white_char (void);
static int       collect_name            (void);
static char     *collect_literal         (char terminator);
static void      error_exception         (char *format, ...);


/*- Global variables used in this source file only --------------------------*/

static int
    feedback,                           /*  Feedback for calling program     */
    char_nbr,                           /*  Current read position in line    */
    line_nbr,                           /*  Input line nbr from file         */
    generation;                         /*  How many levels of children      */

static const char
    *ppath,                             /*  XML file path as specified       */
    *pname;                             /*  XML file name as specified       */

static char
    *fname,                             /*  Full file name of XML file       */
    *literal,                           /*  String of any length             */
    *xmltext,                           /*  Pointer to XML string            */
    *xmlline,                           /*  Current line w/space for EOL     */
    token         [LINE_MAX + 1],       /*  Token from input stream          */
    name          [LINE_MAX + 1],       /*  Saved name                       */
    error_message [LINE_MAX + 1];       /*  Saved name                       */

static FILE
    *xmlfile;

static XML_ITEM
    *item,                              /*  Current XML item                 */
    *top_item,                          /*  Current top-level XML item       */
    *root;                              /*  Root XML item                    */

static Bool
    extended;                           /*  Extended or normal load?         */


/*  Character classification tables and macros                               */

static byte
    cmap [256];                         /*  Character classification tables  */

#define CMAP_NAME        1              /*  Normal name character            */
#define CMAP_NAME_OPEN   2              /*  Valid character to start name    */
#define CMAP_QUOTE       4              /*  Possible string delimiters       */
#define CMAP_PRINTABLE   8              /*  Valid characters in literal      */
#define CMAP_DECIMAL    16              /*  Decimal digits                   */
#define CMAP_HEX        32              /*  Hexadecimal digits               */

                                        /*  Macros for character mapping:    */
#define is_name(ch)      (cmap [(byte) (ch)] & CMAP_NAME)
#define is_name_open(ch) (cmap [(byte) (ch)] & CMAP_NAME_OPEN)
#define is_quote(ch)     (cmap [(byte) (ch)] & CMAP_QUOTE)
#define is_printable(ch) (cmap [(byte) (ch)] & CMAP_PRINTABLE)
#define is_decimal(ch)   (cmap [(byte) (ch)] & CMAP_DECIMAL)
#define is_hex(ch)       (cmap [(byte) (ch)] & CMAP_HEX)


/*  ---------------------------------------------------------------------[<]-
    Function: xml_save_file

    Synopsis: Saves an XML tree to the specified file.  Returns XML_NOERROR
    or XML_FILEERROR.
    ---------------------------------------------------------------------[>]-*/

int
xml_save_file (
    XML_ITEM   *item,
    const char *filename)
{
    FILE
        *xmlfile;                       /*  XML output stream                */
    int
        count;                          /*  How many symbols did we save?    */

    ASSERT (item);
    ASSERT (filename);
    init_charmaps ();                   /*  Initialise character maps        */

    if ((xmlfile = file_open (filename, 'w')) == NULL)
        return XML_FILEERROR;           /*  No permission to write file      */

    /*  Write XML file header                                                */
    fprintf (xmlfile, "<?xml version=\"1.0\"?>\n");

    /*  Output XML root                                                      */
    count = xml_save_file_item (xmlfile, item, 0);

    /*  Output a final carriage return  */
    fprintf (xmlfile, "\n");

    file_close (xmlfile);
    return XML_NOERROR;
}


/*  -------------------------------------------------------------------------
 *  init_charmaps
 *
 *  Initialise character map bit tables.  These are used to speed-up
 *  token recognition and collection.
 */

static void
init_charmaps (void)
{
    memset (cmap, 0, sizeof (cmap));    /*  Clear all bitmaps                */

    /*  Name     ::= (Letter | '_' | ':') (NameChar)*                        */
    /*  NameChar ::= Letter | Digit | MiscName                               */

    /*  Map fixed character sets to various bitmaps                          */
    build_charmap (CMAP_NAME, "abcdefghijklmnopqrstuvwxyz");
    build_charmap (CMAP_NAME, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    build_charmap (CMAP_NAME, "0123456789");
    build_charmap (CMAP_NAME, "_:.-");

    build_charmap (CMAP_NAME_OPEN, "abcdefghijklmnopqrstuvwxyz");
    build_charmap (CMAP_NAME_OPEN, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    build_charmap (CMAP_NAME_OPEN, "_:");

    build_charmap (CMAP_QUOTE, "\"'");

    /*  Printable characters.  ???                                           */
    build_charmap (CMAP_PRINTABLE, "abcdefghijklmnopqrstuvwxyz");
    build_charmap (CMAP_PRINTABLE, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    build_charmap (CMAP_PRINTABLE, "0123456789");
    build_charmap (CMAP_PRINTABLE, "!@#$%^&*()-_=+[]{}\\|;:'\"<>,./?`~ ");

    build_charmap (CMAP_DECIMAL, "0123456789");

    build_charmap (CMAP_HEX, "abcdefghijklmnopqrstuvwxyz");
    build_charmap (CMAP_HEX, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    build_charmap (CMAP_HEX, "0123456789");
}


/*  -------------------------------------------------------------------------
 *  build_charmap
 *
 *  Encode character string and flag into character map table.  Flag should
 *  be a 1-bit value from 1 to 128 (character map is 8 bits wide).
 */

static void
build_charmap (byte flag, char *string)
{
    for (; *string; string++)
        cmap [(byte) *string] |= flag;
}


static int
xml_save_file_item (FILE *xmlfile, XML_ITEM *item, int generation)
{
    int
        count = 1;                      /*  Count 1 for current item         */
    XML_ITEM
        *child,
        *sibling;
    XML_ATTR
        *attr;
    char
        *item_name,
        *attr_name,
        *ptr;
    Bool
        pretty;

    /*  First output item name and attributes                                */
    item_name  = xml_item_name  (item);
    if (item_name)
      {
        fprintf (xmlfile, "<%s", item_name);
        FORATTRIBUTES (attr, item)
          {
            attr_name  = xml_attr_name  (attr);
            ptr        = xml_attr_value (attr);
            http_encode_meta (token, &ptr, LINE_MAX, FALSE);
            fprintf (xmlfile, "\n%*s%s = \"%s", (generation + 1) * 4, "",
                                              attr_name, token);
            while (*ptr)
              {
                http_encode_meta (token, &ptr, LINE_MAX, FALSE);
                fprintf (xmlfile, "\n%s", token);
              }
            fprintf (xmlfile, "\"");
          }

        /*  If value or children exist, use long form, otherwise short form  */
        if ((child = xml_first_child (item)))
          {
            fprintf (xmlfile, ">");

            pretty = TRUE;
            for (sibling = child ;
                 sibling != NULL ;
                 sibling = xml_next_sibling (sibling))
                if (! xml_item_name (sibling))
                    pretty = FALSE;
                else
                    break;

            for ( ; child != NULL; child  = xml_next_sibling (child))
              {
                if (pretty)
                    fprintf (xmlfile, "\n%*s", (generation + 1) * 4, "");

                count += xml_save_file_item (xmlfile, child,
                                             generation + 1);

                if (xml_item_name (child))
                  {
                    pretty = TRUE;
                    for (sibling = xml_next_sibling (child) ;
                         sibling != NULL ;
                         sibling = xml_next_sibling (sibling))
                        if (! xml_item_name (sibling))
                            pretty = FALSE;
                        else
                            break;
                  }
              }
            
            if (pretty)
                fprintf (xmlfile, "\n%*s", generation * 4, "");

            fprintf (xmlfile, "</%s>", item_name);
          }
        else
            fprintf (xmlfile, "/>");
      }
    else            /*  Not name => this is a value node  */
      {
        ptr = xml_item_value (item);
        if (ptr)
            while (*ptr)
              {
                http_encode_meta (token, &ptr, LINE_MAX, FALSE);
                fprintf (xmlfile, "%s", token);
              }
      }
    return (count);
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_save_string

    Synopsis: Saves an XML tree to a string.  Returns a freshly-allocated
    string containing the XML tree, or NULL if there was insufficient memory
    to allocate a new string.
    ---------------------------------------------------------------------[>]-*/

char *
xml_save_string (
    XML_ITEM *item)
{
    size_t
        xml_size;
    char
        *xml_string;
        
    ASSERT (item);
    init_charmaps ();                   /*  Initialise character maps        */
    xml_size = xml_item_size (item);
    xml_string = mem_alloc (xml_size + 1000);
    if (xml_string)
        xml_save_string_item (xml_string, item);

    return (xml_string);
}


/*  Return string size of XML item and all its children                      */

static size_t
xml_item_size (XML_ITEM *item)
{
    size_t
        item_size = 0;
    XML_ITEM
        *child = NULL;
    XML_ATTR
        *attr;
    char
        *item_name,
        *attr_name,
        *ptr;

    /*  First output item name and attributes                                */
    item_name = xml_item_name (item);
    if (item_name)
      {
        /*  Count '<name'                                                    */
        item_size += strlen (item_name) + 1;
        FORATTRIBUTES (attr, item)
          {
            attr_name  = xml_attr_name  (attr);
            ptr        = xml_attr_value (attr);
            /*  Count ' name="value"'                                        */
            item_size += strlen (attr_name) + 4;
            while (*ptr)
              {
                http_encode_meta (token, &ptr, LINE_MAX, FALSE);
                item_size += strlen (token);
              }
          }
        /*  If value or children exist, use long form, otherwise short form  */
        if ((child = xml_first_child (item)))
          {
            /*  Count '>' and '</name>'                                      */
            item_size += strlen (name) + 4;
            for (child  = xml_first_child (item);
                 child != NULL;
                 child  = xml_next_sibling (child))
                item_size += xml_item_size (child);
          }
        else
            /*  Count '/>'                                                   */
            item_size += 2;
      }
    else            /*  No name => this is a value node                      */
      {
        ptr = xml_item_value (item);
        while (*ptr)
          {
            http_encode_meta (token, &ptr, LINE_MAX, FALSE);
            item_size += strlen (token);
          }
      }
    return (item_size);
}


static void
xml_save_string_item (char *xml_string, XML_ITEM *item)
{
    XML_ITEM
        *child = NULL;
    XML_ATTR
        *attr;
    char
        *item_name,
        *attr_name,
        *ptr;

    /*  First output item name and attributes                                */
    xml_string [0] = 0;
    item_name = xml_item_name (item);
    if (item_name)
      {
        xstrcat (xml_string, "<", item_name, NULL);
        FORATTRIBUTES (attr, item)
          {
            attr_name  = xml_attr_name  (attr);
            ptr        = xml_attr_value (attr);
            xstrcat (xml_string, " ", attr_name, "=\"", NULL);
            while (*ptr)
              {
                http_encode_meta (token, &ptr, LINE_MAX, FALSE);
                strcat (xml_string, token);
              }
            strcat (xml_string, "\"");
          }

        /*  If value or children exist, use long form, otherwise short form  */
        if ((child = xml_first_child (item)))
          {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -