[PATCH 12/16] vcs-svn: Learn to parse variable-length integers
The humble beginnings of the svn-format delta applier.
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
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