751 */ |
751 */ |
752 typedef struct { |
752 typedef struct { |
753 PyObject_HEAD |
753 PyObject_HEAD |
754 /* Type-specific fields go here. */ |
754 /* Type-specific fields go here. */ |
755 PyObject *data; /* raw bytes of index */ |
755 PyObject *data; /* raw bytes of index */ |
|
756 Py_buffer buf; /* buffer of data */ |
756 PyObject **cache; /* cached tuples */ |
757 PyObject **cache; /* cached tuples */ |
757 const char **offsets; /* populated on demand */ |
758 const char **offsets; /* populated on demand */ |
758 Py_ssize_t raw_length; /* original number of elements */ |
759 Py_ssize_t raw_length; /* original number of elements */ |
759 Py_ssize_t length; /* current number of elements */ |
760 Py_ssize_t length; /* current number of elements */ |
760 PyObject *added; /* populated on demand */ |
761 PyObject *added; /* populated on demand */ |
806 inline_scan(self, self->offsets); |
807 inline_scan(self, self->offsets); |
807 } |
808 } |
808 return self->offsets[pos]; |
809 return self->offsets[pos]; |
809 } |
810 } |
810 |
811 |
811 return PyBytes_AS_STRING(self->data) + pos * v1_hdrsize; |
812 return (const char *)(self->buf.buf) + pos * v1_hdrsize; |
812 } |
813 } |
813 |
814 |
814 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, |
815 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, |
815 int *ps, int maxrev) |
816 int *ps, int maxrev) |
816 { |
817 { |
2387 * Find all RevlogNG entries in an index that has inline data. Update |
2388 * Find all RevlogNG entries in an index that has inline data. Update |
2388 * the optional "offsets" table with those entries. |
2389 * the optional "offsets" table with those entries. |
2389 */ |
2390 */ |
2390 static Py_ssize_t inline_scan(indexObject *self, const char **offsets) |
2391 static Py_ssize_t inline_scan(indexObject *self, const char **offsets) |
2391 { |
2392 { |
2392 const char *data = PyBytes_AS_STRING(self->data); |
2393 const char *data = (const char *)self->buf.buf; |
2393 Py_ssize_t pos = 0; |
2394 Py_ssize_t pos = 0; |
2394 Py_ssize_t end = PyBytes_GET_SIZE(self->data); |
2395 Py_ssize_t end = self->buf.len; |
2395 long incr = v1_hdrsize; |
2396 long incr = v1_hdrsize; |
2396 Py_ssize_t len = 0; |
2397 Py_ssize_t len = 0; |
2397 |
2398 |
2398 while (pos + v1_hdrsize <= end && pos >= 0) { |
2399 while (pos + v1_hdrsize <= end && pos >= 0) { |
2399 uint32_t comp_len; |
2400 uint32_t comp_len; |
2423 /* Initialize before argument-checking to avoid index_dealloc() crash. */ |
2424 /* Initialize before argument-checking to avoid index_dealloc() crash. */ |
2424 self->raw_length = 0; |
2425 self->raw_length = 0; |
2425 self->added = NULL; |
2426 self->added = NULL; |
2426 self->cache = NULL; |
2427 self->cache = NULL; |
2427 self->data = NULL; |
2428 self->data = NULL; |
|
2429 memset(&self->buf, 0, sizeof(self->buf)); |
2428 self->headrevs = NULL; |
2430 self->headrevs = NULL; |
2429 self->filteredrevs = Py_None; |
2431 self->filteredrevs = Py_None; |
2430 Py_INCREF(Py_None); |
2432 Py_INCREF(Py_None); |
2431 self->nt = NULL; |
2433 self->nt = NULL; |
2432 self->offsets = NULL; |
2434 self->offsets = NULL; |
2433 |
2435 |
2434 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj)) |
2436 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj)) |
2435 return -1; |
2437 return -1; |
2436 if (!PyBytes_Check(data_obj)) { |
2438 if (!PyObject_CheckBuffer(data_obj)) { |
2437 PyErr_SetString(PyExc_TypeError, "data is not a string"); |
2439 PyErr_SetString(PyExc_TypeError, |
|
2440 "data does not support buffer interface"); |
2438 return -1; |
2441 return -1; |
2439 } |
2442 } |
2440 size = PyBytes_GET_SIZE(data_obj); |
2443 |
|
2444 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1) |
|
2445 return -1; |
|
2446 size = self->buf.len; |
2441 |
2447 |
2442 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj); |
2448 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj); |
2443 self->data = data_obj; |
2449 self->data = data_obj; |
2444 |
2450 |
2445 self->ntlength = self->ntcapacity = 0; |
2451 self->ntlength = self->ntcapacity = 0; |
2476 |
2482 |
2477 static void index_dealloc(indexObject *self) |
2483 static void index_dealloc(indexObject *self) |
2478 { |
2484 { |
2479 _index_clearcaches(self); |
2485 _index_clearcaches(self); |
2480 Py_XDECREF(self->filteredrevs); |
2486 Py_XDECREF(self->filteredrevs); |
|
2487 if (self->buf.buf) { |
|
2488 PyBuffer_Release(&self->buf); |
|
2489 memset(&self->buf, 0, sizeof(self->buf)); |
|
2490 } |
2481 Py_XDECREF(self->data); |
2491 Py_XDECREF(self->data); |
2482 Py_XDECREF(self->added); |
2492 Py_XDECREF(self->added); |
2483 PyObject_Del(self); |
2493 PyObject_Del(self); |
2484 } |
2494 } |
2485 |
2495 |
2575 /* |
2585 /* |
2576 * returns a tuple of the form (index, index, cache) with elements as |
2586 * returns a tuple of the form (index, index, cache) with elements as |
2577 * follows: |
2587 * follows: |
2578 * |
2588 * |
2579 * index: an index object that lazily parses RevlogNG records |
2589 * index: an index object that lazily parses RevlogNG records |
2580 * cache: if data is inlined, a tuple (index_file_content, 0), else None |
2590 * cache: if data is inlined, a tuple (0, index_file_content), else None |
|
2591 * index_file_content could be a string, or a buffer |
2581 * |
2592 * |
2582 * added complications are for backwards compatibility |
2593 * added complications are for backwards compatibility |
2583 */ |
2594 */ |
2584 static PyObject *parse_index2(PyObject *self, PyObject *args) |
2595 static PyObject *parse_index2(PyObject *self, PyObject *args) |
2585 { |
2596 { |