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); } } }
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; } }
/** * 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; }