Coverage Report

Created: 2025-09-04 06:25

/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
518k
{
12
518k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
518k
    const void *idata = PyUnicode_DATA(unicode);
14
518k
    int ikind = PyUnicode_KIND(unicode);
15
16
518k
    *odata++ = quote;
17
119M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
118M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
118M
        if ((ch == quote) || (ch == '\\')) {
22
156k
            *odata++ = '\\';
23
156k
            *odata++ = ch;
24
156k
            continue;
25
156k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
118M
        if (ch == '\t') {
29
16.1k
            *odata++ = '\\';
30
16.1k
            *odata++ = 't';
31
16.1k
        }
32
118M
        else if (ch == '\n') {
33
1.93k
            *odata++ = '\\';
34
1.93k
            *odata++ = 'n';
35
1.93k
        }
36
118M
        else if (ch == '\r') {
37
1.96k
            *odata++ = '\\';
38
1.96k
            *odata++ = 'r';
39
1.96k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
118M
        else if (ch < ' ' || ch == 0x7F) {
43
89.3M
            *odata++ = '\\';
44
89.3M
            *odata++ = 'x';
45
89.3M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
89.3M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
89.3M
        }
48
49
        /* Copy ASCII characters as-is */
50
29.2M
        else if (ch < 0x7F) {
51
22.8M
            *odata++ = ch;
52
22.8M
        }
53
54
        /* Non-ASCII characters */
55
6.38M
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
6.38M
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
90.1k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
90.1k
                if (ch <= 0xff) {
63
25.0k
                    *odata++ = 'x';
64
25.0k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
25.0k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
25.0k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
65.1k
                else if (ch <= 0xffff) {
69
43.1k
                    *odata++ = 'u';
70
43.1k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
43.1k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
43.1k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
43.1k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
43.1k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
21.9k
                else {
77
21.9k
                    *odata++ = 'U';
78
21.9k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
21.9k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
21.9k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
21.9k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
21.9k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
21.9k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
21.9k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
21.9k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
21.9k
                }
87
90.1k
            }
88
            /* Copy characters as-is */
89
6.29M
            else {
90
6.29M
                *odata++ = ch;
91
6.29M
            }
92
6.38M
        }
93
118M
    }
94
518k
    *odata = quote;
95
518k
}
unicodeobject.c:ucs1lib_repr
Line
Count
Source
11
327k
{
12
327k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
327k
    const void *idata = PyUnicode_DATA(unicode);
14
327k
    int ikind = PyUnicode_KIND(unicode);
15
16
327k
    *odata++ = quote;
17
26.0M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
25.7M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
25.7M
        if ((ch == quote) || (ch == '\\')) {
22
62.7k
            *odata++ = '\\';
23
62.7k
            *odata++ = ch;
24
62.7k
            continue;
25
62.7k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
25.6M
        if (ch == '\t') {
29
10.3k
            *odata++ = '\\';
30
10.3k
            *odata++ = 't';
31
10.3k
        }
32
25.6M
        else if (ch == '\n') {
33
1.04k
            *odata++ = '\\';
34
1.04k
            *odata++ = 'n';
35
1.04k
        }
36
25.6M
        else if (ch == '\r') {
37
1.11k
            *odata++ = '\\';
38
1.11k
            *odata++ = 'r';
39
1.11k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
25.6M
        else if (ch < ' ' || ch == 0x7F) {
43
19.9M
            *odata++ = '\\';
44
19.9M
            *odata++ = 'x';
45
19.9M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
19.9M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
19.9M
        }
48
49
        /* Copy ASCII characters as-is */
50
5.74M
        else if (ch < 0x7F) {
51
5.69M
            *odata++ = ch;
52
5.69M
        }
53
54
        /* Non-ASCII characters */
55
49.6k
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
49.6k
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
43.4k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
43.4k
                if (ch <= 0xff) {
63
13.2k
                    *odata++ = 'x';
64
13.2k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
13.2k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
13.2k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
30.2k
                else if (ch <= 0xffff) {
69
27.9k
                    *odata++ = 'u';
70
27.9k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
27.9k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
27.9k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
27.9k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
27.9k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
2.23k
                else {
77
2.23k
                    *odata++ = 'U';
78
2.23k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
2.23k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
2.23k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
2.23k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
2.23k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
2.23k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
2.23k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
2.23k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
2.23k
                }
87
43.4k
            }
88
            /* Copy characters as-is */
89
6.19k
            else {
90
6.19k
                *odata++ = ch;
91
6.19k
            }
92
49.6k
        }
93
25.6M
    }
94
327k
    *odata = quote;
95
327k
}
unicodeobject.c:ucs2lib_repr
Line
Count
Source
11
187k
{
12
187k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
187k
    const void *idata = PyUnicode_DATA(unicode);
14
187k
    int ikind = PyUnicode_KIND(unicode);
15
16
187k
    *odata++ = quote;
17
76.5M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
76.3M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
76.3M
        if ((ch == quote) || (ch == '\\')) {
22
73.0k
            *odata++ = '\\';
23
73.0k
            *odata++ = ch;
24
73.0k
            continue;
25
73.0k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
76.2M
        if (ch == '\t') {
29
4.89k
            *odata++ = '\\';
30
4.89k
            *odata++ = 't';
31
4.89k
        }
32
76.2M
        else if (ch == '\n') {
33
622
            *odata++ = '\\';
34
622
            *odata++ = 'n';
35
622
        }
36
76.2M
        else if (ch == '\r') {
37
470
            *odata++ = '\\';
38
470
            *odata++ = 'r';
39
470
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
76.2M
        else if (ch < ' ' || ch == 0x7F) {
43
53.3M
            *odata++ = '\\';
44
53.3M
            *odata++ = 'x';
45
53.3M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
53.3M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
53.3M
        }
48
49
        /* Copy ASCII characters as-is */
50
22.9M
        else if (ch < 0x7F) {
51
16.6M
            *odata++ = ch;
52
16.6M
        }
53
54
        /* Non-ASCII characters */
55
6.24M
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
6.24M
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
41.7k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
41.7k
                if (ch <= 0xff) {
63
10.6k
                    *odata++ = 'x';
64
10.6k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
10.6k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
10.6k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
31.1k
                else if (ch <= 0xffff) {
69
12.2k
                    *odata++ = 'u';
70
12.2k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
12.2k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
12.2k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
12.2k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
12.2k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
18.8k
                else {
77
18.8k
                    *odata++ = 'U';
78
18.8k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
18.8k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
18.8k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
18.8k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
18.8k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
18.8k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
18.8k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
18.8k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
18.8k
                }
87
41.7k
            }
88
            /* Copy characters as-is */
89
6.19M
            else {
90
6.19M
                *odata++ = ch;
91
6.19M
            }
92
6.24M
        }
93
76.2M
    }
94
187k
    *odata = quote;
95
187k
}
unicodeobject.c:ucs4lib_repr
Line
Count
Source
11
3.40k
{
12
3.40k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
3.40k
    const void *idata = PyUnicode_DATA(unicode);
14
3.40k
    int ikind = PyUnicode_KIND(unicode);
15
16
3.40k
    *odata++ = quote;
17
16.6M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
16.6M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
16.6M
        if ((ch == quote) || (ch == '\\')) {
22
20.6k
            *odata++ = '\\';
23
20.6k
            *odata++ = ch;
24
20.6k
            continue;
25
20.6k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
16.6M
        if (ch == '\t') {
29
873
            *odata++ = '\\';
30
873
            *odata++ = 't';
31
873
        }
32
16.6M
        else if (ch == '\n') {
33
269
            *odata++ = '\\';
34
269
            *odata++ = 'n';
35
269
        }
36
16.6M
        else if (ch == '\r') {
37
380
            *odata++ = '\\';
38
380
            *odata++ = 'r';
39
380
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
16.6M
        else if (ch < ' ' || ch == 0x7F) {
43
16.0M
            *odata++ = '\\';
44
16.0M
            *odata++ = 'x';
45
16.0M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
16.0M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
16.0M
        }
48
49
        /* Copy ASCII characters as-is */
50
610k
        else if (ch < 0x7F) {
51
513k
            *odata++ = ch;
52
513k
        }
53
54
        /* Non-ASCII characters */
55
97.0k
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
97.0k
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
4.93k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
4.93k
                if (ch <= 0xff) {
63
1.14k
                    *odata++ = 'x';
64
1.14k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
1.14k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
1.14k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
3.78k
                else if (ch <= 0xffff) {
69
2.96k
                    *odata++ = 'u';
70
2.96k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
2.96k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
2.96k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
2.96k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
2.96k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
822
                else {
77
822
                    *odata++ = 'U';
78
822
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
822
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
822
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
822
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
822
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
822
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
822
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
822
                    *odata++ = Py_hexdigits[ch & 0xF];
86
822
                }
87
4.93k
            }
88
            /* Copy characters as-is */
89
92.1k
            else {
90
92.1k
                *odata++ = ch;
91
92.1k
            }
92
97.0k
        }
93
16.6M
    }
94
3.40k
    *odata = quote;
95
3.40k
}