std.mem.compare: breaking API changes

* `std.mem.Compare` is now `std.math.Order` and the enum tags
   renamed to follow new style convention.
 * `std.mem.compare` is renamed to `std.mem.order`.
 * new function `std.math.order`
This commit is contained in:
Andrew Kelley 2020-01-01 18:08:40 -05:00
parent 7b62d5dfd8
commit 5575e2a168
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
5 changed files with 63 additions and 61 deletions

View File

@ -224,7 +224,7 @@ test "crypto.chacha20 test vector sunscreen" {
// Chacha20 is self-reversing.
var plaintext: [114]u8 = undefined;
chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce);
testing.expect(mem.compare(u8, input, &plaintext) == mem.Compare.Equal);
testing.expect(mem.order(u8, input, &plaintext) == .eq);
}
// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7

View File

@ -70,12 +70,12 @@ const HeaderEntry = struct {
}
// Sort lexicographically on header name
return mem.compare(u8, a.name, b.name) == mem.Compare.LessThan;
return mem.order(u8, a.name, b.name) == .lt;
}
// Sort lexicographically on header value
if (!mem.eql(u8, a.value, b.value)) {
return mem.compare(u8, a.value, b.value) == mem.Compare.LessThan;
return mem.order(u8, a.value, b.value) == .lt;
}
// Doesn't matter here; need to pick something for sort consistency

View File

