コード例 #1
0
ファイル: t-map.c プロジェクト: fort-ascension/ren-c
//
//  Find_Entry: C
// 
// Try to find the entry in the map. If not found
// and val is SET, create the entry and store the key and
// val.
// 
// RETURNS: the index to the VALUE or zero if there is none.
//
static REBCNT Find_Entry(REBSER *series, REBVAL *key, REBVAL *val)
{
    REBSER *hser = series->extra.series; // can be null
    REBCNT *hashes;
    REBCNT hash;
    REBVAL *v;
    REBCNT n;

    if (IS_NONE(key)) return 0;

    // We may not be large enough yet for the hash table to
    // be worthwhile, so just do a linear search:
    if (!hser) {
        if (series->tail < MIN_DICT*2) {
            v = BLK_HEAD(series);
            if (ANY_WORD(key)) {
                for (n = 0; n < series->tail; n += 2, v += 2) {
                    if (
                        ANY_WORD(v)
                        && SAME_SYM(VAL_WORD_SYM(key), VAL_WORD_SYM(v))
                    ) {
                        if (val) *++v = *val;
                        return n/2+1;
                    }
                }
            }
            else if (ANY_BINSTR(key)) {
                for (n = 0; n < series->tail; n += 2, v += 2) {
                    if (VAL_TYPE(key) == VAL_TYPE(v) && 0 == Compare_String_Vals(key, v, (REBOOL)!IS_BINARY(v))) {
                        if (val)
                            *++v = *val;

                        return n/2+1;
                    }
                }
            }
            else if (IS_INTEGER(key)) {
                for (n = 0; n < series->tail; n += 2, v += 2) {
                    if (IS_INTEGER(v) && VAL_INT64(key) == VAL_INT64(v)) {
                        if (val) *++v = *val;
                        return n/2+1;
                    }
                }
            }
            else if (IS_CHAR(key)) {
                for (n = 0; n < series->tail; n += 2, v += 2) {
                    if (IS_CHAR(v) && VAL_CHAR(key) == VAL_CHAR(v)) {
                        if (val) *++v = *val;
                        return n/2+1;
                    }
                }
            }
            else
                fail (Error_Has_Bad_Type(key));

            if (!val) return 0;
            Append_Value(series, key);
            Append_Value(series, val); // does not copy value, e.g. if string
            return series->tail/2;
        }

        // Add hash table:
        //Print("hash added %d", series->tail);
        series->extra.series = hser = Make_Hash_Sequence(series->tail);
        MANAGE_SERIES(hser);
        Rehash_Hash(series);
    }

    // Get hash table, expand it if needed:
    if (series->tail > hser->tail/2) {
        Expand_Hash(hser); // modifies size value
        Rehash_Hash(series);
    }

    hash = Find_Key(series, hser, key, 2, 0, 0);
    hashes = (REBCNT*)hser->data;
    n = hashes[hash];

    // Just a GET of value:
    if (!val) return n;

    // Must set the value:
    if (n) {  // re-set it:
        *BLK_SKIP(series, ((n-1)*2)+1) = *val; // set it
        return n;
    }

    // Create new entry:
    Append_Value(series, key);
    Append_Value(series, val);  // does not copy value, e.g. if string

    return (hashes[hash] = series->tail/2);
}
コード例 #2
0
ファイル: t-map.c プロジェクト: draegtun/ren-c
*/	static REBCNT Find_Entry(REBSER *series, REBVAL *key, REBVAL *val)
/*
**		Try to find the entry in the map. If not found
**		and val is SET, create the entry and store the key and
**		val.
**
**		RETURNS: the index to the VALUE or zero if there is none.
**
***********************************************************************/
{
	REBSER *hser = series->extra.series; // can be null
	REBCNT *hashes;
	REBCNT hash;
	REBVAL *v;
	REBCNT n;

	if (IS_NONE(key)) return 0;

	// We may not be large enough yet for the hash table to
	// be worthwhile, so just do a linear search:
	if (!hser) {
		if (series->tail < MIN_DICT*2) {
			v = BLK_HEAD(series);
			if (ANY_WORD(key)) {
				for (n = 0; n < series->tail; n += 2, v += 2) {
					if (ANY_WORD(v) && SAME_SYM(key, v)) {
						if (val) *++v = *val;
						return n/2+1;
					}
				}
			}
			else if (ANY_BINSTR(key)) {
				for (n = 0; n < series->tail; n += 2, v += 2) {
					if (VAL_TYPE(key) == VAL_TYPE(v) && 0 == Compare_String_Vals(key, v, (REBOOL)!IS_BINARY(v))) {
						if (val) {
							*++v = *val;
//							VAL_SERIES(v) = Copy_Series_Value(val);
//							VAL_INDEX(v) = 0;
						}
						return n/2+1;
					}
				}
			}
			else if (IS_INTEGER(key)) {
				for (n = 0; n < series->tail; n += 2, v += 2) {
					if (IS_INTEGER(v) && VAL_INT64(key) == VAL_INT64(v)) {
						if (val) *++v = *val;
						return n/2+1;
					}
				}
			}
			else if (IS_CHAR(key)) {
				for (n = 0; n < series->tail; n += 2, v += 2) {
					if (IS_CHAR(v) && VAL_CHAR(key) == VAL_CHAR(v)) {
						if (val) *++v = *val;
						return n/2+1;
					}
				}
			}
			else Trap_Type_DEAD_END(key);

			if (!val) return 0;
			Append_Value(series, key);
			Append_Value(series, val); // no Copy_Series_Value(val) on strings
			return series->tail/2;
		}

		// Add hash table:
		//Print("hash added %d", series->tail);
		series->extra.series = hser = Make_Hash_Array(series->tail);
		Rehash_Hash(series);
	}

	// Get hash table, expand it if needed:
	if (series->tail > hser->tail/2) {
		Expand_Hash(hser); // modifies size value
		Rehash_Hash(series);
	}

	hash = Find_Key(series, hser, key, 2, 0, 0);
	hashes = (REBCNT*)hser->data;
	n = hashes[hash];

	// Just a GET of value:
	if (!val) return n;

	// Must set the value:
	if (n) {  // re-set it:
		*BLK_SKIP(series, ((n-1)*2)+1) = *val; // set it
		return n;
	}

	// Create new entry:
	Append_Value(series, key);
	Append_Value(series, val);  // no Copy_Series_Value(val) on strings

	return (hashes[hash] = series->tail/2);
}