xref: /reactos/sdk/lib/ucrt/string/strspn.c (revision 04e0dc4a)
1*04e0dc4aSTimo Kreuzer /***
2*04e0dc4aSTimo Kreuzer *strspn.c - find length of initial substring of chars from a control string
3*04e0dc4aSTimo Kreuzer *
4*04e0dc4aSTimo Kreuzer *       Copyright (c) Microsoft Corporation. All rights reserved.
5*04e0dc4aSTimo Kreuzer *
6*04e0dc4aSTimo Kreuzer *Purpose:
7*04e0dc4aSTimo Kreuzer *       defines strspn() - finds the length of the initial substring of
8*04e0dc4aSTimo Kreuzer *       a string consisting entirely of characters from a control string.
9*04e0dc4aSTimo Kreuzer *
10*04e0dc4aSTimo Kreuzer *       defines strcspn()- finds the length of the initial substring of
11*04e0dc4aSTimo Kreuzer *       a string consisting entirely of characters not in a control string.
12*04e0dc4aSTimo Kreuzer *
13*04e0dc4aSTimo Kreuzer *       defines strpbrk()- finds the index of the first character in a string
14*04e0dc4aSTimo Kreuzer *       that is not in a control string
15*04e0dc4aSTimo Kreuzer *
16*04e0dc4aSTimo Kreuzer *******************************************************************************/
17*04e0dc4aSTimo Kreuzer 
18*04e0dc4aSTimo Kreuzer #include <string.h>
19*04e0dc4aSTimo Kreuzer 
20*04e0dc4aSTimo Kreuzer #pragma warning(disable:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED) // 26018 Prefast doesn't understand reading past buffer but staying on same page.
21*04e0dc4aSTimo Kreuzer #pragma warning(disable:__WARNING_RETURNING_BAD_RESULT) // 28196
22*04e0dc4aSTimo Kreuzer 
23*04e0dc4aSTimo Kreuzer /* Determine which routine we're compiling for (default to STRSPN) */
24*04e0dc4aSTimo Kreuzer #define _STRSPN         1
25*04e0dc4aSTimo Kreuzer #define _STRCSPN        2
26*04e0dc4aSTimo Kreuzer #define _STRPBRK        3
27*04e0dc4aSTimo Kreuzer 
28*04e0dc4aSTimo Kreuzer #if defined (SSTRCSPN)
29*04e0dc4aSTimo Kreuzer     #define ROUTINE _STRCSPN
30*04e0dc4aSTimo Kreuzer #elif defined (SSTRPBRK)
31*04e0dc4aSTimo Kreuzer     #define ROUTINE _STRPBRK
32*04e0dc4aSTimo Kreuzer #else
33*04e0dc4aSTimo Kreuzer     #define ROUTINE _STRSPN
34*04e0dc4aSTimo Kreuzer #endif
35*04e0dc4aSTimo Kreuzer 
36*04e0dc4aSTimo Kreuzer /***
37*04e0dc4aSTimo Kreuzer *int strspn(string, control) - find init substring of control chars
38*04e0dc4aSTimo Kreuzer *
39*04e0dc4aSTimo Kreuzer *Purpose:
40*04e0dc4aSTimo Kreuzer *       Finds the index of the first character in string that does belong
41*04e0dc4aSTimo Kreuzer *       to the set of characters specified by control.  This is
42*04e0dc4aSTimo Kreuzer *       equivalent to the length of the initial substring of string that
43*04e0dc4aSTimo Kreuzer *       consists entirely of characters from control.  The '\0' character
44*04e0dc4aSTimo Kreuzer *       that terminates control is not considered in the matching process.
45*04e0dc4aSTimo Kreuzer *
46*04e0dc4aSTimo Kreuzer *Entry:
47*04e0dc4aSTimo Kreuzer *       char *string - string to search
48*04e0dc4aSTimo Kreuzer *       char *control - string containing characters not to search for
49*04e0dc4aSTimo Kreuzer *
50*04e0dc4aSTimo Kreuzer *Exit:
51*04e0dc4aSTimo Kreuzer *       returns index of first char in string not in control
52*04e0dc4aSTimo Kreuzer *
53*04e0dc4aSTimo Kreuzer *Exceptions:
54*04e0dc4aSTimo Kreuzer *
55*04e0dc4aSTimo Kreuzer *******************************************************************************/
56*04e0dc4aSTimo Kreuzer 
57*04e0dc4aSTimo Kreuzer /***
58*04e0dc4aSTimo Kreuzer *int strcspn(string, control) - search for init substring w/o control chars
59*04e0dc4aSTimo Kreuzer *
60*04e0dc4aSTimo Kreuzer *Purpose:
61*04e0dc4aSTimo Kreuzer *       returns the index of the first character in string that belongs
62*04e0dc4aSTimo Kreuzer *       to the set of characters specified by control.  This is equivalent
63*04e0dc4aSTimo Kreuzer *       to the length of the length of the initial substring of string
64*04e0dc4aSTimo Kreuzer *       composed entirely of characters not in control.  Null chars not
65*04e0dc4aSTimo Kreuzer *       considered.
66*04e0dc4aSTimo Kreuzer *
67*04e0dc4aSTimo Kreuzer *Entry:
68*04e0dc4aSTimo Kreuzer *       char *string - string to search
69*04e0dc4aSTimo Kreuzer *       char *control - set of characters not allowed in init substring
70*04e0dc4aSTimo Kreuzer *
71*04e0dc4aSTimo Kreuzer *Exit:
72*04e0dc4aSTimo Kreuzer *       returns the index of the first char in string
73*04e0dc4aSTimo Kreuzer *       that is in the set of characters specified by control.
74*04e0dc4aSTimo Kreuzer *
75*04e0dc4aSTimo Kreuzer *Exceptions:
76*04e0dc4aSTimo Kreuzer *
77*04e0dc4aSTimo Kreuzer *******************************************************************************/
78*04e0dc4aSTimo Kreuzer 
79*04e0dc4aSTimo Kreuzer /***
80*04e0dc4aSTimo Kreuzer *char *strpbrk(string, control) - scans string for a character from control
81*04e0dc4aSTimo Kreuzer *
82*04e0dc4aSTimo Kreuzer *Purpose:
83*04e0dc4aSTimo Kreuzer *       Finds the first occurence in string of any character from
84*04e0dc4aSTimo Kreuzer *       the control string.
85*04e0dc4aSTimo Kreuzer *
86*04e0dc4aSTimo Kreuzer *Entry:
87*04e0dc4aSTimo Kreuzer *       char *string - string to search in
88*04e0dc4aSTimo Kreuzer *       char *control - string containing characters to search for
89*04e0dc4aSTimo Kreuzer *
90*04e0dc4aSTimo Kreuzer *Exit:
91*04e0dc4aSTimo Kreuzer *       returns a pointer to the first character from control found
92*04e0dc4aSTimo Kreuzer *       in string.
93*04e0dc4aSTimo Kreuzer *       returns NULL if string and control have no characters in common.
94*04e0dc4aSTimo Kreuzer *
95*04e0dc4aSTimo Kreuzer *Exceptions:
96*04e0dc4aSTimo Kreuzer *
97*04e0dc4aSTimo Kreuzer *******************************************************************************/
98*04e0dc4aSTimo Kreuzer 
99*04e0dc4aSTimo Kreuzer 
100*04e0dc4aSTimo Kreuzer 
101*04e0dc4aSTimo Kreuzer /* Routine prototype */
102*04e0dc4aSTimo Kreuzer #if ROUTINE == _STRSPN
strspn(const char * string,const char * control)103*04e0dc4aSTimo Kreuzer size_t __cdecl strspn (
104*04e0dc4aSTimo Kreuzer #elif ROUTINE == _STRCSPN
105*04e0dc4aSTimo Kreuzer size_t __cdecl strcspn (
106*04e0dc4aSTimo Kreuzer #else  /* ROUTINE == _STRCSPN */
107*04e0dc4aSTimo Kreuzer char * __cdecl strpbrk (
108*04e0dc4aSTimo Kreuzer #endif  /* ROUTINE == _STRCSPN */
109*04e0dc4aSTimo Kreuzer         const char * string,
110*04e0dc4aSTimo Kreuzer         const char * control
111*04e0dc4aSTimo Kreuzer         )
112*04e0dc4aSTimo Kreuzer {
113*04e0dc4aSTimo Kreuzer         const unsigned char *str = (unsigned char const*)string;
114*04e0dc4aSTimo Kreuzer         const unsigned char *ctrl = (unsigned char const*)control;
115*04e0dc4aSTimo Kreuzer 
116*04e0dc4aSTimo Kreuzer         unsigned char map[32];
117*04e0dc4aSTimo Kreuzer         int count;
118*04e0dc4aSTimo Kreuzer 
119*04e0dc4aSTimo Kreuzer         /* Clear out bit map */
120*04e0dc4aSTimo Kreuzer         for (count=0; count<32; count++)
121*04e0dc4aSTimo Kreuzer                 map[count] = 0;
122*04e0dc4aSTimo Kreuzer 
123*04e0dc4aSTimo Kreuzer         /* Set bits in control map */
124*04e0dc4aSTimo Kreuzer         while (*ctrl)
125*04e0dc4aSTimo Kreuzer         {
126*04e0dc4aSTimo Kreuzer                 map[*ctrl >> 3] |= (1 << (*ctrl & 7));
127*04e0dc4aSTimo Kreuzer                 ctrl++;
128*04e0dc4aSTimo Kreuzer         }
129*04e0dc4aSTimo Kreuzer 
130*04e0dc4aSTimo Kreuzer #if ROUTINE == _STRSPN
131*04e0dc4aSTimo Kreuzer 
132*04e0dc4aSTimo Kreuzer         /* 1st char NOT in control map stops search */
133*04e0dc4aSTimo Kreuzer         if (*str)
134*04e0dc4aSTimo Kreuzer         {
135*04e0dc4aSTimo Kreuzer                 count=0;
136*04e0dc4aSTimo Kreuzer                 while (map[*str >> 3] & (1 << (*str & 7)))
137*04e0dc4aSTimo Kreuzer                 {
138*04e0dc4aSTimo Kreuzer                         count++;
139*04e0dc4aSTimo Kreuzer                         str++;
140*04e0dc4aSTimo Kreuzer                 }
141*04e0dc4aSTimo Kreuzer                 return(count);
142*04e0dc4aSTimo Kreuzer         }
143*04e0dc4aSTimo Kreuzer         return(0);
144*04e0dc4aSTimo Kreuzer 
145*04e0dc4aSTimo Kreuzer #elif ROUTINE == _STRCSPN
146*04e0dc4aSTimo Kreuzer 
147*04e0dc4aSTimo Kreuzer         /* 1st char in control map stops search */
148*04e0dc4aSTimo Kreuzer         count=0;
149*04e0dc4aSTimo Kreuzer         map[0] |= 1;    /* null chars not considered */
150*04e0dc4aSTimo Kreuzer         while (!(map[*str >> 3] & (1 << (*str & 7))))
151*04e0dc4aSTimo Kreuzer         {
152*04e0dc4aSTimo Kreuzer                 count++;
153*04e0dc4aSTimo Kreuzer                 str++;
154*04e0dc4aSTimo Kreuzer         }
155*04e0dc4aSTimo Kreuzer         return(count);
156*04e0dc4aSTimo Kreuzer 
157*04e0dc4aSTimo Kreuzer #else  /* ROUTINE == _STRCSPN */
158*04e0dc4aSTimo Kreuzer 
159*04e0dc4aSTimo Kreuzer         /* 1st char in control map stops search */
160*04e0dc4aSTimo Kreuzer         while (*str)
161*04e0dc4aSTimo Kreuzer         {
162*04e0dc4aSTimo Kreuzer                 if (map[*str >> 3] & (1 << (*str & 7)))
163*04e0dc4aSTimo Kreuzer                         return((char *)str);
164*04e0dc4aSTimo Kreuzer                 str++;
165*04e0dc4aSTimo Kreuzer         }
166*04e0dc4aSTimo Kreuzer         return(NULL);
167*04e0dc4aSTimo Kreuzer 
168*04e0dc4aSTimo Kreuzer #endif  /* ROUTINE == _STRCSPN */
169*04e0dc4aSTimo Kreuzer 
170*04e0dc4aSTimo Kreuzer }
171