Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/wc/countnl.c
- This file was added.
#include <stdlib.h> | |||||
#include <sys/types.h> | |||||
#include <sys/limits.h> | |||||
#include "countnl.h" | |||||
size_t | |||||
count_newlines(u_char *restrict p, size_t l) { | |||||
size_t n = 0; | |||||
#if CHAR_BIT == 8 /* VROOM VROOM */ | |||||
/* Using long long makes this slower than the naive algorithm | |||||
* on some CPUs. Let's assume that long is the largest | |||||
* integer type that the CPU can work with efficiently. */ | |||||
typedef unsigned long word; | |||||
word *restrict wp; | |||||
size_t wl; | |||||
/* Only do it if we've got at least a few words to process. */ | |||||
if (l > sizeof (word) * 4) { | |||||
/* Align to word boundary. */ | |||||
for (; ((uintptr_t)p & (sizeof(word) - 1)) && l; l--) | |||||
n += *p++ == '\n'; | |||||
/* Process one word at a time. */ | |||||
wp = (void *)p; | |||||
wl = l / sizeof (word); | |||||
l -= wl * sizeof (word); | |||||
p += wl * sizeof (word); | |||||
while (wl--) { | |||||
/* This is from the "Bit Twiddling Hacks" | |||||
* page, "Determine if a word has a byte less | |||||
* than n" using one of their tricks to turn | |||||
* newline bytes into zero bytes and then | |||||
* counting for bytes less than one. No, I do | |||||
* not understand it, but it works. | |||||
* <https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord> | |||||
*/ | |||||
word wv = *wp++ ^ ~(word)0/255 * (word)'\n'; | |||||
n += ((~(word)0/255*(127+(1)) - ((wv)&~(word)0/255*127)) | |||||
& ~(wv) & ~(word)0/255*128) / 128 % 255; | |||||
} | |||||
/* Leftovers handled below. */ | |||||
} | |||||
#endif | |||||
while (l--) | |||||
n += *p++ == '\n'; | |||||
return n; | |||||
} | |||||