static int git_xdiff_scan_int(const char **str, int *value) { const char *scan = *str; int v = 0, digits = 0; /* find next digit */ for (scan = *str; *scan && !git__isdigit(*scan); scan++); /* parse next number */ for (; git__isdigit(*scan); scan++, digits++) v = (v * 10) + (*scan - '0'); *str = scan; *value = v; return (digits > 0) ? 0 : -1; }
static int extract_how_many(int *n, const char *spec, size_t *pos) { const char *end_ptr; int parsed, accumulated; char kind = spec[*pos]; assert(spec[*pos] == '^' || spec[*pos] == '~'); accumulated = 0; do { do { (*pos)++; accumulated++; } while (spec[(*pos)] == kind && kind == '~'); if (git__isdigit(spec[*pos])) { if (git__strtol32(&parsed, spec + *pos, &end_ptr, 10) < 0) return GIT_EINVALIDSPEC; accumulated += (parsed - 1); *pos = end_ptr - spec; } } while (spec[(*pos)] == kind && kind == '~'); *n = accumulated; return 0; }
static int parse_number(git_off_t *out, git_patch_parse_ctx *ctx) { const char *end; int64_t num; if (!git__isdigit(ctx->parse_ctx.line[0])) return -1; if (git__strntol64(&num, ctx->parse_ctx.line, ctx->parse_ctx.line_len, &end, 10) < 0) return -1; if (num < 0) return -1; *out = num; git_parse_advance_chars(&ctx->parse_ctx, (end - ctx->parse_ctx.line)); return 0; }
static int parse_header_percent(uint16_t *out, git_patch_parse_ctx *ctx) { int32_t val; const char *end; if (ctx->line_len < 1 || !git__isdigit(ctx->line[0]) || git__strntol32(&val, ctx->line, ctx->line_len, &end, 10) < 0) return -1; parse_advance_chars(ctx, (end - ctx->line)); if (parse_advance_expected_s(ctx, "%") < 0) return -1; if (val > 100) return -1; *out = val; return 0; }
static int parse_header_mode(uint16_t *mode, git_patch_parse_ctx *ctx) { const char *end; int32_t m; int ret; if (ctx->line_len < 1 || !git__isdigit(ctx->line[0])) return parse_err("invalid file mode at line %d", ctx->line_num); if ((ret = git__strntol32(&m, ctx->line, ctx->line_len, &end, 8)) < 0) return ret; if (m > UINT16_MAX) return -1; *mode = (uint16_t)m; parse_advance_chars(ctx, (end - ctx->line)); return ret; }
static int commit_quick_parse(git_revwalk *walk, git_commit_list_node *commit, git_rawobj *raw) { const size_t parent_len = strlen("parent ") + GIT_OID_HEXSZ + 1; unsigned char *buffer = raw->data; unsigned char *buffer_end = buffer + raw->len; unsigned char *parents_start, *committer_start; int i, parents = 0; int commit_time; buffer += strlen("tree ") + GIT_OID_HEXSZ + 1; parents_start = buffer; while (buffer + parent_len < buffer_end && memcmp(buffer, "parent ", strlen("parent ")) == 0) { parents++; buffer += parent_len; } commit->parents = alloc_parents(walk, commit, parents); GITERR_CHECK_ALLOC(commit->parents); buffer = parents_start; for (i = 0; i < parents; ++i) { git_oid oid; if (git_oid_fromstr(&oid, (char *)buffer + strlen("parent ")) < 0) return -1; commit->parents[i] = git_revwalk__commit_lookup(walk, &oid); if (commit->parents[i] == NULL) return -1; buffer += parent_len; } commit->out_degree = (unsigned short)parents; if ((committer_start = buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) return commit_error(commit, "object is corrupted"); buffer++; if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) return commit_error(commit, "object is corrupted"); /* Skip trailing spaces */ while (buffer > committer_start && git__isspace(*buffer)) buffer--; /* Seek for the begining of the pack of digits */ while (buffer > committer_start && git__isdigit(*buffer)) buffer--; /* Skip potential timezone offset */ if ((buffer > committer_start) && (*buffer == '+' || *buffer == '-')) { buffer--; while (buffer > committer_start && git__isspace(*buffer)) buffer--; while (buffer > committer_start && git__isdigit(*buffer)) buffer--; } if ((buffer == committer_start) || (git__strtol32(&commit_time, (char *)(buffer + 1), NULL, 10) < 0)) return commit_error(commit, "cannot parse commit time"); commit->time = (time_t)commit_time; commit->parsed = 1; return 0; }