Commit e72cb769 by Patrick Steinhardt

parse: implement `git_parse_peek`

Some code parts need to inspect the next few bytes without actually
consuming it yet, for example to examine what content it has to expect
next. Create a new function `git_parse_peek` which returns the next byte
without modifying the parsing context and use it at multiple call sites.
parent 252f2eee
...@@ -94,3 +94,25 @@ int git_parse_advance_digit(int64_t *out, git_parse_ctx *ctx, int base) ...@@ -94,3 +94,25 @@ int git_parse_advance_digit(int64_t *out, git_parse_ctx *ctx, int base)
git_parse_advance_chars(ctx, (end - ctx->line)); git_parse_advance_chars(ctx, (end - ctx->line));
return 0; return 0;
} }
int git_parse_peek(char *out, git_parse_ctx *ctx, int flags)
{
size_t remain = ctx->line_len;
const char *ptr = ctx->line;
while (remain) {
char c = *ptr;
if ((flags & GIT_PARSE_PEEK_SKIP_WHITESPACE) &&
git__isspace(c)) {
remain--;
ptr++;
continue;
}
*out = c;
return 0;
}
return -1;
}
...@@ -48,3 +48,9 @@ int git_parse_advance_expected( ...@@ -48,3 +48,9 @@ int git_parse_advance_expected(
int git_parse_advance_ws(git_parse_ctx *ctx); int git_parse_advance_ws(git_parse_ctx *ctx);
int git_parse_advance_nl(git_parse_ctx *ctx); int git_parse_advance_nl(git_parse_ctx *ctx);
int git_parse_advance_digit(int64_t *out, git_parse_ctx *ctx, int base); int git_parse_advance_digit(int64_t *out, git_parse_ctx *ctx, int base);
enum GIT_PARSE_PEEK_FLAGS {
GIT_PARSE_PEEK_SKIP_WHITESPACE = (1 << 0)
};
int git_parse_peek(char *out, git_parse_ctx *ctx, int flags);
...@@ -142,6 +142,8 @@ static int parse_header_oid( ...@@ -142,6 +142,8 @@ static int parse_header_oid(
static int parse_header_git_index( static int parse_header_git_index(
git_patch_parsed *patch, git_patch_parse_ctx *ctx) git_patch_parsed *patch, git_patch_parse_ctx *ctx)
{ {
char c;
if (parse_header_oid(&patch->base.delta->old_file.id, if (parse_header_oid(&patch->base.delta->old_file.id,
&patch->base.delta->old_file.id_abbrev, ctx) < 0 || &patch->base.delta->old_file.id_abbrev, ctx) < 0 ||
git_parse_advance_expected_str(&ctx->parse_ctx, "..") < 0 || git_parse_advance_expected_str(&ctx->parse_ctx, "..") < 0 ||
...@@ -149,7 +151,7 @@ static int parse_header_git_index( ...@@ -149,7 +151,7 @@ static int parse_header_git_index(
&patch->base.delta->new_file.id_abbrev, ctx) < 0) &patch->base.delta->new_file.id_abbrev, ctx) < 0)
return -1; return -1;
if (ctx->parse_ctx.line_len > 0 && ctx->parse_ctx.line[0] == ' ') { if (git_parse_peek(&c, &ctx->parse_ctx, 0) == 0 && c == ' ') {
uint16_t mode; uint16_t mode;
git_parse_advance_chars(&ctx->parse_ctx, 1); git_parse_advance_chars(&ctx->parse_ctx, 1);
...@@ -458,6 +460,7 @@ static int parse_hunk_header( ...@@ -458,6 +460,7 @@ static int parse_hunk_header(
git_patch_parse_ctx *ctx) git_patch_parse_ctx *ctx)
{ {
const char *header_start = ctx->parse_ctx.line; const char *header_start = ctx->parse_ctx.line;
char c;
hunk->hunk.old_lines = 1; hunk->hunk.old_lines = 1;
hunk->hunk.new_lines = 1; hunk->hunk.new_lines = 1;
...@@ -466,7 +469,7 @@ static int parse_hunk_header( ...@@ -466,7 +469,7 @@ static int parse_hunk_header(
parse_int(&hunk->hunk.old_start, ctx) < 0) parse_int(&hunk->hunk.old_start, ctx) < 0)
goto fail; goto fail;
if (ctx->parse_ctx.line_len > 0 && ctx->parse_ctx.line[0] == ',') { if (git_parse_peek(&c, &ctx->parse_ctx, 0) == 0 && c == ',') {
if (git_parse_advance_expected_str(&ctx->parse_ctx, ",") < 0 || if (git_parse_advance_expected_str(&ctx->parse_ctx, ",") < 0 ||
parse_int(&hunk->hunk.old_lines, ctx) < 0) parse_int(&hunk->hunk.old_lines, ctx) < 0)
goto fail; goto fail;
...@@ -476,7 +479,7 @@ static int parse_hunk_header( ...@@ -476,7 +479,7 @@ static int parse_hunk_header(
parse_int(&hunk->hunk.new_start, ctx) < 0) parse_int(&hunk->hunk.new_start, ctx) < 0)
goto fail; goto fail;
if (ctx->parse_ctx.line_len > 0 && ctx->parse_ctx.line[0] == ',') { if (git_parse_peek(&c, &ctx->parse_ctx, 0) == 0 && c == ',') {
if (git_parse_advance_expected_str(&ctx->parse_ctx, ",") < 0 || if (git_parse_advance_expected_str(&ctx->parse_ctx, ",") < 0 ||
parse_int(&hunk->hunk.new_lines, ctx) < 0) parse_int(&hunk->hunk.new_lines, ctx) < 0)
goto fail; goto fail;
...@@ -523,6 +526,7 @@ static int parse_hunk_body( ...@@ -523,6 +526,7 @@ static int parse_hunk_body(
!git_parse_ctx_contains_s(&ctx->parse_ctx, "@@ -"); !git_parse_ctx_contains_s(&ctx->parse_ctx, "@@ -");
git_parse_advance_line(&ctx->parse_ctx)) { git_parse_advance_line(&ctx->parse_ctx)) {
char c;
int origin; int origin;
int prefix = 1; int prefix = 1;
...@@ -532,7 +536,9 @@ static int parse_hunk_body( ...@@ -532,7 +536,9 @@ static int parse_hunk_body(
goto done; goto done;
} }
switch (ctx->parse_ctx.line[0]) { git_parse_peek(&c, &ctx->parse_ctx, 0);
switch (c) {
case '\n': case '\n':
prefix = 0; prefix = 0;
...@@ -683,9 +689,11 @@ static int parse_patch_binary_side( ...@@ -683,9 +689,11 @@ static int parse_patch_binary_side(
} }
while (ctx->parse_ctx.line_len) { while (ctx->parse_ctx.line_len) {
char c = ctx->parse_ctx.line[0]; char c;
size_t encoded_len, decoded_len = 0, decoded_orig = decoded.size; size_t encoded_len, decoded_len = 0, decoded_orig = decoded.size;
git_parse_peek(&c, &ctx->parse_ctx, 0);
if (c == '\n') if (c == '\n')
break; break;
else if (c >= 'A' && c <= 'Z') else if (c >= 'A' && c <= 'Z')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment