Blame xmlstring.c

Packit 423ecb
/*
Packit 423ecb
 * string.c : an XML string utilities module
Packit 423ecb
 *
Packit 423ecb
 * This module provides various utility functions for manipulating
Packit 423ecb
 * the xmlChar* type. All functions named xmlStr* have been moved here
Packit 423ecb
 * from the parser.c file (their original home).
Packit 423ecb
 *
Packit 423ecb
 * See Copyright for the status of this software.
Packit 423ecb
 *
Packit 423ecb
 * UTF8 string routines from:
Packit 423ecb
 * William Brack <wbrack@mmm.com.hk>
Packit 423ecb
 *
Packit 423ecb
 * daniel@veillard.com
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
#define IN_LIBXML
Packit 423ecb
#include "libxml.h"
Packit 423ecb
Packit 423ecb
#include <stdlib.h>
Packit 423ecb
#include <string.h>
Packit 423ecb
#include <libxml/xmlmemory.h>
Packit 423ecb
#include <libxml/parserInternals.h>
Packit 423ecb
#include <libxml/xmlstring.h>
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *                                                                      *
Packit 423ecb
 *                Commodity functions to handle xmlChars                *
Packit 423ecb
 *                                                                      *
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrndup:
Packit 423ecb
 * @cur:  the input xmlChar *
Packit 423ecb
 * @len:  the len of @cur
Packit 423ecb
 *
Packit 423ecb
 * a strndup for array of xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns a new xmlChar * or NULL
Packit 423ecb
 */
Packit 423ecb
xmlChar *
Packit 423ecb
xmlStrndup(const xmlChar *cur, int len) {
Packit 423ecb
    xmlChar *ret;
Packit 423ecb
Packit 423ecb
    if ((cur == NULL) || (len < 0)) return(NULL);
Packit 423ecb
    ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
        xmlErrMemory(NULL, NULL);
Packit 423ecb
        return(NULL);
Packit 423ecb
    }
Packit 423ecb
    memcpy(ret, cur, len * sizeof(xmlChar));
Packit 423ecb
    ret[len] = 0;
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrdup:
Packit 423ecb
 * @cur:  the input xmlChar *
Packit 423ecb
 *
Packit 423ecb
 * a strdup for array of xmlChar's. Since they are supposed to be
Packit 423ecb
 * encoded in UTF-8 or an encoding with 8bit based chars, we assume
Packit 423ecb
 * a termination mark of '0'.
Packit 423ecb
 *
Packit 423ecb
 * Returns a new xmlChar * or NULL
Packit 423ecb
 */
