/*
 *  call-seq:
 *     hsh.shift -> anArray or obj
 *  
 *  Removes a key-value pair from <i>hsh</i> and returns it as the
 *  two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
 *  the hash's default value if the hash is empty.
 *     
 *     h = { 1 => "a", 2 => "b", 3 => "c" }
 *     h.shift   #=> [1, "a"]
 *     h         #=> {2=>"b", 3=>"c"}
 */

static VALUE
rb_hash_shift(hash)
    VALUE hash;
{
    struct shift_var var;

    rb_hash_modify(hash);
    var.key = Qundef;
    if (RHASH(hash)->iter_lev > 0) {
        rb_hash_foreach(hash, shift_i_safe, (st_data_t)&var);
        if (var.key != Qundef) {
            st_data_t key = var.key;
            if (st_delete_safe(RHASH(hash)->tbl, &key, 0, Qundef)) {
                FL_SET(hash, HASH_DELETED);
            }
        }
    }
    else {
        rb_hash_foreach(hash, shift_i, (st_data_t)&var);
    }

    if (var.key != Qundef) {
        return rb_assoc_new(var.key, var.val);
    }
    else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
        return rb_funcall(RHASH(hash)->ifnone, id_call, 2, hash, Qnil);
    }
    else {
        return RHASH(hash)->ifnone;
    }
}