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

📄 libslpattr.c

📁 SLP协议在linux下的实现。此版本为1.2.1版。官方网站为www.openslp.org
💻 C
📖 第 1 页 / 共 5 页
字号:
#include <stdlib.h>#include <string.h>#include <assert.h>#include <ctype.h>#include "libslpattr.h"#include "libslpattr_internal.h"/* The strings used to represent non-string variables. */#define BOOL_TRUE_STR "true"#define BOOL_TRUE_STR_LEN 4#define BOOL_FALSE_STR "false"#define BOOL_FALSE_STR_LEN 5/* The preamble to every variable. */#define VAR_PREFIX '('#define VAR_PREFIX_LEN 1#define VAR_INFIX '='#define VAR_INFIX_LEN 1#define VAR_SUFFIX ')'#define VAR_SUFFIX_LEN 1#define VAR_SEPARATOR ','#define VAR_SEPARATOR_LEN 1/* The cost of the '(=)' for a non-keyword attribute. */#define VAR_NON_KEYWORD_SEMANTIC_LEN VAR_PREFIX_LEN + VAR_INFIX_LEN + VAR_SUFFIX_LEN/* The character with which to escape other characters. */#define ESCAPE_CHARACTER '\\'/* The number of characters required to escape a single character. */#define ESCAPED_LEN 3/* The preamble for opaques ('\FF') -- this is only used when the attributes * are "put on the wire". */#define OPAQUE_PREFIX "\\FF"#define OPAQUE_PREFIX_LEN 3/****************************************************************************** *                                   Utility *****************************************************************************//* Tests a character to see if it reserved (as defined in RFC 2608, p11). */#define IS_RESERVED(x) \	(((x) == '(' || (x) == ')' || (x) == ',' || (x) == '\\' || (x) == '!' || (x) == '<' \	|| (x) == '=' || (x) == '>' || (x) == '~') || \	((((char)0x01 <= (x)) && ((char)0x1F >= (x))) || ((x) == (char)0x7F)))#define IS_INVALID_VALUE_CHAR(x) \	IS_RESERVED(x)#define IS_INVALID_TAG_CHAR(x) \	(IS_RESERVED(x) \	|| ((x) == '*') || \	((x) == (char)0x0D) || ((x) == (char)0x0A) || ((x) == (char)0x09) || ((x) == '_'))#define IS_VALID_TAG_CHAR(x) !IS_INVALID_TAG_CHAR(x)/* Tests a character to see if it is in set of known hex characters. */#define IS_VALID_HEX(x) ( ((x >= '0') && (x <= '9')) /* Number */ \				|| ((x >= 'A') && (x <= 'F')) /* ABCDEF */ \				|| ((x >= 'a') && (x <= 'f')) /* abcdef */ \				)/* Tests a character to see if it's a digit. */#define IS_DIGIT(x)	((x) >= '0' && (x) <= '9')/* Find the end of a tag, while checking that said tag is valid.  * * Returns: Pointer to the character immediately following the end of the tag, * or NULL if the tag is improperly formed.  */char const *find_tag_end(const char *tag){    char const *cur = tag; /* Pointer into the tag for working. */    while(*cur)    {        if(IS_INVALID_TAG_CHAR(*cur))        {            break;        }        cur++;    }    return cur;}/* Unescapes an escaped character.  * * val should point to the escape character starting the value. */char unescape(char d1, char d2){    assert(isxdigit((int) d1));    assert(isxdigit((int) d2));    if((d1 >= 'A') && (d1 <= 'F'))        d1 = d1 - 'A' + 0x0A;    else if((d1 >= 'a') && (d1 <= 'f'))        d1 = d1 - 'a' + 0x0A;    else        d1 = d1 - '0';    if((d2 >= 'A') && (d2 <= 'F'))        d2 = d2 - 'A' + 0x0A;    else if((d2 >= 'a') && (d2 <= 'f'))        d2 = d2 - 'a' + 0x0A;    else        d2 = d2 - '0';    return d2 + (d1 * 0x10);}/* Unescapes a string.  * * Params: *  dest -- (IN) Where to write *  src -- (IN) Unescaped string *  len -- (IN) length of src *  unescaped_len -- (OUT) number of characters in unescaped  *  * Returns: Pointer to start of unescaped string. If an error occurs, NULL is * returned (an error consists of an escaped value being truncated). */char *unescape_into(char *dest, const char *src, int len, int                    *unescaped_len){    char *start, *write;    int i;    assert(dest);    assert(src);    write = start = dest;    for(i = 0; i < len; i++, write++)    {        if(src[i] == ESCAPE_CHARACTER)        {            /*** Check that the characters are legal, and that the value has             * not been truncated.              ***/            if((i + 2 < len) && isxdigit((int) src[i+1])			   && isxdigit((int) src[i+2]))            {                *write = unescape(src[i+1], src[i+2]);                i += 2;            }            else            {                return NULL;            }        }        else        {            *write = src[i];        }    }    /* Report the unescaped size. */    if(unescaped_len != NULL)    {        *unescaped_len = write - start;    }    return start;}/* Finds the end of a value list, while checking that the value contains legal * characters.  * * PARAMS: *  value -- (IN) The start of the value list *  value_count -- (OUT) The number of values in the value list *  type -- (OUT) The type of the value list *  unescaped_size -- (OUT) The size of the unescaped value list. ASSUMING THAT THE LIST IS EITHER OPAQUE OR STRING! *  cur -- (OUT) End of the parse. *  * Returns: 0 on parse error. 1 on valid parse. */int find_value_list_end(char const *value, int *value_count, SLPType                        *type, int *unescaped_len, char const **cur){    enum    {        START_VAL, /* We're at the start of a value */        IN_VAL /* We're in a val. */    } state = START_VAL; /* The state of the current read. */    enum    {        TYPE_UNKNOWN = -12, /* Could be anything. */        TYPE_INT = SLP_INTEGER, /* Either an int or a string. */        TYPE_OPAQUE = SLP_OPAQUE, /* Definitely an opaque. */        TYPE_STR = SLP_STRING, /* Definitely a string. */        TYPE_BOOL = SLP_BOOLEAN /* A bool, but it could be a string. */     } type_guess = TYPE_UNKNOWN; /* The current possible values for the type. */    *value_count = 1;    *unescaped_len = 0;    *cur = value;    while(**cur)    {        if(**cur == '\\')        {            if(state == START_VAL)            {                /*** Test if we're starting an opaque. ***/                (*cur)++;                if((**cur) != '0')                {                    /* Panic: truncated escaped value. */                    return 0;                }                (*cur)++;                if((**cur) != '0')                {                    /* Panic: truncated escaped value. */                    return 0;                }                /*** We're starting an opaque. Ensure proper typing. ***/                if(type_guess == TYPE_UNKNOWN)                {                    type_guess = TYPE_OPAQUE;                }                else if(type_guess != TYPE_OPAQUE)                {                    /* An opaque is mixed in with non-opaques. Fail. */                    return 0;                }            }            else            {                /*** We're in the middle of a value. ***/                /** Check that next two characters are valid. **/                (*cur)++;                if(!IS_VALID_HEX(**cur))                {                    return 0;                }                (*cur)++;                if(!IS_VALID_HEX(**cur))                {                    return 0;                }                (*unescaped_len)++;            }            state = IN_VAL;        }        else if(**cur == VAR_SEPARATOR)        {            /* A separator. */            /** Check for empty values. **/            if(state != IN_VAL)            {                return 0; /* ERROR! commas side-by-side. */            }            state = START_VAL;            /** Type check. **/            if(type_guess == TYPE_BOOL)            {                /* Bools can only have _one_ value. */                /* Devolve to string. */                type_guess = TYPE_STR;            }            (*value_count)++;        }        else if(**cur == VAR_SUFFIX)        {            /* Nous sommes fini. */            break;        }        else if(IS_INVALID_VALUE_CHAR(**cur))        {            /* Bad char. */            return 0;        }        else        {            /* Normal case */            /*** Ensure that the character is consistent with its type. ***/            /** Opaque. **/            if(type_guess == TYPE_OPAQUE)            {                /* Type error! The string starts with a \00, but has a bare character somewhere following. */                return 0;            }            /** Int. **/            else if(type_guess == TYPE_INT)            {                if(!(IS_DIGIT(**cur) || (state == START_VAL && **cur == '-')))                {                    /* Devolve to a string. */                    type_guess = TYPE_STR;                }            }            /** Bool. **/            else if(type_guess == TYPE_BOOL)            {                if(*unescaped_len < BOOL_TRUE_STR_LEN && **cur ==                    BOOL_TRUE_STR[*unescaped_len])                {                    /* Do nothing. It's valid. */                }                else if(*unescaped_len < BOOL_FALSE_STR_LEN && **cur ==                         BOOL_FALSE_STR[*unescaped_len])                {                    /* Do nothing. It's also valid. */                }                else                {                    /* Devolve to a string. */                    type_guess = TYPE_STR;                }            }            /** Unknown. **/            else if(type_guess == TYPE_UNKNOWN)            {                if(IS_DIGIT(**cur) || (state == START_VAL && **cur == '-'))                {                    type_guess = TYPE_INT;                }                else if(state == START_VAL && (BOOL_TRUE_STR[0] == **cur || **cur == BOOL_FALSE_STR[0]))                {                    type_guess = TYPE_BOOL;                }                else                {                    type_guess = TYPE_STR;                }            }            (*unescaped_len)++;            state = IN_VAL;        }        (*cur)++;    }    if (type_guess == TYPE_UNKNOWN)    {	return 0;	/* empty */    }    *type = type_guess;    return 1;}/* Finds the end of a value, while checking that the value contains legal * characters.  * * Returns: see find_tag_end(). */char *find_value_end(char *value){    char *cur = value; /* Pointer  into the value string. */    while(*cur)    {        if(IS_INVALID_VALUE_CHAR(*cur) && (*cur != '\\'))        {            break;        }        cur++;    }    return cur;}/* Find the number of digits (base 10) necessary to represent an integer.  * * Returns the number of digits. */int count_digits(int number){    int count = (number < 0) ? 1 : 0;	/* do we need a negative sign ? */    /* special case: 0 */    if (number == 0)        return 1;    /* poor man's abs() function */    number = (number < 0 ) ? -number : number;    /* count number of digits required; this only works with integers */    for ( ; number > 0; number /= 10) {	count++;    }    return count;}/* Verifies that a tag contains only legal characters. */SLPBoolean is_valid_tag(const char *tag){    /* TODO Check. */    return SLP_TRUE;}/* A boolean expression that tests a character to see if it must be escaped. */#define ATTRIBUTE_RESERVED_TEST(x) \	(x == '(' || x == ')' || x == ',' || x == '\\' || x == '!' || x == '<' \	 || x == '=' || x == '<' || x == '=' || x == '>' || x == '~' || x == '\0')/* Tests a character to see if it should be escaped. To be used for everything * but opaques. */SLPBoolean is_legal_slp_char(const char to_test){    if(ATTRIBUTE_RESERVED_TEST(to_test))    {        return SLP_FALSE;    }    return SLP_TRUE;}/* Tests a character to see if it should be escaped for an opaque. */SLPBoolean opaque_test(const char to_test){    return SLP_FALSE;}/* Find the size of an unescaped string (given the escaped string).  * * Note that len must be positive.  * * Returns: If positive, the length of the string. If negative, there is some * sort of error.  */int find_unescaped_size(const char *str, int len){    int i;    int size;    assert(len > 0);    size = len;    for(i = 0; i < len; i++)    {        if(str[i] == ESCAPE_CHARACTER)        {            size -= ESCAPED_LEN - 1; /* -1 for the ESCAPE_CHARACTER. */        }    }    return size;}

⌨️ 快捷键说明

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