Coverage Report

Created: 2025-08-29 06:15

/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
549k
{
12
549k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
549k
    const void *idata = PyUnicode_DATA(unicode);
14
549k
    int ikind = PyUnicode_KIND(unicode);
15
16
549k
    *odata++ = quote;
17
111M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
110M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
110M
        if ((ch == quote) || (ch == '\\')) {
22
168k
            *odata++ = '\\';
23
168k
            *odata++ = ch;
24
168k
            continue;
25
168k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
110M
        if (ch == '\t') {
29
17.6k
            *odata++ = '\\';
30
17.6k
            *odata++ = 't';
31
17.6k
        }
32
110M
        else if (ch == '\n') {
33
1.95k
            *odata++ = '\\';
34
1.95k
            *odata++ = 'n';
35
1.95k
        }
36
110M
        else if (ch == '\r') {
37
2.11k
            *odata++ = '\\';
38
2.11k
            *odata++ = 'r';
39
2.11k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
110M
        else if (ch < ' ' || ch == 0x7F) {
43
81.4M
            *odata++ = '\\';
44
81.4M
            *odata++ = 'x';
45
81.4M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
81.4M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
81.4M
        }
48
49
        /* Copy ASCII characters as-is */
50
29.2M
        else if (ch < 0x7F) {
51
22.7M
            *odata++ = ch;
52
22.7M
        }
53
54
        /* Non-ASCII characters */
55
6.50M
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
6.50M
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
93.9k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
93.9k
                if (ch <= 0xff) {
63
24.2k
                    *odata++ = 'x';
64
24.2k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
24.2k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
24.2k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
69.7k
                else if (ch <= 0xffff) {
69
44.0k
                    *odata++ = 'u';
70
44.0k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
44.0k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
44.0k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
44.0k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
44.0k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
25.6k
                else {
77
25.6k
                    *odata++ = 'U';
78
25.6k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
25.6k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
25.6k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
25.6k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
25.6k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
25.6k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
25.6k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
25.6k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
25.6k
                }
87
93.9k
            }
88
            /* Copy characters as-is */
89
6.41M
            else {
90
6.41M
                *odata++ = ch;
91
6.41M
            }
92
6.50M
        }
93
110M
    }
94
549k
    *odata = quote;
95
549k
}
unicodeobject.c:ucs1lib_repr
Line
Count
Source
11
352k
{
12
352k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
352k
    const void *idata = PyUnicode_DATA(unicode);
14
352k
    int ikind = PyUnicode_KIND(unicode);
15
16
352k
    *odata++ = quote;
17
25.1M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
24.7M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
24.7M
        if ((ch == quote) || (ch == '\\')) {
22
75.3k
            *odata++ = '\\';
23
75.3k
            *odata++ = ch;
24
75.3k
            continue;
25
75.3k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
24.6M
        if (ch == '\t') {
29
11.2k
            *odata++ = '\\';
30
11.2k
            *odata++ = 't';
31
11.2k
        }
32
24.6M
        else if (ch == '\n') {
33
1.05k
            *odata++ = '\\';
34
1.05k
            *odata++ = 'n';
35
1.05k
        }
36
24.6M
        else if (ch == '\r') {
37
1.26k
            *odata++ = '\\';
38
1.26k
            *odata++ = 'r';
39
1.26k
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
24.6M
        else if (ch < ' ' || ch == 0x7F) {
43
18.8M
            *odata++ = '\\';
44
18.8M
            *odata++ = 'x';
45
18.8M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
18.8M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
18.8M
        }
48
49
        /* Copy ASCII characters as-is */
50
5.77M
        else if (ch < 0x7F) {
51
5.71M
            *odata++ = ch;
52
5.71M
        }
53
54
        /* Non-ASCII characters */
55
52.2k
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
52.2k
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
46.2k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
46.2k
                if (ch <= 0xff) {
63
12.9k
                    *odata++ = 'x';
64
12.9k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
12.9k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
12.9k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
33.2k
                else if (ch <= 0xffff) {
69
29.0k
                    *odata++ = 'u';
70
29.0k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
29.0k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
29.0k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
29.0k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
29.0k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
4.25k
                else {
77
4.25k
                    *odata++ = 'U';
78
4.25k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
4.25k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
4.25k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
4.25k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
4.25k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
4.25k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
4.25k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
4.25k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
4.25k
                }
87
46.2k
            }
88
            /* Copy characters as-is */
89
5.94k
            else {
90
5.94k
                *odata++ = ch;
91
5.94k
            }
92
52.2k
        }
93
24.6M
    }
94
352k
    *odata = quote;
95
352k
}
unicodeobject.c:ucs2lib_repr
Line
Count
Source
11
193k
{
12
193k
    Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode);
13
193k
    const void *idata = PyUnicode_DATA(unicode);
14
193k
    int ikind = PyUnicode_KIND(unicode);
15
16
193k
    *odata++ = quote;
17
69.7M
    for (Py_ssize_t i = 0; i < isize; i++) {
18
69.5M
        Py_UCS4 ch = PyUnicode_READ(ikind, idata, i);
19
20
        /* Escape quotes and backslashes */
21
69.5M
        if ((ch == quote) || (ch == '\\')) {
22
72.2k
            *odata++ = '\\';
23
72.2k
            *odata++ = ch;
24
72.2k
            continue;
25
72.2k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
69.4M
        if (ch == '\t') {
29
5.44k
            *odata++ = '\\';
30
5.44k
            *odata++ = 't';
31
5.44k
        }
32
69.4M
        else if (ch == '\n') {
33
631
            *odata++ = '\\';
34
631
            *odata++ = 'n';
35
631
        }
36
69.4M
        else if (ch == '\r') {
37
473
            *odata++ = '\\';
38
473
            *odata++ = 'r';
39
473
        }
40
41
        /* Map non-printable US ASCII to '\xhh' */
42
69.4M
        else if (ch < ' ' || ch == 0x7F) {
43
46.5M
            *odata++ = '\\';
44
46.5M
            *odata++ = 'x';
45
46.5M
            *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
46
46.5M
            *odata++ = Py_hexdigits[ch & 0x000F];
47
46.5M
        }
48
49
        /* Copy ASCII characters as-is */
50
22.8M
        else if (ch < 0x7F) {
51
16.5M
            *odata++ = ch;
52
16.5M
        }
53
54
        /* Non-ASCII characters */
55
6.35M
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
6.35M
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
42.4k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
42.4k
                if (ch <= 0xff) {
63
10.0k
                    *odata++ = 'x';
64
10.0k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0x000F];
65
10.0k
                    *odata++ = Py_hexdigits[ch & 0x000F];
66
10.0k
                }
67
                /* Map 16-bit characters to '\uxxxx' */
68
32.3k
                else if (ch <= 0xffff) {
69
11.9k
                    *odata++ = 'u';
70
11.9k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
11.9k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
11.9k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
11.9k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
11.9k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
20.3k
                else {
77
20.3k
                    *odata++ = 'U';
78
20.3k
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
20.3k
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
20.3k
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
20.3k
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
20.3k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
20.3k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
20.3k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
20.3k
                    *odata++ = Py_hexdigits[ch & 0xF];
86
20.3k
                }
87
42.4k
            }
88
            /* Copy characters as-is */
89
6.31M
            else {
90
6.31M
                *odata++ = ch;
91
6.31M
            }
92
6.35M
        }
93
69.4M
    }
94
193k
    *odata = quote;
95
193k
}
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.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
21.0k
            *odata++ = '\\';
