+static int parse_num(const char *line, int len, int offset, const char *expect, unsigned long *p)
+{
+ char *ptr;
+ int digits, ex;
+
+ if (offset < 0 || offset >= len)
+ return -1;
+ line += offset;
+ len -= offset;
+
+ if (!isdigit(*line))
+ return -1;
+ *p = strtoul(line, &ptr, 10);
+
+ digits = ptr - line;
+
+ offset += digits;
+ line += digits;
+ len -= digits;
+
+ ex = strlen(expect);
+ if (ex > len)
+ return -1;
+ if (memcmp(line, expect, ex))
+ return -1;
+
+ return offset + ex;
+}
+
+/*
+ * Parse a unified diff fragment header of the
+ * form "@@ -a,b +c,d @@"
+ */
+static int parse_fragment_header(char *line, int len, unsigned long *pos)
+{
+ int offset;
+
+ if (!len || line[len-1] != '\n')
+ return -1;
+
+ /* Figure out the number of lines in a fragment */
+ offset = parse_num(line, len, 4, ",", pos);
+ offset = parse_num(line, len, offset, " +", pos+1);
+ offset = parse_num(line, len, offset, ",", pos+2);
+ offset = parse_num(line, len, offset, " @@", pos+3);
+
+ return offset;
+}
+