Project

General

Profile

Backport #8328 ยป backport_fix_shift.diff

funny_falcon (Yura Sokolov), 06/02/2013 08:42 PM

View differences:

hash.c
824 824
};
825 825

  
826 826
static int
827
shift_i(VALUE key, VALUE value, VALUE arg)
828
{
829
    struct shift_var *var = (struct shift_var *)arg;
830

  
831
    if (key == Qundef) return ST_CONTINUE;
832
    if (var->key != Qundef) return ST_STOP;
833
    var->key = key;
834
    var->val = value;
835
    return ST_DELETE;
836
}
837

  
838
static int
839 827
shift_i_safe(VALUE key, VALUE value, VALUE arg)
840 828
{
841 829
    struct shift_var *var = (struct shift_var *)arg;
......
866 854

  
867 855
    rb_hash_modify(hash);
868 856
    var.key = Qundef;
869
    rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i,
870
		    (VALUE)&var);
857
    if (RHASH(hash)->iter_lev == 0) {
858
	if (st_shift(RHASH(hash)->ntbl, &var.key, &var.val)) {
859
	    return rb_assoc_new(var.key, var.val);
860
	}
861
    }
862
    else {
863
	rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
871 864

  
872
    if (var.key != Qundef) {
873
	if (RHASH(hash)->iter_lev > 0) {
865
	if (var.key != Qundef) {
874 866
	    rb_hash_delete_key(hash, var.key);
867
	    return rb_assoc_new(var.key, var.val);
875 868
	}
876
	return rb_assoc_new(var.key, var.val);
877 869
    }
878
    else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
870
    if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
879 871
	return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil);
880 872
    }
881 873
    else {
include/ruby/st.h
109 109
st_table *st_init_strcasetable_with_size(st_index_t);
110 110
int st_delete(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */
111 111
int st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t);
112
int st_shift(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */
112 113
int st_insert(st_table *, st_data_t, st_data_t);
113 114
int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t));
114 115
int st_lookup(st_table *, st_data_t, st_data_t *);
st.c
695 695
    return 0;
696 696
}
697 697

  
698
int
699
st_shift(register st_table *table, register st_data_t *key, st_data_t *value)
700
{
701
    st_index_t hash_val;
702
    st_table_entry **prev;
703
    register st_table_entry *ptr;
704

  
705
    if (table->num_entries == 0) {
706
        if (value != 0) *value = 0;
707
        return 0;
708
    }
709

  
710
    if (table->entries_packed) {
711
        if (value != 0) *value = (st_data_t)table->bins[1];
712
        *key = (st_data_t)table->bins[0];
713
        table->num_entries--;
714
        memmove(&table->bins[0], &table->bins[2],
715
                sizeof(struct st_table_entry*) * 2*table->num_entries);
716
        return 1;
717
    }
718

  
719
    hash_val = do_hash_bin(table->head->key, table);
720
    prev = &table->bins[hash_val];
721
    for (;(ptr = *prev) != 0; prev = &ptr->next) {
722
	if (ptr == table->head) {
723
	    *prev = ptr->next;
724
            REMOVE_ENTRY(table, ptr);
725
            if (value != 0) *value = ptr->record;
726
            *key = ptr->key;
727
            free(ptr);
728
            return 1;
729
	}
730
    }
731

  
732
    /* if hash is not consistent and need to be rehashed */
733
    if (value != 0) *value = 0;
734
    return 0;
735
}
736

  
698 737
void
699 738
st_cleanup_safe(st_table *table, st_data_t never)
700 739
{