[前][次][番号順一覧][スレッド一覧]

ruby-changes:35706

From: nobu <ko1@a...>
Date: Sat, 4 Oct 2014 23:13:50 +0900 (JST)
Subject: [ruby-changes:35706] nobu:r47788 (trunk): st.c: update st_reverse_foreach

nobu	2014-10-04 23:13:36 +0900 (Sat, 04 Oct 2014)

  New Revision: 47788

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47788

  Log:
    st.c: update st_reverse_foreach
    
    * st.c (st_reverse_foreach): update as st_foreach().

  Modified files:
    trunk/st.c
Index: st.c
===================================================================
--- st.c	(revision 47787)
+++ st.c	(revision 47788)
@@ -1156,52 +1156,68 @@ st_values_check(st_table *table, st_data https://github.com/ruby/ruby/blob/trunk/st.c#L1156
 
 #if 0  /* unused right now */
 int
-st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
+st_reverse_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never)
 {
     st_table_entry *ptr, **last, *tmp;
     enum st_retval retval;
-    int i;
+    st_index_t i;
 
     if (table->entries_packed) {
-        for (i = table->num_entries-1; 0 <= i; i--) {
-            int j;
-            st_data_t key, val;
-            key = PKEY(table, i);
-            val = PVAL(table, i);
-            retval = (*func)(key, val, arg, 0);
-            switch (retval) {
+	for (i = table->real_entries; 0 < i;) {
+	    st_data_t key, val;
+	    st_index_t hash;
+	    --i;
+	    key = PKEY(table, i);
+	    val = PVAL(table, i);
+	    hash = PHASH(table, i);
+	    if (key == never) continue;
+	    retval = (*func)(key, val, arg, 0);
+	    if (!table->entries_packed) {
+		FIND_ENTRY(table, ptr, hash, i);
+		if (retval == ST_CHECK) {
+		    if (!ptr) goto deleted;
+		    goto unpacked_continue;
+		}
+		goto unpacked;
+	    }
+	    switch (retval) {
 	      case ST_CHECK:	/* check if hash is modified during iteration */
-                for (j = 0; j < table->num_entries; j++) {
-                    if (PKEY(table, j) == key)
-                        break;
-                }
-                if (j == table->num_entries) {
-                    /* call func with error notice */
-                    retval = (*func)(0, 0, arg, 1);
-                    return 1;
-                }
+		if (PHASH(table, i) == 0 && PKEY(table, i) == never) {
+		    break;
+		}
+		i = find_packed_index_from(table, hash, key, i);
+		if (i >= table->real_entries) {
+		    i = find_packed_index(table, hash, key);
+		    if (i >= table->real_entries) goto deleted;
+		}
 		/* fall through */
 	      case ST_CONTINUE:
 		break;
 	      case ST_STOP:
 		return 0;
 	      case ST_DELETE:
-		remove_packed_entry(table, i);
-                break;
-            }
-        }
-        return 0;
+		remove_safe_packed_entry(table, i, never);
+		break;
+	    }
+	}
+	return 0;
+    }
+    else {
+	ptr = table->tail;
     }
 
-    if ((ptr = table->head) != 0) {
-	ptr = ptr->back;
+    if (ptr != 0) {
 	do {
+	    if (ptr->key == never)
+		goto unpacked_continue;
+	    i = hash_pos(ptr->hash, table->num_bins);
 	    retval = (*func)(ptr->key, ptr->record, arg, 0);
+	  unpacked:
 	    switch (retval) {
 	      case ST_CHECK:	/* check if hash is modified during iteration */
-		i = hash_pos(ptr->hash, table->num_bins);
 		for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) {
 		    if (!tmp) {
+		      deleted:
 			/* call func with error notice */
 			retval = (*func)(0, 0, arg, 1);
 			return 1;
@@ -1209,8 +1225,77 @@ st_reverse_foreach(st_table *table, int https://github.com/ruby/ruby/blob/trunk/st.c#L1225
 		}
 		/* fall through */
 	      case ST_CONTINUE:
+	      unpacked_continue:
+		ptr = ptr->back;
+		break;
+	      case ST_STOP:
+		return 0;
+	      case ST_DELETE:
+		last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
+		for (; (tmp = *last) != 0; last = &tmp->next) {
+		    if (ptr == tmp) {
+			tmp = ptr->back;
+			remove_entry(table, ptr);
+			ptr->key = ptr->record = never;
+			ptr->hash = 0;
+			ptr = tmp;
+			break;
+		    }
+		}
+	    }
+	} while (ptr && table->head);
+    }
+    return 0;
+}
+
+int
+st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
+{
+    st_table_entry *ptr, **last, *tmp;
+    enum st_retval retval;
+    st_index_t i;
+
+    if (table->entries_packed) {
+	for (i = table->real_entries; 0 < i;) {
+	    st_data_t key, val;
+	    st_index_t hash;
+	    --i;
+	    key = PKEY(table, i);
+	    val = PVAL(table, i);
+	    hash = PHASH(table, i);
+	    retval = (*func)(key, val, arg, 0);
+	    if (!table->entries_packed) {
+		FIND_ENTRY(table, ptr, hash, i);
+		if (!ptr) return 0;
+		goto unpacked;
+	    }
+	    switch (retval) {
+	      case ST_CONTINUE:
+		break;
+	      case ST_CHECK:
+	      case ST_STOP:
+		return 0;
+	      case ST_DELETE:
+		remove_packed_entry(table, i);
+		break;
+	    }
+	}
+	return 0;
+    }
+    else {
+	ptr = table->tail;
+    }
+
+    if (ptr != 0) {
+	do {
+	    i = hash_pos(ptr->hash, table->num_bins);
+	    retval = (*func)(ptr->key, ptr->record, arg, 0);
+	  unpacked:
+	    switch (retval) {
+	      case ST_CONTINUE:
 		ptr = ptr->back;
 		break;
+	      case ST_CHECK:
 	      case ST_STOP:
 		return 0;
 	      case ST_DELETE:
@@ -1225,9 +1310,6 @@ st_reverse_foreach(st_table *table, int https://github.com/ruby/ruby/blob/trunk/st.c#L1310
 			break;
 		    }
 		}
-		ptr = ptr->next;
-		free(tmp);
-		table->num_entries--;
 	    }
 	} while (ptr && table->head);
     }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]