Example #1
0
/**
 * 同じキーがあれば上書き
 * なければ追加
 * 例外発生時はNULLを返す
 * keyのカウンタを増やす
 */
HashValueEntry *refmap_add(RefMap *rm, Value key, int overwrite, int raise_error)
{
    HashValueEntry *ep, **epp;
    uint32_t hash;

    if (!map_search_sub(&epp, &hash, rm, key)) {
        return NULL;
    }

    ep = *epp;
    if (ep != NULL) {
        if (overwrite) {
            // 一致(上書き)
            if (Value_isref(ep->val)) {
                RefHeader *rh = Value_ref_header(ep->val);
                if (rh->nref > 0 && --rh->nref == 0) {
                    Value_release_ref(ep->val);
                }
            }
            ep->val = VALUE_NULL;
            return ep;
        } else {
            if (raise_error) {
                throw_errorf(fs->mod_lang, "IndexError", "Duplicate key detected");
                return NULL;
            } else {
                return ep;
            }
        }
    } else {
        // 一致しない(追加)
        ep = malloc(sizeof(HashValueEntry));
        ep->next = NULL;
        ep->hash = hash;
        ep->key = Value_cp(key);
        ep->val = VALUE_NULL;
        *epp = ep;
        rm->count++;

        if (rm->count > rm->entry_num) {
            map_grow_entry(rm);
        }
        return ep;
    }
}
Example #2
0
static void xmlelem_add_attr(Ref *r, const char *ckey, const char *cval)
{
    RefMap *rm;
    Value key;
    HashValueEntry *ve;

    if (Value_isref(r->v[INDEX_ELEM_ATTR])) {
        rm = Value_vp(r->v[INDEX_ELEM_ATTR]);
    } else {
        rm = fs->refmap_new(0);
        r->v[INDEX_ELEM_ATTR] = vp_Value(rm);
    }
    key = fs->cstr_Value(fs->cls_str, ckey, -1);
    ve = fs->refmap_add(rm, key, TRUE, FALSE);
    fs->unref(key);
    fs->unref(ve->val);
    ve->val = fs->cstr_Value(fs->cls_str, cval, -1);
}
Example #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;
}