equal
deleted
inserted
replaced
361 hit->deleted = true; |
361 hit->deleted = true; |
362 self->livelines--; |
362 self->livelines--; |
363 return 0; |
363 return 0; |
364 } |
364 } |
365 |
365 |
|
366 /* Do a binary search for the insertion point for new, creating the |
|
367 * new entry if needed. */ |
|
368 static int internalsetitem(lazymanifest *self, line *new) { |
|
369 int start = 0, end = self->numlines; |
|
370 while (start < end) { |
|
371 int pos = start + (end - start) / 2; |
|
372 int c = linecmp(new, self->lines + pos); |
|
373 if (c < 0) |
|
374 end = pos; |
|
375 else if (c > 0) |
|
376 start = pos + 1; |
|
377 else { |
|
378 if (self->lines[pos].deleted) |
|
379 self->livelines++; |
|
380 start = pos; |
|
381 goto finish; |
|
382 } |
|
383 } |
|
384 /* being here means we need to do an insert */ |
|
385 if (!realloc_if_full(self)) { |
|
386 PyErr_NoMemory(); |
|
387 return -1; |
|
388 } |
|
389 memmove(self->lines + start + 1, self->lines + start, |
|
390 (self->numlines - start) * sizeof(line)); |
|
391 self->numlines++; |
|
392 self->livelines++; |
|
393 finish: |
|
394 self->lines[start] = *new; |
|
395 self->dirty = true; |
|
396 return 0; |
|
397 } |
|
398 |
366 static int lazymanifest_setitem( |
399 static int lazymanifest_setitem( |
367 lazymanifest *self, PyObject *key, PyObject *value) |
400 lazymanifest *self, PyObject *key, PyObject *value) |
368 { |
401 { |
369 char *path; |
402 char *path; |
370 Py_ssize_t plen; |
403 Py_ssize_t plen; |
376 Py_ssize_t flen; |
409 Py_ssize_t flen; |
377 size_t dlen; |
410 size_t dlen; |
378 char *dest; |
411 char *dest; |
379 int i; |
412 int i; |
380 line new; |
413 line new; |
381 line *hit; |
|
382 if (!PyString_Check(key)) { |
414 if (!PyString_Check(key)) { |
383 PyErr_Format(PyExc_TypeError, |
415 PyErr_Format(PyExc_TypeError, |
384 "setitem: manifest keys must be a string."); |
416 "setitem: manifest keys must be a string."); |
385 return -1; |
417 return -1; |
386 } |
418 } |
444 if (hlen > 20) { |
476 if (hlen > 20) { |
445 new.hash_suffix = hash[20]; |
477 new.hash_suffix = hash[20]; |
446 } |
478 } |
447 new.from_malloc = true; /* is `start` a pointer we allocated? */ |
479 new.from_malloc = true; /* is `start` a pointer we allocated? */ |
448 new.deleted = false; /* is this entry deleted? */ |
480 new.deleted = false; /* is this entry deleted? */ |
449 hit = bsearch(&new, self->lines, self->numlines, |
481 if (internalsetitem(self, &new)) { |
450 sizeof(line), &linecmp); |
482 return -1; |
451 self->dirty = true; |
|
452 if (hit) { |
|
453 /* updating a line we already had */ |
|
454 if (hit->from_malloc) { |
|
455 free(hit->start); |
|
456 } |
|
457 if (hit->deleted) { |
|
458 self->livelines++; |
|
459 } |
|
460 *hit = new; |
|
461 } else { |
|
462 /* new line */ |
|
463 if (!realloc_if_full(self)) { |
|
464 PyErr_NoMemory(); |
|
465 return -1; |
|
466 } |
|
467 self->lines[self->numlines++] = new; |
|
468 self->livelines++; |
|
469 /* TODO: do a binary search and insert rather than |
|
470 * append and qsort. Also offer a batch-insert |
|
471 * interface, which should be a nice little |
|
472 * performance win. |
|
473 */ |
|
474 qsort(self->lines, self->numlines, sizeof(line), &linecmp); |
|
475 } |
483 } |
476 return 0; |
484 return 0; |
477 } |
485 } |
478 |
486 |
479 static PyMappingMethods lazymanifest_mapping_methods = { |
487 static PyMappingMethods lazymanifest_mapping_methods = { |