Switch over tree descriptors to contain a pre-parsed entry
This makes the tree descriptor contain a "struct name_entry" as part of it, and it gets filled in so that it always contains a valid entry. On some benchmarks, it improves performance by up to 15%. That makes tree entry "extract" trivial, and means that we only actually need to decode each tree entry just once: we decode the first one when we initialize the tree descriptor, and each subsequent one when doing "update_tree_entry()". In particular, this means that we don't need to do strlen() both at extract time _and_ at update time. Finally, it also allows more sharing of code (entry_extract(), that wanted a "struct name_entry", just got totally trivial, along with the "tree_entry()" function). Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
6fda5e5180
commit
4651ece854
101
tree-walk.c
101
tree-walk.c
@ -2,10 +2,42 @@
|
|||||||
#include "tree-walk.h"
|
#include "tree-walk.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
|
||||||
|
static const char *get_mode(const char *str, unsigned int *modep)
|
||||||
|
{
|
||||||
|
unsigned char c;
|
||||||
|
unsigned int mode = 0;
|
||||||
|
|
||||||
|
while ((c = *str++) != ' ') {
|
||||||
|
if (c < '0' || c > '7')
|
||||||
|
return NULL;
|
||||||
|
mode = (mode << 3) + (c - '0');
|
||||||
|
}
|
||||||
|
*modep = mode;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_tree_entry(struct tree_desc *desc, const void *buf, unsigned long size)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
unsigned int mode, len;
|
||||||
|
|
||||||
|
path = get_mode(buf, &mode);
|
||||||
|
if (!path)
|
||||||
|
die("corrupt tree file");
|
||||||
|
len = strlen(path) + 1;
|
||||||
|
|
||||||
|
/* Initialize the descriptor entry */
|
||||||
|
desc->entry.path = path;
|
||||||
|
desc->entry.mode = mode;
|
||||||
|
desc->entry.sha1 = (const unsigned char *)(path + len);
|
||||||
|
}
|
||||||
|
|
||||||
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size)
|
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size)
|
||||||
{
|
{
|
||||||
desc->buffer = buffer;
|
desc->buffer = buffer;
|
||||||
desc->size = size;
|
desc->size = size;
|
||||||
|
if (size)
|
||||||
|
decode_tree_entry(desc, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1)
|
void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1)
|
||||||
@ -36,78 +68,33 @@ static void entry_clear(struct name_entry *a)
|
|||||||
|
|
||||||
static void entry_extract(struct tree_desc *t, struct name_entry *a)
|
static void entry_extract(struct tree_desc *t, struct name_entry *a)
|
||||||
{
|
{
|
||||||
a->sha1 = tree_entry_extract(t, &a->path, &a->mode);
|
*a = t->entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_tree_entry(struct tree_desc *desc)
|
void update_tree_entry(struct tree_desc *desc)
|
||||||
{
|
{
|
||||||
const void *buf = desc->buffer;
|
const void *buf = desc->buffer;
|
||||||
|
const unsigned char *end = desc->entry.sha1 + 20;
|
||||||
unsigned long size = desc->size;
|
unsigned long size = desc->size;
|
||||||
int len = strlen(buf) + 1 + 20;
|
unsigned long len = end - (const unsigned char *)buf;
|
||||||
|
|
||||||
if (size < len)
|
if (size < len)
|
||||||
die("corrupt tree file");
|
die("corrupt tree file");
|
||||||
desc->buffer = (char *) buf + len;
|
buf = end;
|
||||||
desc->size = size - len;
|
size -= len;
|
||||||
}
|
desc->buffer = buf;
|
||||||
|
desc->size = size;
|
||||||
static const char *get_mode(const char *str, unsigned int *modep)
|
if (size)
|
||||||
{
|
decode_tree_entry(desc, buf, size);
|
||||||
unsigned char c;
|
|
||||||
unsigned int mode = 0;
|
|
||||||
|
|
||||||
while ((c = *str++) != ' ') {
|
|
||||||
if (c < '0' || c > '7')
|
|
||||||
return NULL;
|
|
||||||
mode = (mode << 3) + (c - '0');
|
|
||||||
}
|
|
||||||
*modep = mode;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep)
|
|
||||||
{
|
|
||||||
const void *tree = desc->buffer;
|
|
||||||
unsigned long size = desc->size;
|
|
||||||
int len = strlen(tree)+1;
|
|
||||||
const unsigned char *sha1 = (unsigned char *) tree + len;
|
|
||||||
const char *path;
|
|
||||||
unsigned int mode;
|
|
||||||
|
|
||||||
path = get_mode(tree, &mode);
|
|
||||||
if (!path || size < len + 20)
|
|
||||||
die("corrupt tree file");
|
|
||||||
*pathp = path;
|
|
||||||
*modep = canon_mode(mode);
|
|
||||||
return sha1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tree_entry(struct tree_desc *desc, struct name_entry *entry)
|
int tree_entry(struct tree_desc *desc, struct name_entry *entry)
|
||||||
{
|
{
|
||||||
const void *tree = desc->buffer;
|
if (!desc->size)
|
||||||
const char *path;
|
|
||||||
unsigned long len, size = desc->size;
|
|
||||||
|
|
||||||
if (!size)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
path = get_mode(tree, &entry->mode);
|
*entry = desc->entry;
|
||||||
if (!path)
|
update_tree_entry(desc);
|
||||||
die("corrupt tree file");
|
|
||||||
|
|
||||||
entry->path = path;
|
|
||||||
len = strlen(path);
|
|
||||||
|
|
||||||
path += len + 1;
|
|
||||||
entry->sha1 = (const unsigned char *) path;
|
|
||||||
|
|
||||||
path += 20;
|
|
||||||
len = path - (char *) tree;
|
|
||||||
if (len > size)
|
|
||||||
die("corrupt tree file");
|
|
||||||
|
|
||||||
desc->buffer = path;
|
|
||||||
desc->size = size - len;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
tree-walk.h
18
tree-walk.h
@ -1,17 +1,25 @@
|
|||||||
#ifndef TREE_WALK_H
|
#ifndef TREE_WALK_H
|
||||||
#define TREE_WALK_H
|
#define TREE_WALK_H
|
||||||
|
|
||||||
struct tree_desc {
|
|
||||||
const void *buffer;
|
|
||||||
unsigned int size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct name_entry {
|
struct name_entry {
|
||||||
const unsigned char *sha1;
|
const unsigned char *sha1;
|
||||||
const char *path;
|
const char *path;
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tree_desc {
|
||||||
|
const void *buffer;
|
||||||
|
struct name_entry entry;
|
||||||
|
unsigned int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep)
|
||||||
|
{
|
||||||
|
*pathp = desc->entry.path;
|
||||||
|
*modep = canon_mode(desc->entry.mode);
|
||||||
|
return desc->entry.sha1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int tree_entry_len(const char *name, const unsigned char *sha1)
|
static inline int tree_entry_len(const char *name, const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
return (char *)sha1 - (char *)name - 1;
|
return (char *)sha1 - (char *)name - 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user