diff options
Diffstat (limited to 'hash.h')
-rw-r--r-- | hash.h | 96 |
1 files changed, 66 insertions, 30 deletions
@@ -95,6 +95,29 @@ static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *s /* Number of algorithms supported (including unknown). */ #define GIT_HASH_NALGOS (GIT_HASH_SHA256 + 1) +/* The length in bytes and in hex digits of an object name (SHA-1 value). */ +#define GIT_SHA1_RAWSZ 20 +#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ) +/* The block size of SHA-1. */ +#define GIT_SHA1_BLKSZ 64 + +/* The length in bytes and in hex digits of an object name (SHA-256 value). */ +#define GIT_SHA256_RAWSZ 32 +#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ) +/* The block size of SHA-256. */ +#define GIT_SHA256_BLKSZ 64 + +/* The length in byte and in hex digits of the largest possible hash value. */ +#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ +#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ +/* The largest possible block size for any supported hash. */ +#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ + +struct object_id { + unsigned char hash[GIT_MAX_RAWSZ]; + int algo; +}; + /* A suitably aligned type for stack allocations of hash contexts. */ union git_hash_ctx { git_SHA_CTX sha1; @@ -106,6 +129,7 @@ typedef void (*git_hash_init_fn)(git_hash_ctx *ctx); typedef void (*git_hash_clone_fn)(git_hash_ctx *dst, const git_hash_ctx *src); typedef void (*git_hash_update_fn)(git_hash_ctx *ctx, const void *in, size_t len); typedef void (*git_hash_final_fn)(unsigned char *hash, git_hash_ctx *ctx); +typedef void (*git_hash_final_oid_fn)(struct object_id *oid, git_hash_ctx *ctx); struct git_hash_algo { /* @@ -138,11 +162,17 @@ struct git_hash_algo { /* The hash finalization function. */ git_hash_final_fn final_fn; + /* The hash finalization function for object IDs. */ + git_hash_final_oid_fn final_oid_fn; + /* The OID of the empty tree. */ const struct object_id *empty_tree; /* The OID of the empty blob. */ const struct object_id *empty_blob; + + /* The all-zeros OID. */ + const struct object_id *null_oid; }; extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS]; @@ -161,67 +191,65 @@ static inline int hash_algo_by_ptr(const struct git_hash_algo *p) return p - hash_algos; } -/* The length in bytes and in hex digits of an object name (SHA-1 value). */ -#define GIT_SHA1_RAWSZ 20 -#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ) -/* The block size of SHA-1. */ -#define GIT_SHA1_BLKSZ 64 - -/* The length in bytes and in hex digits of an object name (SHA-256 value). */ -#define GIT_SHA256_RAWSZ 32 -#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ) -/* The block size of SHA-256. */ -#define GIT_SHA256_BLKSZ 64 - -/* The length in byte and in hex digits of the largest possible hash value. */ -#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ -#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ -/* The largest possible block size for any supported hash. */ -#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ - -struct object_id { - unsigned char hash[GIT_MAX_RAWSZ]; -}; - #define the_hash_algo the_repository->hash_algo -extern const struct object_id null_oid; +const struct object_id *null_oid(void); -static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2) +static inline int hashcmp_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop) { /* * Teach the compiler that there are only two possibilities of hash size * here, so that it can optimize for this case as much as possible. */ - if (the_hash_algo->rawsz == GIT_MAX_RAWSZ) + if (algop->rawsz == GIT_MAX_RAWSZ) return memcmp(sha1, sha2, GIT_MAX_RAWSZ); return memcmp(sha1, sha2, GIT_SHA1_RAWSZ); } +static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2) +{ + return hashcmp_algop(sha1, sha2, the_hash_algo); +} + static inline int oidcmp(const struct object_id *oid1, const struct object_id *oid2) { - return hashcmp(oid1->hash, oid2->hash); + const struct git_hash_algo *algop; + if (!oid1->algo) + algop = the_hash_algo; + else + algop = &hash_algos[oid1->algo]; + return hashcmp_algop(oid1->hash, oid2->hash, algop); } -static inline int hasheq(const unsigned char *sha1, const unsigned char *sha2) +static inline int hasheq_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop) { /* * We write this here instead of deferring to hashcmp so that the * compiler can properly inline it and avoid calling memcmp. */ - if (the_hash_algo->rawsz == GIT_MAX_RAWSZ) + if (algop->rawsz == GIT_MAX_RAWSZ) return !memcmp(sha1, sha2, GIT_MAX_RAWSZ); return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ); } +static inline int hasheq(const unsigned char *sha1, const unsigned char *sha2) +{ + return hasheq_algop(sha1, sha2, the_hash_algo); +} + static inline int oideq(const struct object_id *oid1, const struct object_id *oid2) { - return hasheq(oid1->hash, oid2->hash); + const struct git_hash_algo *algop; + if (!oid1->algo) + algop = the_hash_algo; + else + algop = &hash_algos[oid1->algo]; + return hasheq_algop(oid1->hash, oid2->hash, algop); } static inline int is_null_oid(const struct object_id *oid) { - return oideq(oid, &null_oid); + return oideq(oid, null_oid()); } static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src) @@ -232,6 +260,7 @@ static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src) static inline void oidcpy(struct object_id *dst, const struct object_id *src) { memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ); + dst->algo = src->algo; } static inline struct object_id *oiddup(const struct object_id *src) @@ -249,11 +278,13 @@ static inline void hashclr(unsigned char *hash) static inline void oidclr(struct object_id *oid) { memset(oid->hash, 0, GIT_MAX_RAWSZ); + oid->algo = hash_algo_by_ptr(the_hash_algo); } static inline void oidread(struct object_id *oid, const unsigned char *hash) { memcpy(oid->hash, hash, the_hash_algo->rawsz); + oid->algo = hash_algo_by_ptr(the_hash_algo); } static inline int is_empty_blob_sha1(const unsigned char *sha1) @@ -276,6 +307,11 @@ static inline int is_empty_tree_oid(const struct object_id *oid) return oideq(oid, the_hash_algo->empty_tree); } +static inline void oid_set_algo(struct object_id *oid, const struct git_hash_algo *algop) +{ + oid->algo = hash_algo_by_ptr(algop); +} + const char *empty_tree_oid_hex(void); const char *empty_blob_oid_hex(void); |