Coverage Report

Created: 2026-09-03 07:04

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
708k
   ({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
708k
#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
436k
    { \
47
436k
        unsigned itype msk, wrd; \
48
436k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
436k
        msk = TURBO_LCMASK(wrd); \
50
436k
        return (wrd | msk); \
51
436k
    }
digest_parser.c:turbo_tolower_long
Line
Count
Source
46
36.0k
    { \
47
36.0k
        unsigned itype msk, wrd; \
48
36.0k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
36.0k
        msk = TURBO_LCMASK(wrd); \
50
36.0k
        return (wrd | msk); \
51
36.0k
    }
digest_parser.c:turbo_tolower_int
Line
Count
Source
46
31.0k
    { \
47
31.0k
        unsigned itype msk, wrd; \
48
31.0k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
31.0k
        msk = TURBO_LCMASK(wrd); \
50
31.0k
        return (wrd | msk); \
51
31.0k
    }
digest_parser.c:turbo_tolower_short
Line
Count
Source
46
580
    { \
47
580
        unsigned itype msk, wrd; \
48
580
        memcpy(&wrd, wp, sizeof(wrd)); \
49
580
        msk = TURBO_LCMASK(wrd); \
50
580
        return (wrd | msk); \
51
580
    }
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
355k
    { \
47
355k
        unsigned itype msk, wrd; \
48
355k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
355k
        msk = TURBO_LCMASK(wrd); \
50
355k
        return (wrd | msk); \
51
355k
    }
parse_authenticate.c:turbo_tolower_short
Line
Count
Source
46
13.4k
    { \
47
13.4k
        unsigned itype msk, wrd; \
48
13.4k
        memcpy(&wrd, wp, sizeof(wrd)); \
49
13.4k
        msk = TURBO_LCMASK(wrd); \
50
13.4k
        return (wrd | msk); \
51
13.4k
    }
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
397k
    while (len >= sizeof(unsigned itype)) { \
60
218k
        if (turbo_tolower_##itype(us1.itype##_p) != turbo_tolower_##itype(us2.itype##_p)) \
61
218k
            return 0; \
62
218k
        len -= sizeof(unsigned itype); \
63
194k
        if (len == 0) \
64
194k
            return 1; \
65
194k
  if (len < sizeof(unsigned itype)) { \
66
31.2k
      us1.char_p -= sizeof(unsigned itype) - len; \
67
31.2k
      us2.char_p -= sizeof(unsigned itype) - len; \
68
31.2k
      len = sizeof(unsigned itype); \
69
31.2k
        } \
70
34.0k
        us1.itype##_p++; \
71
34.0k
        us2.itype##_p++; \
72
34.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
184k
{
85
184k
    union {
86
184k
        const char *char_p;
87
184k
        const unsigned long *long_p;
88
184k
        const unsigned int *int_p;
89
184k
        const unsigned short *short_p;
90
184k
    } us1, us2;
91
184k
    us1.char_p = s1;
92
184k
    us2.char_p = s2;
93
184k
    FASTCASEMATCH_LOOP(long);
94
174k
    FASTCASEMATCH_LOOP(int);
95
4.50k
    FASTCASEMATCH_LOOP(short);
96
0
    FASTCASEMATCH_LOOP(char);
97
0
    return 1;
98
0
}
digest_parser.c:turbo_casematch
Line
Count
Source
84
17.5k
{
85
17.5k
    union {
86
17.5k
        const char *char_p;
87
17.5k
        const unsigned long *long_p;
88
17.5k
        const unsigned int *int_p;
89
17.5k
        const unsigned short *short_p;
90
17.5k
    } us1, us2;
91
17.5k
    us1.char_p = s1;
92
17.5k
    us2.char_p = s2;
93
17.5k
    FASTCASEMATCH_LOOP(long);
94
7.98k
    FASTCASEMATCH_LOOP(int);
95
151
    FASTCASEMATCH_LOOP(short);
96
0
    FASTCASEMATCH_LOOP(char);
97
0
    return 1;
98
0
}
parse_authenticate.c:turbo_casematch
Line
Count
Source
84
166k
{
85
166k
    union {
86
166k
        const char *char_p;
87
166k
        const unsigned long *long_p;
88
166k
        const unsigned int *int_p;
89
166k
        const unsigned short *short_p;
90
166k
    } us1, us2;
91
166k
    us1.char_p = s1;
92
166k
    us2.char_p = s2;
93
166k
    FASTCASEMATCH_LOOP(long);
94
166k
    FASTCASEMATCH_LOOP(int);
95
4.35k
    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
47.4k
#define turbo_strcasematch(sarg, S, Slen) ((sarg)->len == (Slen) && \
105
47.4k
  turbo_casematch((sarg)->s, (S), (Slen)))
106
107
#endif