Coverage Report

Created: 2026-01-09 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensips/lib/turbocompare.h
Line
Count
Source
1
/*
2
 * Copyright (C) 2020 Maksym Sobolyev
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version
10
 *
11
 * opensips is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19
 *
20
 */
21
22
#if !defined(_turbocompare_h)
23
#define _turbocompare_h
24
25
/*
26
 * markbetween() macro takes int-like type in x treats it as a sequence of bytes
27
 * and produces a value of the same type and lengh with bytes of original
28
 * value in the range m > bX < n replaced with 0x80 and the rest with 0x00, i.e.
29
 *
30
 * markbetween((uint64_t)0x0102030405060708, 0x03, 0x08) == (uint64_t)0x0000008080808000
31
 *
32
 * Obtained from Bit Twiddling Hacks By Sean Eron Anderson <seander@cs.stanford.edu>
33
 */
34
#define markbetween(x,m,n) \
35
550k
   ({const typeof(x) cFF = ~(typeof(x))0, c01 = cFF / 255; (((c01*(127+(n))-((x)&c01*127))&~(x)&(((x)&c01*127)+c01*(127-(m))))&c01*128);})
36
37
/*
38
 * TURBO_LCMASK() generates mask that can be ORed with original int-like
39
 * value x to produce lower-case version of the sequence of bytes contained
40
 * in x.
41
 */
42
550k
#define TURBO_LCMASK(x) (markbetween(x, 'A' - 1, 'Z' + 1) >> 2)
43
#define TOLOWER_FUNC(itype) \
44
    static inline unsigned itype \
45
    turbo_tolower_##itype(const void *wp) \
46
238k
    { \
47
238k
        unsigned itype msk, wrd; \
48
238k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
238k
        msk = TURBO_LCMASK(wrd); \
50
238k
        return (wrd | msk); \
51
238k
    }
digest_parser.c:turbo_tolower_long
Line
Count
Source
46
22.5k
    { \
47
22.5k
        unsigned itype msk, wrd; \
48
22.5k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
22.5k
        msk = TURBO_LCMASK(wrd); \
50
22.5k
        return (wrd | msk); \
51
22.5k
    }
digest_parser.c:turbo_tolower_int
Line
Count
Source
46
35.3k
    { \
47
35.3k
        unsigned itype msk, wrd; \
48
35.3k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
35.3k
        msk = TURBO_LCMASK(wrd); \
50
35.3k
        return (wrd | msk); \
51
35.3k
    }
digest_parser.c:turbo_tolower_short
Line
Count
Source
46
1.30k
    { \
47
1.30k
        unsigned itype msk, wrd; \
48
1.30k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
1.30k
        msk = TURBO_LCMASK(wrd); \
50
1.30k
        return (wrd | msk); \
51
1.30k
    }
Unexecuted instantiation: digest_parser.c:turbo_tolower_char
Unexecuted instantiation: parse_authenticate.c:turbo_tolower_long
parse_authenticate.c:turbo_tolower_int
Line
Count
Source
46
129k
    { \
47
129k
        unsigned itype msk, wrd; \
48
129k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
129k
        msk = TURBO_LCMASK(wrd); \
50
129k
        return (wrd | msk); \
51
129k
    }
parse_authenticate.c:turbo_tolower_short
Line
Count
Source
46
50.2k
    { \
47
50.2k
        unsigned itype msk, wrd; \
48
50.2k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
50.2k
        msk = TURBO_LCMASK(wrd); \
50
50.2k
        return (wrd | msk); \
51
50.2k
    }
