ReactOS 0.4.16-dev-716-g2b2bdab
strspn.c File Reference
#include <string.h>
#include <emmintrin.h>
#include <intrin.h>
Include dependency graph for strspn.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define _STRSPN   1
 
#define _STRCSPN   2
 
#define _STRPBRK   3
 
#define ROUTINE   _STRSPN
 
#define STRSPN_USE_SSE2
 

Functions

 __declspec (noinline)
 
size_t __cdecl strspn (const char *string, const char *control)
 

Macro Definition Documentation

◆ _STRCSPN

#define _STRCSPN   2

Definition at line 25 of file strspn.c.

◆ _STRPBRK

#define _STRPBRK   3

Definition at line 26 of file strspn.c.

◆ _STRSPN

#define _STRSPN   1

Definition at line 24 of file strspn.c.

◆ ROUTINE

#define ROUTINE   _STRSPN

Definition at line 33 of file strspn.c.

◆ STRSPN_USE_SSE2

#define STRSPN_USE_SSE2

Definition at line 34 of file strspn.c.

Function Documentation

◆ __declspec()

__declspec ( noinline  )

Definition at line 105 of file strspn.c.

128{
129 const unsigned char *str = (unsigned char const*)string;
130 const unsigned char *ctrl = (unsigned char const*)control;
131
132 unsigned char map[32];
133 int count;
134
135 /* Clear out bit map */
136 for (count=0; count<32; count++)
137 map[count] = 0;
138
139 /* Set bits in control map */
140 while (*ctrl)
141 {
142 map[*ctrl >> 3] |= (1 << (*ctrl & 7));
143 ctrl++;
144 }
145
146#if ROUTINE == _STRSPN
147
148 /* 1st char NOT in control map stops search */
149 if (*str)
150 {
151 count=0;
152 while (map[*str >> 3] & (1 << (*str & 7)))
153 {
154 count++;
155 str++;
156 }
157 return(count);
158 }
159 return(0);
160
161#elif ROUTINE == _STRCSPN
162
163 /* 1st char in control map stops search */
164 count=0;
165 map[0] |= 1; /* null chars not considered */
166 while (!(map[*str >> 3] & (1 << (*str & 7))))
167 {
168 count++;
169 str++;
170 }
171 return(count);
172
173#else /* ROUTINE == _STRCSPN */
174
175 /* 1st char in control map stops search */
176 while (*str)
177 {
178 if (map[*str >> 3] & (1 << (*str & 7)))
179 return((char *)str);
180 str++;
181 }
182 return(NULL);
183
184#endif /* ROUTINE == _STRCSPN */
185
186}
Definition: _map.h:48
#define NULL
Definition: types.h:112
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define ctrl
Definition: input.c:1756
const WCHAR * str
Definition: dialog.c:52

◆ strspn()

size_t __cdecl strspn ( const char string,
const char control 
)

Definition at line 196 of file strspn.c.

204{
205 unsigned long long shift = (unsigned long long) control & 0xf;
206
207 // Mask off the lower bits of the address to get a 16-byte aligned pointer
208 char * alignedControl = (char *) control - shift;
209
210 // Load 16 bytes. This will not cross a page boundary but will have spurious data
211 __m128i search = _mm_loadu_si128((__m128i *) alignedControl);
212 __m128i zero = _mm_xor_si128(zero, zero);
213 __m128i temp, tempMask, smearedChar;
214 unsigned int mask, terminatorSeen = 0;
215 unsigned long bitCount;
216
217 // Sse2 provides immediate shifts of the full 128 bit register.
218 // Shift out the spurious data on the right and shift in zeros.
219 switch (shift)
220 {
221 case 1:
223 break;
224 case 2:
226 break;
227 case 3:
229 break;
230 case 4:
232 break;
233 case 5:
235 break;
236 case 6:
238 break;
239 case 7:
241 break;
242 case 8:
244 break;
245 case 9:
247 break;
248 case 10:
250 break;
251 case 11:
253 break;
254 case 12:
256 break;
257 case 13:
259 break;
260 case 14:
262 break;
263 case 15:
265 break;
266 case 0:
267 default:
268 break;
269 }
270
271 // Search for zero bytes in this initial string
274
275 if (mask)
276 {
277 // We found zeros and now need to mask away the spurious data that may follow
278 (void) _BitScanForward(&bitCount, mask);
279
280 terminatorSeen = (shift == 0) ? 1 : (bitCount < (16 - shift));
281
282 switch (16 - bitCount)
283 {
284 case 1:
287 break;
288 case 2:
291 break;
292 case 3:
295 break;
296 case 4:
299 break;
300 case 5:
303 break;
304 case 6:
307 break;
308 case 7:
311 break;
312 case 8:
315 break;
316 case 9:
319 break;
320 case 10:
323 break;
324 case 11:
327 break;
328 case 12:
331 break;
332 case 13:
335 break;
336 case 14:
339 break;
340 case 15:
343 break;
344 case 16:
345 search = zero;
346 break;
347 }
348 }
349 else if (shift == 0)
350 {
351 // We loaded 16 bytes and found no zero. Check if the first byte in
352 // the next 16-byte aligned block is zero. This load will not page fault
353 // on a correct program since we have not see the terminator.
354 if (*(alignedControl + 1) == 0)
355 {
356 terminatorSeen = 1;
357 }
358 else
359 {
360 // We already have 16 bytes and have not seen the terminator. Fallback to
361 // non-Sse2 version.
362 return fallbackMethod(string, control);
363 }
364 }
365
366 // If was have not seen the string terminator, attempt to piece-together a search
367 // mask of bytes from those in the next 16-byte aligned group that follows.
368 // We will allow at most 16 bytes in the search string.
369 if (!terminatorSeen)
370 {
371 // Go get the next 16 bytes, again this will not page fault.
372 alignedControl += 16;
373 temp = _mm_loadu_si128((__m128i *) alignedControl);
374
375 tempMask = _mm_cmpeq_epi8(temp, zero);
376 terminatorSeen = _mm_movemask_epi8(tempMask);
377
378 if (!terminatorSeen)
379 {
380 return fallbackMethod(string, control);
381 }
382
383 (void) _BitScanForward(&bitCount, terminatorSeen);
384
385 if ((16 - shift + bitCount) > 16)
386 {
387 return fallbackMethod(string, control);
388 }
389
390 // Shift the 2nd part of the search mask into place with the 16 bytes
391 switch (16 - bitCount)
392 {
393 case 1:
395 break;
396 case 2:
398 break;
399 case 3:
401 break;
402 case 4:
404 break;
405 case 5:
407 break;
408 case 6:
410 break;
411 case 7:
413 break;
414 case 8:
416 break;
417 case 9:
419 break;
420 case 10:
421 temp = _mm_slli_si128(temp, 10);
422 break;
423 case 11:
424 temp = _mm_slli_si128(temp, 11);
425 break;
426 case 12:
427 temp = _mm_slli_si128(temp, 12);
428 break;
429 case 13:
430 temp = _mm_slli_si128(temp, 13);
431 break;
432 case 14:
433 temp = _mm_slli_si128(temp, 14);
434 break;
435 case 15:
436 temp = _mm_slli_si128(temp, 15);
437 break;
438 case 16:
439 temp = zero;
440 break;
441
442 }
443
444 // Or the two parts together to obtain a single up-to 16-byte search mask
446 }
447
448 // Now loop through the string do a 16-compare with our search mask
449#if (ROUTINE == _STRSPN) || (ROUTINE == _STRCSPN)
450 size_t count = 0;
451#endif
452 while (*string)
453 {
454 int smear = (int) *string;
455 // Get the byte in a register
456 smearedChar = _mm_cvtsi32_si128(smear);
457
458 // The following 3 instructions smear this one character through each byte of the 16-byte register
459 smearedChar = _mm_unpacklo_epi8(smearedChar, smearedChar);
460 smearedChar = _mm_unpacklo_epi8(smearedChar, smearedChar);
461 smearedChar = _mm_shuffle_epi32(smearedChar, 0);
462
463 // Look for a match
464 temp = _mm_cmpeq_epi8(search, smearedChar);
466
467#if (ROUTINE == _STRSPN)
468 // Break if no match
469 if (!mask)
470 {
471 break;
472 }
473
474 string++;
475 count++;
476#elif (ROUTINE == _STRCSPN)
477 // Break on first match
478 if (mask)
479 {
480 break;
481 }
482
483 string++;
484 count++;
485#else // strpbrk case
486 // Return current string location on a match
487 if (mask)
488 {
489 return (char *) string;
490 }
491
492 string++;
493#endif
494 }
495
496#if (ROUTINE == _STRSPN) || (ROUTINE == _STRCSPN)
497 return count;
498#else
499 return NULL;
500#endif
501}
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
__m128i _mm_slli_si128(__m128i a, int i)
Definition: emmintrin.h:1352
__m128i _mm_xor_si128(__m128i a, __m128i b)
Definition: emmintrin.h:1343
__m128i _mm_cmpeq_epi8(__m128i a, __m128i b)
Definition: emmintrin.h:1448
__m128i _mm_cvtsi32_si128(int a)
Definition: emmintrin.h:1533
__m128i _mm_or_si128(__m128i a, __m128i b)
Definition: emmintrin.h:1338
int _mm_movemask_epi8(__m128i a)
Definition: emmintrin.h:1786
__m128i _mm_srli_si128(__m128i a, int imm)
Definition: emmintrin.h:1412
__m128i _mm_unpacklo_epi8(__m128i a, __m128i b)
Definition: emmintrin.h:1840
#define _mm_shuffle_epi32(a, imm)
Definition: emmintrin.h:1791
__m128i _mm_loadu_si128(__m128i_u const *p)
Definition: emmintrin.h:1559
GLenum GLint GLuint mask
Definition: glext.h:6028
unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask)
Definition: intrin_arm.h:57
char string[160]
Definition: util.h:11
#define shift
Definition: input.c:1755
static short search(int val, const short *table, int size)
Definition: msg711.c:255
#define long
Definition: qsort.c:33
static calc_node_t temp
Definition: rpn_ieee.c:38
int zero
Definition: sehframes.cpp:29