274 static char *tuple_format = "Kiiiiiis#"; |
274 static char *tuple_format = "Kiiiiiis#"; |
275 #else |
275 #else |
276 static char *tuple_format = "kiiiiiis#"; |
276 static char *tuple_format = "kiiiiiis#"; |
277 #endif |
277 #endif |
278 |
278 |
|
279 /* A RevlogNG v1 index entry is 64 bytes long. */ |
|
280 static const long v1_hdrsize = 64; |
|
281 |
279 /* |
282 /* |
280 * Return a pointer to the beginning of a RevlogNG record. |
283 * Return a pointer to the beginning of a RevlogNG record. |
281 */ |
284 */ |
282 static const char *index_deref(indexObject *self, Py_ssize_t pos) |
285 static const char *index_deref(indexObject *self, Py_ssize_t pos) |
283 { |
286 { |
290 inline_scan(self, self->offsets); |
293 inline_scan(self, self->offsets); |
291 } |
294 } |
292 return self->offsets[pos]; |
295 return self->offsets[pos]; |
293 } |
296 } |
294 |
297 |
295 return PyString_AS_STRING(self->data) + pos * 64; |
298 return PyString_AS_STRING(self->data) + pos * v1_hdrsize; |
296 } |
299 } |
297 |
300 |
298 /* |
301 /* |
299 * RevlogNG format (all in big endian, data may be inlined): |
302 * RevlogNG format (all in big endian, data may be inlined): |
300 * 6 bytes: offset |
303 * 6 bytes: offset |
1135 */ |
1138 */ |
1136 static long inline_scan(indexObject *self, const char **offsets) |
1139 static long inline_scan(indexObject *self, const char **offsets) |
1137 { |
1140 { |
1138 const char *data = PyString_AS_STRING(self->data); |
1141 const char *data = PyString_AS_STRING(self->data); |
1139 const char *end = data + PyString_GET_SIZE(self->data); |
1142 const char *end = data + PyString_GET_SIZE(self->data); |
1140 const long hdrsize = 64; |
1143 long incr = v1_hdrsize; |
1141 long incr = hdrsize; |
|
1142 Py_ssize_t len = 0; |
1144 Py_ssize_t len = 0; |
1143 |
1145 |
1144 while (data + hdrsize <= end) { |
1146 while (data + v1_hdrsize <= end) { |
1145 uint32_t comp_len; |
1147 uint32_t comp_len; |
1146 const char *old_data; |
1148 const char *old_data; |
1147 /* 3rd element of header is length of compressed inline data */ |
1149 /* 3rd element of header is length of compressed inline data */ |
1148 comp_len = getbe32(data + 8); |
1150 comp_len = getbe32(data + 8); |
1149 incr = hdrsize + comp_len; |
1151 incr = v1_hdrsize + comp_len; |
1150 if (incr < hdrsize) |
1152 if (incr < v1_hdrsize) |
1151 break; |
1153 break; |
1152 if (offsets) |
1154 if (offsets) |
1153 offsets[len] = data; |
1155 offsets[len] = data; |
1154 len++; |
1156 len++; |
1155 old_data = data; |
1157 old_data = data; |
1156 data += incr; |
1158 data += incr; |
1157 if (data <= old_data) |
1159 if (data <= old_data) |
1158 break; |
1160 break; |
1159 } |
1161 } |
1160 |
1162 |
1161 if (data != end && data + hdrsize != end) { |
1163 if (data != end && data + v1_hdrsize != end) { |
1162 if (!PyErr_Occurred()) |
1164 if (!PyErr_Occurred()) |
1163 PyErr_SetString(PyExc_ValueError, "corrupt index file"); |
1165 PyErr_SetString(PyExc_ValueError, "corrupt index file"); |
1164 return -1; |
1166 return -1; |
1165 } |
1167 } |
1166 |
1168 |
1199 if (len == -1) |
1201 if (len == -1) |
1200 goto bail; |
1202 goto bail; |
1201 self->raw_length = len; |
1203 self->raw_length = len; |
1202 self->length = len + 1; |
1204 self->length = len + 1; |
1203 } else { |
1205 } else { |
1204 if (size % 64) { |
1206 if (size % v1_hdrsize) { |
1205 PyErr_SetString(PyExc_ValueError, "corrupt index file"); |
1207 PyErr_SetString(PyExc_ValueError, "corrupt index file"); |
1206 goto bail; |
1208 goto bail; |
1207 } |
1209 } |
1208 self->raw_length = size / 64; |
1210 self->raw_length = size / v1_hdrsize; |
1209 self->length = self->raw_length + 1; |
1211 self->length = self->raw_length + 1; |
1210 } |
1212 } |
1211 |
1213 |
1212 return 0; |
1214 return 0; |
1213 bail: |
1215 bail: |