~ubuntu-branches/ubuntu/trusty/haproxy/trusty-updates

« back to all changes in this revision

Viewing changes to contrib/halog/fgets2-64.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2010-06-18 00:42:53 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20100618004253-ygka2bh6nblkhfj2
Tags: 1.4.8-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
// return 1 if the integer contains at least one zero byte
25
25
static inline unsigned int has_zero(unsigned int x)
26
26
{
27
 
        if (!(x & 0xFF000000U) ||
28
 
            !(x & 0xFF0000U) ||
29
 
            !(x & 0xFF00U) ||
30
 
            !(x & 0xFFU))
31
 
                return 1;
32
 
        return 0;
 
27
        unsigned int y;
 
28
 
 
29
        /* Principle: we want to perform 4 tests on one 32-bit int at once. For
 
30
         * this, we have to simulate an SIMD instruction which we don't have by
 
31
         * default. The principle is that a zero byte is the only one which
 
32
         * will cause a 1 to appear on the upper bit of a byte/word/etc... when
 
33
         * we subtract 1. So we can detect a zero byte if a one appears at any
 
34
         * of the bits 7, 15, 23 or 31 where it was not. It takes only one
 
35
         * instruction to test for the presence of any of these bits, but it is
 
36
         * still complex to check for their initial absence. Thus, we'll
 
37
         * proceed differently : we first save and clear only those bits, then
 
38
         * we check in the final result if one of them is present and was not.
 
39
         */
 
40
        y = x;
 
41
        x = ~x & 0x80808080; /* save and invert bits 7, 15, 23, 31 */
 
42
        y &= 0x7F7F7F7F;     /* clear them */
 
43
        y -= 0x01010101;     /* generate a carry */
 
44
        y &= x;              /* clear the bits that were already set */
 
45
        return !!y;
33
46
}
34
47
 
 
48
 
 
49
// return 1 if the argument contains at least one zero byte. See principle above.
35
50
static inline unsigned int has_zero64(unsigned long long x)
36
51
{
37
 
        unsigned long long x2;
38
 
 
39
 
        x2 = x & (x >> 8);
40
 
        /* no need to split it further */
41
 
        if ((x2 & 0x00FF) && (x2 & 0x00FF0000) && (x2 & 0x00FF00000000ULL) && (x2 & 0x00FF000000000000ULL))
42
 
                        return 0; // approx 11/12 return here
43
 
 
44
 
        if (!(x & 0xff00000000000000ULL) ||
45
 
            !(x & 0xff000000000000ULL) ||
46
 
            !(x & 0xff0000000000ULL) ||
47
 
            !(x & 0xff00000000ULL) ||
48
 
            !(x & 0xff000000UL) ||
49
 
            !(x & 0xff0000UL) ||
50
 
            !(x & 0xff00UL) ||
51
 
            !(x & 0xffUL))
52
 
                return 1; // approx 1/3 of the remaining return here
53
 
 
54
 
        return 0;
 
52
        unsigned long long y;
 
53
 
 
54
        y = x;
 
55
        x = ~x & 0x8080808080808080ULL; /* save bits 7, 15, 23, 31, 39, 47, 55 and 63 */
 
56
        y &= 0x7F7F7F7F7F7F7F7FULL;     /* clear them */
 
57
        y -= 0x0101010101010101ULL;     /* generate a carry */
 
58
        y &= x;                         /* clear the bits that were already set */
 
59
        return !!y;
55
60
}
56
61
 
57
62
#define FGETS2_BUFSIZE          (256*1024)
58
63
const char *fgets2(FILE *stream)
59
64
{
60
 
        static char buffer[FGETS2_BUFSIZE + 5];
 
65
        static char buffer[FGETS2_BUFSIZE + 9]; // +9 to have zeroes past the end
61
66
        static char *end = buffer;
62
67
        static char *line = buffer;
63
68
 
67
72
        next = line;
68
73
 
69
74
        while (1) {
70
 
                /* this is a speed-up, we read 32 bits at once and check for an
 
75
                /* this is a speed-up, we read 64 bits at once and check for an
71
76
                 * LF character there. We stop if found then continue one at a
72
77
                 * time.
73
78
                 */
74
 
                while (next < end && (((unsigned long)next) & 7) && *next != '\n')
75
 
                        next++;
76
 
 
77
 
                /* now next is multiple of 4 or equal to end */
78
 
                while (next <= (end-32)) {
79
 
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
80
 
                                break;
81
 
                        next += 8;
82
 
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
83
 
                                break;
84
 
                        next += 8;
85
 
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
86
 
                                break;
87
 
                        next += 8;
88
 
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
89
 
                                break;
90
 
                        next += 8;
91
 
                }
 
79
 
 
80
                if (next <= (end-12)) {
 
81
                        /* max 3 bytes tested here */
 
82
                        while ((((unsigned long)next) & 3) && *next != '\n')
 
83
                                next++;
 
84
 
 
85
                        /* maybe we have can skip 4 more bytes */
 
86
                        if ((((unsigned long)next) & 4) && !has_zero(*(unsigned int *)next ^ 0x0A0A0A0AU))
 
87
                                next += 4;
 
88
                }
 
89
 
 
90
                /* now next is multiple of 8 or equal to end */
 
91
                while (next <= (end-68)) {
 
92
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
 
93
                                break;
 
94
                        next += 8;
 
95
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
 
96
                                break;
 
97
                        next += 8;
 
98
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
 
99
                                break;
 
100
                        next += 8;
 
101
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
 
102
                                break;
 
103
                        next += 8;
 
104
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
 
105
                                break;
 
106
                        next += 8;
 
107
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
 
108
                                break;
 
109
                        next += 8;
 
110
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
 
111
                                break;
 
112
                        next += 8;
 
113
                        if (has_zero64(*(unsigned long long *)next ^ 0x0A0A0A0A0A0A0A0AULL))
 
114
                                break;
 
115
                        next += 8;
 
116
                }
 
117
 
 
118
                /* maybe we can skip 4 more bytes */
 
119
                if (!has_zero(*(unsigned int *)next ^ 0x0A0A0A0AU))
 
120
                        next += 4;
92
121
 
93
122
                /* we finish if needed. Note that next might be slightly higher
94
123
                 * than end here because we might have gone past it above.