190075Sobrien/*- 290075Sobrien * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG> 3132718Skan * All rights reserved. 490075Sobrien * 5132718Skan * Redistribution and use in source and binary forms, with or without 690075Sobrien * modification, are permitted provided that the following conditions 7132718Skan * are met: 8132718Skan * 1. Redistributions of source code must retain the above copyright 9132718Skan * notice, this list of conditions and the following disclaimer. 10132718Skan * 2. Redistributions in binary form must reproduce the above copyright 1190075Sobrien * notice, this list of conditions and the following disclaimer in the 12132718Skan * documentation and/or other materials provided with the distribution. 13132718Skan * 14132718Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1690075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132718Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19132718Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20132718Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2190075Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2290075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2390075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2490075Sobrien * SUCH DAMAGE. 25117395Skan */ 2690075Sobrien 2790075Sobrien#include <sys/cdefs.h> 2890075Sobrien__FBSDID("$FreeBSD: releng/11.0/sys/libkern/strspn.c 144545 2005-04-02 18:52:44Z das $"); 2990075Sobrien 3090075Sobrien#include <sys/libkern.h> 3190075Sobrien#include <sys/limits.h> 3290075Sobrien#include <sys/types.h> 3390075Sobrien 3490075Sobrien#define IDX(c) ((u_char)(c) / LONG_BIT) 3590075Sobrien#define BIT(c) ((u_long)1 << ((u_char)(c) % LONG_BIT)) 3690075Sobrien 3790075Sobriensize_t 3890075Sobrienstrspn(const char *s, const char *charset) 3990075Sobrien{ 4090075Sobrien /* 4190075Sobrien * NB: idx and bit are temporaries whose use causes gcc 3.4.2 to 4290075Sobrien * generate better code. Without them, gcc gets a little confused. 4390075Sobrien */ 4490075Sobrien const char *s1; 4590075Sobrien u_long bit; 4690075Sobrien u_long tbl[(UCHAR_MAX + 1) / LONG_BIT]; 4790075Sobrien int idx; 4890075Sobrien 4990075Sobrien if(*s == '\0') 5090075Sobrien return (0); 5190075Sobrien 5290075Sobrien#if LONG_BIT == 64 /* always better to unroll on 64-bit architectures */ 5390075Sobrien tbl[3] = tbl[2] = tbl[1] = tbl[0] = 0; 5490075Sobrien#else 5590075Sobrien for (idx = 0; idx < sizeof(tbl) / sizeof(tbl[0]); idx++) 5690075Sobrien tbl[idx] = 0; 5790075Sobrien#endif 5890075Sobrien for (; *charset != '\0'; charset++) { 5990075Sobrien idx = IDX(*charset); 6090075Sobrien bit = BIT(*charset); 6190075Sobrien tbl[idx] |= bit; 6290075Sobrien } 6390075Sobrien 6490075Sobrien for(s1 = s; ; s1++) { 6590075Sobrien idx = IDX(*s1); 6690075Sobrien bit = BIT(*s1); 6790075Sobrien if ((tbl[idx] & bit) == 0) 6890075Sobrien break; 6990075Sobrien } 7090075Sobrien return (s1 - s); 7190075Sobrien} 72132718Skan