mercurial/manifest.c
author Augie Fackler <augie@google.com>
Fri, 30 Jan 2015 21:30:40 -0800
changeset 24228 542c891274b2
parent 24214 a5f1bccd2996
child 24286 40528ad1b1e8
permissions -rw-r--r--
lazymanifest: use a binary search to do an insertion This makes insertions log(n) plus some memmove() overhead, rather than doing an append followed by an n*log(n) sort. There's probably a lot of performance to be gained by adding a batch-add method, which could be smarter about the memmove()s performed. Includes a couple of extra tests that should help prevent bugs. Thanks to Martin for some significant pre-mail cleanup of this change.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
24214
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     1
/*
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     2
 * manifest.c - manifest type that does on-demand parsing.
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     3
 *
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     4
 * Copyright 2015, Google Inc.
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     5
 *
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     6
 * This software may be used and distributed according to the terms of
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     7
 * the GNU General Public License, incorporated herein by reference.
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     8
 */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
     9
#include <assert.h>
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    10
#include <string.h>
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    11
#include <stdlib.h>
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    12
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    13
#include <Python.h>
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    14
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    15
/* VC9 doesn't include bool and lacks stdbool.h based on my searching */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
#ifdef _MSC_VER
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    17
#define true 1
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    18
#define false 0
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    19
typedef unsigned char bool;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
#else
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    21
#include <stdbool.h>
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    22
#endif
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    24
#define DEFAULT_LINES 100000
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    25
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    26
typedef struct {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    27
	char *start;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
	Py_ssize_t len; /* length of line including terminal newline */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    29
	char hash_suffix;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    30
	bool from_malloc;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    31
	bool deleted;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    32
} line;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    33
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    34
typedef struct {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    35
	PyObject_HEAD
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
	PyObject *pydata;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    37
	line *lines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
	int numlines; /* number of line entries */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
	int livelines; /* number of non-deleted lines */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
	int maxlines; /* allocated number of lines */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
	bool dirty;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
} lazymanifest;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    43
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
#define MANIFEST_OOM -1
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
#define MANIFEST_NOT_SORTED -2
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
#define MANIFEST_MALFORMED -3
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
/* defined in parsers.c */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
PyObject *unhexlify(const char *str, int len);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    51
/* get the length of the path for a line */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
static size_t pathlen(line *l) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
	return strlen(l->start);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    55
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    56
/* get the node value of a single line */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    57
static PyObject *nodeof(line *l) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
	char *s = l->start;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    59
	ssize_t llen = pathlen(l);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    60
	PyObject *hash = unhexlify(s + llen + 1, 40);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    61
	if (!hash) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    62
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    63
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
	if (l->hash_suffix != '\0') {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    65
		char newhash[21];
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
		memcpy(newhash, PyString_AsString(hash), 20);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    67
		Py_DECREF(hash);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    68
		newhash[20] = l->hash_suffix;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    69
		hash = PyString_FromStringAndSize(newhash, 21);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    70
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    71
	return hash;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    72
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    73
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    74
/* get the node hash and flags of a line as a tuple */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    75
static PyObject *hashflags(line *l)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    76
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    77
	char *s = l->start;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    78
	size_t plen = pathlen(l);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    79
	PyObject *hash = nodeof(l);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    80
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    81
	/* 40 for hash, 1 for null byte, 1 for newline */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    82
	size_t hplen = plen + 42;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    83
	Py_ssize_t flen = l->len - hplen;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    84
	PyObject *flags;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    85
	PyObject *tup;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    86
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    87
	if (!hash)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    88
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    89
	flags = PyString_FromStringAndSize(s + hplen - 1, flen);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    90
	if (!flags) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    91
		Py_DECREF(hash);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    92
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    93
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    94
	tup = PyTuple_Pack(2, hash, flags);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    95
	Py_DECREF(flags);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    96
	Py_DECREF(hash);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    97
	return tup;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    98
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
    99
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   100
/* if we're about to run out of space in the line index, add more */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
static bool realloc_if_full(lazymanifest *self)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   102
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
	if (self->numlines == self->maxlines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   104
		self->maxlines *= 2;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   105
		self->lines = realloc(self->lines, self->maxlines * sizeof(line));
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   106
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   107
	return self->lines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   108
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   109
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   110
/*
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   111
 * Find the line boundaries in the manifest that 'data' points to and store
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
 * information about each line in 'self'.
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
 */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
static int find_lines(lazymanifest *self, char *data, Py_ssize_t len)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
	char *prev = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   117
	while (len > 0) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
		line *l;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   119
		char *next = memchr(data, '\n', len);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   120
		if (!next) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   121
			return MANIFEST_MALFORMED;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   122
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   123
		next++; /* advance past newline */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   124
		if (!realloc_if_full(self)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   125
			return MANIFEST_OOM; /* no memory */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   126
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   127
		if (prev && strcmp(prev, data) > -1) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   128
			/* This data isn't sorted, so we have to abort. */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   129
			return MANIFEST_NOT_SORTED;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   130
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   131
		l = self->lines + ((self->numlines)++);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   132
		l->start = data;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   133
		l->len = next - data;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   134
		l->hash_suffix = '\0';
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   135
		l->from_malloc = false;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   136
		l->deleted = false;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   137
		len = len - l->len;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   138
		prev = data;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   139
		data = next;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   140
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   141
	self->livelines = self->numlines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   142
	return 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   143
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   144
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   145
static int lazymanifest_init(lazymanifest *self, PyObject *args)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   146
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   147
	char *data;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   148
	Py_ssize_t len;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   149
	int err, ret;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   150
	PyObject *pydata;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   151
	if (!PyArg_ParseTuple(args, "S", &pydata)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   152
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   153
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   154
	err = PyString_AsStringAndSize(pydata, &data, &len);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   155
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   156
	self->dirty = false;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   157
	if (err == -1)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   158
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   159
	self->pydata = pydata;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   160
	Py_INCREF(self->pydata);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   161
	Py_BEGIN_ALLOW_THREADS
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   162
	self->lines = malloc(DEFAULT_LINES * sizeof(line));
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   163
	self->maxlines = DEFAULT_LINES;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   164
	self->numlines = 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   165
	if (!self->lines)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   166
		ret = MANIFEST_OOM;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   167
	else
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   168
		ret = find_lines(self, data, len);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   169
	Py_END_ALLOW_THREADS
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   170
	switch (ret) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   171
	case 0:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   172
		break;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   173
	case MANIFEST_OOM:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   174
		PyErr_NoMemory();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   175
		break;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   176
	case MANIFEST_NOT_SORTED:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   177
		PyErr_Format(PyExc_ValueError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   178
			     "Manifest lines not in sorted order.");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   179
		break;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   180
	case MANIFEST_MALFORMED:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   181
		PyErr_Format(PyExc_ValueError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   182
			     "Manifest did not end in a newline.");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   183
		break;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   184
	default:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   185
		PyErr_Format(PyExc_ValueError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   186
			     "Unknown problem parsing manifest.");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   187
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   188
	return ret == 0 ? 0 : -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   189
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   190
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   191
static void lazymanifest_dealloc(lazymanifest *self)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   192
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   193
	/* free any extra lines we had to allocate */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   194
	int i;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   195
	for (i = 0; i < self->numlines; i++) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   196
		if (self->lines[i].from_malloc) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   197
			free(self->lines[i].start);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   198
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   199
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   200
	if (self->lines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   201
		free(self->lines);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   202
		self->lines = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   203
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   204
	if (self->pydata) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   205
		Py_DECREF(self->pydata);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   206
		self->pydata = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   207
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   208
	PyObject_Del(self);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   209
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   210
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   211
/* iteration support */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   212
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   213
typedef struct {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   214
	PyObject_HEAD lazymanifest *m;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   215
	Py_ssize_t pos;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   216
} lmIter;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   217
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   218
static void lmiter_dealloc(PyObject *o)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   219
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   220
	lmIter *self = (lmIter *)o;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   221
	Py_DECREF(self->m);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   222
	PyObject_Del(self);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   223
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   224
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   225
static PyObject *lmiter_iternext(PyObject *o)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   226
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   227
	size_t pl;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   228
	line *l;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   229
	Py_ssize_t consumed;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   230
	PyObject *ret = NULL, *path = NULL, *hash = NULL, *flags = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   231
	lmIter *self = (lmIter *)o;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   232
	do {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   233
		self->pos++;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   234
		if (self->pos >= self->m->numlines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   235
			goto bail;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   236
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   237
		/* skip over deleted manifest entries */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   238
	} while (self->m->lines[self->pos].deleted);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   239
	l = self->m->lines + self->pos;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   240
	pl = pathlen(l);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   241
	path = PyString_FromStringAndSize(l->start, pl);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   242
	hash = nodeof(l);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   243
	consumed = pl + 41;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   244
	flags = PyString_FromStringAndSize(l->start + consumed,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   245
									   l->len - consumed - 1);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   246
	if (!flags) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   247
		goto bail;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   248
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   249
	ret = PyTuple_Pack(3, path, hash, flags);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   250
 bail:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   251
	Py_XDECREF(path);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   252
	Py_XDECREF(hash);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   253
	Py_XDECREF(flags);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   254
	return ret;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   255
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   256
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   257
static PyTypeObject lazymanifestIterator = {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   258
	PyObject_HEAD_INIT(NULL)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   259
	0,                               /*ob_size */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   260
	"parsers.lazymanifest.iterator", /*tp_name */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   261
	sizeof(lmIter),                  /*tp_basicsize */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   262
	0,                               /*tp_itemsize */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   263
	lmiter_dealloc,                  /*tp_dealloc */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   264
	0,                               /*tp_print */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   265
	0,                               /*tp_getattr */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   266
	0,                               /*tp_setattr */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   267
	0,                               /*tp_compare */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   268
	0,                               /*tp_repr */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   269
	0,                               /*tp_as_number */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   270
	0,                               /*tp_as_sequence */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   271
	0,                               /*tp_as_mapping */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   272
	0,                               /*tp_hash */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   273
	0,                               /*tp_call */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   274
	0,                               /*tp_str */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   275
	0,                               /*tp_getattro */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   276
	0,                               /*tp_setattro */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   277
	0,                               /*tp_as_buffer */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   278
	/* tp_flags: Py_TPFLAGS_HAVE_ITER tells python to
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   279
	   use tp_iter and tp_iternext fields. */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   280
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   281
	"Iterator for a lazymanifest.",  /* tp_doc */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   282
	0,                               /* tp_traverse */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   283
	0,                               /* tp_clear */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   284
	0,                               /* tp_richcompare */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   285
	0,                               /* tp_weaklistoffset */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   286
	PyObject_SelfIter,               /* tp_iter: __iter__() method */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   287
	lmiter_iternext,                 /* tp_iternext: next() method */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   288
};
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   289
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   290
static lazymanifest *lazymanifest_copy(lazymanifest *self);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   291
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   292
static PyObject *lazymanifest_getiter(lazymanifest *self)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   293
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   294
	lmIter *i = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   295
	lazymanifest *t = lazymanifest_copy(self);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   296
	if (!t) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   297
		PyErr_NoMemory();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   298
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   299
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   300
	i = PyObject_New(lmIter, &lazymanifestIterator);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   301
	if (i) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   302
		i->m = t;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   303
		i->pos = -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   304
	} else {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   305
		Py_DECREF(t);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   306
		PyErr_NoMemory();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   307
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   308
	return (PyObject *)i;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   309
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   310
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   311
/* __getitem__ and __setitem__ support */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   312
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   313
static Py_ssize_t lazymanifest_size(lazymanifest *self)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   314
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   315
	return self->livelines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   316
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   317
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   318
static int linecmp(const void *left, const void *right)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   319
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   320
	return strcmp(((const line *)left)->start,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   321
		      ((const line *)right)->start);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   322
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   323
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   324
static PyObject *lazymanifest_getitem(lazymanifest *self, PyObject *key)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   325
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   326
	line needle;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   327
	line *hit;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   328
	if (!PyString_Check(key)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   329
		PyErr_Format(PyExc_TypeError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   330
			     "getitem: manifest keys must be a string.");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   331
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   332
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   333
	needle.start = PyString_AsString(key);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   334
	hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   335
		      &linecmp);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   336
	if (!hit || hit->deleted) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   337
		PyErr_Format(PyExc_KeyError, "No such manifest entry.");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   338
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   339
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   340
	return hashflags(hit);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   341
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   342
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   343
static int lazymanifest_delitem(lazymanifest *self, PyObject *key)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   344
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   345
	line needle;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   346
	line *hit;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   347
	if (!PyString_Check(key)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   348
		PyErr_Format(PyExc_TypeError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   349
			     "delitem: manifest keys must be a string.");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   350
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   351
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   352
	needle.start = PyString_AsString(key);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   353
	hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   354
		      &linecmp);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   355
	if (!hit || hit->deleted) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   356
		PyErr_Format(PyExc_KeyError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   357
			     "Tried to delete nonexistent manifest entry.");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   358
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   359
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   360
	self->dirty = true;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   361
	hit->deleted = true;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   362
	self->livelines--;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   363
	return 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   364
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   365
24228
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   366
/* Do a binary search for the insertion point for new, creating the
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   367
 * new entry if needed. */
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   368
static int internalsetitem(lazymanifest *self, line *new) {
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   369
	int start = 0, end = self->numlines;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   370
	while (start < end) {
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   371
		int pos = start + (end - start) / 2;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   372
		int c = linecmp(new, self->lines + pos);
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   373
		if (c < 0)
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   374
			end = pos;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   375
		else if (c > 0)
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   376
			start = pos + 1;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   377
		else {
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   378
			if (self->lines[pos].deleted)
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   379
				self->livelines++;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   380
			start = pos;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   381
			goto finish;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   382
		}
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   383
	}
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   384
	/* being here means we need to do an insert */
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   385
	if (!realloc_if_full(self)) {
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   386
		PyErr_NoMemory();
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   387
		return -1;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   388
	}
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   389
	memmove(self->lines + start + 1, self->lines + start,
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   390
		(self->numlines - start) * sizeof(line));
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   391
	self->numlines++;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   392
	self->livelines++;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   393
finish:
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   394
	self->lines[start] = *new;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   395
	self->dirty = true;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   396
	return 0;
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   397
}
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   398
24214
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   399
static int lazymanifest_setitem(
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   400
	lazymanifest *self, PyObject *key, PyObject *value)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   401
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   402
	char *path;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   403
	Py_ssize_t plen;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   404
	PyObject *pyhash;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   405
	Py_ssize_t hlen;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   406
	char *hash;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   407
	PyObject *pyflags;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   408
	char *flags;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   409
	Py_ssize_t flen;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   410
	size_t dlen;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   411
	char *dest;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   412
	int i;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   413
	line new;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   414
	if (!PyString_Check(key)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   415
		PyErr_Format(PyExc_TypeError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   416
			     "setitem: manifest keys must be a string.");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   417
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   418
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   419
	if (!value) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   420
		return lazymanifest_delitem(self, key);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   421
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   422
	if (!PyTuple_Check(value) || PyTuple_Size(value) != 2) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   423
		PyErr_Format(PyExc_TypeError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   424
			     "Manifest values must be a tuple of (node, flags).");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   425
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   426
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   427
	if (PyString_AsStringAndSize(key, &path, &plen) == -1) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   428
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   429
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   430
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   431
	pyhash = PyTuple_GetItem(value, 0);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   432
	if (!PyString_Check(pyhash)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   433
		PyErr_Format(PyExc_TypeError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   434
			     "node must be a 20-byte string");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   435
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   436
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   437
	hlen = PyString_Size(pyhash);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   438
	/* Some parts of the codebase try and set 21 or 22
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   439
	 * byte "hash" values in order to perturb things for
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   440
	 * status. We have to preserve at least the 21st
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   441
	 * byte. Sigh. If there's a 22nd byte, we drop it on
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   442
	 * the floor, which works fine.
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   443
	 */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   444
	if (hlen != 20 && hlen != 21 && hlen != 22) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   445
		PyErr_Format(PyExc_TypeError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   446
			     "node must be a 20-byte string");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   447
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   448
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   449
	hash = PyString_AsString(pyhash);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   450
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   451
	pyflags = PyTuple_GetItem(value, 1);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   452
	if (!PyString_Check(pyflags) || PyString_Size(pyflags) > 1) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   453
		PyErr_Format(PyExc_TypeError,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   454
			     "flags must a 0 or 1 byte string");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   455
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   456
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   457
	if (PyString_AsStringAndSize(pyflags, &flags, &flen) == -1) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   458
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   459
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   460
	/* one null byte and one newline */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   461
	dlen = plen + 41 + flen + 1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   462
	dest = malloc(dlen);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   463
	if (!dest) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   464
		PyErr_NoMemory();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   465
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   466
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   467
	memcpy(dest, path, plen + 1);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   468
	for (i = 0; i < 20; i++) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   469
		sprintf(dest + plen + 1 + (i * 2), "%02hhx", hash[i]);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   470
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   471
	memcpy(dest + plen + 41, flags, flen);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   472
	dest[plen + 41 + flen] = '\n';
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   473
	new.start = dest;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   474
	new.len = dlen;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   475
	new.hash_suffix = '\0';
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   476
	if (hlen > 20) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   477
		new.hash_suffix = hash[20];
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   478
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   479
	new.from_malloc = true;     /* is `start` a pointer we allocated? */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   480
	new.deleted = false;        /* is this entry deleted? */
24228
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   481
	if (internalsetitem(self, &new)) {
542c891274b2 lazymanifest: use a binary search to do an insertion
Augie Fackler <augie@google.com>
parents: 24214
diff changeset
   482
		return -1;
24214
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   483
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   484
	return 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   485
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   486
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   487
static PyMappingMethods lazymanifest_mapping_methods = {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   488
	(lenfunc)lazymanifest_size,             /* mp_length */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   489
	(binaryfunc)lazymanifest_getitem,       /* mp_subscript */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   490
	(objobjargproc)lazymanifest_setitem,    /* mp_ass_subscript */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   491
};
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   492
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   493
/* sequence methods (important or __contains__ builds an iterator */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   494
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   495
static int lazymanifest_contains(lazymanifest *self, PyObject *key)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   496
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   497
	line needle;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   498
	line *hit;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   499
	if (!PyString_Check(key)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   500
		/* Our keys are always strings, so if the contains
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   501
		 * check is for a non-string, just return false. */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   502
		return 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   503
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   504
	needle.start = PyString_AsString(key);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   505
	hit = bsearch(&needle, self->lines, self->numlines, sizeof(line),
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   506
		      &linecmp);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   507
	if (!hit || hit->deleted) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   508
		return 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   509
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   510
	return 1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   511
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   512
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   513
static PySequenceMethods lazymanifest_seq_meths = {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   514
	(lenfunc)lazymanifest_size, /* sq_length */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   515
	0, /* sq_concat */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   516
	0, /* sq_repeat */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   517
	0, /* sq_item */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   518
	0, /* sq_slice */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   519
	0, /* sq_ass_item */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   520
	0, /* sq_ass_slice */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   521
	(objobjproc)lazymanifest_contains, /* sq_contains */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   522
	0, /* sq_inplace_concat */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   523
	0, /* sq_inplace_repeat */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   524
};
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   525
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   526
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   527
/* Other methods (copy, diff, etc) */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   528
static PyTypeObject lazymanifestType;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   529
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   530
/* If the manifest has changes, build the new manifest text and reindex it. */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   531
static int compact(lazymanifest *self) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   532
	int i;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   533
	ssize_t need = 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   534
	char *data;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   535
	line *src, *dst;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   536
	PyObject *pydata;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   537
	if (!self->dirty)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   538
		return 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   539
	for (i = 0; i < self->numlines; i++) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   540
		if (!self->lines[i].deleted) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   541
			need += self->lines[i].len;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   542
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   543
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   544
	pydata = PyString_FromStringAndSize(NULL, need);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   545
	if (!pydata)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   546
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   547
	data = PyString_AsString(pydata);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   548
	if (!data) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   549
		return -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   550
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   551
	src = self->lines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   552
	dst = self->lines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   553
	for (i = 0; i < self->numlines; i++, src++) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   554
		char *tofree = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   555
		if (src->from_malloc) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   556
			tofree = src->start;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   557
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   558
		if (!src->deleted) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   559
			memcpy(data, src->start, src->len);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   560
			*dst = *src;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   561
			dst->start = data;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   562
			dst->from_malloc = false;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   563
			data += dst->len;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   564
			dst++;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   565
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   566
		free(tofree);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   567
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   568
	Py_DECREF(self->pydata);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   569
	self->pydata = pydata;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   570
	self->numlines = self->livelines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   571
	self->dirty = false;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   572
	return 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   573
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   574
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   575
static PyObject *lazymanifest_text(lazymanifest *self)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   576
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   577
	if (compact(self) != 0) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   578
		PyErr_NoMemory();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   579
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   580
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   581
	Py_INCREF(self->pydata);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   582
	return self->pydata;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   583
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   584
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   585
static lazymanifest *lazymanifest_copy(lazymanifest *self)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   586
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   587
	lazymanifest *copy = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   588
	if (compact(self) != 0) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   589
		goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   590
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   591
	copy = PyObject_New(lazymanifest, &lazymanifestType);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   592
	if (!copy) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   593
		goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   594
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   595
	copy->numlines = self->numlines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   596
	copy->livelines = self->livelines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   597
	copy->dirty = false;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   598
	copy->lines = malloc(self->maxlines *sizeof(line));
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   599
	if (!copy->lines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   600
		goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   601
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   602
	memcpy(copy->lines, self->lines, self->numlines * sizeof(line));
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   603
	copy->maxlines = self->maxlines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   604
	copy->pydata = self->pydata;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   605
	Py_INCREF(copy->pydata);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   606
	return copy;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   607
 nomem:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   608
	PyErr_NoMemory();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   609
	Py_XDECREF(copy);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   610
	return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   611
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   612
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   613
static lazymanifest *lazymanifest_filtercopy(
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   614
	lazymanifest *self, PyObject *matchfn)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   615
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   616
	lazymanifest *copy = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   617
	int i;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   618
	if (!PyCallable_Check(matchfn)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   619
		PyErr_SetString(PyExc_TypeError, "matchfn must be callable");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   620
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   621
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   622
	/* compact ourselves first to avoid double-frees later when we
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   623
	 * compact tmp so that it doesn't have random pointers to our
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   624
	 * underlying from_malloc-data (self->pydata is safe) */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   625
	if (compact(self) != 0) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   626
		goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   627
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   628
	copy = PyObject_New(lazymanifest, &lazymanifestType);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   629
	copy->dirty = true;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   630
	copy->lines = malloc(self->maxlines * sizeof(line));
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   631
	if (!copy->lines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   632
		goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   633
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   634
	copy->maxlines = self->maxlines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   635
	copy->numlines = 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   636
	copy->pydata = self->pydata;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   637
	Py_INCREF(self->pydata);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   638
	for (i = 0; i < self->numlines; i++) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   639
		PyObject *arg = PyString_FromString(self->lines[i].start);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   640
		PyObject *arglist = PyTuple_Pack(1, arg);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   641
		PyObject *result = PyObject_CallObject(matchfn, arglist);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   642
		Py_DECREF(arglist);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   643
		Py_DECREF(arg);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   644
		/* if the callback raised an exception, just let it
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   645
		 * through and give up */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   646
		if (!result) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   647
			free(copy->lines);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   648
			Py_DECREF(self->pydata);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   649
			return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   650
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   651
		if (PyObject_IsTrue(result)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   652
			assert(!(self->lines[i].from_malloc));
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   653
			copy->lines[copy->numlines++] = self->lines[i];
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   654
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   655
		Py_DECREF(result);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   656
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   657
	copy->livelines = copy->numlines;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   658
	return copy;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   659
 nomem:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   660
	PyErr_NoMemory();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   661
	Py_XDECREF(copy);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   662
	return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   663
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   664
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   665
static PyObject *lazymanifest_diff(lazymanifest *self, PyObject *args)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   666
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   667
	lazymanifest *other;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   668
	PyObject *pyclean = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   669
	bool listclean;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   670
	PyObject *emptyTup = NULL, *ret = NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   671
	PyObject *es;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   672
	int sneedle = 0, oneedle = 0;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   673
	if (!PyArg_ParseTuple(args, "O!|O", &lazymanifestType, &other, &pyclean)) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   674
		return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   675
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   676
	listclean = (!pyclean) ? false : PyObject_IsTrue(pyclean);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   677
	es = PyString_FromString("");
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   678
	if (!es) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   679
		goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   680
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   681
	emptyTup = PyTuple_Pack(2, Py_None, es);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   682
	Py_DECREF(es);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   683
	if (!emptyTup) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   684
		goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   685
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   686
	ret = PyDict_New();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   687
	if (!ret) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   688
		goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   689
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   690
	while (sneedle != self->numlines || oneedle != other->numlines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   691
		line *left = self->lines + sneedle;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   692
		line *right = other->lines + oneedle;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   693
		int result;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   694
		PyObject *key;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   695
		PyObject *outer;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   696
		/* If we're looking at a deleted entry and it's not
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   697
		 * the end of the manifest, just skip it. */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   698
		if (left->deleted && sneedle < self->numlines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   699
			sneedle++;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   700
			continue;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   701
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   702
		if (right->deleted && oneedle < other->numlines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   703
			oneedle++;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   704
			continue;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   705
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   706
		/* if we're at the end of either manifest, then we
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   707
		 * know the remaining items are adds so we can skip
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   708
		 * the strcmp. */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   709
		if (sneedle == self->numlines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   710
			result = 1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   711
		} else if (oneedle == other->numlines) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   712
			result = -1;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   713
		} else {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   714
			result = linecmp(left, right);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   715
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   716
		key = result <= 0 ?
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   717
			PyString_FromString(left->start) :
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   718
			PyString_FromString(right->start);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   719
		if (!key)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   720
			goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   721
		if (result < 0) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   722
			PyObject *l = hashflags(left);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   723
			if (!l) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   724
				goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   725
			}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   726
			outer = PyTuple_Pack(2, l, emptyTup);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   727
			Py_DECREF(l);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   728
			if (!outer) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   729
				goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   730
			}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   731
			PyDict_SetItem(ret, key, outer);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   732
			Py_DECREF(outer);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   733
			sneedle++;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   734
		} else if (result > 0) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   735
			PyObject *r = hashflags(right);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   736
			if (!r) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   737
				goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   738
			}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   739
			outer = PyTuple_Pack(2, emptyTup, r);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   740
			Py_DECREF(r);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   741
			if (!outer) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   742
				goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   743
			}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   744
			PyDict_SetItem(ret, key, outer);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   745
			Py_DECREF(outer);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   746
			oneedle++;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   747
		} else {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   748
			/* file exists in both manifests */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   749
			if (left->len != right->len
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   750
			    || memcmp(left->start, right->start, left->len)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   751
			    || left->hash_suffix != right->hash_suffix) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   752
				PyObject *l = hashflags(left);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   753
				PyObject *r;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   754
				if (!l) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   755
					goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   756
				}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   757
				r = hashflags(right);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   758
				if (!r) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   759
					Py_DECREF(l);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   760
					goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   761
				}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   762
				outer = PyTuple_Pack(2, l, r);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   763
				Py_DECREF(l);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   764
				Py_DECREF(r);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   765
				if (!outer) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   766
					goto nomem;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   767
				}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   768
				PyDict_SetItem(ret, key, outer);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   769
				Py_DECREF(outer);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   770
			} else if (listclean) {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   771
				PyDict_SetItem(ret, key, Py_None);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   772
			}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   773
			sneedle++;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   774
			oneedle++;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   775
		}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   776
		Py_DECREF(key);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   777
	}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   778
	Py_DECREF(emptyTup);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   779
	return ret;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   780
 nomem:
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   781
	PyErr_NoMemory();
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   782
	Py_XDECREF(ret);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   783
	Py_XDECREF(emptyTup);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   784
	return NULL;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   785
}
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   786
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   787
static PyMethodDef lazymanifest_methods[] = {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   788
	{"copy", (PyCFunction)lazymanifest_copy, METH_NOARGS,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   789
	 "Make a copy of this lazymanifest."},
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   790
	{"filtercopy", (PyCFunction)lazymanifest_filtercopy, METH_O,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   791
	 "Make a copy of this manifest filtered by matchfn."},
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   792
	{"diff", (PyCFunction)lazymanifest_diff, METH_VARARGS,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   793
	 "Compare this lazymanifest to another one."},
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   794
	{"text", (PyCFunction)lazymanifest_text, METH_NOARGS,
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   795
	 "Encode this manifest to text."},
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   796
	{NULL},
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   797
};
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   798
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   799
static PyTypeObject lazymanifestType = {
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   800
	PyObject_HEAD_INIT(NULL)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   801
	0,                                                /* ob_size */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   802
	"parsers.lazymanifest",                           /* tp_name */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   803
	sizeof(lazymanifest),                             /* tp_basicsize */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   804
	0,                                                /* tp_itemsize */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   805
	(destructor)lazymanifest_dealloc,                 /* tp_dealloc */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   806
	0,                                                /* tp_print */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   807
	0,                                                /* tp_getattr */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   808
	0,                                                /* tp_setattr */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   809
	0,                                                /* tp_compare */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   810
	0,                                                /* tp_repr */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   811
	0,                                                /* tp_as_number */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   812
	&lazymanifest_seq_meths,                          /* tp_as_sequence */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   813
	&lazymanifest_mapping_methods,                    /* tp_as_mapping */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   814
	0,                                                /* tp_hash */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   815
	0,                                                /* tp_call */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   816
	0,                                                /* tp_str */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   817
	0,                                                /* tp_getattro */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   818
	0,                                                /* tp_setattro */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   819
	0,                                                /* tp_as_buffer */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   820
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_SEQUENCE_IN, /* tp_flags */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   821
	"TODO(augie)",                                    /* tp_doc */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   822
	0,                                                /* tp_traverse */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   823
	0,                                                /* tp_clear */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   824
	0,                                                /* tp_richcompare */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   825
	0,                                             /* tp_weaklistoffset */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   826
	(getiterfunc)lazymanifest_getiter,                /* tp_iter */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   827
	0,                                                /* tp_iternext */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   828
	lazymanifest_methods,                             /* tp_methods */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   829
	0,                                                /* tp_members */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   830
	0,                                                /* tp_getset */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   831
	0,                                                /* tp_base */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   832
	0,                                                /* tp_dict */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   833
	0,                                                /* tp_descr_get */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   834
	0,                                                /* tp_descr_set */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   835
	0,                                                /* tp_dictoffset */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   836
	(initproc)lazymanifest_init,                      /* tp_init */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   837
	0,                                                /* tp_alloc */
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   838
};
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   839
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   840
void manifest_module_init(PyObject * mod)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   841
{
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   842
	lazymanifestType.tp_new = PyType_GenericNew;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   843
	if (PyType_Ready(&lazymanifestType) < 0)
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   844
		return;
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   845
	Py_INCREF(&lazymanifestType);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   846
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   847
	PyModule_AddObject(mod, "lazymanifest",
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   848
			   (PyObject *)&lazymanifestType);
a5f1bccd2996 manifest.c: new extension code to lazily parse manifests
Augie Fackler <augie@google.com>
parents:
diff changeset
   849
}