Coverage Report

Created: 2025-07-18 06:09

/src/cpython/Objects/stringlib/repr.h
Line
Count
Source
1
/* stringlib: repr() implementation */
2
3
#ifndef STRINGLIB_FASTSEARCH_H
4
#error must include "stringlib/fastsearch.h" before including this module
5
#endif
6
7
8
static void
9
STRINGLIB(repr)(PyObject *unicode, Py_UCS4 quote,
10
                STRINGLIB_CHAR *odata)
11
574k
{
12
574k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
574k
    const void *idata = PyUnicode_DATA(unicode);
14
574k
    int ikind = PyUnicode_KIND(unicode);
15
16
574k
    *odata++ = quote;
17
122M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
121M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
121M
        if ((ch == quote) || (ch == '\\')) {
22
246k
            *odata++ = '\\';
23
246k
            *odata++ = ch;
24
246k
            continue;
25
246k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
121M
        if (ch == '\t') {
29
28.3k
            *odata++ = '\\';
30
28.3k
            *odata++ = 't';
31
28.3k
        }
32
121M
        else if (ch == '\n') {
33
2.20k
            *odata++ = '\\';
34
2.20k
            *odata++ = 'n';
35
2.20k
        }
36
121M
        else if (ch == '\r') {
37
2.89k
            *odata++ = '\\';
38
2.89k
            *odata++ = 'r';
39
2.89k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
121M
        else if (ch < ' ' || ch == 0x7F) {
43
87.5M
            *odata++ = '\\';
44
87.5M
            *odata++ = 'x';
45
87.5M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
87.5M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
87.5M
        }
48
49
        /* Copy ASCII characters as-is */
50
33.9M
        else if (ch < 0x7F) {
51
26.3M
            *odata++ = ch;
52
26.3M
        }
53
54
        /* Non-ASCII characters */
55
7.61M
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
7.61M
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
107k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
107k
                if (ch <= 0xff) {
63
23.9k
                    *odata++ = 'x';
64
23.9k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
23.9k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
23.9k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
83.3k
                else if (ch <= 0xffff) {
69
53.2k
                    *odata++ = 'u';
70
53.2k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
53.2k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
53.2k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
53.2k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
53.2k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
30.1k
                else {
77
30.1k
                    *odata++ = 'U';
78
30.1k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
30.1k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
30.1k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
30.1k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
30.1k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
30.1k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
30.1k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
30.1k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
30.1k
                }
87
107k
            }
88
            /* Copy characters as-is */
89
7.51M
            else {
90
7.51M
                *odata++ = ch;
91
7.51M
            }
92
7.61M
        }
93
121M
    }
94
574k
    *odata = quote;
95
574k
}
unicodeobject.c:ucs1lib_repr
Line
Count
Source
11
366k
{
12
366k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
366k
    const void *idata = PyUnicode_DATA(unicode);
14
366k
    int ikind = PyUnicode_KIND(unicode);
15
16
366k
    *odata++ = quote;
17
25.9M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
25.6M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
25.6M
        if ((ch == quote) || (ch == '\\')) {
22
131k
            *odata++ = '\\';
23
131k
            *odata++ = ch;
24
131k
            continue;
25
131k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
25.4M
        if (ch == '\t') {
29
14.8k
            *odata++ = '\\';
30
14.8k
            *odata++ = 't';
31
14.8k
        }
32
25.4M
        else if (ch == '\n') {
33
1.14k
            *odata++ = '\\';
34
1.14k
            *odata++ = 'n';
35
1.14k
        }
36
25.4M
        else if (ch == '\r') {
37
1.61k
            *odata++ = '\\';
38
1.61k
            *odata++ = 'r';
39
1.61k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
25.4M
        else if (ch < ' ' || ch == 0x7F) {
43
19.3M
            *odata++ = '\\';
44
19.3M
            *odata++ = 'x';
45
19.3M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
19.3M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
19.3M
        }
48
49
        /* Copy ASCII characters as-is */
50
6.15M
        else if (ch < 0x7F) {
51
6.09M
            *odata++ = ch;
52
6.09M
        }
53
54
        /* Non-ASCII characters */
55
64.1k
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
64.1k
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
52.9k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
52.9k
                if (ch <= 0xff) {
63
13.3k
                    *odata++ = 'x';
64
13.3k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
13.3k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
13.3k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
39.5k
                else if (ch <= 0xffff) {
69
35.0k
                    *odata++ = 'u';
70
35.0k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
35.0k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
35.0k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
35.0k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
35.0k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
4.55k
                else {
77
4.55k
                    *odata++ = 'U';
78
4.55k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
4.55k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
4.55k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
4.55k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
4.55k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
4.55k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
4.55k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
4.55k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
4.55k
                }
87
52.9k
            }
88
            /* Copy characters as-is */
89
11.2k
            else {
90
11.2k
                *odata++ = ch;
91
11.2k
            }
92
64.1k
        }
93
25.4M
    }
94
366k
    *odata = quote;
95
366k
}
unicodeobject.c:ucs2lib_repr
Line
Count
Source
11
204k
{
12
204k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
204k
    const void *idata = PyUnicode_DATA(unicode);
14
204k
    int ikind = PyUnicode_KIND(unicode);
15
16
204k
    *odata++ = quote;
17
82.3M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
82.1M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
82.1M
        if ((ch == quote) || (ch == '\\')) {
22
92.1k
            *odata++ = '\\';
23
92.1k
            *odata++ = ch;
24
92.1k
            continue;
25
92.1k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
82.0M
        if (ch == '\t') {
29
11.3k
            *odata++ = '\\';
30
11.3k
            *odata++ = 't';
31
11.3k
        }
32
82.0M
        else if (ch == '\n') {
33
773
            *odata++ = '\\';
34
773
            *odata++ = 'n';
35
773
        }
36
82.0M
        else if (ch == '\r') {
37
1.07k
            *odata++ = '\\';
38
1.07k
            *odata++ = 'r';
39
1.07k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
82.0M
        else if (ch < ' ' || ch == 0x7F) {
43
55.1M
            *odata++ = '\\';
44
55.1M
            *odata++ = 'x';
45
55.1M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
55.1M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
55.1M
        }
48
49
        /* Copy ASCII characters as-is */
50
26.9M
        else if (ch < 0x7F) {
51
19.5M
            *odata++ = ch;
52
19.5M
        }
53
54
        /* Non-ASCII characters */
55
7.35M
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
7.35M
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
50.5k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
50.5k
                if (ch <= 0xff) {
63
9.69k
                    *odata++ = 'x';
64
9.69k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
9.69k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
9.69k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
40.8k
                else if (ch <= 0xffff) {
69
16.9k
                    *odata++ = 'u';
70
16.9k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
16.9k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
16.9k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
16.9k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
16.9k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
23.9k
                else {
77
23.9k
                    *odata++ = 'U';
78
23.9k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
23.9k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
23.9k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
23.9k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
23.9k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
23.9k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
23.9k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
23.9k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
23.9k
                }
87
50.5k
            }
88
            /* Copy characters as-is */
89
7.29M
            else {
90
7.29M
                *odata++ = ch;
91
7.29M
            }
92
7.35M
        }
93
82.0M
    }
94
204k
    *odata = quote;
95
204k
}
unicodeobject.c:ucs4lib_repr
Line
Count
Source
11
3.39k
{
12
3.39k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
3.39k
    const void *idata = PyUnicode_DATA(unicode);
14
3.39k
    int ikind = PyUnicode_KIND(unicode);
15
16
3.39k
    *odata++ = quote;
17
13.9M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
13.9M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
13.9M
        if ((ch == quote) || (ch == '\\')) {
22
23.1k
            *odata++ = '\\';
23
23.1k
            *odata++ = ch;
24
23.1k
            continue;
25
23.1k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
13.9M
        if (ch == '\t') {
29
2.09k
            *odata++ = '\\';
30
2.09k
            *odata++ = 't';
31
2.09k
        }
32
13.9M
        else if (ch == '\n') {
33
280
            *odata++ = '\\';
34
280
            *odata++ = 'n';
35
280
        }
36
13.9M
        else if (ch == '\r') {
37
204
            *odata++ = '\\';
38
204
            *odata++ = 'r';
39
204
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
13.9M
        else if (ch < ' ' || ch == 0x7F) {
43
13.0M
            *odata++ = '\\';
44
13.0M
            *odata++ = 'x';
45
13.0M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
13.0M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
13.0M
        }
48
49
        /* Copy ASCII characters as-is */
50
861k
        else if (ch < 0x7F) {
51
657k
            *odata++ = ch;
52
657k
        }
53
54
        /* Non-ASCII characters */
55
203k
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
203k
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
3.81k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
3.81k
                if (ch <= 0xff) {
63
905
                    *odata++ = 'x';
64
905
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
905
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
905
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
2.90k
                else if (ch <= 0xffff) {
69
1.27k
                    *odata++ = 'u';
70
1.27k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
1.27k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
1.27k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
1.27k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
1.27k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
1.63k
                else {
77
1.63k
                    *odata++ = 'U';
78
1.63k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
1.63k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
1.63k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
1.63k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
1.63k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
1.63k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
1.63k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
1.63k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
1.63k
                }
87
3.81k
            }
88
            /* Copy characters as-is */
89
199k
            else {
90
199k
                *odata++ = ch;
91
199k
            }
92
203k
        }
93
13.9M
    }
94
3.39k
    *odata = quote;
95
3.39k
}