Unexecuted instantiation: parse_authenticate.c:turbo_tolower_char
52
53
TOLOWER_FUNC(long);
54
TOLOWER_FUNC(int);
55
TOLOWER_FUNC(short);
56
TOLOWER_FUNC(char);
57
58
#define FASTCASEMATCH_LOOP(itype) \
59
208k
    while (len >= sizeof(unsigned itype)) { \
60
119k
        if (turbo_tolower_##itype(us1.itype##_p) != turbo_tolower_##itype(us2.itype##_p)) \
61
119k
            return 0; \
62
119k
        len -= sizeof(unsigned itype); \
63
101k
        if (len == 0) \
64
101k
            return 1; \
65
101k
  if (len < sizeof(unsigned itype)) { \
66
37.3k
      us1.char_p -= sizeof(unsigned itype) - len; \
67
37.3k
      us2.char_p -= sizeof(unsigned itype) - len; \
68
37.3k
      len = sizeof(unsigned itype); \
69
37.3k
        } \
70
39.0k
        us1.itype##_p++; \
71
39.0k
        us2.itype##_p++; \
72
39.0k
    }
73
74
/*
75
 * The turbo_casematch() function compares ASCII byte strings s1 against s2,
76
 * ignoring case and returning non-zero if they are identical, zero otherwise.
77
 * Both strings are assumed to be len bytes long. Zero-length strings are always
78
 * identical. No special treatment for \0 is performed, the comparison will
79
 * continue if both strings are matching until len bytes are compared, i.e.
80
 * turbo_casematch("1234\05678", "1234\05679", 9) will return 0 (i.e. mismatch).
81
 */
82
static inline int
83
turbo_casematch(const char *s1, const char *s2, unsigned int len)
84
80.2k
{
85
80.2k
    union {
86
80.2k
        const char *char_p;
87
80.2k
        const unsigned long *long_p;
88
80.2k
        const unsigned int *int_p;
89
80.2k
        const unsigned short *short_p;
90
80.2k
    } us1, us2;
91
80.2k
    us1.char_p = s1;
92
80.2k
    us2.char_p = s2;
93
80.2k
    FASTCASEMATCH_LOOP(long);
94
74.1k
    FASTCASEMATCH_LOOP(int);
95
14.7k
    FASTCASEMATCH_LOOP(short);
96
0
    FASTCASEMATCH_LOOP(char);
97
0
    return 1;
98
0
}
digest_parser.c:turbo_casematch
Line
Count
Source
84
15.5k
{
85
15.5k
    union {
86
15.5k
        const char *char_p;
87
15.5k
        const unsigned long *long_p;
88
15.5k
        const unsigned int *int_p;
89
15.5k
        const unsigned short *short_p;
90
15.5k
    } us1, us2;
91
15.5k
    us1.char_p = s1;
92
15.5k
    us2.char_p = s2;
93
15.5k
    FASTCASEMATCH_LOOP(long);
94
9.47k
    FASTCASEMATCH_LOOP(int);
95
352
    FASTCASEMATCH_LOOP(short);
96
0
    FASTCASEMATCH_LOOP(char);
97
0
    return 1;
98
0
}
parse_authenticate.c:turbo_casematch
Line
Count
Source
84
64.7k
{
85
64.7k
    union {
86
64.7k
        const char *char_p;
87
64.7k
        const unsigned long *long_p;
88
64.7k
        const unsigned int *int_p;
89
64.7k
        const unsigned short *short_p;
90
64.7k
    } us1, us2;
91
64.7k
    us1.char_p = s1;
92
64.7k
    us2.char_p = s2;
93
64.7k
    FASTCASEMATCH_LOOP(long);
94
64.7k
    FASTCASEMATCH_LOOP(int);
95
14.4k
    FASTCASEMATCH_LOOP(short);
96
0
    FASTCASEMATCH_LOOP(char);
97
0
    return 1;
98
0
}
99
100
/*
101
 * Convinience macro: return true if both sargs->len is the same as Slen and
102
 * string S matches sarg->s (ignoring the case in both).
103
 */
104
2.73k
#define turbo_strcasematch(sarg, S, Slen) ((sarg)->len == (Slen) && \
105
2.73k
  turbo_casematch((sarg)->s, (S), (Slen)))
106
107
#endif