zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

string.zig (4479B) - Raw


      1 const builtin = @import("builtin");
      2 const std = @import("std");
      3 const common = @import("common.zig");
      4 
      5 comptime {
      6     @export(&strcmp, .{ .name = "strcmp", .linkage = common.linkage, .visibility = common.visibility });
      7     @export(&strlen, .{ .name = "strlen", .linkage = common.linkage, .visibility = common.visibility });
      8     @export(&strncmp, .{ .name = "strncmp", .linkage = common.linkage, .visibility = common.visibility });
      9     @export(&strcasecmp, .{ .name = "strcasecmp", .linkage = common.linkage, .visibility = common.visibility });
     10     @export(&strncasecmp, .{ .name = "strncasecmp", .linkage = common.linkage, .visibility = common.visibility });
     11     @export(&__strcasecmp_l, .{ .name = "__strcasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
     12     @export(&__strncasecmp_l, .{ .name = "__strncasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
     13     @export(&__strcasecmp_l, .{ .name = "strcasecmp_l", .linkage = .weak, .visibility = common.visibility });
     14     @export(&__strncasecmp_l, .{ .name = "strncasecmp_l", .linkage = .weak, .visibility = common.visibility });
     15 }
     16 
     17 fn strcmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
     18     // We need to perform unsigned comparisons.
     19     return switch (std.mem.orderZ(u8, @ptrCast(s1), @ptrCast(s2))) {
     20         .lt => -1,
     21         .eq => 0,
     22         .gt => 1,
     23     };
     24 }
     25 
     26 fn strncmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c) c_int {
     27     if (n == 0) return 0;
     28 
     29     var l: [*:0]const u8 = @ptrCast(s1);
     30     var r: [*:0]const u8 = @ptrCast(s2);
     31     var i = n - 1;
     32 
     33     while (l[0] != 0 and r[0] != 0 and i != 0 and l[0] == r[0]) {
     34         l += 1;
     35         r += 1;
     36         i -= 1;
     37     }
     38 
     39     return @as(c_int, l[0]) - @as(c_int, r[0]);
     40 }
     41 
     42 fn strcasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
     43     const toLower = std.ascii.toLower;
     44     var l: [*:0]const u8 = @ptrCast(s1);
     45     var r: [*:0]const u8 = @ptrCast(s2);
     46 
     47     while (l[0] != 0 and r[0] != 0 and (l[0] == r[0] or toLower(l[0]) == toLower(r[0]))) {
     48         l += 1;
     49         r += 1;
     50     }
     51 
     52     return @as(c_int, toLower(l[0])) - @as(c_int, toLower(r[0]));
     53 }
     54 
     55 fn __strcasecmp_l(s1: [*:0]const c_char, s2: [*:0]const c_char, locale: *anyopaque) callconv(.c) c_int {
     56     _ = locale;
     57     return strcasecmp(s1, s2);
     58 }
     59 
     60 fn strncasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c) c_int {
     61     const toLower = std.ascii.toLower;
     62     var l: [*:0]const u8 = @ptrCast(s1);
     63     var r: [*:0]const u8 = @ptrCast(s2);
     64     var i = n - 1;
     65 
     66     while (l[0] != 0 and r[0] != 0 and i != 0 and (l[0] == r[0] or toLower(l[0]) == toLower(r[0]))) {
     67         l += 1;
     68         r += 1;
     69         i -= 1;
     70     }
     71 
     72     return @as(c_int, toLower(l[0])) - @as(c_int, toLower(r[0]));
     73 }
     74 
     75 fn __strncasecmp_l(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize, locale: *anyopaque) callconv(.c) c_int {
     76     _ = locale;
     77     return strncasecmp(s1, s2, n);
     78 }
     79 
     80 test strcasecmp {
     81     try std.testing.expect(strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
     82     try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
     83     try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
     84     try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
     85     try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
     86     try std.testing.expect(strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
     87     try std.testing.expect(strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
     88 }
     89 
     90 test strncasecmp {
     91     try std.testing.expect(strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
     92     try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
     93     try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
     94     try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
     95     try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
     96     try std.testing.expect(strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
     97     try std.testing.expect(strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
     98 }
     99 
    100 test strncmp {
    101     try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
    102     try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
    103     try std.testing.expect(strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
    104     try std.testing.expect(strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
    105 }
    106 
    107 fn strlen(s: [*:0]const c_char) callconv(.c) usize {
    108     return std.mem.len(s);
    109 }