static void combust_tree(graphcut_workspace_t*w, posqueue_t*q1, posqueue_t*q2, path_t*path) { graph_t*graph = w->graph; int t; for(t=0;t<path->length-1 && path->firsthalf[t+1];t++) { node_t*pos = path->pos[t]; halfedge_t*dir = path->dir[t]; node_t*newpos = dir->fwd->node; if(!dir->weight) { /* disconnect node */ DBG printf("remove link %d -> %d from tree 1\n", NR(pos), NR(newpos)); dir->used = 0; w->flags1[NR(newpos)] &= ACTIVE; bool_op(w, w->flags1, newpos, ~IN_TREE, 0); /* try to reconnect the path to some other tree part */ if(reconnect(w, w->flags1, newpos, 0)) { bool_op(w, w->flags1, newpos, ~0, IN_TREE); } else { destroy_subtree(w, w->flags1, newpos, q1); break; } } } for(t=path->length-1;t>0 && !path->firsthalf[t-1];t--) { node_t*pos = path->pos[t]; node_t*newpos = path->pos[t-1]; halfedge_t*dir = path->dir[t-1]->fwd; node_t*newpos2 = dir->fwd->node; assert(newpos == newpos2); if(!dir->fwd->weight) { /* disconnect node */ DBG printf("remove link %d->%d from tree 2\n", NR(pos), NR(newpos)); dir->used = 0; w->flags2[NR(newpos)] &= ACTIVE; bool_op(w, w->flags2, newpos, ~IN_TREE, 0); /* try to reconnect the path to some other tree part */ if(reconnect(w, w->flags2, newpos, 1)) { bool_op(w, w->flags2, newpos, ~0, IN_TREE); } else { destroy_subtree(w, w->flags2, newpos, q2); break; } } } }
/*--------------------------------------------------------------------------*/ 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 */ /* returned through end. */ /*--------------------------------------------------------------------------*/ { 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. */ if(recursion_depth <= 0) { return FR_PARSE_ERROR; } recursion_depth--; 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. *****/ { FilterResult stop_condition; /* Stop when this value is received. Used for short circuiting. */ 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 = filter(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 = filter(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. ****/ /* Since all search operators contain a "=", 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) { /**** 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 + 1; /* Check for APPROX, GREATER, or LESS. Note that we shuffle the operator pointer back to point at the start of the op. */ if(operator == cur) {/* Check that we can poke back one char. */ return FR_PARSE_ERROR; } switch(*(operator - 1)) { case('~'): op = EQUAL; /* See Assumptions. */ operator--; break; case('>'): op = GREATER; operator--; break; case('<'): op = LESS; operator--; break; default: /* No prefix to the '='. */ /**** Check for PRESENT. ****/ if((operator == last_char - 2) && (*(operator+1) == '*')) { op = PRESENT; } /**** It's none of the above: therefore it's EQUAL. ****/ else { 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; }