24 * |
24 * |
25 * A few implementation notes: |
25 * A few implementation notes: |
26 * |
26 * |
27 * We modify Python integers for refcounting, but those integers are |
27 * We modify Python integers for refcounting, but those integers are |
28 * never visible to Python code. |
28 * never visible to Python code. |
29 * |
|
30 * We mutate strings in-place, but leave them immutable once they can |
|
31 * be seen by Python code. |
|
32 */ |
29 */ |
33 typedef struct { |
30 typedef struct { |
34 PyObject_HEAD |
31 PyObject_HEAD |
35 PyObject *dict; |
32 PyObject *dict; |
36 } dirsObject; |
33 } dirsObject; |
61 * The implementation, therefore, is heavily dependent on CPython |
58 * The implementation, therefore, is heavily dependent on CPython |
62 * implementation details. We also commit violations of the Python |
59 * implementation details. We also commit violations of the Python |
63 * "protocol" such as mutating immutable objects. But since we only |
60 * "protocol" such as mutating immutable objects. But since we only |
64 * mutate objects created in this function or in other well-defined |
61 * mutate objects created in this function or in other well-defined |
65 * locations, the references are known so these violations should go |
62 * locations, the references are known so these violations should go |
66 * unnoticed. The code for adjusting the length of a PyBytesObject is |
63 * unnoticed. */ |
67 * essentially a minimal version of _PyBytes_Resize. */ |
|
68 while ((pos = _finddir(cpath, pos - 1)) != -1) { |
64 while ((pos = _finddir(cpath, pos - 1)) != -1) { |
69 PyObject *val; |
65 PyObject *val; |
70 |
66 |
71 if (pos < 2) { |
67 key = PyBytes_FromStringAndSize(cpath, pos); |
72 key = PyBytes_FromStringAndSize(cpath, pos); |
68 if (key == NULL) |
73 if (key == NULL) |
69 goto bail; |
74 goto bail; |
|
75 } else { |
|
76 /* It's likely that every prefix already has an entry |
|
77 in our dict. Try to avoid allocating and |
|
78 deallocating a string for each prefix we check. */ |
|
79 if (key != NULL) |
|
80 ((PyBytesObject *)key)->ob_shash = -1; |
|
81 else { |
|
82 /* We know pos >= 2, so we won't get a small |
|
83 * shared string. */ |
|
84 key = PyBytes_FromStringAndSize(cpath, pos); |
|
85 if (key == NULL) |
|
86 goto bail; |
|
87 } |
|
88 /* Py_SIZE(o) refers to the ob_size member of |
|
89 * the struct. Yes, assigning to what looks |
|
90 * like a function seems wrong. */ |
|
91 Py_SIZE(key) = pos; |
|
92 ((PyBytesObject *)key)->ob_sval[pos] = '\0'; |
|
93 } |
|
94 |
70 |
95 val = PyDict_GetItem(dirs, key); |
71 val = PyDict_GetItem(dirs, key); |
96 if (val != NULL) { |
72 if (val != NULL) { |
97 PYLONG_VALUE(val) += 1; |
73 PYLONG_VALUE(val) += 1; |
98 if (pos < 2) { |
74 Py_CLEAR(key); |
99 /* This was a short string, so we |
|
100 * probably got a small shared string |
|
101 * we can't mutate on the next loop |
|
102 * iteration. Clear it. |
|
103 */ |
|
104 Py_CLEAR(key); |
|
105 } |
|
106 break; |
75 break; |
107 } |
76 } |
108 |
77 |
109 /* Force Python to not reuse a small shared int. */ |
78 /* Force Python to not reuse a small shared int. */ |
110 #ifdef IS_PY3K |
79 #ifdef IS_PY3K |