Coverage Report

Created: 2025-08-26 06:26

/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
613k
{
12
613k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
613k
    const void *idata = PyUnicode_DATA(unicode);
14
613k
    int ikind = PyUnicode_KIND(unicode);
15
16
613k
    *odata++ = quote;
17
123M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
122M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
122M
        if ((ch == quote) || (ch == '\\')) {
22
215k
            *odata++ = '\\';
23
215k
            *odata++ = ch;
24
215k
            continue;
25
215k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
122M
        if (ch == '\t') {
29
17.1k
            *odata++ = '\\';
30
17.1k
            *odata++ = 't';
31
17.1k
        }
32
122M
        else if (ch == '\n') {
33
1.95k
            *odata++ = '\\';
34
1.95k
            *odata++ = 'n';
35
1.95k
        }
36
122M
        else if (ch == '\r') {
37
1.97k
            *odata++ = '\\';
38
1.97k
            *odata++ = 'r';
39
1.97k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
122M
        else if (ch < ' ' || ch == 0x7F) {
43
82.5M
            *odata++ = '\\';
44
82.5M
            *odata++ = 'x';
45
82.5M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
82.5M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
82.5M
        }
48
49
        /* Copy ASCII characters as-is */
50
39.9M
        else if (ch < 0x7F) {
51
32.1M
            *odata++ = ch;
52
32.1M
        }
53
54
        /* Non-ASCII characters */
55
7.84M
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
7.84M
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
96.6k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
96.6k
                if (ch <= 0xff) {
63
26.4k
                    *odata++ = 'x';
64
26.4k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
26.4k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
26.4k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
70.1k
                else if (ch <= 0xffff) {
69
45.8k
                    *odata++ = 'u';
70
45.8k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
45.8k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
45.8k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
45.8k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
45.8k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
24.3k
                else {
77
24.3k
                    *odata++ = 'U';
78
24.3k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
24.3k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
24.3k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
24.3k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
24.3k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
24.3k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
24.3k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
24.3k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
24.3k
                }
87
96.6k
            }
88
            /* Copy characters as-is */
89
7.74M
            else {
90
7.74M
                *odata++ = ch;
91
7.74M
            }
92
7.84M
        }
93
122M
    }
94
613k
    *odata = quote;
95
613k
}
unicodeobject.c:ucs1lib_repr
Line
Count
Source
11
392k
{
12
392k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
392k
    const void *idata = PyUnicode_DATA(unicode);
14
392k
    int ikind = PyUnicode_KIND(unicode);
15
16
392k
    *odata++ = quote;
17
27.4M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
27.0M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
27.0M
        if ((ch == quote) || (ch == '\\')) {
22
79.0k
            *odata++ = '\\';
23
79.0k
            *odata++ = ch;
24
79.0k
            continue;
25
79.0k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
26.9M
        if (ch == '\t') {
29
10.8k
            *odata++ = '\\';
30
10.8k
            *odata++ = 't';
31
10.8k
        }
32
26.9M
        else if (ch == '\n') {
33
1.05k
            *odata++ = '\\';
34
1.05k
            *odata++ = 'n';
35
1.05k
        }
36
26.9M
        else if (ch == '\r') {
37
1.14k
            *odata++ = '\\';
38
1.14k
            *odata++ = 'r';
39
1.14k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
26.9M
        else if (ch < ' ' || ch == 0x7F) {
43
20.6M
            *odata++ = '\\';
44
20.6M
            *odata++ = 'x';
45
20.6M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
20.6M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
20.6M
        }
48
49
        /* Copy ASCII characters as-is */
50
6.26M
        else if (ch < 0x7F) {
51
6.20M
            *odata++ = ch;
52
6.20M
        }
53
54
        /* Non-ASCII characters */
55
54.9k
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
54.9k
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
48.2k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
48.2k
                if (ch <= 0xff) {
63
13.1k
                    *odata++ = 'x';
64
13.1k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
13.1k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
13.1k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
35.1k
                else if (ch <= 0xffff) {
69
30.5k
                    *odata++ = 'u';
70
30.5k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
30.5k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
30.5k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
30.5k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
30.5k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
4.62k
                else {
77
4.62k
                    *odata++ = 'U';
78
4.62k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
4.62k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
4.62k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
4.62k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
4.62k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
4.62k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
4.62k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
4.62k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
4.62k
                }
87
48.2k
            }
88
            /* Copy characters as-is */
89
6.63k
            else {
90
6.63k
                *odata++ = ch;
91
6.63k
            }
92
54.9k
        }
93
26.9M
    }
94
392k
    *odata = quote;
95
392k
}
unicodeobject.c:ucs2lib_repr
Line
Count
Source
11
217k
{
12
217k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
217k
    const void *idata = PyUnicode_DATA(unicode);
14
217k
    int ikind = PyUnicode_KIND(unicode);
15
16
217k
    *odata++ = quote;
17
79.0M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
78.8M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
78.8M
        if ((ch == quote) || (ch == '\\')) {
22
115k
            *odata++ = '\\';
23
115k
            *odata++ = ch;
24
115k
            continue;
25
115k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
78.7M
        if (ch == '\t') {
29
5.31k
            *odata++ = '\\';
30
5.31k
            *odata++ = 't';
31
5.31k
        }
32
78.7M
        else if (ch == '\n') {
33
623
            *odata++ = '\\';
34
623
            *odata++ = 'n';
35
623
        }
36
78.7M
        else if (ch == '\r') {
37
455
            *odata++ = '\\';
38
455
            *odata++ = 'r';
39
455
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
78.7M
        else if (ch < ' ' || ch == 0x7F) {
43
45.7M
            *odata++ = '\\';
44
45.7M
            *odata++ = 'x';
45
45.7M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
45.7M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
45.7M
        }
48
49
        /* Copy ASCII characters as-is */
50
32.9M
        else if (ch < 0x7F) {
51
25.2M
            *odata++ = ch;
52
25.2M
        }
53
54
        /* Non-ASCII characters */
55
7.67M
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
7.67M
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
42.8k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
42.8k
                if (ch <= 0xff) {
63
12.1k
                    *odata++ = 'x';
64
12.1k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
12.1k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
12.1k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
30.6k
                else if (ch <= 0xffff) {
69
12.0k
                    *odata++ = 'u';
70
12.0k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
12.0k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
12.0k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
12.0k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
12.0k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
18.5k
                else {
77
18.5k
                    *odata++ = 'U';
78
18.5k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
18.5k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
18.5k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
18.5k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
18.5k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
18.5k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
18.5k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
18.5k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
18.5k
                }
87
42.8k
            }
88
            /* Copy characters as-is */
89
7.63M
            else {
90
7.63M
                *odata++ = ch;
91
7.63M
            }
92
7.67M
        }
93
78.7M
    }
94
217k
    *odata = quote;
95
217k
}
unicodeobject.c:ucs4lib_repr
Line
Count
Source
11
3.43k
{
12
3.43k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
3.43k
    const void *idata = PyUnicode_DATA(unicode);
14
3.43k
    int ikind = PyUnicode_KIND(unicode);
15
16
3.43k
    *odata++ = quote;
17
16.8M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
16.8M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
16.8M
        if ((ch == quote) || (ch == '\\')) {
22
21.2k
            *odata++ = '\\';
23
21.2k
            *odata++ = ch;
24
21.2k
            continue;
25
21.2k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
16.8M
        if (ch == '\t') {
29
961
            *odata++ = '\\';
30
961
            *odata++ = 't';
31
961
        }
32
16.8M
        else if (ch == '\n') {
33
281
            *odata++ = '\\';
34
281
            *odata++ = 'n';
35
281
        }
36
16.8M
        else if (ch == '\r') {
37
379
            *odata++ = '\\';
38
379
            *odata++ = 'r';
39
379
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
16.8M
        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
751k
        else if (ch < 0x7F) {
51
642k
            *odata++ = ch;
52
642k
        }
53
54
        /* Non-ASCII characters */
55
109k
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
109k
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
5.54k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
5.54k
                if (ch <= 0xff) {
63
1.20k
                    *odata++ = 'x';
64
1.20k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
1.20k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
1.20k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
4.34k
                else if (ch <= 0xffff) {
69
3.22k
                    *odata++ = 'u';
70
3.22k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
3.22k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
3.22k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
3.22k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
3.22k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
1.12k
                else {
77
1.12k
                    *odata++ = 'U';
78
1.12k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
1.12k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
1.12k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
1.12k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
1.12k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
1.12k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
1.12k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
1.12k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
1.12k
                }
87
5.54k
            }
88
            /* Copy characters as-is */
89
103k
            else {
90
103k
                *odata++ = ch;
91
103k
            }
92
109k
        }
93
16.8M
    }
94
3.43k
    *odata = quote;
95
3.43k
}