in src/git_cache.h [758:828]
int git_cache::note_tree_raw(sha1_ref sha1, const char *rawtree) {
auto parse_mode = [](const char *¤t, auto &type) {
assert(type == git_tree::item_type::unknown);
#define PARSE_MODE_FOR_TYPE(VALUE) \
PARSE_MODE_FOR_TYPE_IMPL( \
git_tree::item_type::get_mode(git_tree::item_type::VALUE), VALUE)
#define PARSE_MODE_FOR_TYPE_IMPL(PATTERN, VALUE) \
do { \
if (!strncmp(current, PATTERN, strlen(PATTERN))) { \
type = git_tree::item_type::VALUE; \
current += strlen(PATTERN); \
return 0; \
} \
} while (false)
PARSE_MODE_FOR_TYPE(tree);
PARSE_MODE_FOR_TYPE(regular);
PARSE_MODE_FOR_TYPE(exec);
PARSE_MODE_FOR_TYPE(symlink);
PARSE_MODE_FOR_TYPE(submodule);
#undef PARSE_MODE_FOR_TYPE
#undef PARSE_MODE_FOR_TYPE_IMPL
return 1;
};
auto parse_type = [](const char *¤t, auto type) {
assert(type != git_tree::item_type::unknown);
#define PARSE_TYPE_AND_CHECK(VALUE) \
PARSE_TYPE_AND_CHECK_IMPL( \
git_tree::item_type::get_type(git_tree::item_type::VALUE), VALUE)
#define PARSE_TYPE_AND_CHECK_IMPL(PATTERN, VALUE) \
do \
if (!strncmp(current, PATTERN, strlen(PATTERN))) \
if (type == git_tree::item_type::VALUE) { \
current += strlen(PATTERN); \
return 0; \
} \
while (false)
PARSE_TYPE_AND_CHECK(tree);
PARSE_TYPE_AND_CHECK(regular);
PARSE_TYPE_AND_CHECK(exec);
PARSE_TYPE_AND_CHECK(symlink);
PARSE_TYPE_AND_CHECK(submodule);
#undef PARSE_TYPE_AND_CHECK
#undef PARSE_TYPE_AND_CHECK_IMPL
return 1;
};
constexpr const int max_items = dir_mask::max_size;
git_tree::item_type items[max_items];
git_tree::item_type *last = items;
const char *current = rawtree;
while (*current) {
if (last - items == max_items)
return error(
"ls-tree: too many items (max: " + std::to_string(max_items) + ")");
if (parse_mode(current, last->type) || parse_ch(current, ' ') ||
parse_type(current, last->type) || parse_ch(current, ' ') ||
pool.parse_sha1(current, last->sha1) || parse_ch(current, '\t') ||
parse_name(current, last->name) || parse_ch(current, '\n'))
return error("ls-tree: could not parse entry");
++last;
}
git_tree tree;
tree.sha1 = sha1;
tree.num_items = last - items;
tree.items = make_items(items, last);
note_tree(tree);
return 0;
}