155714Skris/*-
255714Skris * SPDX-License-Identifier: BSD-2-Clause
355714Skris *
455714Skris * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
555714Skris * All rights reserved.
655714Skris *
755714Skris * Redistribution and use in source and binary forms, with or without
8280304Sjkim * modification, are permitted provided that the following conditions
955714Skris * are met:
1055714Skris * 1. Redistributions of source code must retain the above copyright
1155714Skris *    notice, this list of conditions and the following disclaimer.
1255714Skris * 2. Redistributions in binary form must reproduce the above copyright
1355714Skris *    notice, this list of conditions and the following disclaimer in the
1455714Skris *    documentation and/or other materials provided with the distribution.
15280304Sjkim *
1655714Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1755714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1855714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1955714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2055714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2155714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22280304Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2355714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2455714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2555714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2655714Skris * SUCH DAMAGE.
2755714Skris */
2855714Skris
2955714Skris#include <sys/cdefs.h>
3055714Skris#include <sys/libkern.h>
3155714Skris#include <sys/types.h>
3255714Skris#include <sys/limits.h>
3355714Skris
3455714Skris#define	IDX(c)	((u_char)(c) / LONG_BIT)
3555714Skris#define	BIT(c)	((u_long)1 << ((u_char)(c) % LONG_BIT))
3655714Skris
37280304Sjkimsize_t
3855714Skrisstrcspn(const char *s, const char *charset)
3955714Skris{
40280304Sjkim	/*
4155714Skris	 * NB: idx and bit are temporaries whose use causes gcc 3.4.2 to
4255714Skris	 * generate better code.  Without them, gcc gets a little confused.
4355714Skris	 */
4455714Skris	const char *s1;
4555714Skris	u_long bit;
4655714Skris	u_long tbl[(UCHAR_MAX + 1) / LONG_BIT];
4755714Skris	int idx;
4855714Skris
4955714Skris	if(*s == '\0')
5055714Skris		return (0);
5155714Skris
52280304Sjkim#if LONG_BIT == 64	/* always better to unroll on 64-bit architectures */
5355714Skris	tbl[0] = 1;
5455714Skris	tbl[3] = tbl[2] = tbl[1] = 0;
5555714Skris#else
5655714Skris	for (tbl[0] = idx = 1; idx < sizeof(tbl) / sizeof(tbl[0]); idx++)
5755714Skris		tbl[idx] = 0;
58160814Ssimon#endif
59238405Sjkim	for (; *charset != '\0'; charset++) {
60162911Ssimon		idx = IDX(*charset);
61162911Ssimon		bit = BIT(*charset);
62162911Ssimon		tbl[idx] |= bit;
63162911Ssimon	}
64162911Ssimon
65162911Ssimon	for(s1 = s; ; s1++) {
66280304Sjkim		idx = IDX(*s1);
67162911Ssimon		bit = BIT(*s1);
68162911Ssimon		if ((tbl[idx] & bit) != 0)
69162911Ssimon			break;
70162911Ssimon	}
71162911Ssimon	return (s1 - s);
72162911Ssimon}
73162911Ssimon