@ -926,9 +926,6 @@ test "minInt and maxInt" {
}
test "max value type" {
// If the type of maxInt(i32) was i32 then this implicit cast to
// u32 would not work. But since the value is a number literal,
// it works fine.
const x: u32 = maxInt(i32);
testing.expect(x == 2147483647);
}
@ -944,7 +941,32 @@ test "math.mulWide" {
testing.expect(mulWide(u8, 100, 100) == 10000);
}
/// Not to be confused with `std.mem.Compare`.
/// See also `CompareOperator`.
pub const Order = enum {
/// Less than (`<`)
lt,
/// Equal (`==`)
eq,
/// Greater than (`>`)
gt,
};
/// Given two numbers, this function returns the order they are with respect to each other.
pub fn order(a: var, b: var) Order {
if (a == b) {
return .eq;
} else if (a < b) {
return .lt;
} else if (a > b) {
return .gt;
} else {
unreachable;
}
}
/// See also `Order`.
pub const CompareOperator = enum {
/// Less than (`<`)
lt,
@ -979,7 +1001,7 @@ pub fn compare(a: var, op: CompareOperator, b: var) bool {
};
}
test "math.lt, et al < <= > >= between signed and unsigned" {
test "compare between signed and unsigned" {
testing.expect(compare(@as(i8, -1), .lt, @as(u8, 255)));
testing.expect(compare(@as(i8, 2), .gt, @as(u8, 1)));
testing.expect(!compare(@as(i8, -1), .gte, @as(u8, 255)));

View File

@ -239,12 +239,6 @@ pub const Allocator = struct {
}
};
pub const Compare = enum {
LessThan,
Equal,
GreaterThan,
};
/// Copy all of source into dest at position 0.
/// dest.len must be >= source.len.
/// dest.ptr must be <= src.ptr.
@ -297,46 +291,30 @@ test "mem.secureZero" {
testing.expectEqualSlices(u8, a[0..], b[0..]);
}
pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order {
const n = math.min(lhs.len, rhs.len);
var i: usize = 0;
while (i < n) : (i += 1) {
if (lhs[i] == rhs[i]) {
continue;
} else if (lhs[i] < rhs[i]) {
return Compare.LessThan;
} else if (lhs[i] > rhs[i]) {
return Compare.GreaterThan;
} else {
unreachable;
switch (math.order(lhs[i], rhs[i])) {
.eq => continue,
.lt => return .lt,
.gt => return .gt,
}
}
if (lhs.len == rhs.len) {
return Compare.Equal;
} else if (lhs.len < rhs.len) {
return Compare.LessThan;
} else if (lhs.len > rhs.len) {
return Compare.GreaterThan;
}
unreachable;
return math.order(lhs.len, rhs.len);
}
test "mem.compare" {
testing.expect(compare(u8, "abcd", "bee") == Compare.LessThan);
testing.expect(compare(u8, "abc", "abc") == Compare.Equal);
testing.expect(compare(u8, "abc", "abc0") == Compare.LessThan);
testing.expect(compare(u8, "", "") == Compare.Equal);
testing.expect(compare(u8, "", "a") == Compare.LessThan);
test "order" {
testing.expect(order(u8, "abcd", "bee") == .lt);
testing.expect(order(u8, "abc", "abc") == .eq);
testing.expect(order(u8, "abc", "abc0") == .lt);
testing.expect(order(u8, "", "") == .eq);
testing.expect(order(u8, "", "a") == .lt);
}
/// Returns true if lhs < rhs, false otherwise
pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
var result = compare(T, lhs, rhs);
if (result == Compare.LessThan) {
return true;
} else
return false;
return order(T, lhs, rhs) == .lt;
}
test "mem.lessThan" {

View File

@ -1,7 +1,7 @@
const std = @import("std.zig");
const assert = std.debug.assert;
const testing = std.testing;
const mem = std.mem; // For mem.Compare
const Order = std.math.Order;
const Color = enum(u1) {
Black,
@ -132,7 +132,7 @@ pub const Node = struct {
pub const Tree = struct {
root: ?*Node,
compareFn: fn (*Node, *Node) mem.Compare,
compareFn: fn (*Node, *Node) Order,
/// If you have a need for a version that caches this, please file a bug.
pub fn first(tree: *Tree) ?*Node {
@ -389,7 +389,7 @@ pub const Tree = struct {
var new = newconst;
// I assume this can get optimized out if the caller already knows.
if (tree.compareFn(old, new) != mem.Compare.Equal) return ReplaceError.NotEqual;
if (tree.compareFn(old, new) != .eq) return ReplaceError.NotEqual;
if (old.getParent()) |parent| {
parent.setChild(new, parent.left == old);
@ -404,7 +404,7 @@ pub const Tree = struct {
new.* = old.*;
}
pub fn init(tree: *Tree, f: fn (*Node, *Node) mem.Compare) void {
pub fn init(tree: *Tree, f: fn (*Node, *Node) Order) void {
tree.root = null;
tree.compareFn = f;
}
@ -469,19 +469,21 @@ fn doLookup(key: *Node, tree: *Tree, pparent: *?*Node, is_left: *bool) ?*Node {
is_left.* = false;
while (maybe_node) |node| {
var res: mem.Compare = tree.compareFn(node, key);
if (res == mem.Compare.Equal) {
const res = tree.compareFn(node, key);
if (res == .eq) {
return node;
}
pparent.* = node;
if (res == mem.Compare.GreaterThan) {
is_left.* = true;
maybe_node = node.left;
} else if (res == mem.Compare.LessThan) {
is_left.* = false;
maybe_node = node.right;
} else {
unreachable;
switch (res) {
.gt => {
is_left.* = true;
maybe_node = node.left;
},
.lt => {
is_left.* = false;
maybe_node = node.right;
},
.eq => unreachable, // handled above
}
}
return null;
@ -496,16 +498,16 @@ fn testGetNumber(node: *Node) *testNumber {
return @fieldParentPtr(testNumber, "node", node);
}
fn testCompare(l: *Node, r: *Node) mem.Compare {
fn testCompare(l: *Node, r: *Node) Order {
var left = testGetNumber(l);
var right = testGetNumber(r);
if (left.value < right.value) {
return mem.Compare.LessThan;
return .lt;
} else if (left.value == right.value) {
return mem.Compare.Equal;
return .eq;
} else if (left.value > right.value) {
return mem.Compare.GreaterThan;
return .gt;
}
unreachable;
}