Packit 423ecb
xmlChar *
Packit 423ecb
xmlStrdup(const xmlChar *cur) {
Packit 423ecb
    const xmlChar *p = cur;
Packit 423ecb
Packit 423ecb
    if (cur == NULL) return(NULL);
Packit 423ecb
    while (*p != 0) p++; /* non input consuming */
Packit 423ecb
    return(xmlStrndup(cur, p - cur));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlCharStrndup:
Packit 423ecb
 * @cur:  the input char *
Packit 423ecb
 * @len:  the len of @cur
Packit 423ecb
 *
Packit 423ecb
 * a strndup for char's to xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns a new xmlChar * or NULL
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
xmlChar *
Packit 423ecb
xmlCharStrndup(const char *cur, int len) {
Packit 423ecb
    int i;
Packit 423ecb
    xmlChar *ret;
Packit 423ecb
Packit 423ecb
    if ((cur == NULL) || (len < 0)) return(NULL);
Packit 423ecb
    ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
        xmlErrMemory(NULL, NULL);
Packit 423ecb
        return(NULL);
Packit 423ecb
    }
Packit 423ecb
    for (i = 0;i < len;i++) {
Packit 423ecb
        ret[i] = (xmlChar) cur[i];
Packit 423ecb
        if (ret[i] == 0) return(ret);
Packit 423ecb
    }
Packit 423ecb
    ret[len] = 0;
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlCharStrdup:
Packit 423ecb
 * @cur:  the input char *
Packit 423ecb
 *
Packit 423ecb
 * a strdup for char's to xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns a new xmlChar * or NULL
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
xmlChar *
Packit 423ecb
xmlCharStrdup(const char *cur) {
Packit 423ecb
    const char *p = cur;
Packit 423ecb
Packit 423ecb
    if (cur == NULL) return(NULL);
Packit 423ecb
    while (*p != '\0') p++; /* non input consuming */
Packit 423ecb
    return(xmlCharStrndup(cur, p - cur));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrcmp:
Packit 423ecb
 * @str1:  the first xmlChar *
Packit 423ecb
 * @str2:  the second xmlChar *
Packit 423ecb
 *
Packit 423ecb
 * a strcmp for xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns the integer result of the comparison
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
Packit 423ecb
    register int tmp;
Packit 423ecb
Packit 423ecb
    if (str1 == str2) return(0);
Packit 423ecb
    if (str1 == NULL) return(-1);
Packit 423ecb
    if (str2 == NULL) return(1);
Packit 423ecb
    do {
Packit 423ecb
        tmp = *str1++ - *str2;
Packit 423ecb
        if (tmp != 0) return(tmp);
Packit 423ecb
    } while (*str2++ != 0);
Packit 423ecb
    return 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrEqual:
Packit 423ecb
 * @str1:  the first xmlChar *
Packit 423ecb
 * @str2:  the second xmlChar *
Packit 423ecb
 *
Packit 423ecb
 * Check if both strings are equal of have same content.
Packit 423ecb
 * Should be a bit more readable and faster than xmlStrcmp()
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if they are equal, 0 if they are different
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlStrEqual(const xmlChar *str1, const xmlChar *str2) {
Packit 423ecb
    if (str1 == str2) return(1);
Packit 423ecb
    if (str1 == NULL) return(0);
Packit 423ecb
    if (str2 == NULL) return(0);
Packit 423ecb
    do {
Packit 423ecb
        if (*str1++ != *str2) return(0);
Packit 423ecb
    } while (*str2++);
Packit 423ecb
    return(1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrQEqual:
Packit 423ecb
 * @pref:  the prefix of the QName
Packit 423ecb
 * @name:  the localname of the QName
Packit 423ecb
 * @str:  the second xmlChar *
Packit 423ecb
 *
Packit 423ecb
 * Check if a QName is Equal to a given string
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if they are equal, 0 if they are different
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlStrQEqual(const xmlChar *pref, const xmlChar *name, const xmlChar *str) {
Packit 423ecb
    if (pref == NULL) return(xmlStrEqual(name, str));
Packit 423ecb
    if (name == NULL) return(0);
Packit 423ecb
    if (str == NULL) return(0);
Packit 423ecb
Packit 423ecb
    do {
Packit 423ecb
        if (*pref++ != *str) return(0);
Packit 423ecb
    } while ((*str++) && (*pref));
Packit 423ecb
    if (*str++ != ':') return(0);
Packit 423ecb
    do {
Packit 423ecb
        if (*name++ != *str) return(0);
Packit 423ecb
    } while (*str++);
Packit 423ecb
    return(1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrncmp:
Packit 423ecb
 * @str1:  the first xmlChar *
Packit 423ecb
 * @str2:  the second xmlChar *
Packit 423ecb
 * @len:  the max comparison length
Packit 423ecb
 *
Packit 423ecb
 * a strncmp for xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns the integer result of the comparison
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
Packit 423ecb
    register int tmp;
Packit 423ecb
Packit 423ecb
    if (len <= 0) return(0);
Packit 423ecb
    if (str1 == str2) return(0);
Packit 423ecb
    if (str1 == NULL) return(-1);
Packit 423ecb
    if (str2 == NULL) return(1);
Packit 423ecb
#ifdef __GNUC__
Packit 423ecb
    tmp = strncmp((const char *)str1, (const char *)str2, len);
Packit 423ecb
    return tmp;
Packit 423ecb
#else
Packit 423ecb
    do {
Packit 423ecb
        tmp = *str1++ - *str2;
Packit 423ecb
        if (tmp != 0 || --len == 0) return(tmp);
Packit 423ecb
    } while (*str2++ != 0);
Packit 423ecb
    return 0;
Packit 423ecb
#endif
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static const xmlChar casemap[256] = {
Packit 423ecb
    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
Packit 423ecb
    0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
Packit 423ecb
    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
Packit 423ecb
    0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
Packit 423ecb
    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
Packit 423ecb
    0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
Packit 423ecb
    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
Packit 423ecb
    0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
Packit 423ecb
    0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
Packit 423ecb
    0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
Packit 423ecb
    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
Packit 423ecb
    0x78,0x79,0x7A,0x7B,0x5C,0x5D,0x5E,0x5F,
Packit 423ecb
    0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
Packit 423ecb
    0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
Packit 423ecb
    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
Packit 423ecb
    0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
Packit 423ecb
    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
Packit 423ecb
    0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
Packit 423ecb
    0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
Packit 423ecb
    0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
Packit 423ecb
    0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
Packit 423ecb
    0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
Packit 423ecb
    0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
Packit 423ecb
    0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
Packit 423ecb
    0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
Packit 423ecb
    0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
Packit 423ecb
    0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
Packit 423ecb
    0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
Packit 423ecb
    0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
Packit 423ecb
    0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
Packit 423ecb
    0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
Packit 423ecb
    0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrcasecmp:
Packit 423ecb
 * @str1:  the first xmlChar *
Packit 423ecb
 * @str2:  the second xmlChar *
Packit 423ecb
 *
Packit 423ecb
 * a strcasecmp for xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns the integer result of the comparison
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2) {
Packit 423ecb
    register int tmp;
Packit 423ecb
Packit 423ecb
    if (str1 == str2) return(0);
Packit 423ecb
    if (str1 == NULL) return(-1);
Packit 423ecb
    if (str2 == NULL) return(1);
Packit 423ecb
    do {
Packit 423ecb
        tmp = casemap[*str1++] - casemap[*str2];
Packit 423ecb
        if (tmp != 0) return(tmp);
Packit 423ecb
    } while (*str2++ != 0);
Packit 423ecb
    return 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrncasecmp:
Packit 423ecb
 * @str1:  the first xmlChar *
Packit 423ecb
 * @str2:  the second xmlChar *
Packit 423ecb
 * @len:  the max comparison length
Packit 423ecb
 *
Packit 423ecb
 * a strncasecmp for xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns the integer result of the comparison
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlStrncasecmp(const xmlChar *str1, const xmlChar *str2, int len) {
Packit 423ecb
    register int tmp;
Packit 423ecb
Packit 423ecb
    if (len <= 0) return(0);
Packit 423ecb
    if (str1 == str2) return(0);
Packit 423ecb
    if (str1 == NULL) return(-1);
Packit 423ecb
    if (str2 == NULL) return(1);
Packit 423ecb
    do {
Packit 423ecb
        tmp = casemap[*str1++] - casemap[*str2];
Packit 423ecb
        if (tmp != 0 || --len == 0) return(tmp);
Packit 423ecb
    } while (*str2++ != 0);
Packit 423ecb
    return 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrchr:
Packit 423ecb
 * @str:  the xmlChar * array
Packit 423ecb
 * @val:  the xmlChar to search
Packit 423ecb
 *
Packit 423ecb
 * a strchr for xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlChar * for the first occurrence or NULL.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
const xmlChar *
Packit 423ecb
xmlStrchr(const xmlChar *str, xmlChar val) {
Packit 423ecb
    if (str == NULL) return(NULL);
Packit 423ecb
    while (*str != 0) { /* non input consuming */
Packit 423ecb
        if (*str == val) return((xmlChar *) str);
Packit 423ecb
        str++;
Packit 423ecb
    }
Packit 423ecb
    return(NULL);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrstr:
Packit 423ecb
 * @str:  the xmlChar * array (haystack)
Packit 423ecb
 * @val:  the xmlChar to search (needle)
Packit 423ecb
 *
Packit 423ecb
 * a strstr for xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlChar * for the first occurrence or NULL.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
const xmlChar *
Packit 423ecb
xmlStrstr(const xmlChar *str, const xmlChar *val) {
Packit 423ecb
    int n;
Packit 423ecb
Packit 423ecb
    if (str == NULL) return(NULL);
Packit 423ecb
    if (val == NULL) return(NULL);
Packit 423ecb
    n = xmlStrlen(val);
Packit 423ecb
Packit 423ecb
    if (n == 0) return(str);
Packit 423ecb
    while (*str != 0) { /* non input consuming */
Packit 423ecb
        if (*str == *val) {
Packit 423ecb
            if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
Packit 423ecb
        }
Packit 423ecb
        str++;
Packit 423ecb
    }
Packit 423ecb
    return(NULL);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrcasestr:
Packit 423ecb
 * @str:  the xmlChar * array (haystack)
Packit 423ecb
 * @val:  the xmlChar to search (needle)
Packit 423ecb
 *
Packit 423ecb
 * a case-ignoring strstr for xmlChar's
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlChar * for the first occurrence or NULL.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
const xmlChar *
Packit 423ecb
xmlStrcasestr(const xmlChar *str, const xmlChar *val) {
Packit 423ecb
    int n;
Packit 423ecb
Packit 423ecb
    if (str == NULL) return(NULL);
Packit 423ecb
    if (val == NULL) return(NULL);
Packit 423ecb
    n = xmlStrlen(val);
Packit 423ecb
Packit 423ecb
    if (n == 0) return(str);
Packit 423ecb
    while (*str != 0) { /* non input consuming */
Packit 423ecb
        if (casemap[*str] == casemap[*val])
Packit 423ecb
            if (!xmlStrncasecmp(str, val, n)) return(str);
Packit 423ecb
        str++;
Packit 423ecb
    }
Packit 423ecb
    return(NULL);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrsub:
Packit 423ecb
 * @str:  the xmlChar * array (haystack)
Packit 423ecb
 * @start:  the index of the first char (zero based)
Packit 423ecb
 * @len:  the length of the substring
Packit 423ecb
 *
Packit 423ecb
 * Extract a substring of a given string
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlChar * for the first occurrence or NULL.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
xmlChar *
Packit 423ecb
xmlStrsub(const xmlChar *str, int start, int len) {
Packit 423ecb
    int i;
Packit 423ecb
Packit 423ecb
    if (str == NULL) return(NULL);
Packit 423ecb
    if (start < 0) return(NULL);
Packit 423ecb
    if (len < 0) return(NULL);
Packit 423ecb
Packit 423ecb
    for (i = 0;i < start;i++) {
Packit 423ecb
        if (*str == 0) return(NULL);
Packit 423ecb
        str++;
Packit 423ecb
    }
Packit 423ecb
    if (*str == 0) return(NULL);
Packit 423ecb
    return(xmlStrndup(str, len));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrlen:
Packit 423ecb
 * @str:  the xmlChar * array
Packit 423ecb
 *
Packit 423ecb
 * length of a xmlChar's string
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of xmlChar contained in the ARRAY.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlStrlen(const xmlChar *str) {
Packit 423ecb
    int len = 0;
Packit 423ecb
Packit 423ecb
    if (str == NULL) return(0);
Packit 423ecb
    while (*str != 0) { /* non input consuming */
Packit 423ecb
        str++;
Packit 423ecb
        len++;
Packit 423ecb
    }
Packit 423ecb
    return(len);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrncat:
Packit 423ecb
 * @cur:  the original xmlChar * array
Packit 423ecb
 * @add:  the xmlChar * array added
Packit 423ecb
 * @len:  the length of @add
Packit 423ecb
 *
Packit 423ecb
 * a strncat for array of xmlChar's, it will extend @cur with the len
Packit 423ecb
 * first bytes of @add. Note that if @len < 0 then this is an API error
Packit 423ecb
 * and NULL will be returned.
Packit 423ecb
 *
Packit 423ecb
 * Returns a new xmlChar *, the original @cur is reallocated and should
Packit 423ecb
 * not be freed.
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
xmlChar *
Packit 423ecb
xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
Packit 423ecb
    int size;
Packit 423ecb
    xmlChar *ret;
Packit 423ecb
Packit 423ecb
    if ((add == NULL) || (len == 0))
Packit 423ecb
        return(cur);
Packit 423ecb
    if (len < 0)
Packit 423ecb
	return(NULL);
Packit 423ecb
    if (cur == NULL)
Packit 423ecb
        return(xmlStrndup(add, len));
Packit 423ecb
Packit 423ecb
    size = xmlStrlen(cur);
Packit 423ecb
    if (size < 0)
Packit 423ecb
        return(NULL);
Packit 423ecb
    ret = (xmlChar *) xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
        xmlErrMemory(NULL, NULL);
Packit 423ecb
        return(cur);
Packit 423ecb
    }
Packit 423ecb
    memcpy(&ret[size], add, len * sizeof(xmlChar));
Packit 423ecb
    ret[size + len] = 0;
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrncatNew:
Packit 423ecb
 * @str1:  first xmlChar string
Packit 423ecb
 * @str2:  second xmlChar string
Packit 423ecb
 * @len:  the len of @str2 or < 0
Packit 423ecb
 *
Packit 423ecb
 * same as xmlStrncat, but creates a new string.  The original
Packit 423ecb
 * two strings are not freed. If @len is < 0 then the length
Packit 423ecb
 * will be calculated automatically.
Packit 423ecb
 *
Packit 423ecb
 * Returns a new xmlChar * or NULL
Packit 423ecb
 */
Packit 423ecb
xmlChar *
Packit 423ecb
xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) {
Packit 423ecb
    int size;
Packit 423ecb
    xmlChar *ret;
Packit 423ecb
Packit 423ecb
    if (len < 0) {
Packit 423ecb
        len = xmlStrlen(str2);
Packit 423ecb
        if (len < 0)
Packit 423ecb
            return(NULL);
Packit 423ecb
    }
Packit 423ecb
    if ((str2 == NULL) || (len == 0))
Packit 423ecb
        return(xmlStrdup(str1));
Packit 423ecb
    if (str1 == NULL)
Packit 423ecb
        return(xmlStrndup(str2, len));
Packit 423ecb
Packit 423ecb
    size = xmlStrlen(str1);
Packit 423ecb
    if (size < 0)
Packit 423ecb
        return(NULL);
Packit 423ecb
    ret = (xmlChar *) xmlMalloc((size + len + 1) * sizeof(xmlChar));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
        xmlErrMemory(NULL, NULL);
Packit 423ecb
        return(xmlStrndup(str1, size));
Packit 423ecb
    }
Packit 423ecb
    memcpy(ret, str1, size * sizeof(xmlChar));
Packit 423ecb
    memcpy(&ret[size], str2, len * sizeof(xmlChar));
Packit 423ecb
    ret[size + len] = 0;
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrcat:
Packit 423ecb
 * @cur:  the original xmlChar * array
Packit 423ecb
 * @add:  the xmlChar * array added
Packit 423ecb
 *
Packit 423ecb
 * a strcat for array of xmlChar's. Since they are supposed to be
Packit 423ecb
 * encoded in UTF-8 or an encoding with 8bit based chars, we assume
Packit 423ecb
 * a termination mark of '0'.
Packit 423ecb
 *
Packit 423ecb
 * Returns a new xmlChar * containing the concatenated string. The original
Packit 423ecb
 * @cur is reallocated and should not be freed.
Packit 423ecb
 */
Packit 423ecb
xmlChar *
Packit 423ecb
xmlStrcat(xmlChar *cur, const xmlChar *add) {
Packit 423ecb
    const xmlChar *p = add;
Packit 423ecb
Packit 423ecb
    if (add == NULL) return(cur);
Packit 423ecb
    if (cur == NULL)
Packit 423ecb
        return(xmlStrdup(add));
Packit 423ecb
Packit 423ecb
    while (*p != 0) p++; /* non input consuming */
Packit 423ecb
    return(xmlStrncat(cur, add, p - add));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrPrintf:
Packit 423ecb
 * @buf:   the result buffer.
Packit 423ecb
 * @len:   the result buffer length.
Packit 423ecb
 * @msg:   the message with printf formatting.
Packit 423ecb
 * @...:   extra parameters for the message.
Packit 423ecb
 *
Packit 423ecb
 * Formats @msg and places result into @buf.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of characters written to @buf or -1 if an error occurs.
Packit 423ecb
 */
Packit 423ecb
int XMLCDECL
Packit 423ecb
xmlStrPrintf(xmlChar *buf, int len, const char *msg, ...) {
Packit 423ecb
    va_list args;
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    if((buf == NULL) || (msg == NULL)) {
Packit 423ecb
        return(-1);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    va_start(args, msg);
Packit 423ecb
    ret = vsnprintf((char *) buf, len, (const char *) msg, args);
Packit 423ecb
    va_end(args);
Packit 423ecb
    buf[len - 1] = 0; /* be safe ! */
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlStrVPrintf:
Packit 423ecb
 * @buf:   the result buffer.
Packit 423ecb
 * @len:   the result buffer length.
Packit 423ecb
 * @msg:   the message with printf formatting.
Packit 423ecb
 * @ap:    extra parameters for the message.
Packit 423ecb
 *
Packit 423ecb
 * Formats @msg and places result into @buf.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of characters written to @buf or -1 if an error occurs.
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlStrVPrintf(xmlChar *buf, int len, const char *msg, va_list ap) {
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    if((buf == NULL) || (msg == NULL)) {
Packit 423ecb
        return(-1);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    ret = vsnprintf((char *) buf, len, (const char *) msg, ap);
Packit 423ecb
    buf[len - 1] = 0; /* be safe ! */
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *                                                                      *
Packit 423ecb
 *              Generic UTF8 handling routines                          *
Packit 423ecb
 *                                                                      *
Packit 423ecb
 * From rfc2044: encoding of the Unicode values on UTF-8:               *
Packit 423ecb
 *                                                                      *
Packit 423ecb
 * UCS-4 range (hex.)           UTF-8 octet sequence (binary)           *
Packit 423ecb
 * 0000 0000-0000 007F   0xxxxxxx                                       *
Packit 423ecb
 * 0000 0080-0000 07FF   110xxxxx 10xxxxxx                              *
Packit 423ecb
 * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx                     *
Packit 423ecb
 *                                                                      *
Packit 423ecb
 * I hope we won't use values > 0xFFFF anytime soon !                   *
Packit 423ecb
 *                                                                      *
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlUTF8Size:
Packit 423ecb
 * @utf: pointer to the UTF8 character
Packit 423ecb
 *
Packit 423ecb
 * calculates the internal size of a UTF8 character
Packit 423ecb
 *
Packit 423ecb
 * returns the numbers of bytes in the character, -1 on format error
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlUTF8Size(const xmlChar *utf) {
Packit 423ecb
    xmlChar mask;
Packit 423ecb
    int len;
Packit 423ecb
Packit 423ecb
    if (utf == NULL)
Packit 423ecb
        return -1;
Packit 423ecb
    if (*utf < 0x80)
Packit 423ecb
        return 1;
Packit 423ecb
    /* check valid UTF8 character */
Packit 423ecb
    if (!(*utf & 0x40))
Packit 423ecb
        return -1;
Packit 423ecb
    /* determine number of bytes in char */
Packit 423ecb
    len = 2;
Packit 423ecb
    for (mask=0x20; mask != 0; mask>>=1) {
Packit 423ecb
        if (!(*utf & mask))
Packit 423ecb
            return len;
Packit 423ecb
        len++;
Packit 423ecb
    }
Packit 423ecb
    return -1;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlUTF8Charcmp:
Packit 423ecb
 * @utf1: pointer to first UTF8 char
Packit 423ecb
 * @utf2: pointer to second UTF8 char
Packit 423ecb
 *
Packit 423ecb
 * compares the two UCS4 values
Packit 423ecb
 *
Packit 423ecb
 * returns result of the compare as with xmlStrncmp
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlUTF8Charcmp(const xmlChar *utf1, const xmlChar *utf2) {
Packit 423ecb
Packit 423ecb
    if (utf1 == NULL ) {
Packit 423ecb
        if (utf2 == NULL)
Packit 423ecb
            return 0;
Packit 423ecb
        return -1;
Packit 423ecb
    }
Packit 423ecb
    return xmlStrncmp(utf1, utf2, xmlUTF8Size(utf1));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlUTF8Strlen:
Packit 423ecb
 * @utf:  a sequence of UTF-8 encoded bytes
Packit 423ecb
 *
Packit 423ecb
 * compute the length of an UTF8 string, it doesn't do a full UTF8
Packit 423ecb
 * checking of the content of the string.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of characters in the string or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlUTF8Strlen(const xmlChar *utf) {
Packit 423ecb
    int ret = 0;
Packit 423ecb
Packit 423ecb
    if (utf == NULL)
Packit 423ecb
        return(-1);
Packit 423ecb
Packit 423ecb
    while (*utf != 0) {
Packit 423ecb
        if (utf[0] & 0x80) {
Packit 423ecb
            if ((utf[1] & 0xc0) != 0x80)
Packit 423ecb
                return(-1);
Packit 423ecb
            if ((utf[0] & 0xe0) == 0xe0) {
Packit 423ecb
                if ((utf[2] & 0xc0) != 0x80)
Packit 423ecb
                    return(-1);
Packit 423ecb
                if ((utf[0] & 0xf0) == 0xf0) {
Packit 423ecb
                    if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
Packit 423ecb
                        return(-1);
Packit 423ecb
                    utf += 4;
Packit 423ecb
                } else {
Packit 423ecb
                    utf += 3;
Packit 423ecb
                }
Packit 423ecb
            } else {
Packit 423ecb
                utf += 2;
Packit 423ecb
            }
Packit 423ecb
        } else {
Packit 423ecb
            utf++;
Packit 423ecb
        }
Packit 423ecb
        ret++;
Packit 423ecb
    }
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlGetUTF8Char:
Packit 423ecb
 * @utf:  a sequence of UTF-8 encoded bytes
Packit 423ecb
 * @len:  a pointer to the minimum number of bytes present in
Packit 423ecb
 *        the sequence.  This is used to assure the next character
Packit 423ecb
 *        is completely contained within the sequence.
Packit 423ecb
 *
Packit 423ecb
 * Read the first UTF8 character from @utf
Packit 423ecb
 *
Packit 423ecb
 * Returns the char value or -1 in case of error, and sets *len to
Packit 423ecb
 *        the actual number of bytes consumed (0 in case of error)
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlGetUTF8Char(const unsigned char *utf, int *len) {
Packit 423ecb
    unsigned int c;
Packit 423ecb
Packit 423ecb
    if (utf == NULL)
Packit 423ecb
        goto error;
Packit 423ecb
    if (len == NULL)
Packit 423ecb
        goto error;
Packit 423ecb
    if (*len < 1)
Packit 423ecb
        goto error;
Packit 423ecb
Packit 423ecb
    c = utf[0];
Packit 423ecb
    if (c & 0x80) {
Packit 423ecb
        if (*len < 2)
Packit 423ecb
            goto error;
Packit 423ecb
        if ((utf[1] & 0xc0) != 0x80)
Packit 423ecb
            goto error;
Packit 423ecb
        if ((c & 0xe0) == 0xe0) {
Packit 423ecb
            if (*len < 3)
Packit 423ecb
                goto error;
Packit 423ecb
            if ((utf[2] & 0xc0) != 0x80)
Packit 423ecb
                goto error;
Packit 423ecb
            if ((c & 0xf0) == 0xf0) {
Packit 423ecb
                if (*len < 4)
Packit 423ecb
                    goto error;
Packit 423ecb
                if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
Packit 423ecb
                    goto error;
Packit 423ecb
                *len = 4;
Packit 423ecb
                /* 4-byte code */
Packit 423ecb
                c = (utf[0] & 0x7) << 18;
Packit 423ecb
                c |= (utf[1] & 0x3f) << 12;
Packit 423ecb
                c |= (utf[2] & 0x3f) << 6;
Packit 423ecb
                c |= utf[3] & 0x3f;
Packit 423ecb
            } else {
Packit 423ecb
              /* 3-byte code */
Packit 423ecb
                *len = 3;
Packit 423ecb
                c = (utf[0] & 0xf) << 12;
Packit 423ecb
                c |= (utf[1] & 0x3f) << 6;
Packit 423ecb
                c |= utf[2] & 0x3f;
Packit 423ecb
            }
Packit 423ecb
        } else {
Packit 423ecb
          /* 2-byte code */
Packit 423ecb
            *len = 2;
Packit 423ecb
            c = (utf[0] & 0x1f) << 6;
Packit 423ecb
            c |= utf[1] & 0x3f;
Packit 423ecb
        }
Packit 423ecb
    } else {
Packit 423ecb
        /* 1-byte code */
Packit 423ecb
        *len = 1;
Packit 423ecb
    }
Packit 423ecb
    return(c);
Packit 423ecb
Packit 423ecb
error:
Packit 423ecb
    if (len != NULL)
Packit 423ecb
	*len = 0;
Packit 423ecb
    return(-1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlCheckUTF8:
Packit 423ecb
 * @utf: Pointer to putative UTF-8 encoded string.
Packit 423ecb
 *
Packit 423ecb
 * Checks @utf for being valid UTF-8. @utf is assumed to be
Packit 423ecb
 * null-terminated. This function is not super-strict, as it will
Packit 423ecb
 * allow longer UTF-8 sequences than necessary. Note that Java is
Packit 423ecb
 * capable of producing these sequences if provoked. Also note, this
Packit 423ecb
 * routine checks for the 4-byte maximum size, but does not check for
Packit 423ecb
 * 0x10ffff maximum value.
Packit 423ecb
 *
Packit 423ecb
 * Return value: true if @utf is valid.
Packit 423ecb
 **/
Packit 423ecb
int
Packit 423ecb
xmlCheckUTF8(const unsigned char *utf)
Packit 423ecb
{
Packit 423ecb
    int ix;
Packit 423ecb
    unsigned char c;
Packit 423ecb
Packit 423ecb
    if (utf == NULL)
Packit 423ecb
        return(0);
Packit 423ecb
    /*
Packit 423ecb
     * utf is a string of 1, 2, 3 or 4 bytes.  The valid strings
Packit 423ecb
     * are as follows (in "bit format"):
Packit 423ecb
     *    0xxxxxxx                                      valid 1-byte
Packit 423ecb
     *    110xxxxx 10xxxxxx                             valid 2-byte
Packit 423ecb
     *    1110xxxx 10xxxxxx 10xxxxxx                    valid 3-byte
Packit 423ecb
     *    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx           valid 4-byte
Packit 423ecb
     */
Packit 423ecb
    for (ix = 0; (c = utf[ix]);) {      /* string is 0-terminated */
Packit 423ecb
        if ((c & 0x80) == 0x00) {	/* 1-byte code, starts with 10 */
Packit 423ecb
            ix++;
Packit 423ecb
	} else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
Packit 423ecb
	    if ((utf[ix+1] & 0xc0 ) != 0x80)
Packit 423ecb
	        return 0;
Packit 423ecb
	    ix += 2;
Packit 423ecb
	} else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
Packit 423ecb
	    if (((utf[ix+1] & 0xc0) != 0x80) ||
Packit 423ecb
	        ((utf[ix+2] & 0xc0) != 0x80))
Packit 423ecb
		    return 0;
Packit 423ecb
	    ix += 3;
Packit 423ecb
	} else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
Packit 423ecb
	    if (((utf[ix+1] & 0xc0) != 0x80) ||
Packit 423ecb
	        ((utf[ix+2] & 0xc0) != 0x80) ||
Packit 423ecb
		((utf[ix+3] & 0xc0) != 0x80))
Packit 423ecb
		    return 0;
Packit 423ecb
	    ix += 4;
Packit 423ecb
	} else				/* unknown encoding */
Packit 423ecb
	    return 0;
Packit 423ecb
      }
Packit 423ecb
      return(1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlUTF8Strsize:
Packit 423ecb
 * @utf:  a sequence of UTF-8 encoded bytes
Packit 423ecb
 * @len:  the number of characters in the array
Packit 423ecb
 *
Packit 423ecb
 * storage size of an UTF8 string
Packit 423ecb
 * the behaviour is not guaranteed if the input string is not UTF-8
Packit 423ecb
 *
Packit 423ecb
 * Returns the storage size of
Packit 423ecb
 * the first 'len' characters of ARRAY
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
xmlUTF8Strsize(const xmlChar *utf, int len) {
Packit 423ecb
    const xmlChar   *ptr=utf;
Packit 423ecb
    xmlChar         ch;
Packit 423ecb
Packit 423ecb
    if (utf == NULL)
Packit 423ecb
        return(0);
Packit 423ecb
Packit 423ecb
    if (len <= 0)
Packit 423ecb
        return(0);
Packit 423ecb
Packit 423ecb
    while ( len-- > 0) {
Packit 423ecb
        if ( !*ptr )
Packit 423ecb
            break;
Packit 423ecb
        if ( (ch = *ptr++) & 0x80)
Packit 423ecb
            while ((ch<<=1) & 0x80 ) {
Packit 423ecb
		if (*ptr == 0) break;
Packit 423ecb
                ptr++;
Packit 423ecb
	    }
Packit 423ecb
    }
Packit 423ecb
    return (ptr - utf);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlUTF8Strndup:
Packit 423ecb
 * @utf:  the input UTF8 *
Packit 423ecb
 * @len:  the len of @utf (in chars)
Packit 423ecb
 *
Packit 423ecb
 * a strndup for array of UTF8's
Packit 423ecb
 *
Packit 423ecb
 * Returns a new UTF8 * or NULL
Packit 423ecb
 */
Packit 423ecb
xmlChar *
Packit 423ecb
xmlUTF8Strndup(const xmlChar *utf, int len) {
Packit 423ecb
    xmlChar *ret;
Packit 423ecb
    int i;
Packit 423ecb
Packit 423ecb
    if ((utf == NULL) || (len < 0)) return(NULL);
Packit 423ecb
    i = xmlUTF8Strsize(utf, len);
Packit 423ecb
    ret = (xmlChar *) xmlMallocAtomic((i + 1) * sizeof(xmlChar));
Packit 423ecb
    if (ret == NULL) {
Packit 423ecb
        xmlGenericError(xmlGenericErrorContext,
Packit 423ecb
                "malloc of %ld byte failed\n",
Packit 423ecb
                (len + 1) * (long)sizeof(xmlChar));
Packit 423ecb
        return(NULL);
Packit 423ecb
    }
Packit 423ecb
    memcpy(ret, utf, i * sizeof(xmlChar));
Packit 423ecb
    ret[i] = 0;
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlUTF8Strpos:
Packit 423ecb
 * @utf:  the input UTF8 *
Packit 423ecb
 * @pos:  the position of the desired UTF8 char (in chars)
Packit 423ecb
 *
Packit 423ecb
 * a function to provide the equivalent of fetching a
Packit 423ecb
 * character from a string array
Packit 423ecb
 *
Packit 423ecb
 * Returns a pointer to the UTF8 character or NULL
Packit 423ecb
 */
Packit 423ecb
const xmlChar *
Packit 423ecb
xmlUTF8Strpos(const xmlChar *utf, int pos) {
Packit 423ecb
    xmlChar ch;
Packit 423ecb
Packit 423ecb
    if (utf == NULL) return(NULL);
Packit 423ecb
    if (pos < 0)
Packit 423ecb
        return(NULL);
Packit 423ecb
    while (pos--) {
Packit 423ecb
        if ((ch=*utf++) == 0) return(NULL);
Packit 423ecb
        if ( ch & 0x80 ) {
Packit 423ecb
            /* if not simple ascii, verify proper format */
Packit 423ecb
            if ( (ch & 0xc0) != 0xc0 )
Packit 423ecb
                return(NULL);
Packit 423ecb
            /* then skip over remaining bytes for this char */
Packit 423ecb
            while ( (ch <<= 1) & 0x80 )
Packit 423ecb
                if ( (*utf++ & 0xc0) != 0x80 )
Packit 423ecb
                    return(NULL);
Packit 423ecb
        }
Packit 423ecb
    }
Packit 423ecb
    return((xmlChar *)utf);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlUTF8Strloc:
Packit 423ecb
 * @utf:  the input UTF8 *
Packit 423ecb
 * @utfchar:  the UTF8 character to be found
Packit 423ecb
 *
Packit 423ecb
 * a function to provide the relative location of a UTF8 char
Packit 423ecb
 *
Packit 423ecb
 * Returns the relative character position of the desired char
Packit 423ecb
 * or -1 if not found
Packit 423ecb
 */
Packit 423ecb
int
Packit 423ecb
xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar) {
Packit 423ecb
    int i, size;
Packit 423ecb
    xmlChar ch;
Packit 423ecb
Packit 423ecb
    if (utf==NULL || utfchar==NULL) return -1;
Packit 423ecb
    size = xmlUTF8Strsize(utfchar, 1);
Packit 423ecb
        for(i=0; (ch=*utf) != 0; i++) {
Packit 423ecb
            if (xmlStrncmp(utf, utfchar, size)==0)
Packit 423ecb
                return(i);
Packit 423ecb
            utf++;
Packit 423ecb
            if ( ch & 0x80 ) {
Packit 423ecb
                /* if not simple ascii, verify proper format */
Packit 423ecb
                if ( (ch & 0xc0) != 0xc0 )
Packit 423ecb
                    return(-1);
Packit 423ecb
                /* then skip over remaining bytes for this char */
Packit 423ecb
                while ( (ch <<= 1) & 0x80 )
Packit 423ecb
                    if ( (*utf++ & 0xc0) != 0x80 )
Packit 423ecb
                        return(-1);
Packit 423ecb
            }
Packit 423ecb
        }
Packit 423ecb
Packit 423ecb
    return(-1);
Packit 423ecb
}
Packit 423ecb
/**
Packit 423ecb
 * xmlUTF8Strsub:
Packit 423ecb
 * @utf:  a sequence of UTF-8 encoded bytes
Packit 423ecb
 * @start: relative pos of first char
Packit 423ecb
 * @len:   total number to copy
Packit 423ecb
 *
Packit 423ecb
 * Create a substring from a given UTF-8 string
Packit 423ecb
 * Note:  positions are given in units of UTF-8 chars
Packit 423ecb
 *
Packit 423ecb
 * Returns a pointer to a newly created string
Packit 423ecb
 * or NULL if any problem
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
xmlChar *
Packit 423ecb
xmlUTF8Strsub(const xmlChar *utf, int start, int len) {
Packit 423ecb
    int            i;
Packit 423ecb
    xmlChar ch;
Packit 423ecb
Packit 423ecb
    if (utf == NULL) return(NULL);
Packit 423ecb
    if (start < 0) return(NULL);
Packit 423ecb
    if (len < 0) return(NULL);
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Skip over any leading chars
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < start;i++) {
Packit 423ecb
        if ((ch=*utf++) == 0) return(NULL);
Packit 423ecb
        if ( ch & 0x80 ) {
Packit 423ecb
            /* if not simple ascii, verify proper format */
Packit 423ecb
            if ( (ch & 0xc0) != 0xc0 )
Packit 423ecb
                return(NULL);
Packit 423ecb
            /* then skip over remaining bytes for this char */
Packit 423ecb
            while ( (ch <<= 1) & 0x80 )
Packit 423ecb
                if ( (*utf++ & 0xc0) != 0x80 )
Packit 423ecb
                    return(NULL);
Packit 423ecb
        }
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    return(xmlUTF8Strndup(utf, len));
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlEscapeFormatString:
Packit 423ecb
 * @msg:  a pointer to the string in which to escape '%' characters.
Packit 423ecb
 * Must be a heap-allocated buffer created by libxml2 that may be
Packit 423ecb
 * returned, or that may be freed and replaced.
Packit 423ecb
 *
Packit 423ecb
 * Replaces the string pointed to by 'msg' with an escaped string.
Packit 423ecb
 * Returns the same string with all '%' characters escaped.
Packit 423ecb
 */
Packit 423ecb
xmlChar *
Packit 423ecb
xmlEscapeFormatString(xmlChar **msg)
Packit 423ecb
{
Packit 423ecb
    xmlChar *msgPtr = NULL;
Packit 423ecb
    xmlChar *result = NULL;
Packit 423ecb
    xmlChar *resultPtr = NULL;
Packit 423ecb
    size_t count = 0;
Packit 423ecb
    size_t msgLen = 0;
Packit 423ecb
    size_t resultLen = 0;
Packit 423ecb
Packit 423ecb
    if (!msg || !*msg)
Packit 423ecb
        return(NULL);
Packit 423ecb
Packit 423ecb
    for (msgPtr = *msg; *msgPtr != '\0'; ++msgPtr) {
Packit 423ecb
        ++msgLen;
Packit 423ecb
        if (*msgPtr == '%')
Packit 423ecb
            ++count;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    if (count == 0)
Packit 423ecb
        return(*msg);
Packit 423ecb
Packit 423ecb
    resultLen = msgLen + count + 1;
Packit 423ecb
    result = (xmlChar *) xmlMallocAtomic(resultLen * sizeof(xmlChar));
Packit 423ecb
    if (result == NULL) {
Packit 423ecb
        /* Clear *msg to prevent format string vulnerabilities in
Packit 423ecb
           out-of-memory situations. */
Packit 423ecb
        xmlFree(*msg);
Packit 423ecb
        *msg = NULL;
Packit 423ecb
        xmlErrMemory(NULL, NULL);
Packit 423ecb
        return(NULL);
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    for (msgPtr = *msg, resultPtr = result; *msgPtr != '\0'; ++msgPtr, ++resultPtr) {
Packit 423ecb
        *resultPtr = *msgPtr;
Packit 423ecb
        if (*msgPtr == '%')
Packit 423ecb
            *(++resultPtr) = '%';
Packit 423ecb
    }
Packit 423ecb
    result[resultLen - 1] = '\0';
Packit 423ecb
Packit 423ecb
    xmlFree(*msg);
Packit 423ecb
    *msg = result;
Packit 423ecb
Packit 423ecb
    return *msg;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#define bottom_xmlstring
Packit 423ecb
#include "elfgcchack.h"