35
35
Py_ssize_t PyTuple_GET_SIZE(object t)
36
36
int PyString_CheckExact(object)
37
37
char *PyString_AS_STRING(object s)
38
PyObject *PyString_FromStringAndSize_ptr "PyString_FromStringAndSize" (char *, Py_ssize_t)
38
39
Py_ssize_t PyString_GET_SIZE(object)
40
void PyString_InternInPlace(PyObject **)
41
unsigned long PyInt_AsUnsignedLongMask(object) except? -1
40
43
int PyDict_SetItem(object d, object k, object v) except -1
54
58
# cimport all of the definitions we will need to access
55
59
from _static_tuple_c cimport StaticTuple,\
56
60
import_static_tuple_c, StaticTuple_New, \
57
StaticTuple_Intern, StaticTuple_SET_ITEM, StaticTuple_CheckExact
61
StaticTuple_Intern, StaticTuple_SET_ITEM, StaticTuple_CheckExact, \
59
64
cdef extern from "_static_tuple_c.h":
60
65
# Defined explicitly rather than cimport-ing. Trying to use cimport, the
63
68
PyObject * StaticTuple_GET_ITEM_ptr "StaticTuple_GET_ITEM" (StaticTuple,
66
cdef extern from "zlib.h":
67
ctypedef unsigned long uLong
68
ctypedef unsigned int uInt
69
ctypedef unsigned char Bytef
71
uLong crc32(uLong crc, Bytef *buf, uInt len)
72
from zlib import crc32
74
75
# Set up the StaticTuple C_API functionality
100
cdef object safe_interned_string_from_size(char *s, Py_ssize_t size):
101
cdef PyObject *py_str
103
raise AssertionError(
104
'tried to create a string with an invalid size: %d @0x%x'
106
py_str = PyString_FromStringAndSize_ptr(s, size)
107
PyString_InternInPlace(&py_str)
108
result = <object>py_str
109
# Casting a PyObject* to an <object> triggers an INCREF from Pyrex, so we
110
# DECREF it to avoid geting immortal strings
111
Py_DECREF_ptr(py_str)
99
115
def _search_key_16(key):
100
116
"""See chk_map._search_key_16."""
101
117
cdef Py_ssize_t num_bits
102
118
cdef Py_ssize_t i, j
103
119
cdef Py_ssize_t num_out_bytes
120
cdef unsigned long crc_val
107
121
cdef Py_ssize_t out_off
111
if not StaticTuple_CheckExact(key):
112
raise TypeError('key %r is not a StaticTuple' % (key,))
113
124
num_bits = len(key)
114
125
# 4 bytes per crc32, and another 1 byte between bits
115
126
num_out_bytes = (9 * num_bits) - 1
120
131
c_out[0] = c'\x00'
121
132
c_out = c_out + 1
122
# We use the _ptr variant, because GET_ITEM returns a borrowed
123
# reference, and Pyrex assumes that returned 'object' are a new
125
bit = StaticTuple_GET_ITEM_ptr(key, i)
126
if not PyString_CheckExact_ptr(bit):
127
raise TypeError('Bit %d of %r is not a string' % (i, key))
128
c_bit = <Bytef *>PyString_AS_STRING_ptr(bit)
129
c_len = PyString_GET_SIZE_ptr(bit)
130
crc_val = crc32(0, c_bit, c_len)
133
crc_val = PyInt_AsUnsignedLongMask(crc32(key[i]))
132
135
sprintf(c_out, '%08X', crc_val)
133
136
c_out = c_out + 8
139
142
cdef Py_ssize_t num_bits
140
143
cdef Py_ssize_t i, j
141
144
cdef Py_ssize_t num_out_bytes
145
cdef unsigned long crc_val
145
146
cdef Py_ssize_t out_off
149
if not StaticTuple_CheckExact(key):
150
raise TypeError('key %r is not a StaticTuple' % (key,))
151
149
num_bits = len(key)
152
150
# 4 bytes per crc32, and another 1 byte between bits
153
151
num_out_bytes = (5 * num_bits) - 1
158
156
c_out[0] = c'\x00'
159
157
c_out = c_out + 1
160
bit = StaticTuple_GET_ITEM_ptr(key, i)
161
if not PyString_CheckExact_ptr(bit):
162
raise TypeError('Bit %d of %r is not a string: %r'
163
% (i, key, <object>bit))
164
c_bit = <Bytef *>PyString_AS_STRING_ptr(bit)
165
c_len = PyString_GET_SIZE_ptr(bit)
166
crc_val = crc32(0, c_bit, c_len)
158
crc_val = PyInt_AsUnsignedLongMask(crc32(key[i]))
168
160
c_out[0] = (crc_val >> 24) & 0xFF
169
161
c_out[1] = (crc_val >> 16) & 0xFF
193
cdef _import_globals():
194
"""Set the global attributes. Done lazy to avoid recursive import loops."""
195
global _LeafNode, _InternalNode, _unknown
197
from bzrlib import chk_map
198
_LeafNode = chk_map.LeafNode
199
_InternalNode = chk_map.InternalNode
200
_unknown = chk_map._unknown
201
203
def _deserialise_leaf_node(bytes, key, search_key_func=None):
202
204
"""Deserialise bytes, with key key, into a LeafNode.
215
217
cdef StaticTuple entry_bits
217
219
if _LeafNode is None:
218
from bzrlib import chk_map
219
_LeafNode = chk_map.LeafNode
220
_InternalNode = chk_map.InternalNode
221
_unknown = chk_map._unknown
223
222
result = _LeafNode(search_key_func=search_key_func)
224
223
# Splitlines can split on '\r' so don't use it, split('\n') adds an
322
321
next_null - entry_start)
324
323
StaticTuple_SET_ITEM(entry_bits, i, entry)
325
if len(entry_bits) != width:
324
if StaticTuple_GET_SIZE(entry_bits) != width:
326
325
raise AssertionError(
327
326
'Incorrect number of elements (%d vs %d)'
328
327
% (len(entry_bits)+1, width + 1))
358
357
cdef char *prefix, *line_prefix, *next_null, *c_item_prefix
360
359
if _InternalNode is None:
361
from bzrlib import chk_map
362
_LeafNode = chk_map.LeafNode
363
_InternalNode = chk_map.InternalNode
364
_unknown = chk_map._unknown
365
361
result = _InternalNode(search_key_func=search_key_func)
367
363
if not StaticTuple_CheckExact(key):
422
418
result._node_width = len(item_prefix)
423
419
result._search_prefix = PyString_FromStringAndSize(prefix, prefix_length)
423
def _bytes_to_text_key(bytes):
424
"""Take a CHKInventory value string and return a (file_id, rev_id) tuple"""
426
cdef char *byte_str, *cur_end, *file_id_str, *byte_end
427
cdef char *revision_str
428
cdef Py_ssize_t byte_size, pos, file_id_len
430
if not PyString_CheckExact(bytes):
431
raise TypeError('bytes must be a string')
432
byte_str = PyString_AS_STRING(bytes)
433
byte_size = PyString_GET_SIZE(bytes)
434
byte_end = byte_str + byte_size
435
cur_end = <char*>memchr(byte_str, c':', byte_size)
437
raise ValueError('No kind section found.')
438
if cur_end[1] != c' ':
439
raise ValueError('Kind section should end with ": "')
440
file_id_str = cur_end + 2
441
# file_id is now the data up until the next newline
442
cur_end = <char*>memchr(file_id_str, c'\n', byte_end - file_id_str)
444
raise ValueError('no newline after file-id')
445
file_id = safe_interned_string_from_size(file_id_str,
446
cur_end - file_id_str)
447
# this is the end of the parent_str
448
cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
450
raise ValueError('no newline after parent_str')
451
# end of the name str
452
cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
454
raise ValueError('no newline after name str')
455
# the next section is the revision info
456
revision_str = cur_end + 1
457
cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
459
# This is probably a dir: entry, which has revision as the last item
461
revision = safe_interned_string_from_size(revision_str,
462
cur_end - revision_str)
463
key = StaticTuple_New(2)
465
StaticTuple_SET_ITEM(key, 0, file_id)
467
StaticTuple_SET_ITEM(key, 1, revision)
468
return StaticTuple_Intern(key)