📄 libslpattr.c
字号:
{ tag_cur = (char *)tags; } tag_end = tag_cur; var = NULL; /***** Find the size of string needed for the attribute string. *****/ while(var_iter(slp_attr, &tag_cur, &tag_end, &var)) { /*** Skip bad tags? ***/ if(var == NULL) { continue; } /*** Skip old attributes. ***/ if(find_delta == SLP_TRUE && var->modified == SLP_FALSE) { continue; } /*** Get size of tag ***/ size += var->tag_len; /*** Count the size needed for the value list ***/ if(var->type != SLP_KEYWORD) { value_t *value; /** Get size of data **/ value = var->list; while(value) { size += value->escaped_len; value = value->next; } /** Count number of commas needed for multivalued attributes. **/ assert(var->list_size >= 0); size += (var->list_size - 1) * VAR_SEPARATOR_LEN; /** Count the semantics needed to store a multivalue list **/ size += VAR_NON_KEYWORD_SEMANTIC_LEN; } else { assert(var->list == NULL); } /*** Count number of variables ***/ var_count++; } /*** Count the number of characters between attributes. ***/ if(var_count > 0) { size += (var_count - 1) * VAR_SEPARATOR_LEN; } /***** Return the size needed/used. *****/ if(count != NULL) { *count = size + 1; } /***** Create the string. *****/ if(*out_buffer == NULL) { /* We have to locally alloc the string. */ build_str = (char *)malloc( size + 1); if(build_str == NULL) { return SLP_MEMORY_ALLOC_FAILED; } } else { /* We write into a pre-alloc'd buffer. */ /**** Check that out_buffer is big enough. ****/ if((int)size + 1 > bufferlen) { return SLP_BUFFER_OVERFLOW; } build_str = *out_buffer; } build_str[0] = '\0'; /***** Add values *****/ /**** Decide on our looping mode. ****/ if(tags == NULL || *tags == 0) { tag_cur = NULL; } else { tag_cur = (char *)tags; } tag_end = tag_cur; var = NULL; /**** Find the size of string needed for the attribute string. ****/ cur = build_str; while(var_iter(slp_attr, &tag_cur, &tag_end, &var)) { /*** Skip bad tags? ***/ if(var == NULL) { continue; } /*** Skip old attributes. ***/ if(find_delta == SLP_TRUE && var->modified == SLP_FALSE) { continue; } if(var->type == SLP_KEYWORD) { /**** Handle keywords. ****/ memcpy(cur, var->tag, var->tag_len); cur += var->tag_len; } else { /**** Handle everything else. ****/ char *to_add; int to_add_len; value_t *value; /*** Add the prefix. ***/ *cur = VAR_PREFIX; cur += VAR_PREFIX_LEN; /*** Add the tag. ***/ memcpy(cur, var->tag, var->tag_len); cur += var->tag_len; /*** Add the infix. ***/ *cur = VAR_INFIX; cur += VAR_INFIX_LEN; /*** Insert value (list) ***/ value = var->list; assert(value); while(value) { /* foreach member value of an attribute. */ assert(var->type != SLP_KEYWORD); switch(var->type) { case(SLP_BOOLEAN): assert(value->next == NULL); /* Can't be a multivalued list. */ assert(value->data.va_bool == SLP_TRUE || value->data.va_bool == SLP_FALSE); if(value->data.va_bool == SLP_TRUE) { to_add = BOOL_TRUE_STR; to_add_len = BOOL_TRUE_STR_LEN; } else { to_add = BOOL_FALSE_STR; to_add_len = BOOL_FALSE_STR_LEN; } memcpy(cur, to_add, to_add_len); cur += to_add_len; break; case(SLP_STRING): cur = escape_into(cur, value->data.va_str, value->unescaped_len); break; case(SLP_INTEGER): sprintf(cur, "%d", value->data.va_int); cur += value->escaped_len; break; case(SLP_OPAQUE): memcpy(cur, OPAQUE_PREFIX, OPAQUE_PREFIX_LEN); cur += OPAQUE_PREFIX_LEN; cur = escape_opaque_into(cur, value->data.va_str, value->unescaped_len); break; default: printf("Unknown type (%s:%d).\n", __FILE__, __LINE__); /* TODO Clean up memory leak: the output string */ return SLP_INTERNAL_SYSTEM_ERROR; } value = value->next; /*** Add separator (if necessary) ***/ if(value != NULL) { *cur = VAR_SEPARATOR; cur += VAR_SEPARATOR_LEN; *cur = 0; } } /*** Add the suffix. ***/ *cur = VAR_SUFFIX; cur += VAR_SUFFIX_LEN; *cur = 0; } /*** Add separator. This is fixed for the last val outside the loop ***/ /* if (var->next != NULL) { */ if((unsigned)(cur - build_str) < size) { *cur = VAR_SEPARATOR; cur += VAR_SEPARATOR_LEN; *cur = 0; } /*** Reset the modified flag. ***/ var->modified = SLP_FALSE; } /**** Shift back to erase the last comma. ****/ /***** Append a null (This is actually done by strcpy, but its better to * be safe than sorry =) *****/ *cur = '\0'; assert((unsigned)(cur - build_str) == size && size == strlen(build_str)); *out_buffer = build_str; return SLP_OK;} /* Stores an escaped value into an attribute. Determines type of attribute at * the same time. * * tag must be null terminated. * val must be of length len. * policy will only be respected where it can be (ints, strings, and opaques). * * the contents of tag are NOT verified. * * Returns: * SLP_PARAMETER_BAD - Syntax error in the value. * SLP_MEMORY_ALLOC_FAILED */SLPError SLPAttrStore(struct xx_SLPAttributes *slp_attr, const char *tag, const char *val, int len, SLPInsertionPolicy policy ){ int i; /* Index into val. */ SLPBoolean is_str; /* Flag used for checking if given is string. */ char *unescaped; int unescaped_len; /* Length of the unescaped text. */ /***** Check opaque. *****/ if(strncmp(val, OPAQUE_PREFIX, OPAQUE_PREFIX_LEN) == 0) { /*** Verify length (ie, that it is the multiple of the size of an * escaped character). ***/ if(len % ESCAPED_LEN != 0) { return SLP_PARAMETER_BAD; } unescaped_len = (len / ESCAPED_LEN) - 1; /* -1 to drop the OPAQUE_PREFIX. */ /*** Verify that every character has been escaped. ***/ /* TODO */ /***** Unescape the value. *****/ unescaped = (char *)malloc(unescaped_len); if(unescaped == NULL) { return SLP_MEMORY_ALLOC_FAILED; /* FIXME: Real error code. */ } if(unescape_into(unescaped, (char *)(val + OPAQUE_PREFIX_LEN), len - OPAQUE_PREFIX_LEN, NULL) != NULL) { SLPError err; err = SLPAttrSet_opaque((SLPAttributes)slp_attr, tag, unescaped, (len - OPAQUE_PREFIX_LEN) / 3, policy); free(unescaped);/* FIXME This should be put into the val, and free()'d in val_destroy(). */ return err; } return SLP_PARAMETER_BAD; /* FIXME Verify. Is this really a bad parameter?*/ } /***** Check boolean. *****/ if((BOOL_TRUE_STR_LEN == len) && (strncmp(val, BOOL_TRUE_STR, len) == 0)) { return SLPAttrSet_bool((SLPAttributes)slp_attr, tag, SLP_TRUE); } if((BOOL_FALSE_STR_LEN == len) && strncmp(val, BOOL_FALSE_STR, len) == 0) { return SLPAttrSet_bool((SLPAttributes)slp_attr, tag, SLP_FALSE); } /***** Check integer *****/ if(*val == '-' || isdigit((int)*val)) { /*** Verify. ***/ SLPBoolean is_int = SLP_TRUE; /* Flag true if the attr is an int. */ for(i = 1; i < len; i++) { /* We start at 1 since first char has already been checked. */ if(!isdigit((int)val[i])) { is_int = SLP_FALSE; break; } } /*** Handle the int-ness. ***/ if(is_int == SLP_TRUE) { char *end; /* To verify that the correct length was read. */ SLPError err; err = SLPAttrSet_int((SLPAttributes)slp_attr, tag, (int) strtol(val, &end, 10), policy); assert(end == val + len); return err; } } /***** Check string. *****/ is_str = SLP_TRUE; for(i = 0; i < len; i++) { if(IS_RESERVED(val[i]) && (val[i] != '\\')) { is_str = SLP_FALSE; break; } } if(is_str == SLP_TRUE) { unescaped_len = find_unescaped_size(val, len); unescaped = (char *)malloc( unescaped_len + 1 ); if(unescape_into(unescaped, val, len, NULL) != NULL) { SLPError err; unescaped[unescaped_len] = '\0'; err = SLPAttrSet_str((SLPAttributes)slp_attr, tag, unescaped, policy); free(unescaped); /* FIXME This should be put into the val, and free()'d in val_destroy(). */ return err; } return SLP_PARAMETER_BAD; } /* We don't bother checking for a keyword attribute since it can't have a * value. */ return SLP_PARAMETER_BAD; /* Could not determine type. */}/* Converts an attribute string into an attr struct. * * Note that the attribute string is trashed. * * Returns: * SLP_PARAMETER_BAD -- If there is a parse error in the attribute string. * SLP_OK -- If everything went okay. */SLPError attr_destringify( struct xx_SLPAttributes *slp_attr, char const *str, SLPInsertionPolicy policy ){ char const *cur; /* Current index into str. */ enum { /* Note: everything contained in []s in this enum is a production from * RFC 2608's grammar defining attribute lists. */ START_ATTR /* The start of an individual [attribute]. */, START_TAG /* The start of a [attr-tag]. */, VALUE /* The start of an [attr-val]. */, STOP_VALUE /* The end of an [attr-val]. */ } state = START_ATTR; /* The current state of the parse. */ char const *tag; /* A tag that has been parsed. (carries data across state changes)*/ int tag_len = 0; /* length of the tag (in bytes) */ assert(str != NULL); if(strlen(str) == 0) { return SLP_OK; } tag = NULL; cur = str; /***** Pull apart str. *****/ while(*cur) { char const *end; /* The end of a parse entity. */ switch(state) { case(START_ATTR): /* At the beginning of an attribute. */ if(*cur == VAR_PREFIX) { /* At the start of a non-keyword. */ state = START_TAG; cur += VAR_PREFIX_LEN; } else { /* At the start of a keyword: * Gobble up the keyword and set it. */ end = find_tag_end(cur); if(end == NULL) { /* FIXME Ummm, I dunno. */ assert(0); } /*** Check that the tag ends on a legal ending char. ***/ if(*end == ',') { /** Add the keyword. **/ SLPAttrSet_keyw_len((SLPAttributes)slp_attr, cur, end - cur); cur = end + 1; break; } else if(*end == '\0') { SLPAttrSet_keyw_len((SLPAttributes)slp_attr, cur, end - cur); return SLP_OK; /* FIXME Return success. */ break; } else { return SLP_PARAMETER_BAD; /* FIXME Return error code. -- Illegal tag char */ } } break; case(START_TAG): /* At the beginning of a tag, in brackets. */ end = find_tag_end(cur); if(end == NULL) { return SLP_PARAMETER_BAD; /* FIXME Err. code -- Illegal char. */ } if(*end == '\0') { return SLP_PARAMETER_BAD; /* FIXME err: Premature end. */ } /*** Check the the end character is valid. ***/ if(*end == VAR_INFIX) { tag_len = (int)(end - cur); /* Note that end is on the character _after_ the last character of the tag (the =). */ assert(tag == NULL); tag = cur; cur = end + VAR_INFIX_LEN; state = VALUE; } else { /** ERROR! **/ return SLP_PARAMETER_BAD; /* FIXME Err. code.-- Logic error. */ } break; case(VALUE): /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -