Subject: [PATCH 12/16] vcs-svn: Learn to parse variable-length integers

From: Jonathan Nieder <[email-masked]>
Date: Sun, 10 Oct 2010 21:55:56 -0500

The humble beginnings of the svn-format delta applier.

Signed-off-by: Jonathan Nieder <[email-masked]>
---
Maybe this should be squashed with patch 16.

Ideas for eliminating the code duplication?

 vcs-svn/svndiff.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)
 create mode 100644 vcs-svn/svndiff.c

diff --git a/vcs-svn/svndiff.c b/vcs-svn/svndiff.c
new file mode 100644
index 0000000..4d122a5
--- /dev/null
+++ b/vcs-svn/svndiff.c
@@ -0,0 +1,59 @@
+/*
+ * Licensed under a two-clause BSD-style license.
+ * See LICENSE for details.
+ */
+
+#include "git-compat-util.h"
+#include "line_buffer.h"
+
+/*
+ * svndiff0 applier
+ *
+ * See http://svn.apache.org/repos/asf/subversion/trunk/notes/svndiff.
+ *
+ * int ::= highdigit* lowdigit;
+ * highdigit ::= # binary 1000 0000 OR-ed with 7 bit value;
+ * lowdigit ::= # 7 bit value;
+ */
+
+#define VLI_CONTINUE	0x80
+#define VLI_DIGIT_MASK	0x7f
+#define VLI_BITS_PER_DIGIT 7
+
+static int read_int(struct line_buffer *in, uintmax_t *result, off_t *len)
+{
+	off_t sz = *len;
+	uintmax_t rv = 0;
+	while (sz) {
+		int ch = buffer_read_char(in);
+		if (ch == EOF)
+			break;
+		sz--;
+		rv <<= VLI_BITS_PER_DIGIT;
+		rv += (ch & VLI_DIGIT_MASK);
+		if (!(ch & VLI_CONTINUE)) {
+			*result = rv;
+			*len = sz;
+			return 0;
+		}
+	}
+	return error("Invalid delta: incomplete integer %"PRIuMAX, rv);
+}
+
+static int parse_int(const char **buf, size_t *result, const char *end)
+{
+	const char *pos;
+	size_t rv = 0;
+	for (pos = *buf; pos != end; pos++) {
+		unsigned char ch = *pos;
+		rv <<= VLI_BITS_PER_DIGIT;
+		rv += (ch & VLI_DIGIT_MASK);
+		if (!(ch & VLI_CONTINUE)) {
+			*result = rv;
+			*buf = pos + 1;
+			return 0;
+		}
+	}
+	return error("Invalid instruction: incomplete integer %"PRIu64,
+		     (uint64_t) rv);
+}
-- 
1.7.2.3