41
43
int PyDict_SetItem(object d, object k, object v) except -1
43
45
void Py_INCREF(object)
46
void Py_INCREF_ptr "Py_INCREF" (PyObject *)
46
51
int PyObject_RichCompareBool(object, object, int opid) except -1
52
int PyObject_RichCompareBool_ptr "PyObject_RichCompareBool" (
53
PyObject *, PyObject *, int opid)
48
55
from bzrlib import errors, graph as _mod_graph, osutils, patiencediff, ui
128
cdef PyObject *_next_tuple_entry(object tpl, Py_ssize_t *pos):
130
if pos[0] >= PyTuple_GET_SIZE(tpl):
132
return PyTuple_GET_ITEM(tpl, pos[0])
121
135
cdef object _combine_annotations(ann_one, ann_two, cache):
122
136
"""Combine the annotations from both sides."""
123
137
cdef Py_ssize_t pos_one, pos_two, len_one, len_two
124
138
cdef Py_ssize_t out_pos
139
cdef PyObject *temp, *left, *right
127
141
cache_key = (ann_one, ann_two)
128
142
temp = PyDict_GetItem(cache, cache_key)
133
147
raise TypeError('annotations must be tuples')
134
148
# We know that annotations are tuples, and that both sides are already
135
149
# sorted, so we can just walk and update a new list.
136
len_one = PyTuple_GET_SIZE(ann_one)
137
len_two = PyTuple_GET_SIZE(ann_two)
138
if len_one < 1 or len_two < 1:
139
raise ValueError('annotations cannot claim 0 references.')
143
temp = PyTuple_GET_ITEM(ann_one, pos_one); left = <object>temp
144
temp = PyTuple_GET_ITEM(ann_two, pos_two); right = <object>temp
145
new_ann = PyTuple_New(len_one + len_two)
146
while left is not None or right is not None:
147
if PyObject_RichCompareBool(left, right, Py_EQ):
148
# Append once, increment both
150
PyTuple_SET_ITEM(new_ann, out_pos, left)
151
pos_one = pos_one + 1
152
pos_two = pos_two + 1
153
if pos_one >= len_one:
156
temp = PyTuple_GET_ITEM(ann_one, pos_one); left = <object>temp
157
if pos_two >= len_two:
160
temp = PyTuple_GET_ITEM(ann_two, pos_two); right = <object>temp
161
elif right is None or (left is not None and left < right):
163
PyTuple_SET_ITEM(new_ann, out_pos, left)
164
pos_one = pos_one + 1
165
if pos_one >= len_one:
168
temp = PyTuple_GET_ITEM(ann_one, pos_one); left = <object>temp
171
PyTuple_SET_ITEM(new_ann, out_pos, right)
172
pos_two = pos_two + 1
173
if pos_two >= len_two:
176
temp = PyTuple_GET_ITEM(ann_two, pos_two); right = <object>temp
177
out_pos = out_pos + 1
178
if out_pos != len_one + len_two:
153
left = _next_tuple_entry(ann_one, &pos_one)
154
right = _next_tuple_entry(ann_two, &pos_two)
155
new_ann = PyTuple_New(PyTuple_GET_SIZE(ann_one)
156
+ PyTuple_GET_SIZE(ann_two))
157
while left != NULL and right != NULL:
158
if (PyObject_RichCompareBool_ptr(left, right, Py_EQ)):
159
# Identical values, step both
161
PyTuple_SET_ITEM_ptr(new_ann, out_pos, left)
162
left = _next_tuple_entry(ann_one, &pos_one)
163
right = _next_tuple_entry(ann_two, &pos_two)
164
elif (PyObject_RichCompareBool_ptr(left, right, Py_LT)):
165
# left < right or right == NULL
167
PyTuple_SET_ITEM_ptr(new_ann, out_pos, left)
168
left = _next_tuple_entry(ann_one, &pos_one)
169
else: # right < left or left == NULL
171
PyTuple_SET_ITEM_ptr(new_ann, out_pos, right)
172
right = _next_tuple_entry(ann_two, &pos_two)
173
out_pos = out_pos + 1
176
PyTuple_SET_ITEM_ptr(new_ann, out_pos, left)
177
left = _next_tuple_entry(ann_one, &pos_one)
178
out_pos = out_pos + 1
181
PyTuple_SET_ITEM_ptr(new_ann, out_pos, right)
182
right = _next_tuple_entry(ann_two, &pos_two)
183
out_pos = out_pos + 1
184
if out_pos != PyTuple_GET_SIZE(new_ann):
185
# Timing _PyTuple_Resize was not significantly faster that slicing
179
186
# PyTuple_Resize((<PyObject **>new_ann), out_pos)
180
187
new_ann = new_ann[0:out_pos]
181
188
PyDict_SetItem(cache, cache_key, new_ann)