diff options
author | Mattias Andrée <maandree@kth.se> | 2024-01-09 22:04:24 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2024-01-09 22:04:24 +0100 |
commit | ae850b1ac755f471beac4dbfef4654fe3fbaaae9 (patch) | |
tree | 319e7f7f1b99cd1ee75e100f0a29b0f7c827ccea /libpatch_guess_format.c | |
download | libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.gz libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.bz2 libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.xz |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'libpatch_guess_format.c')
-rw-r--r-- | libpatch_guess_format.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/libpatch_guess_format.c b/libpatch_guess_format.c new file mode 100644 index 0000000..48ce419 --- /dev/null +++ b/libpatch_guess_format.c @@ -0,0 +1,121 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +static int +is_unsigned(const char *text, size_t textlen, size_t *off) +{ + if (*off == textlen || !isdigit(text[*off])) + return 0; + while (isdigit(++*off)); + return 1; +} + + +enum libpatch_style +libpatch_guess_format(const char *text, size_t textlen, size_t *offset) +{ + enum libpatch_style guess = LIBPATCH_STYLE_GARBAGE; + size_t off = offset ? *offset : 0; + size_t two_nums; + + while (off < textlen) { + if (text[off] == '+') { + if (textlen - off < 3 || strncmp(&text[off], "+++", 3)) + goto skip_line; + goto unified; + + } else if (text[off] == '*') { + if (textlen - off < 3 || strncmp(&text[off], "***", 3)) + goto skip_line; + goto copied; + + } else if (text[off] == '@') { + if (textlen - off < 3 || strncmp(&text[off], "@@ ", 3)) + goto skip_line; + goto unified; + + } else if (text[off] == 'a') { + off++; + if (!is_unsigned(text, textlen, &off)) + goto skip_line; + if (off != textlen && text[off] == ' ') + off++; + if (is_unsigned(text, textlen, &off)) + goto rcs; + else + goto ed_alternative; + + } else if (text[off] == 'd') { + off++; + if (!is_unsigned(text, textlen, &off)) + goto skip_line; + if (off != textlen && text[off] == ' ') + off++; + if (!is_unsigned(text, textlen, &off)) + goto ed_alternative; + guess = LIBPATCH_STYLE_RCS; + /* could also be LIBPATCH_STYLE_ED_ALTERNATIVE, + * whould cannot be parsed so LIBPATCH_STYLE_RCS + * is preferred if the patch happens to be valid + * in both */ + goto skip_line; + + } else if (text[off] == 'c') { + off++; + if (!is_unsigned(text, textlen, &off)) + goto skip_line; + goto ed_alternative; + + } else if (isdigit(text[off])) { + if (!is_unsigned(text, textlen, &off)) + goto skip_line; + two_nums = (off != textlen && text[off] == ','); + if (two_nums) { + off += 1; + if (!is_unsigned(text, textlen, &off)) + goto skip_line; + } + switch (text[off]) { + case 'i': + goto ed; + case 'a': + if (two_nums) + goto normal; + /* fall through */ + case 'c': + case 'd': + off++; + if (off == textlen || text[off] == '\n') + goto ed; + else if (isdigit(text[off])) + goto normal; + /* fall through */ + default: + goto skip_line; + } + + } else { + skip_line: + while (off != textlen && text[off] != '\n') + off++; + off += (off != textlen); + } + } + + *offset = off; + return guess; + +determined: + while (off != textlen && text[off] != '\n') + off++; + *offset = off += (off != textlen); + return guess; + +normal: guess = LIBPATCH_STYLE_NORMAL; goto determined; +copied: guess = LIBPATCH_STYLE_COPIED; goto determined; +unified: guess = LIBPATCH_STYLE_UNIFIED; goto determined; +ed: guess = LIBPATCH_STYLE_ED; goto determined; +ed_alternative: guess = LIBPATCH_STYLE_ED_ALTERNATIVE; goto determined; +rcs: guess = LIBPATCH_STYLE_RCS; goto determined; +} |