23
21.0k
            *odata++ = ch;
24
21.0k
            continue;
25
21.0k
        }
26
27
        /* Map special whitespace to '\t', \n', '\r' */
28
16.6M
        if (ch == '\t') {
29
935
            *odata++ = '\\';
30
935
            *odata++ = 't';
31
935
        }
32
16.6M
        else if (ch == '\n') {
33
269
            *odata++ = '\\';
34
269
            *odata++ = 'n';
35
269
        }
36
16.6M
        else if (ch == '\r') {
37
379
            *odata++ = '\\';
38
379
            *odata++ = 'r';
39
379
        }
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
620k
        else if (ch < 0x7F) {
51
522k
            *odata++ = ch;
52
522k
        }
53
54
        /* Non-ASCII characters */
55
97.4k
        else {
56
            /* Map Unicode whitespace and control characters
57
               (categories Z* and C* except ASCII space)
58
            */
59
97.4k
            if (!Py_UNICODE_ISPRINTABLE(ch)) {
60
5.26k
                *odata++ = '\\';
61
                /* Map 8-bit characters to '\xhh' */
62
5.26k
                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.06k
                else if (ch <= 0xffff) {
69
3.07k
                    *odata++ = 'u';
70
3.07k
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
71
3.07k
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
72
3.07k
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
73
3.07k
                    *odata++ = Py_hexdigits[ch & 0xF];
74
3.07k
                }
75
                /* Map 21-bit characters to '\U00xxxxxx' */
76
993
                else {
77
993
                    *odata++ = 'U';
78
993
                    *odata++ = Py_hexdigits[(ch >> 28) & 0xF];
79
993
                    *odata++ = Py_hexdigits[(ch >> 24) & 0xF];
80
993
                    *odata++ = Py_hexdigits[(ch >> 20) & 0xF];
81
993
                    *odata++ = Py_hexdigits[(ch >> 16) & 0xF];
82
993
                    *odata++ = Py_hexdigits[(ch >> 12) & 0xF];
83
993
                    *odata++ = Py_hexdigits[(ch >> 8) & 0xF];
84
993
                    *odata++ = Py_hexdigits[(ch >> 4) & 0xF];
85
993
                    *odata++ = Py_hexdigits[ch & 0xF];
86
993
                }
87
5.26k
            }
88
            /* Copy characters as-is */
89
92.1k
            else {
90
92.1k
                *odata++ = ch;
91
92.1k
            }
92
97.4k
        }
93
16.6M
    }
94
3.43k
    *odata = quote;
95
3.43k
}