Skip to content

Instantly share code, notes, and snippets.

@d0k
Created September 18, 2010 02:17
Show Gist options
  • Save d0k/585257 to your computer and use it in GitHub Desktop.
Save d0k/585257 to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __SSE2__
#include <emmintrin.h>
#endif
static const char *SkipToNewline(const char *CurPtr, const char *BufferEnd) {
unsigned char C = *CurPtr;
if (CurPtr + 24 < BufferEnd) {
// While not aligned to a 16-byte boundary.
while (C != '\n' && C != '\r' && ((intptr_t)CurPtr & 0x0F) != 0)
C = *CurPtr++;
if (C == '\n' || C == '\r') return CurPtr;
#ifdef __SSE2__
__m128i NLs = _mm_set1_epi8('\n');
__m128i CRs = _mm_set1_epi8('\r');
while (CurPtr+16 <= BufferEnd) {
__m128 Data = *(__m128i*)CurPtr;
__m128 CmpNL = _mm_cmpeq_epi8(Data, NLs);
__m128 CmpCR = _mm_cmpeq_epi8(Data, CRs);
__m128 Or = _mm_or_si128(CmpNL, CmpCR);
if (_mm_movemask_epi8(Or) != 0)
break;
CurPtr += 16;
}
#else
while (CurPtr+4 < BufferEnd &&
CurPtr[0] != '\n' && CurPtr[0] != '\r' &&
CurPtr[1] != '\n' && CurPtr[1] != '\r' &&
CurPtr[2] != '\n' && CurPtr[2] != '\r' &&
CurPtr[3] != '\n' && CurPtr[3] != '\r')
CurPtr += 4;
#endif
// It has to be one of the bytes scanned, increment to it and read one.
C = *CurPtr++;
}
// Loop to scan the remainder.
while (C != '\n' && C != '\r' && C != '\0')
C = *CurPtr++;
return CurPtr;
}
int main(int argc, char *argv[]) {
FILE *fd = fopen(argv[1], "r");
fseek(fd, 0, SEEK_END);
unsigned long len = ftell(fd);
fseek(fd, 0, SEEK_SET);
char *buf = malloc(len+1);
char *end = buf + len;
fread(buf, 1, len, fd);
*end = 0;
const char *ptr = buf-1;
unsigned lines = 0;
while ((ptr = SkipToNewline(ptr+1, end)) != end) {
printf("%zu\n", ptr-buf);
lines++;
}
printf("\n%u\n", lines);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment