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