| 
					
				 | 
			
			
				@@ -571,31 +571,109 @@ smartlist_bsearch_idx(const smartlist_t *sl, const void *key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                       int (*compare)(const void *key, const void **member), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                       int *found_out) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  int hi = smartlist_len(sl) - 1, lo = 0, cmp, mid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int hi, lo, cmp, mid, len, diff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(sl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(compare); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(found_out); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  len = smartlist_len(sl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Check for the trivial case of a zero-length list */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (len == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *found_out = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* We already know smartlist_len(sl) is 0 in this case */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Okay, we have a real search to do */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(len > 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  lo = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  hi = len - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * These invariants are always true: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * For all i such that 0 <= i < lo, sl[i] < key 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * For all i such that hi < i <= len, sl[i] > key 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   while (lo <= hi) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mid = (lo + hi) / 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    diff = hi - lo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * We want mid = (lo + hi) / 2, but that could lead to overflow, so 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * instead diff = hi - lo (non-negative because of loop condition), and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * then hi = lo + diff, mid = (lo + lo + diff) / 2 = lo + (diff / 2). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mid = lo + (diff / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cmp = compare(key, (const void**) &(sl->list[mid])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (cmp>0) { /* key > sl[mid] */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      lo = mid+1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } else if (cmp<0) { /* key < sl[mid] */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      hi = mid-1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } else { /* key == sl[mid] */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (cmp == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* sl[mid] == key; we found it */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       *found_out = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return mid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* lo > hi. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    tor_assert(lo >= 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (lo < smartlist_len(sl)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      cmp = compare(key, (const void**) &(sl->list[lo])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if (cmp > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * key > sl[mid] and an index i such that sl[i] == key must 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * have i > mid if it exists. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * Since lo <= mid <= hi, hi can only decrease on each iteration (by 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * being set to mid - 1) and hi is initially len - 1, mid < len should 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * always hold, and this is not symmetric with the left end of list 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * mid > 0 test below.  A key greater than the right end of the list 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * should eventually lead to lo == hi == mid == len - 1, and then 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * we set lo to len below and fall out to the same exit we hit for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * a key in the middle of the list but not matching.  Thus, we just 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * assert for consistency here rather than handle a mid == len case. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      tor_assert(mid < len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* Move lo to the element immediately after sl[mid] */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      lo = mid + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* This should always be true in this case */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       tor_assert(cmp < 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } else if (smartlist_len(sl)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      cmp = compare(key, (const void**) &(sl->list[smartlist_len(sl)-1])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      tor_assert(cmp > 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * key < sl[mid] and an index i such that sl[i] == key must 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * have i < mid if it exists. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (mid > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* Normal case, move hi to the element immediately before sl[mid] */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        hi = mid - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* These should always be true in this case */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tor_assert(mid == lo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tor_assert(mid == 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * We were at the beginning of the list and concluded that every 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * element e compares e > key. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        *found_out = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * lo > hi; we have no element matching key but we have elements falling 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * on both sides of it.  The lo index points to the first element > key. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(lo == hi + 1); /* All other cases should have been handled */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(lo >= 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(lo <= len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(hi >= 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(hi <= len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (lo < len) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cmp = compare(key, (const void **) &(sl->list[lo])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tor_assert(cmp < 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cmp = compare(key, (const void **) &(sl->list[len-1])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tor_assert(cmp > 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   *found_out = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return lo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |