Пример #1
0
static void cstr_to_heading_id(StrBuf *sb, const char *p, int size)
{
    int i;
    for (i = 0; i < size; i++) {
        int ch = p[i] & 0xFF;
        if (isalnumu_fox(ch) || ch == '-') {
            fs->StrBuf_add_c(sb, ch);
        } else {
            char cbuf[8];
            sprintf(cbuf, ".%02X", ch);
            fs->StrBuf_add(sb, cbuf, 3);
        }
    }
}
Пример #2
0
static void SelectorTok_next(SelectorTok *tk)
{
    int ch;

    if (tk->p < tk->end && isspace_fox(*tk->p)) {
        tk->p++;
        while (tk->p < tk->end && isspace_fox(*tk->p)) {
            tk->p++;
        }
        tk->type = STK_SPACE;
        return;
    }
    if (tk->p >= tk->end) {
        tk->type = STK_EOS;
        return;
    }

    ch = *tk->p++;
    switch (ch) {
    case '/':
        tk->type = STK_SLASH;
        break;
    case '=':
        tk->type = STK_EQ;
        break;
    case '[':
        tk->type = STK_LB;
        break;
    case ']':
        tk->type = STK_RB;
        break;
    case '(':
        tk->type = STK_LP;
        break;
    case ')':
        tk->type = STK_RP;
        break;
    case '.':
        tk->type = STK_DOT;
        break;
    case '#':
        tk->type = STK_HASH;
        break;
    case ':':
        tk->type = STK_COLON;
        break;
    case ',':
        tk->type = STK_COMMA;
        break;
    case '"':
        // TODO "str" の解析
        tk->type = STK_ERROR;
        break;
    case '\'':
        // TODO 'str' の解析
        tk->type = STK_ERROR;
        break;
    case '+':
        tk->type = STK_PLUS;
        break;
    case '<':
        tk->type = STK_LT;
        break;
    case '>':
        tk->type = STK_GT;
        break;
    case '~':
        if (*tk->p == '=') {
            tk->p++;
            tk->type = STK_TILDE_EQ;
        } else {
            tk->type = STK_ERROR;
            break;
        }
        break;
    case '|':
        if (*tk->p == '=') {
            tk->p++;
            tk->type = STK_BAR_EQ;
        } else {
            tk->type = STK_ERROR;
            break;
        }
        break;
    case '^':
        if (*tk->p == '=') {
            tk->p++;
            tk->type = STK_HAT_EQ;
        } else {
            tk->type = STK_ERROR;
            break;
        }
        break;
    case '$':
        if (*tk->p == '=') {
            tk->p++;
            tk->type = STK_DOLL_EQ;
        } else {
            tk->type = STK_ERROR;
            break;
        }
        break;
    case '*':
        if (*tk->p == '=') {
            tk->p++;
            tk->type = STK_STAR_EQ;
        } else {
            tk->type = STK_STAR;
            break;
        }
        break;
    default:
        if (isalnumu_fox(ch) || (ch & 0x80) != 0) {
            // 識別子
            tk->p--;
            tk->val.p = tk->p;
            for (;;) {
                int ch2 = fs->utf8_codepoint_at(tk->p);
                int type = ch_get_category(ch2);

                if (type < CATE_Ll || type > CATE_No) {
                    if (ch2 != '-' && ch2 != '_') {
                        break;
                    }
                }
                fs->utf8_next((const char**)&tk->p, tk->end);
            }
            tk->val.size = tk->p - tk->val.p;
            if (tk->val.size > 0) {
                tk->type = STK_IDENT;
            } else {
                tk->type = STK_ERROR;
            }
        } else {
            tk->type = STK_ERROR;
        }
        break;
    }
}
Пример #3
0
/**
 * XMLPatternListから、XMLNodeを選択
 */
static int select_xml_match_node(Ref *r, XMLPattern *pat)
{
    XMLAttrPattern *attr;

    for (attr = pat->attr; attr != NULL; attr = attr->next) {
        switch (attr->type) {
        case XT_ANY:
            break;
        case XT_NAME: {
            RefStr *name = Value_vp(r->v[INDEX_ELEM_NAME]);
            if (!str_eq(name->c, name->size, attr->val.p, attr->val.size)) {
                return FALSE;
            }
            break;
        }
        case XT_ATTR_EQ:
        case XT_ATTR_MATCH:
        case XT_ATTR_FIRST: {
            HashValueEntry *he;
            Value key;
            RefStr *val;
            Value v_rm = r->v[INDEX_ELEM_ATTR];

            key = fs->cstr_Value(fs->cls_str, attr->key.p, attr->key.size);
            // Str#_op_eqでは、例外が発生しないのでチェックを省略
            if (!Value_isref(v_rm)) {
                break;
            }
            fs->refmap_get(&he, Value_vp(v_rm), key);
            if (he == NULL) {
                return FALSE;
            }
            val = Value_vp(he->val);
            switch (attr->type) {
            case XT_ATTR_EXIST:
                break;
            case XT_ATTR_EQ:
                if (!str_eq(val->c, val->size, attr->val.p, attr->val.size)) {
                    return FALSE;
                }
                break;
            case XT_ATTR_MATCH: {
                int i = 0;
                int asize = attr->val.size;
                int found = FALSE;
                for (;;) {
                    while (i < val->size - asize && isspace_fox(val->c[i])) {
                        i++;
                    }
                    if (memcmp(val->c, attr->val.p + i, asize) == 0) {
                        if (i + asize == val->size || isspace_fox(val->c[i + asize])) {
                            found = TRUE;
                            break;
                        }
                    }
                    while (i < val->size - asize && !isspace_fox(val->c[i])) {
                        i++;
                    }
                    if (i >= val->size - asize) {
                        break;
                    }
                }
                if (!found) {
                    return FALSE;
                }
                break;
            }
            case XT_ATTR_FIRST: {
                int asize = attr->val.size;
                int found = FALSE;
                if (val->size >= asize && memcmp(val->c, attr->val.p, asize) == 0) {
                    if (val->size == asize || !isalnumu_fox(val->c[asize])) {
                        found = TRUE;
                    }
                }
                if (!found) {
                    return FALSE;
                }
                break;
            }
            }
            break;
        }
        default:
            return FALSE;
        }
    }
    return TRUE;
}