/home/mdboom/Work/builds/cpython/Objects/accu.c
Line | Count | Source (jump to first uncovered line) |
1 | /* Accumulator struct implementation */ |
2 | |
3 | #include "Python.h" |
4 | #include "pycore_accu.h" |
5 | |
6 | static PyObject * |
7 | join_list_unicode(PyObject *lst) |
8 | { |
9 | /* return ''.join(lst) */ |
10 | PyObject *sep, *ret; |
11 | sep = PyUnicode_FromStringAndSize("", 0); |
12 | ret = PyUnicode_Join(sep, lst); |
13 | Py_DECREF(sep); |
14 | return ret; |
15 | } |
16 | |
17 | int |
18 | _PyAccu_Init(_PyAccu *acc) |
19 | { |
20 | /* Lazily allocated */ |
21 | acc->large = NULL; |
22 | acc->small = PyList_New(0); |
23 | if (acc->small == NULL) Branch (23:9): [True: 0, False: 103k]
|
24 | return -1; |
25 | return 0; |
26 | } |
27 | |
28 | static int |
29 | flush_accumulator(_PyAccu *acc) |
30 | { |
31 | Py_ssize_t nsmall = PyList_GET_SIZE(acc->small); |
32 | if (nsmall) { Branch (32:9): [True: 134, False: 0]
|
33 | int ret; |
34 | PyObject *joined; |
35 | if (acc->large == NULL) { Branch (35:13): [True: 134, False: 0]
|
36 | acc->large = PyList_New(0); |
37 | if (acc->large == NULL) Branch (37:17): [True: 0, False: 134]
|
38 | return -1; |
39 | } |
40 | joined = join_list_unicode(acc->small); |
41 | if (joined == NULL) Branch (41:13): [True: 0, False: 134]
|
42 | return -1; |
43 | if (PyList_SetSlice(acc->small, 0, nsmall, NULL)) { Branch (43:13): [True: 0, False: 134]
|
44 | Py_DECREF(joined); |
45 | return -1; |
46 | } |
47 | ret = PyList_Append(acc->large, joined); |
48 | Py_DECREF(joined); |
49 | return ret; |
50 | } |
51 | return 0; |
52 | } |
53 | |
54 | int |
55 | _PyAccu_Accumulate(_PyAccu *acc, PyObject *unicode) |
56 | { |
57 | Py_ssize_t nsmall; |
58 | assert(PyUnicode_Check(unicode)); |
59 | |
60 | if (PyList_Append(acc->small, unicode)) Branch (60:9): [True: 0, False: 180k]
|
61 | return -1; |
62 | nsmall = PyList_GET_SIZE(acc->small); |
63 | /* Each item in a list of unicode objects has an overhead (in 64-bit |
64 | * builds) of: |
65 | * - 8 bytes for the list slot |
66 | * - 56 bytes for the header of the unicode object |
67 | * that is, 64 bytes. 100000 such objects waste more than 6 MiB |
68 | * compared to a single concatenated string. |
69 | */ |
70 | if (nsmall < 100000) Branch (70:9): [True: 180k, False: 0]
|
71 | return 0; |
72 | return flush_accumulator(acc); |
73 | } |
74 | |
75 | PyObject * |
76 | _PyAccu_FinishAsList(_PyAccu *acc) |
77 | { |
78 | int ret; |
79 | PyObject *res; |
80 | |
81 | ret = flush_accumulator(acc); |
82 | Py_CLEAR(acc->small); |
83 | if (ret) { Branch (83:9): [True: 0, False: 134]
|
84 | Py_CLEAR(acc->large); |
85 | return NULL; |
86 | } |
87 | res = acc->large; |
88 | acc->large = NULL; |
89 | return res; |
90 | } |
91 | |
92 | PyObject * |
93 | _PyAccu_Finish(_PyAccu *acc) |
94 | { |
95 | PyObject *list, *res; |
96 | if (acc->large == NULL) { Branch (96:9): [True: 11.4k, False: 0]
|
97 | list = acc->small; |
98 | acc->small = NULL; |
99 | } |
100 | else { |
101 | list = _PyAccu_FinishAsList(acc); |
102 | if (!list) Branch (102:13): [True: 0, False: 0]
|
103 | return NULL; |
104 | } |
105 | res = join_list_unicode(list); |
106 | Py_DECREF(list); |
107 | return res; |
108 | } |
109 | |
110 | void |
111 | _PyAccu_Destroy(_PyAccu *acc) |
112 | { |
113 | Py_CLEAR(acc->small); |
114 | Py_CLEAR(acc->large); |
115 | } |