|
5 | 5 |
|
6 | 6 | static struct diff_stats_t* diff_stats_prepare_item(struct diff_stats_t* d) {
|
7 | 7 | d->starts_at = -1;
|
| 8 | + d->additions = 0; |
| 9 | + d->deletions = 0; |
8 | 10 | d->count = 0;
|
9 | 11 | d->hunks = 10;
|
10 | 12 | d->hunks_at = (long*)malloc(sizeof(long) * 10);
|
11 | 13 | memset(d->hunks_at, 0, sizeof(long) * 10);
|
12 | 14 | return d;
|
13 | 15 | }
|
14 | 16 |
|
15 |
| -int diff_stats_is_diff_header(const char* text, long column) { |
16 |
| - return *text == 'd' && strncmp(text, (char*)"diff", 4) == 0 && column == 0; |
| 17 | +int diff_stats_is_diff_header(const char* text) { |
| 18 | + return (*text == 'd' && strncmp(text, (char*)"diff", 4) == 0); |
17 | 19 | }
|
18 | 20 |
|
19 |
| -int diff_stats_is_hunk_header(const char* text, long column) { |
20 |
| - return *text == '@' && strncmp(text, (char*)"@@", 2) == 0 && column == 0; |
| 21 | +int diff_stats_is_hunk_header(const char* text) { |
| 22 | + return (*text == '@' && strncmp(text, (char*)"@@", 2) == 0); |
| 23 | +} |
| 24 | + |
| 25 | +int diff_stats_line_type(const char* text) { |
| 26 | + if (diff_stats_is_diff_header(text)) { |
| 27 | + return DIFF_HEADER; |
| 28 | + } |
| 29 | + if (diff_stats_is_hunk_header(text)) { |
| 30 | + return HUNK_HEADER; |
| 31 | + } |
| 32 | + switch (*text) { |
| 33 | + case '-': { return DELETION_LINE; } break; |
| 34 | + case '+': { return ADDITION_LINE; } break; |
| 35 | + default: { return DIFF_NOTHING; } break; |
| 36 | + } |
21 | 37 | }
|
22 | 38 |
|
23 | 39 | void diff_stats_add_hunk_at(struct diff_stats_t* d, long i) {
|
@@ -53,43 +69,61 @@ void diff_stats_free(struct diff_stats_t* d, long count) {
|
53 | 69 | free(d);
|
54 | 70 | }
|
55 | 71 |
|
| 72 | +char* diff_stats_find_hunk(const char* str) { |
| 73 | + char* text = (char*)str; |
| 74 | + while (*text && *(text + 1)) { |
| 75 | + if (*text == '\n' && *(text + 1) == '@') { |
| 76 | + break; |
| 77 | + } |
| 78 | + text++; |
| 79 | + } |
| 80 | + return text; |
| 81 | +} |
| 82 | + |
56 | 83 | struct diff_stats_t* diff_stats_parser(const char* str, long* counter, int* err) {
|
57 | 84 | char* hold = (char*)str;
|
58 | 85 | char* text = hold;
|
59 |
| - long column = 0; |
60 | 86 | long index = 0;
|
61 | 87 | long count = 12;
|
62 | 88 | struct diff_stats_t* diff =
|
63 | 89 | (struct diff_stats_t*)malloc(sizeof(struct diff_stats_t) * count);
|
64 | 90 | struct diff_stats_t* head = NULL;
|
65 | 91 |
|
66 | 92 | while (*text) {
|
67 |
| - if (diff_stats_is_diff_header(text, column)) { |
| 93 | + int type = diff_stats_line_type(text); |
| 94 | + |
| 95 | + switch (type) { |
| 96 | + case DIFF_HEADER: { |
68 | 97 | if (index + 1 <= count) {
|
69 | 98 | count += 12;
|
70 |
| - diff = (struct diff_stats_t*)realloc(diff, sizeof(struct diff_stats_t) * count); |
| 99 | + diff = (struct diff_stats_t*)realloc(diff, |
| 100 | + sizeof(struct diff_stats_t) * count); |
71 | 101 | }
|
72 | 102 | head = diff_stats_prepare_item(diff + index);
|
73 | 103 | head->starts_at = (long)(text - hold);
|
74 | 104 | index++;
|
75 |
| - } |
76 | 105 |
|
77 |
| - if (diff_stats_is_hunk_header(text, column)) { |
| 106 | + text = diff_stats_find_hunk(text); |
| 107 | + continue; |
| 108 | + } break; |
| 109 | + case HUNK_HEADER: { |
78 | 110 | if (!head) {
|
79 | 111 | *err = HUNK_WITHOUT_DIFF;
|
80 | 112 | free(diff);
|
81 | 113 | diff = NULL;
|
82 | 114 | goto diff_stats_end;
|
83 | 115 | }
|
84 | 116 | diff_stats_add_hunk_at(head, (long)(text - hold));
|
| 117 | + } break; |
| 118 | + case ADDITION_LINE: { head->additions++; goto diff_stats_skip; } break; |
| 119 | + case DELETION_LINE: { head->deletions++; goto diff_stats_skip; } break; |
| 120 | + default: { |
| 121 | +diff_stats_skip: |
| 122 | + while (*text && *text != '\n') text++; |
85 | 123 | }
|
86 |
| - |
87 |
| - if (*text == '\n') { |
88 |
| - column = 0; |
89 |
| - } else { |
90 |
| - column++; |
91 | 124 | }
|
92 |
| - ++text; |
| 125 | + |
| 126 | + text++; |
93 | 127 | }
|
94 | 128 |
|
95 | 129 | *err = 0;
|
|
0 commit comments