mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Merge e97d3f043f into 53e615b920
This commit is contained in:
commit
86ab6e3480
14 changed files with 172 additions and 376 deletions
|
|
@ -17,11 +17,11 @@ comptime {
|
|||
_ = @import("c/inttypes.zig");
|
||||
_ = @import("c/stdlib.zig");
|
||||
_ = @import("c/math.zig");
|
||||
_ = @import("c/string.zig");
|
||||
_ = @import("c/strings.zig");
|
||||
|
||||
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
||||
// Files specific to musl and wasi-libc.
|
||||
_ = @import("c/string.zig");
|
||||
_ = @import("c/strings.zig");
|
||||
}
|
||||
|
||||
if (builtin.target.isMuslLibC()) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const builtin = @import("builtin");
|
|||
|
||||
comptime {
|
||||
if (builtin.target.isMinGW()) {
|
||||
// Files specific to MinGW-w64.
|
||||
@export(&isnan, .{ .name = "isnan", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&isnan, .{ .name = "__isnan", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&isnanf, .{ .name = "isnanf", .linkage = common.linkage, .visibility = common.visibility });
|
||||
|
|
|
|||
203
lib/c/string.zig
203
lib/c/string.zig
|
|
@ -3,30 +3,44 @@ const std = @import("std");
|
|||
const common = @import("common.zig");
|
||||
|
||||
comptime {
|
||||
@export(&strcmp, .{ .name = "strcmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strncmp, .{ .name = "strncmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strcasecmp, .{ .name = "strcasecmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strncasecmp, .{ .name = "strncasecmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&__strcasecmp_l, .{ .name = "__strcasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&__strncasecmp_l, .{ .name = "__strncasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&__strcasecmp_l, .{ .name = "strcasecmp_l", .linkage = .weak, .visibility = common.visibility });
|
||||
@export(&__strncasecmp_l, .{ .name = "strncasecmp_l", .linkage = .weak, .visibility = common.visibility });
|
||||
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
||||
// Functions specific to musl and wasi-libc.
|
||||
@export(&strcmp, .{ .name = "strcmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strncmp, .{ .name = "strncmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strcasecmp, .{ .name = "strcasecmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strncasecmp, .{ .name = "strncasecmp", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&__strcasecmp_l, .{ .name = "__strcasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&__strncasecmp_l, .{ .name = "__strncasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&__strcasecmp_l, .{ .name = "strcasecmp_l", .linkage = .weak, .visibility = common.visibility });
|
||||
@export(&__strncasecmp_l, .{ .name = "strncasecmp_l", .linkage = .weak, .visibility = common.visibility });
|
||||
@export(&strspn, .{ .name = "strspn", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strcspn, .{ .name = "strcspn", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strpbrk, .{ .name = "strpbrk", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strstr, .{ .name = "strstr", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strtok, .{ .name = "strtok", .linkage = common.linkage, .visibility = common.visibility });
|
||||
@export(&strtok_r, .{ .name = "strtok_r", .linkage = common.linkage, .visibility = common.visibility });
|
||||
}
|
||||
|
||||
if (builtin.target.isMinGW()) {
|
||||
// Files specific to MinGW-w64.
|
||||
@export(&strtok_r, .{ .name = "strtok_r", .linkage = common.linkage, .visibility = common.visibility });
|
||||
}
|
||||
}
|
||||
|
||||
fn strcmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
|
||||
fn strcmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) c_int {
|
||||
// We need to perform unsigned comparisons.
|
||||
return switch (std.mem.orderZ(u8, @ptrCast(s1), @ptrCast(s2))) {
|
||||
return switch (std.mem.orderZ(u8, s1, s2)) {
|
||||
.lt => -1,
|
||||
.eq => 0,
|
||||
.gt => 1,
|
||||
};
|
||||
}
|
||||
|
||||
fn strncmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c) c_int {
|
||||
fn strncmp(s1: [*:0]const u8, s2: [*:0]const u8, n: usize) callconv(.c) c_int {
|
||||
if (n == 0) return 0;
|
||||
|
||||
var l: [*:0]const u8 = @ptrCast(s1);
|
||||
var r: [*:0]const u8 = @ptrCast(s2);
|
||||
var l = s1;
|
||||
var r = s2;
|
||||
var i = n - 1;
|
||||
|
||||
while (l[0] != 0 and r[0] != 0 and i != 0 and l[0] == r[0]) {
|
||||
|
|
@ -38,10 +52,10 @@ fn strncmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c)
|
|||
return @as(c_int, l[0]) - @as(c_int, r[0]);
|
||||
}
|
||||
|
||||
fn strcasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
|
||||
fn strcasecmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) c_int {
|
||||
const toLower = std.ascii.toLower;
|
||||
var l: [*:0]const u8 = @ptrCast(s1);
|
||||
var r: [*:0]const u8 = @ptrCast(s2);
|
||||
var l = s1;
|
||||
var r = s2;
|
||||
|
||||
while (l[0] != 0 and r[0] != 0 and (l[0] == r[0] or toLower(l[0]) == toLower(r[0]))) {
|
||||
l += 1;
|
||||
|
|
@ -51,15 +65,15 @@ fn strcasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
|
|||
return @as(c_int, toLower(l[0])) - @as(c_int, toLower(r[0]));
|
||||
}
|
||||
|
||||
fn __strcasecmp_l(s1: [*:0]const c_char, s2: [*:0]const c_char, locale: *anyopaque) callconv(.c) c_int {
|
||||
fn __strcasecmp_l(s1: [*:0]const u8, s2: [*:0]const u8, locale: *anyopaque) callconv(.c) c_int {
|
||||
_ = locale;
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
|
||||
fn strncasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c) c_int {
|
||||
fn strncasecmp(s1: [*:0]const u8, s2: [*:0]const u8, n: usize) callconv(.c) c_int {
|
||||
const toLower = std.ascii.toLower;
|
||||
var l: [*:0]const u8 = @ptrCast(s1);
|
||||
var r: [*:0]const u8 = @ptrCast(s2);
|
||||
var l = s1;
|
||||
var r = s2;
|
||||
var i = n - 1;
|
||||
|
||||
while (l[0] != 0 and r[0] != 0 and i != 0 and (l[0] == r[0] or toLower(l[0]) == toLower(r[0]))) {
|
||||
|
|
@ -71,34 +85,145 @@ fn strncasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(
|
|||
return @as(c_int, toLower(l[0])) - @as(c_int, toLower(r[0]));
|
||||
}
|
||||
|
||||
fn __strncasecmp_l(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize, locale: *anyopaque) callconv(.c) c_int {
|
||||
fn __strncasecmp_l(s1: [*:0]const u8, s2: [*:0]const u8, n: usize, locale: *anyopaque) callconv(.c) c_int {
|
||||
_ = locale;
|
||||
return strncasecmp(s1, s2, n);
|
||||
}
|
||||
|
||||
test strcasecmp {
|
||||
try std.testing.expect(strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
|
||||
try std.testing.expect(strcasecmp("a", "b") < 0);
|
||||
try std.testing.expect(strcasecmp("b", "a") > 0);
|
||||
try std.testing.expect(strcasecmp("A", "b") < 0);
|
||||
try std.testing.expect(strcasecmp("b", "A") > 0);
|
||||
try std.testing.expect(strcasecmp("A", "A") == 0);
|
||||
try std.testing.expect(strcasecmp("B", "b") == 0);
|
||||
try std.testing.expect(strcasecmp("bb", "AA") > 0);
|
||||
}
|
||||
|
||||
test strncasecmp {
|
||||
try std.testing.expect(strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
|
||||
try std.testing.expect(strncasecmp("a", "b", 1) < 0);
|
||||
try std.testing.expect(strncasecmp("b", "a", 1) > 0);
|
||||
try std.testing.expect(strncasecmp("A", "b", 1) < 0);
|
||||
try std.testing.expect(strncasecmp("b", "A", 1) > 0);
|
||||
try std.testing.expect(strncasecmp("A", "A", 1) == 0);
|
||||
try std.testing.expect(strncasecmp("B", "b", 1) == 0);
|
||||
try std.testing.expect(strncasecmp("bb", "AA", 2) > 0);
|
||||
}
|
||||
|
||||
test strncmp {
|
||||
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
|
||||
try std.testing.expect(strncmp("a", "b", 1) < 0);
|
||||
try std.testing.expect(strncmp("a", "c", 1) < 0);
|
||||
try std.testing.expect(strncmp("b", "a", 1) > 0);
|
||||
try std.testing.expect(strncmp("\xff", "\x02", 1) > 0);
|
||||
}
|
||||
|
||||
fn strspn(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) usize {
|
||||
const slice1 = std.mem.span(s1);
|
||||
const slice2 = std.mem.span(s2);
|
||||
return std.mem.indexOfNone(u8, slice1, slice2) orelse slice1.len;
|
||||
}
|
||||
|
||||
test strspn {
|
||||
try std.testing.expectEqual(0, strspn("foobarbaz", ""));
|
||||
try std.testing.expectEqual(0, strspn("foobarbaz", "c"));
|
||||
try std.testing.expectEqual(3, strspn("foobarbaz", "fo"));
|
||||
try std.testing.expectEqual(9, strspn("foobarbaz", "fobarz"));
|
||||
try std.testing.expectEqual(9, strspn("foobarbaz", "abforz"));
|
||||
}
|
||||
|
||||
fn strcspn(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) usize {
|
||||
const slice1 = std.mem.span(s1);
|
||||
const slice2 = std.mem.span(s2);
|
||||
return std.mem.indexOfAny(u8, slice1, slice2) orelse slice1.len;
|
||||
}
|
||||
|
||||
test strcspn {
|
||||
try std.testing.expectEqual(0, strcspn("foobarbaz", "f"));
|
||||
try std.testing.expectEqual(3, strcspn("foobarbaz", "rab"));
|
||||
try std.testing.expectEqual(4, strcspn("foobarbaz", "ra"));
|
||||
try std.testing.expectEqual(9, strcspn("foobarbaz", ""));
|
||||
}
|
||||
|
||||
fn strpbrk(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) ?[*:0]const u8 {
|
||||
const slice1 = std.mem.span(s1);
|
||||
const slice2 = std.mem.span(s2);
|
||||
const index = std.mem.indexOfAny(u8, slice1, slice2) orelse
|
||||
return null;
|
||||
return s1 + index;
|
||||
}
|
||||
|
||||
test strpbrk {
|
||||
try std.testing.expectEqualStrings("barbaz", std.mem.span(strpbrk("foobarbaz", "rab").?));
|
||||
try std.testing.expectEqualStrings("arbaz", std.mem.span(strpbrk("foobarbaz", "ra").?));
|
||||
try std.testing.expectEqual(null, strpbrk("foobarbaz", ""));
|
||||
}
|
||||
|
||||
fn strstr(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) ?[*:0]const u8 {
|
||||
const slice1 = std.mem.span(s1);
|
||||
const slice2 = std.mem.span(s2);
|
||||
const index = std.mem.indexOf(u8, slice1, slice2) orelse
|
||||
return null;
|
||||
return s1 + index;
|
||||
}
|
||||
|
||||
test strstr {
|
||||
try std.testing.expectEqualStrings("barbaz", std.mem.span(strstr("foobarbaz", "ba").?));
|
||||
try std.testing.expectEqualStrings("foobarbaz", std.mem.span(strstr("foobarbaz", "fo").?));
|
||||
try std.testing.expectEqualStrings("foobarbaz", std.mem.span(strstr("foobarbaz", "f").?));
|
||||
try std.testing.expectEqualStrings("foobarbaz", std.mem.span(strstr("foobarbaz", "").?));
|
||||
try std.testing.expectEqual(null, strstr("foobarbaz", "boofarfaz"));
|
||||
try std.testing.expectEqual(null, strstr("foobarbaz", "fa"));
|
||||
try std.testing.expectEqual(null, strstr("foobarbaz", "c"));
|
||||
}
|
||||
|
||||
fn strtok_r(s: ?[*:0]u8, sep: [*:0]const u8, lasts: *?[*:0]u8) callconv(.c) ?[*:0]u8 {
|
||||
const slice = std.mem.span(s orelse lasts.* orelse return null);
|
||||
const delim = std.mem.span(sep);
|
||||
const index = std.mem.indexOfNone(u8, slice, delim) orelse {
|
||||
lasts.* = null;
|
||||
return null;
|
||||
};
|
||||
if (std.mem.indexOfAny(u8, slice[index..], delim)) |len| {
|
||||
slice[index + len] = 0;
|
||||
lasts.* = slice[index + len + 1 ..];
|
||||
} else {
|
||||
lasts.* = null;
|
||||
}
|
||||
return slice[index..];
|
||||
}
|
||||
|
||||
fn strtok(s: ?[*:0]u8, sep: [*:0]const u8) callconv(.c) ?[*:0]u8 {
|
||||
const static = struct {
|
||||
var lasts: ?[*:0]u8 = null;
|
||||
};
|
||||
return strtok_r(s, sep, &static.lasts);
|
||||
}
|
||||
|
||||
test strtok {
|
||||
var str = "?a???b,,,#c?#,".*;
|
||||
{
|
||||
const ret = strtok(&str, "?");
|
||||
try std.testing.expectEqual(str[1..], ret);
|
||||
try std.testing.expectEqualStrings("a", std.mem.span(ret.?));
|
||||
}
|
||||
{
|
||||
const ret = strtok(null, ",");
|
||||
try std.testing.expectEqual(str[3..], ret);
|
||||
try std.testing.expectEqualStrings("??b", std.mem.span(ret.?));
|
||||
}
|
||||
{
|
||||
const ret = strtok(null, "#,");
|
||||
try std.testing.expectEqual(str[10..], ret);
|
||||
try std.testing.expectEqualStrings("c?", std.mem.span(ret.?));
|
||||
}
|
||||
{
|
||||
const ret = strtok(null, "?");
|
||||
try std.testing.expectEqual(str[13..], ret);
|
||||
try std.testing.expectEqualStrings(",", std.mem.span(ret.?));
|
||||
}
|
||||
{
|
||||
const ret = strtok(null, "?");
|
||||
try std.testing.expectEqual(null, ret);
|
||||
}
|
||||
try std.testing.expectEqualSlices(u8, "?a" ++ .{0} ++ "??b" ++ .{0} ++ ",,#c?" ++ .{0} ++ ",", &str);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const common = @import("common.zig");
|
||||
|
||||
comptime {
|
||||
@export(&bzero, .{ .name = "bzero", .linkage = common.linkage, .visibility = common.visibility });
|
||||
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
|
||||
// Functions specific to musl and wasi-libc.
|
||||
@export(&bzero, .{ .name = "bzero", .linkage = common.linkage, .visibility = common.visibility });
|
||||
}
|
||||
}
|
||||
|
||||
fn bzero(s: *anyopaque, n: usize) callconv(.c) void {
|
||||
|
|
|
|||
98
lib/libc/mingw/stdio/strtok_r.c
vendored
98
lib/libc/mingw/stdio/strtok_r.c
vendored
|
|
@ -1,98 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1998 Softweyr LLC. All rights reserved.
|
||||
*
|
||||
* strtok_r, from Berkeley strtok
|
||||
* Oct 13, 1998 by Wes Peters <wes@softweyr.com>
|
||||
*
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notices, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notices, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE
|
||||
* REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define _POSIX_SOURCE 1
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* strtok_r documentation:
|
||||
* http://pubs.opengroup.org/onlinepubs/009695399/functions/strtok.html
|
||||
*
|
||||
* Implementation:
|
||||
* http://svnweb.freebsd.org/base/head/lib/libc/string/strtok.c?view=co
|
||||
*
|
||||
* strtok_r cannot completely be implemented by strtok because of the internal state.
|
||||
* It breaks when used on 2 strings where they are scanned A, B then A, B.
|
||||
* Thread-safety is not the issue.
|
||||
*
|
||||
* Sample strtok implemenatation, note the internal state:
|
||||
* char *strtok(char *s, const char *d) { static char *t; return strtok_r(s,d,t); }
|
||||
*
|
||||
*/
|
||||
|
||||
char *
|
||||
strtok_r(char * __restrict s, const char * __restrict delim, char ** __restrict last)
|
||||
{
|
||||
char *spanp, *tok;
|
||||
int c, sc;
|
||||
|
||||
if (s == NULL && (s = *last) == NULL)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
|
||||
*/
|
||||
cont:
|
||||
c = *s++;
|
||||
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
|
||||
if (c == sc)
|
||||
goto cont;
|
||||
}
|
||||
|
||||
if (c == 0) { /* no non-delimiter characters */
|
||||
*last = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
tok = s - 1;
|
||||
|
||||
/*
|
||||
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
|
||||
* Note that delim must have one NUL; we stop if we see that, too.
|
||||
*/
|
||||
for (;;) {
|
||||
c = *s++;
|
||||
spanp = (char *)delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = '\0';
|
||||
*last = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
17
lib/libc/musl/src/string/strcspn.c
vendored
17
lib/libc/musl/src/string/strcspn.c
vendored
|
|
@ -1,17 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
#define BITOP(a,b,op) \
|
||||
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
|
||||
|
||||
size_t strcspn(const char *s, const char *c)
|
||||
{
|
||||
const char *a = s;
|
||||
size_t byteset[32/sizeof(size_t)];
|
||||
|
||||
if (!c[0] || !c[1]) return __strchrnul(s, *c)-a;
|
||||
|
||||
memset(byteset, 0, sizeof byteset);
|
||||
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
|
||||
for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++);
|
||||
return s-a;
|
||||
}
|
||||
7
lib/libc/musl/src/string/strpbrk.c
vendored
7
lib/libc/musl/src/string/strpbrk.c
vendored
|
|
@ -1,7 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
char *strpbrk(const char *s, const char *b)
|
||||
{
|
||||
s += strcspn(s, b);
|
||||
return *s ? (char *)s : 0;
|
||||
}
|
||||
20
lib/libc/musl/src/string/strspn.c
vendored
20
lib/libc/musl/src/string/strspn.c
vendored
|
|
@ -1,20 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
#define BITOP(a,b,op) \
|
||||
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
|
||||
|
||||
size_t strspn(const char *s, const char *c)
|
||||
{
|
||||
const char *a = s;
|
||||
size_t byteset[32/sizeof(size_t)] = { 0 };
|
||||
|
||||
if (!c[0]) return 0;
|
||||
if (!c[1]) {
|
||||
for (; *s == *c; s++);
|
||||
return s-a;
|
||||
}
|
||||
|
||||
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
|
||||
for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++);
|
||||
return s-a;
|
||||
}
|
||||
154
lib/libc/musl/src/string/strstr.c
vendored
154
lib/libc/musl/src/string/strstr.c
vendored
|
|
@ -1,154 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
|
||||
{
|
||||
uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
|
||||
for (h++; *h && hw != nw; hw = hw<<8 | *++h);
|
||||
return *h ? (char *)h-1 : 0;
|
||||
}
|
||||
|
||||
static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
|
||||
{
|
||||
uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
|
||||
uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
|
||||
for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
|
||||
return *h ? (char *)h-2 : 0;
|
||||
}
|
||||
|
||||
static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
|
||||
{
|
||||
uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
|
||||
uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
|
||||
for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
|
||||
return *h ? (char *)h-3 : 0;
|
||||
}
|
||||
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
#define BITOP(a,b,op) \
|
||||
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
|
||||
|
||||
static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
|
||||
{
|
||||
const unsigned char *z;
|
||||
size_t l, ip, jp, k, p, ms, p0, mem, mem0;
|
||||
size_t byteset[32 / sizeof(size_t)] = { 0 };
|
||||
size_t shift[256];
|
||||
|
||||
/* Computing length of needle and fill shift table */
|
||||
for (l=0; n[l] && h[l]; l++)
|
||||
BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
|
||||
if (n[l]) return 0; /* hit the end of h */
|
||||
|
||||
/* Compute maximal suffix */
|
||||
ip = -1; jp = 0; k = p = 1;
|
||||
while (jp+k<l) {
|
||||
if (n[ip+k] == n[jp+k]) {
|
||||
if (k == p) {
|
||||
jp += p;
|
||||
k = 1;
|
||||
} else k++;
|
||||
} else if (n[ip+k] > n[jp+k]) {
|
||||
jp += k;
|
||||
k = 1;
|
||||
p = jp - ip;
|
||||
} else {
|
||||
ip = jp++;
|
||||
k = p = 1;
|
||||
}
|
||||
}
|
||||
ms = ip;
|
||||
p0 = p;
|
||||
|
||||
/* And with the opposite comparison */
|
||||
ip = -1; jp = 0; k = p = 1;
|
||||
while (jp+k<l) {
|
||||
if (n[ip+k] == n[jp+k]) {
|
||||
if (k == p) {
|
||||
jp += p;
|
||||
k = 1;
|
||||
} else k++;
|
||||
} else if (n[ip+k] < n[jp+k]) {
|
||||
jp += k;
|
||||
k = 1;
|
||||
p = jp - ip;
|
||||
} else {
|
||||
ip = jp++;
|
||||
k = p = 1;
|
||||
}
|
||||
}
|
||||
if (ip+1 > ms+1) ms = ip;
|
||||
else p = p0;
|
||||
|
||||
/* Periodic needle? */
|
||||
if (memcmp(n, n+p, ms+1)) {
|
||||
mem0 = 0;
|
||||
p = MAX(ms, l-ms-1) + 1;
|
||||
} else mem0 = l-p;
|
||||
mem = 0;
|
||||
|
||||
/* Initialize incremental end-of-haystack pointer */
|
||||
z = h;
|
||||
|
||||
/* Search loop */
|
||||
for (;;) {
|
||||
/* Update incremental end-of-haystack pointer */
|
||||
if (z-h < l) {
|
||||
/* Fast estimate for MAX(l,63) */
|
||||
size_t grow = l | 63;
|
||||
const unsigned char *z2 = memchr(z, 0, grow);
|
||||
if (z2) {
|
||||
z = z2;
|
||||
if (z-h < l) return 0;
|
||||
} else z += grow;
|
||||
}
|
||||
|
||||
/* Check last byte first; advance by shift on mismatch */
|
||||
if (BITOP(byteset, h[l-1], &)) {
|
||||
k = l-shift[h[l-1]];
|
||||
if (k) {
|
||||
if (k < mem) k = mem;
|
||||
h += k;
|
||||
mem = 0;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
h += l;
|
||||
mem = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Compare right half */
|
||||
for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
|
||||
if (n[k]) {
|
||||
h += k-ms;
|
||||
mem = 0;
|
||||
continue;
|
||||
}
|
||||
/* Compare left half */
|
||||
for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
|
||||
if (k <= mem) return (char *)h;
|
||||
h += p;
|
||||
mem = mem0;
|
||||
}
|
||||
}
|
||||
|
||||
char *strstr(const char *h, const char *n)
|
||||
{
|
||||
/* Return immediately on empty needle */
|
||||
if (!n[0]) return (char *)h;
|
||||
|
||||
/* Use faster algorithms for short needles */
|
||||
h = strchr(h, *n);
|
||||
if (!h || !n[1]) return (char *)h;
|
||||
if (!h[1]) return 0;
|
||||
if (!n[2]) return twobyte_strstr((void *)h, (void *)n);
|
||||
if (!h[2]) return 0;
|
||||
if (!n[3]) return threebyte_strstr((void *)h, (void *)n);
|
||||
if (!h[3]) return 0;
|
||||
if (!n[4]) return fourbyte_strstr((void *)h, (void *)n);
|
||||
|
||||
return twoway_strstr((void *)h, (void *)n);
|
||||
}
|
||||
13
lib/libc/musl/src/string/strtok.c
vendored
13
lib/libc/musl/src/string/strtok.c
vendored
|
|
@ -1,13 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
char *strtok(char *restrict s, const char *restrict sep)
|
||||
{
|
||||
static char *p;
|
||||
if (!s && !(s = p)) return NULL;
|
||||
s += strspn(s, sep);
|
||||
if (!*s) return p = 0;
|
||||
p = s + strcspn(s, sep);
|
||||
if (*p) *p++ = 0;
|
||||
else p = 0;
|
||||
return s;
|
||||
}
|
||||
12
lib/libc/musl/src/string/strtok_r.c
vendored
12
lib/libc/musl/src/string/strtok_r.c
vendored
|
|
@ -1,12 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
char *strtok_r(char *restrict s, const char *restrict sep, char **restrict p)
|
||||
{
|
||||
if (!s && !(s = *p)) return NULL;
|
||||
s += strspn(s, sep);
|
||||
if (!*s) return *p = 0;
|
||||
*p = s + strcspn(s, sep);
|
||||
if (**p) *(*p)++ = 0;
|
||||
else *p = 0;
|
||||
return s;
|
||||
}
|
||||
|
|
@ -740,7 +740,6 @@ const mingw32_generic_src = [_][]const u8{
|
|||
"stdio" ++ path.sep_str ++ "mingw_vswscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "snprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "snwprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "strtok_r.c",
|
||||
"stdio" ++ path.sep_str ++ "truncate.c",
|
||||
"stdio" ++ path.sep_str ++ "ulltoa.c",
|
||||
"stdio" ++ path.sep_str ++ "ulltow.c",
|
||||
|
|
|
|||
|
|
@ -1768,7 +1768,6 @@ const src_files = [_][]const u8{
|
|||
"musl/src/string/strchr.c",
|
||||
"musl/src/string/strchrnul.c",
|
||||
"musl/src/string/strcpy.c",
|
||||
"musl/src/string/strcspn.c",
|
||||
"musl/src/string/strdup.c",
|
||||
"musl/src/string/strerror_r.c",
|
||||
"musl/src/string/strlcat.c",
|
||||
|
|
@ -1777,14 +1776,9 @@ const src_files = [_][]const u8{
|
|||
"musl/src/string/strncpy.c",
|
||||
"musl/src/string/strndup.c",
|
||||
"musl/src/string/strnlen.c",
|
||||
"musl/src/string/strpbrk.c",
|
||||
"musl/src/string/strrchr.c",
|
||||
"musl/src/string/strsep.c",
|
||||
"musl/src/string/strsignal.c",
|
||||
"musl/src/string/strspn.c",
|
||||
"musl/src/string/strstr.c",
|
||||
"musl/src/string/strtok.c",
|
||||
"musl/src/string/strtok_r.c",
|
||||
"musl/src/string/strverscmp.c",
|
||||
"musl/src/string/swab.c",
|
||||
"musl/src/string/wcpcpy.c",
|
||||
|
|
|
|||
|
|
@ -1045,7 +1045,6 @@ const libc_top_half_src_files = [_][]const u8{
|
|||
"musl/src/string/strcat.c",
|
||||
"musl/src/string/strchr.c",
|
||||
"musl/src/string/strcpy.c",
|
||||
"musl/src/string/strcspn.c",
|
||||
"musl/src/string/strdup.c",
|
||||
"musl/src/string/strerror_r.c",
|
||||
"musl/src/string/strlcat.c",
|
||||
|
|
@ -1054,13 +1053,8 @@ const libc_top_half_src_files = [_][]const u8{
|
|||
"musl/src/string/strncpy.c",
|
||||
"musl/src/string/strndup.c",
|
||||
"musl/src/string/strnlen.c",
|
||||
"musl/src/string/strpbrk.c",
|
||||
"musl/src/string/strrchr.c",
|
||||
"musl/src/string/strsep.c",
|
||||
"musl/src/string/strspn.c",
|
||||
"musl/src/string/strstr.c",
|
||||
"musl/src/string/strtok.c",
|
||||
"musl/src/string/strtok_r.c",
|
||||
"musl/src/string/strverscmp.c",
|
||||
"musl/src/string/swab.c",
|
||||
"musl/src/string/wcpcpy.c",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue