1 /*
2  * Copyright (C) the libgit2 contributors. All rights reserved.
3  *
4  * This file is part of libgit2, distributed under the GNU GPL v2 with
5  * a Linking Exception. For full terms see the included COPYING file.
6  */
7 #include "parse.h"
8 
git_parse_ctx_init(git_parse_ctx * ctx,const char * content,size_t content_len)9 int git_parse_ctx_init(git_parse_ctx *ctx, const char *content, size_t content_len)
10 {
11 	if (content && content_len) {
12 		ctx->content = content;
13 		ctx->content_len = content_len;
14 	} else {
15 		ctx->content = "";
16 		ctx->content_len = 0;
17 	}
18 
19 	ctx->remain = ctx->content;
20 	ctx->remain_len = ctx->content_len;
21 	ctx->line = ctx->remain;
22 	ctx->line_len = git__linenlen(ctx->line, ctx->remain_len);
23 	ctx->line_num = 1;
24 
25 	return 0;
26 }
27 
git_parse_ctx_clear(git_parse_ctx * ctx)28 void git_parse_ctx_clear(git_parse_ctx *ctx)
29 {
30 	memset(ctx, 0, sizeof(*ctx));
31 	ctx->content = "";
32 }
33 
git_parse_advance_line(git_parse_ctx * ctx)34 void git_parse_advance_line(git_parse_ctx *ctx)
35 {
36 	ctx->line += ctx->line_len;
37 	ctx->remain_len -= ctx->line_len;
38 	ctx->line_len = git__linenlen(ctx->line, ctx->remain_len);
39 	ctx->line_num++;
40 }
41 
git_parse_advance_chars(git_parse_ctx * ctx,size_t char_cnt)42 void git_parse_advance_chars(git_parse_ctx *ctx, size_t char_cnt)
43 {
44 	ctx->line += char_cnt;
45 	ctx->remain_len -= char_cnt;
46 	ctx->line_len -= char_cnt;
47 }
48 
git_parse_advance_expected(git_parse_ctx * ctx,const char * expected,size_t expected_len)49 int git_parse_advance_expected(
50 	git_parse_ctx *ctx,
51 	const char *expected,
52 	size_t expected_len)
53 {
54 	if (ctx->line_len < expected_len)
55 		return -1;
56 
57 	if (memcmp(ctx->line, expected, expected_len) != 0)
58 		return -1;
59 
60 	git_parse_advance_chars(ctx, expected_len);
61 	return 0;
62 }
63 
git_parse_advance_ws(git_parse_ctx * ctx)64 int git_parse_advance_ws(git_parse_ctx *ctx)
65 {
66 	int ret = -1;
67 
68 	while (ctx->line_len > 0 &&
69 		ctx->line[0] != '\n' &&
70 		git__isspace(ctx->line[0])) {
71 		ctx->line++;
72 		ctx->line_len--;
73 		ctx->remain_len--;
74 		ret = 0;
75 	}
76 
77 	return ret;
78 }
79 
git_parse_advance_nl(git_parse_ctx * ctx)80 int git_parse_advance_nl(git_parse_ctx *ctx)
81 {
82 	if (ctx->line_len != 1 || ctx->line[0] != '\n')
83 		return -1;
84 
85 	git_parse_advance_line(ctx);
86 	return 0;
87 }
88 
git_parse_advance_digit(int64_t * out,git_parse_ctx * ctx,int base)89 int git_parse_advance_digit(int64_t *out, git_parse_ctx *ctx, int base)
90 {
91 	const char *end;
92 	int ret;
93 
94 	if (ctx->line_len < 1 || !git__isdigit(ctx->line[0]))
95 		return -1;
96 
97 	if ((ret = git__strntol64(out, ctx->line, ctx->line_len, &end, base)) < 0)
98 		return -1;
99 
100 	git_parse_advance_chars(ctx, (end - ctx->line));
101 	return 0;
102 }
103 
git_parse_advance_oid(git_oid * out,git_parse_ctx * ctx)104 int git_parse_advance_oid(git_oid *out, git_parse_ctx *ctx)
105 {
106 	if (ctx->line_len < GIT_OID_HEXSZ)
107 		return -1;
108 	if ((git_oid_fromstrn(out, ctx->line, GIT_OID_HEXSZ)) < 0)
109 		return -1;
110 	git_parse_advance_chars(ctx, GIT_OID_HEXSZ);
111 	return 0;
112 }
113 
git_parse_peek(char * out,git_parse_ctx * ctx,int flags)114 int git_parse_peek(char *out, git_parse_ctx *ctx, int flags)
115 {
116 	size_t remain = ctx->line_len;
117 	const char *ptr = ctx->line;
118 
119 	while (remain) {
120 		char c = *ptr;
121 
122 		if ((flags & GIT_PARSE_PEEK_SKIP_WHITESPACE) &&
123 		    git__isspace(c)) {
124 			remain--;
125 			ptr++;
126 			continue;
127 		}
128 
129 		*out = c;
130 		return 0;
131 	}
132 
133 	return -1;
134 }
135