Changeset 1559 for trunk/src


Ignore:
Timestamp:
Jul 30, 2009 4:13:32 PM (15 years ago)
Author:
gah
Message:

fix for scew character data handler and entityref::decode/encode bottlenecks

Location:
trunk/src/core
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/RpEntityRef.cc

    r1366 r1559  
    11/*
     2 * ======================================================================
     3 *  AUTHOR:  Derrick Kearney, Purdue University
     4 *  Copyright (c) 2004-2006  Purdue Research Foundation
     5 *
     6 *  See the file "license.terms" for information on usage and
     7 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
     8 *
     9 *  Also see below text for additional information on usage and redistribution
     10 *
     11 * ======================================================================
    212 * ----------------------------------------------------------------------
    313 *  Rappture Library Entity Reference Translation Header
     
    1323 *        &lt;           "<"
    1424 *        &gt;           ">"
    15  *        &nbsp;         " "
     25 *        &quot          "\""
     26 *        &apos          "'"
    1627 *
    17  *
    18  * ======================================================================
    19  *  AUTHOR:  Derrick Kearney, Purdue University
    20  *  Copyright (c) 2004-2006  Purdue Research Foundation
    21  *
    22  *  See the file "license.terms" for information on usage and
    23  *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    24  *
    25  *  Also see below text for additional information on usage and redistribution
    26  *
    27  * ======================================================================
    2828 */
    2929
     
    3232#include <cstring>
    3333
    34 #ifdef __cplusplus
    35     extern "C" {
    36 #endif // ifdef __cplusplus
    37 
    3834using namespace Rappture;
    3935
     36typedef struct {
     37    const char *replacement;            /* Replacement string. */
     38    size_t length;                      /* Length of replacement string,
     39                                         * including the ampersand. */
     40    const char *entity;                 /* Single character entity. */
     41} PredefEntityRef;
     42
     43static PredefEntityRef predef[] = {
     44    { "&quot",  5,  "\"" },
     45    { "&amp",   4,  "&"  },
     46    { "&lt",    3,  "<"  },
     47    { "&gt",    3,  ">"  },
     48    { "&apos",  5,  "'"  }
     49};
     50static int nPredefs = sizeof(predef) / sizeof (PredefEntityRef);
     51
     52/*
     53 * EntityRef::decode --
     54 *
     55 *      Convert XML character data into the original text.  The trick
     56 *      here determine the runs of characters that do not require
     57 *      replacements and to append the substring in one shot. 
     58 */
    4059const char*
    41 EntityRef::decode (const char* value, unsigned int len)
     60EntityRef::decode (const char* string, unsigned int len)
    4261{
    43     unsigned int pos = 0;
    44 
    45     if (value == NULL) {
    46         // empty string, noting to do
     62    if (string == NULL) {
     63        // Don't do anything with NULL strings.
    4764        return NULL;
    4865    }
    49 
    5066    _bout.clear();
    5167    if (len == 0) {
    52         len = strlen(value);
     68        len = strlen(string);
    5369    }
    54 
    55     while (pos < len) {
    56         if (value[pos] == '&') {
    57             pos++;
    58             if ((pos < len)) {
    59                 if (value[pos] && isalpha(value[pos])) {
    60                     if (        (value[pos] == 'q')
    61                             &&  (strncmp("quot;",value+pos,5) == 0) ) {
    62                         _bout.append("\"");
    63                         pos += 5;
    64                     }
    65                     else if (   (value[pos] == 'a')
    66                             &&  (strncmp("amp;",value+pos,4) == 0) ) {
    67                         _bout.append("&");
    68                         pos += 4;
    69                     }
    70                     else if (   (value[pos] == 'l')
    71                             &&  (strncmp("lt;",value+pos,3) == 0) ) {
    72                         _bout.append("<");
    73                         pos += 3;
    74                     }
    75                     else if (   (value[pos] == 'g')
    76                             &&  (strncmp("gt;",value+pos,3) == 0) ) {
    77                         _bout.append(">");
    78                         pos += 3;
    79                     }
    80                     else {
    81                         // unrecognized
    82                         _bout.append(value+pos,1);
    83                         pos++;
    84                     }
    85                 }
    86                 else {
    87                     _bout.append(value+pos,1);
    88                     pos++;
    89                 }
    90             }
    91             else {
    92                 // last character was really an ampersand
    93                 // add it to the buffer
    94                 pos--;
    95                 _bout.append(value+pos,1);
    96                 pos++;
    97             }
    98         }
    99         else
    100         {
    101             // non entity ref character
    102             _bout.append(value+pos,1);
    103             pos++;
    104         }
     70    const char *p, *start, *pend;
     71    start = string;                     /* Mark the start of a run of
     72                                         * characters that contain no
     73                                         * replacements. */
     74    for (p = string, pend = p + len; p < pend; /*empty*/) {
     75        if (*p == '&') {
     76            PredefEntityRef *ep, *epend;
     77            for (ep = predef, epend = ep + nPredefs; ep < epend; ep++) {
     78                size_t length;
     79                length = pend - p;      /* Get the # bytes left. */
     80                if ((length >= ep->length) && (ep->replacement[1] == *(p+1)) &&
     81                    (strncmp(ep->replacement, p, ep->length) == 0)) {
     82                    /* Found entity replacement. Append any preceding
     83                     * characters into the buffer before the entity itself. */
     84                    if (p > start) {
     85                        _bout.append(start, p - start);
     86                        start = p + ep->length;
     87                    }
     88                    _bout.append(ep->entity, 1);
     89                    p += ep->length;
     90                    goto next;
     91                }
     92            }
     93        }
     94        p++;
     95    next:
     96        ;
    10597    }
    106 
    107     _bout.append("\0",1);
     98    if (p > start) {
     99        /* Append any left over characters into the buffer. */
     100        _bout.append(start, p - start);
     101    }
     102    _bout.append("\0", 1);
    108103    return _bout.bytes();
    109104}
    110105
    111106const char*
    112 EntityRef::encode (
    113     const char* value,
    114     unsigned int len
    115 )
     107EntityRef::encode (const char* string, unsigned int len)
    116108{
    117109    unsigned int pos = 0;
    118110
    119 
    120     if (value == NULL) {
    121         // empty string, noting to do
     111    if (string == NULL) {
     112        // Don't do anything with NULL strings.
    122113        return NULL;
    123114    }
    124 
    125115    _bout.clear();
    126116    if (len == 0) {
    127         len = strlen(value);
     117        len = strlen(string);
    128118    }
    129 
    130     while (pos < len) {
    131         if (*(value+pos) == '"') {
    132             _bout.append("&quot;");
    133         }
    134         else if (*(value+pos) == '&') {
    135             _bout.append("&amp;");
    136         }
    137         else if (*(value+pos) == '<') {
    138             _bout.append("&lt;");
    139         }
    140         else if (*(value+pos) == '>') {
    141             _bout.append("&gt;");
    142         }
    143         /*
    144         else if (*(value+pos) == '\n') {
    145             _bout.append("&#xA;");
    146         }
    147         */
    148         else
    149         {
    150             _bout.append(value+pos,1);
    151         }
    152         pos++;
     119    const char *p, *start, *pend;
     120    start = string;                     /* Mark the start of a run of
     121                                         * characters that contain no
     122                                         * replacements. */
     123    for (p = string, pend = p + len; p < pend; p++) {
     124        PredefEntityRef *ep, *epend;
     125        for (ep = predef, epend = ep + nPredefs; ep < epend; ep++) {
     126            if (ep->entity[0] == *p) {
     127                /* Found entity requiring replacement. Append any preceding
     128                 * characters into the buffer before the entity itself. */
     129                if (p > start) {
     130                    _bout.append(start, p - start);
     131                    start = p + 1;
     132                }
     133                _bout.append(ep->replacement, ep->length);
     134                break;
     135            }
     136        }
    153137    }
    154 
    155     _bout.append("\0",1);
     138    if (p > start) {
     139        /* Append any left over characters into the buffer. */
     140        _bout.append(start, p - start);
     141    }
     142    _bout.append("\0", 1);
    156143    return _bout.bytes();
    157144}
     
    163150
    164151
    165 #ifdef __cplusplus
    166     } // extern c
    167 #endif // ifdef __cplusplus
  • trunk/src/core/scew/xelement.h

    r1018 r1559  
    4343    XML_Char* name;
    4444    XML_Char* contents;
     45    size_t used;                        /* # bytes used for contents. */
     46    size_t allocated;                   /* # bytes allocated for contents */
    4547    attribute_list* attributes;
    4648
  • trunk/src/core/scew/xhandler.c

    r1018 r1559  
    149149char_handler(void* data, XML_Char const* s, int len)
    150150{
    151     int total = 0;
    152     int total_old = 0;
    153     scew_element* current = NULL;
    154     scew_parser* parser = (scew_parser*) data;
    155 
    156     if (parser == NULL)
    157     {
    158         return;
    159     }
    160 
    161     current = parser->current;
    162 
    163     if (current == NULL)
    164     {
    165         return;
    166     }
    167 
    168     if (current->contents != NULL)
    169     {
    170         total_old = scew_strlen(current->contents);
    171     }
    172     total = (total_old + len + 1) * sizeof(XML_Char);
    173     current->contents = (XML_Char*) realloc(current->contents, total);
    174 
    175     if (total_old == 0)
    176     {
    177         current->contents[0] = '\0';
    178     }
    179 
    180     scew_strncat(current->contents, s, len);
    181 }
     151    size_t need;
     152    scew_element* elemPtr;
     153    scew_parser* parser = (scew_parser*) data;
     154
     155    if (parser == NULL) {
     156        return;
     157    }
     158
     159    elemPtr = parser->current;
     160    if (elemPtr == NULL) {
     161        return;
     162    }
     163    if (len == 0) {
     164        return;
     165    }
     166    need = elemPtr->used + len;
     167#ifdef notdef
     168    fprintf(stderr, "char handler %x allocated=%d used=%d, len=%d need=%d\n",
     169            elemPtr->contents, elemPtr->allocated, elemPtr->used, len, need);
     170#endif
     171    if (need > elemPtr->allocated) {
     172        XML_Char *bytes;
     173        size_t size;
     174
     175        if (elemPtr->allocated == 0) {
     176            size = len;                 /* Start with given size. */
     177        } else {
     178            size = elemPtr->allocated;
     179            while (size < need) {
     180                size += size;           /* Double the current size. */
     181            }
     182        }
     183#ifdef notdef
     184        fprintf(stderr, "trying to allocate %d bytes for character data\n",
     185                    size);
     186#endif
     187        /* Always allocate an extra byte for the NUL, but don't include it in
     188         * the allocated or used totals. */
     189        if (elemPtr->contents == NULL) {
     190            bytes = malloc(size + 1);
     191        } else {
     192            bytes = realloc(elemPtr->contents, size + 1);
     193        }
     194        if (bytes == NULL) {
     195            fprintf(stderr, "can't allocated %d bytes for character data\n",
     196                    size);
     197            return;
     198        }
     199        elemPtr->contents = bytes;
     200        elemPtr->allocated = size;
     201    }
     202    strncpy(elemPtr->contents + elemPtr->used, s, len);
     203    elemPtr->used += len;
     204    elemPtr->contents[elemPtr->used] = '\0';
     205}
Note: See TracChangeset for help on using the changeset viewer.