Coverage Report

Created: 2025-07-09 06:29

/src/opensips/lib/turbocompare.h
Line
Count
Source (jump to first uncovered line)
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
0
   ({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
0
#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
0
    { \
47
0
        unsigned itype msk, wrd; \
48
0
        memcpy(&wrd, wp, sizeof(wrd)); \
49
0
        msk = TURBO_LCMASK(wrd); \
50
0
        return (wrd | msk); \
51
0
    }
Unexecuted instantiation: digest_parser.c:turbo_tolower_long
Unexecuted instantiation: digest_parser.c:turbo_tolower_int
Unexecuted instantiation: digest_parser.c:turbo_tolower_short
Unexecuted instantiation: digest_parser.c:turbo_tolower_char
Unexecuted instantiation: parse_authenticate.c:turbo_tolower_long
Unexecuted instantiation: parse_authenticate.c:turbo_tolower_int
Unexecuted instantiation: parse_authenticate.c:turbo_tolower_short
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
0
    while (len >= sizeof(unsigned itype)) { \
60
0
        if (turbo_tolower_##itype(us1.itype##_p) != turbo_tolower_##itype(us2.itype##_p)) \
61
0
            return 0; \
62
0
        len -= sizeof(unsigned itype); \
63
0
        if (len == 0) \
64
0
            return 1; \
65
0
  if (len < sizeof(unsigned itype)) { \
66
0
      us1.char_p -= sizeof(unsigned itype) - len; \
67
0
      us2.char_p -= sizeof(unsigned itype) - len; \
68
0
      len = sizeof(unsigned itype); \
69
0
        } \
70
0
        us1.itype##_p++; \
71
0
        us2.itype##_p++; \
72
0
    }
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
0
{
85
0
    union {
86
0
        const char *char_p;
87
0
        const unsigned long *long_p;
88
0
        const unsigned int *int_p;
89
0
        const unsigned short *short_p;
90
0
    } us1, us2;
91
0
    us1.char_p = s1;
92
0
    us2.char_p = s2;
93
0
    FASTCASEMATCH_LOOP(long);
94
0
    FASTCASEMATCH_LOOP(int);
95
0
    FASTCASEMATCH_LOOP(short);
96
0
    FASTCASEMATCH_LOOP(char);
97
0
    return 1;
98
0
}
Unexecuted instantiation: digest_parser.c:turbo_casematch
Unexecuted instantiation: parse_authenticate.c:turbo_casematch
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
0
#define turbo_strcasematch(sarg, S, Slen) ((sarg)->len == (Slen) && \
105
0
  turbo_casematch((sarg)->s, (S), (Slen)))
106
107
#endif