📄 slpd_predicate.c
字号:
/***** Verify and convert rhs. *****/ str_val = rhs; str_len = rhs_len; /***** Get tag value. *****/ var = attr_val_find_str((struct xx_SLPAttributes *)slp_attr, tag, tag_len); if(var == NULL) { return FR_EVAL_FALSE; } /**** Check type. ****/ if(var->type != SLP_OPAQUE) { return FR_EVAL_FALSE; } /***** Compare. *****/ assert(op != PRESENT); if(op == APPROX) { assert(0); /* TODO: Figure out how this works later. */ } else if(op == EQUAL) { int result; value_t *value; for(value = var->list; value; value = value->next) { result = wildcard(str_val, str_len, value->data.va_str, value->unescaped_len); /* We only keep going if the test fails. Let caller handle other problems. */ if(result != FR_EVAL_FALSE) { return result; } } } else { value_t *value; /* We know that the op must be comparative. */ assert(op == LESS || op == GREATER); for(value = var->list; value; value = value->next) { int result; result = memcmp(value->data.va_str, str_val, MIN(str_len, value->unescaped_len)); if( (result <= 0 && op == LESS) || (result >= 0 && op == GREATER) ) { return FR_EVAL_TRUE; } } } return FR_EVAL_FALSE;}/*--------------------------------------------------------------------------*/int is_int_string(const char *str)/* Tests a string to see if it consists wholly of numeric characters. *//*--------------------------------------------------------------------------*/{ int i; for(i=0; str[i] != '\0'; i++) { if(!((!isdigit((int)str[i])) || str[i] == '-')) { return 0; } } return 1;}/*--------------------------------------------------------------------------*/char *find_substr(char *src, int src_len, char *to_find)/* Returns ptr to start of substring, or null. *//*--------------------------------------------------------------------------*/{ int i; for(i = 0; i < src_len; i++) { if(src[i] == *to_find) { int old_i = i; /* Save the old start. */ int find_index; for(find_index = 0; (to_find[find_index] != '\0') && (i < src_len) && (to_find[find_index] == src[i]); to_find++, i++) { } if(to_find[find_index] == '\0') { return src + i; } i = old_i; /* Restor the old start. */ } } return 0;}/*--------------------------------------------------------------------------*/char *find_bracket_end(const char *str)/* Finds a bracket matched to this one. Returns 0 if there isn't one. *//*--------------------------------------------------------------------------*/{ int open_count; const char *cur; if(*str != BRACKET_OPEN) { return 0; } open_count = 0; /***** Count brackets. *****/ for(cur = str; *cur != '\0'; cur++) { assert(open_count >= 0); /**** Check current character. ****/ if(*cur == BRACKET_OPEN) { open_count++; } else if(*cur == BRACKET_CLOSE) { open_count--; } /**** Check if we've found bracket end. ****/ if(open_count == 0) { return(char *)cur; } } return 0;} /*--------------------------------------------------------------------------*/struct pair/* Represents a string and its length. */{ char *start; char *end; /* Stop reading _BEFORE_ end. ie, at end-1. */};/*--------------------------------------------------------------------------*/#if defined(ENABLE_SLPv1)/*--------------------------------------------------------------------------*/FilterResult filterv1(const char *start, const char **end, SLPAttributes slp_attr, int recursion_depth)/* Parameters: *//* start -- (IN) The start of the string to work in. *//* end -- (OUT) The end of the string processed. After successful processing*//* (ie, no PARSE_ERRORs), this will be pointed at the character*//* following the last char in this level of the expression. *//* slp_attr -- (IN) The attributes handle to compare on. *//* return_value -- (OUT) The result of the search. Only valid if SLP_OK was *//* returned. *//* *//* Returns: SLP_OK on successful search (ie, the search was do-able). *//* SLP_PARSE_ERROR on search error. The end of the expression is *//* returned through end. *//* NOTE: This attempt only implements one comparision operator (==) *//*--------------------------------------------------------------------------*/{ char *operator; /* Pointer to the operator substring. */ const char *cur; /* Current working character. */ const char *last_char; /* The last character in the working string. */ FilterResult err = FR_UNSET; /* The result of an evaluation. */ FilterResult stop_condition = FR_UNSET; if(recursion_depth <= 0) { return FR_PARSE_ERROR; } recursion_depth--; if(*start == 0) { *end = start; return FR_EVAL_TRUE; } if(*start != BRACKET_OPEN) { return FR_PARSE_ERROR; } /***** Get the current expression. *****/ last_char = *end = find_bracket_end(start); if(*end == 0) { return FR_PARSE_ERROR; } (*end)++; /* Move the end pointer past the closing bracket. */ /**** * Check for the three legal characters that can follow an expression, * if the following character isn't one of those, the following character * is trash. ****/ if(!(**end == BRACKET_OPEN || **end == BRACKET_CLOSE || **end == '\0')) { return FR_PARSE_ERROR; } /***** check for boolean op. *****/ cur = start; cur++; switch(*cur) { case('&'): /***** And. *****/ case('|'): /***** Or. *****/ { if(*cur == '&') { stop_condition = FR_EVAL_FALSE; } else if(*cur == '|') { stop_condition = FR_EVAL_TRUE; } cur++; /* Move past operator. */ /*** Ensure that we have at least one operator. ***/ if(*cur != BRACKET_OPEN || cur >= last_char) { return FR_PARSE_ERROR; } /*** Evaluate each operand. ***/ /* NOTE: Due to the condition on the above "if", we are guarenteed that the first iteration of the loop is valid. */ do { err = filterv1(cur, &cur, slp_attr, recursion_depth); /*** Propagate errors. ***/ if(err != FR_EVAL_TRUE && err != FR_EVAL_FALSE) { return err; } /*** Short circuit. ***/ if(err == stop_condition) { return stop_condition; } } while(*cur == BRACKET_OPEN && cur < last_char); /*** If we ever get here, it means we've evaluated every operand without short circuiting -- meaning that the operation failed. ***/ return(stop_condition == FR_EVAL_TRUE ? FR_EVAL_FALSE : FR_EVAL_TRUE); } case('!'): /***** Not. *****/ /**** Child. ****/ cur++; err = filterv1(cur, &cur, slp_attr, recursion_depth); /*** Return errors. ***/ if(err != FR_EVAL_TRUE && err != FR_EVAL_FALSE) { return err; } /*** Perform "not". ***/ return(err == FR_EVAL_TRUE ? FR_EVAL_FALSE : FR_EVAL_TRUE); default: /***** Unknown operator. *****/ ; /* We don't do anything here because this will catch the first character of every leaf predicate. */ } /***** Check for leaf operator. *****/ if(IS_VALID_TAG_CHAR(*cur)) { Operation op; char *lhs, *rhs; /* The two operands. */ char *val_start; /* The character after the operator. ie, the start of the rhs. */ int lhs_len, rhs_len; /* Length of the lhs/rhs. */ SLPType type; SLPError slp_err; /**** Demux leaf op. ****/ /* Support only "==", we look for the equals * sign, and then poke around on either side of that for the real * value. */ operator = (char *)memchr(cur, '=', last_char - cur); if(operator == 0 || *(operator + 1) != '=') { /**** No search operator. ****/ return FR_PARSE_ERROR; } /* The rhs always follows the operator. (This doesn't really make sense for PRESENT ops, but ignore that). */ val_start = operator + 2; if(operator == cur) {/* Check that we can poke back one char. */ return FR_PARSE_ERROR; } op = EQUAL; /***** Get operands. *****/ /**** Left. ****/ lhs_len = operator - cur; lhs = (char *)cur; /**** Right ****/ rhs_len = last_char - val_start; rhs = val_start; /***** Do leaf operation. *****/ /**** Check that tag exists. ****/ slp_err = SLPAttrGetType_len(slp_attr, lhs, lhs_len, &type); if(slp_err == SLP_TAG_ERROR) { /* Tag doesn't exist. */ return FR_EVAL_FALSE; } else if(slp_err == SLP_OK) { /* Tag exists. */ /**** Do operation. *****/ if(op == PRESENT) { /*** Since the PRESENT operation is the same for all types, do that now. ***/ return FR_EVAL_TRUE; } else { /*** A type-specific operation. ***/ switch(type) { case(SLP_BOOLEAN): err = bool_op(slp_attr, lhs, lhs_len, rhs, rhs_len, op); break; case(SLP_INTEGER): err = int_op(slp_attr, lhs, lhs_len, rhs, op); break; case(SLP_KEYWORD): err = keyw_op(slp_attr, lhs, rhs, op); break; case(SLP_STRING): err = str_op(slp_attr, lhs, lhs_len, rhs, rhs_len, op); break; case(SLP_OPAQUE): assert(0); /* Opaque is not yet supported. */ } } } else { /* Some other tag-related error. */ err = FR_INTERNAL_SYSTEM_ERROR; } assert(err != FR_UNSET); return err; } /***** No operator. *****/ return FR_PARSE_ERROR;}#endif/*--------------------------------------------------------------------------*/FilterResult filter(const char *start, const char **end, SLPAttributes slp_attr, int recursion_depth)/* Parameters: *//* start -- (IN) The start of the string to work in. *//* end -- (OUT) The end of the string processed. After successful processing*//* (ie, no PARSE_ERRORs), this will be pointed at the character*//* following the last char in this level of the expression. *//* slp_attr -- (IN) The attributes handle to compare on. *//* return_value -- (OUT) The result of the search. Only valid if SLP_OK was *//* returned. *//* *//* Returns: SLP_OK on successful search (ie, the search was do-able). *//* SLP_PARSE_ERROR on search error. The end of the expression is */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -