Skip to content

Commit

Permalink
Merge branch 'pr/969' into devel
Browse files Browse the repository at this point in the history
  • Loading branch information
glasser committed May 7, 2013
2 parents aa83b9d + 69644fd commit 28fbbc8
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 10 deletions.
4 changes: 3 additions & 1 deletion History.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@
the existence of `window.localStorage` to detect if the full localStorage API
is supported.) #979

* Use binary search in minimongo when updating ordered queries. #969

* Fix EJSON base64 decoding bug. #1001

* Support `appcache` on Chromium. #958

Patches contributed by GitHub users awwx and spang.
Patches contributed by GitHub users awwx, jagill, and spang.

## v0.6.2.1

Expand Down
29 changes: 20 additions & 9 deletions packages/minimongo/minimongo.js
Original file line number Diff line number Diff line change
Expand Up @@ -694,21 +694,32 @@ LocalCollection._findInOrderedResults = function (query, doc) {
throw Error("object missing from query");
};

// This binary search puts a value between any equal values, and the first
// lesser value.
LocalCollection._binarySearch = function (cmp, array, value) {
var first = 0, rangeLength = array.length;

while (rangeLength > 0) {
var halfRange = Math.floor(rangeLength/2);
if (cmp(value, array[first + halfRange]) >= 0) {
first += halfRange + 1;
rangeLength -= halfRange + 1;
} else {
rangeLength = halfRange;
}
}
return first;
};

LocalCollection._insertInSortedList = function (cmp, array, value) {
if (array.length === 0) {
array.push(value);
return 0;
}

for (var i = 0; i < array.length; i++) {
if (cmp(value, array[i]) < 0) {
array.splice(i, 0, value);
return i;
}
}

array.push(value);
return array.length - 1;
var idx = LocalCollection._binarySearch(cmp, array, value);
array.splice(idx, 0, value);
return idx;
};

// To track what documents are affected by a piece of code, call saveOriginals()
Expand Down
56 changes: 56 additions & 0 deletions packages/minimongo/minimongo_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,62 @@ Tinytest.add("minimongo - array sort", function (test) {
_.range(c.find().count()));
});

Tinytest.add("minimongo - binary search", function (test) {
var forwardCmp = function (a, b) {
return a - b;
};

var backwardCmp = function (a, b) {
return -1 * forwardCmp(a, b);
};

var checkSearch = function (cmp, array, value, expected, message) {
var actual = LocalCollection._binarySearch(cmp, array, value);
if (expected != actual) {
test.fail({type: "minimongo-binary-search",
message: message + " : Expected index " + expected +
" but had " + actual
});
}
};

var checkSearchForward = function (array, value, expected, message) {
checkSearch(forwardCmp, array, value, expected, message);
};
var checkSearchBackward = function (array, value, expected, message) {
checkSearch(backwardCmp, array, value, expected, message);
};

checkSearchForward([1, 2, 5, 7], 4, 2, "Inner insert");
checkSearchForward([1, 2, 3, 4], 3, 3, "Inner insert, equal value");
checkSearchForward([1, 2, 5], 4, 2, "Inner insert, odd length");
checkSearchForward([1, 3, 5, 6], 9, 4, "End insert");
checkSearchForward([1, 3, 5, 6], 0, 0, "Beginning insert");
checkSearchForward([1], 0, 0, "Single array, less than.");
checkSearchForward([1], 1, 1, "Single array, equal.");
checkSearchForward([1], 2, 1, "Single array, greater than.");
checkSearchForward([], 1, 0, "Empty array");
checkSearchForward([1, 1, 1, 2, 2, 2, 2], 1, 3, "Highly degenerate array, lower");
checkSearchForward([1, 1, 1, 2, 2, 2, 2], 2, 7, "Highly degenerate array, upper");
checkSearchForward([2, 2, 2, 2, 2, 2, 2], 1, 0, "Highly degenerate array, lower");
checkSearchForward([2, 2, 2, 2, 2, 2, 2], 2, 7, "Highly degenerate array, equal");
checkSearchForward([2, 2, 2, 2, 2, 2, 2], 3, 7, "Highly degenerate array, upper");

checkSearchBackward([7, 5, 2, 1], 4, 2, "Backward: Inner insert");
checkSearchBackward([4, 3, 2, 1], 3, 2, "Backward: Inner insert, equal value");
checkSearchBackward([5, 2, 1], 4, 1, "Backward: Inner insert, odd length");
checkSearchBackward([6, 5, 3, 1], 9, 0, "Backward: Beginning insert");
checkSearchBackward([6, 5, 3, 1], 0, 4, "Backward: End insert");
checkSearchBackward([1], 0, 1, "Backward: Single array, less than.");
checkSearchBackward([1], 1, 1, "Backward: Single array, equal.");
checkSearchBackward([1], 2, 0, "Backward: Single array, greater than.");
checkSearchBackward([], 1, 0, "Backward: Empty array");
checkSearchBackward([2, 2, 2, 2, 1, 1, 1], 1, 7, "Backward: Degenerate array, lower");
checkSearchBackward([2, 2, 2, 2, 1, 1, 1], 2, 4, "Backward: Degenerate array, upper");
checkSearchBackward([2, 2, 2, 2, 2, 2, 2], 1, 7, "Backward: Highly degenerate array, upper");
checkSearchBackward([2, 2, 2, 2, 2, 2, 2], 2, 7, "Backward: Highly degenerate array, upper");
checkSearchBackward([2, 2, 2, 2, 2, 2, 2], 3, 0, "Backward: Highly degenerate array, upper");
});

Tinytest.add("minimongo - modify", function (test) {
var modify = function (doc, mod, result) {
Expand Down

0 comments on commit 28fbbc8

Please sign in to comment.