hash: create union for hash context allocation

In various parts of our code, we want to allocate a structure representing the internal state of a hash algorithm. The original implementation of the hash algorithm abstraction assumed we would do that using heap allocations, and added a context size element to struct git_hash_algo. However, most of the existing code uses stack allocations and conversion would needlessly complicate various parts of the code. Add a union for the purpose of allocating hash contexts on the stack and a typedef for ease of use. Use this union for defining the init, update, and final functions to avoid casts. Remove the ctxsz element for struct git_hash_algo, which is no longer very useful. This does mean that stack allocations will grow slightly as additional hash functions are added, but this should not be a significant problem, since we don't allocate many hash contexts. The improved usability and benefits from avoiding dynamic allocation outweigh this small downside. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Feb 1, 2018 at 02:18 UTC ac73cedff0db06671e2cab871b84b909b71adbd2
2 files changed +18 -17
hash.h
+9 -6
@@ -55,9 +55,15 @@
55 /* Number of algorithms supported (including unknown). */
56 #define GIT_HASH_NALGOS (GIT_HASH_SHA1 + 1)
57
58 -typedef void (*git_hash_init_fn)(void *ctx);
59 -typedef void (*git_hash_update_fn)(void *ctx, const void *in, size_t len);
60 -typedef void (*git_hash_final_fn)(unsigned char *hash, void *ctx);
58 +/* A suitably aligned type for stack allocations of hash contexts. */
59 +union git_hash_ctx {
60 + git_SHA_CTX sha1;
61 +};
62 +typedef union git_hash_ctx git_hash_ctx;
63 +
64 +typedef void (*git_hash_init_fn)(git_hash_ctx *ctx);
65 +typedef void (*git_hash_update_fn)(git_hash_ctx *ctx, const void *in, size_t len);
66 +typedef void (*git_hash_final_fn)(unsigned char *hash, git_hash_ctx *ctx);
67
68 struct git_hash_algo {
69 /*
@@ -69,9 +75,6 @@ struct git_hash_algo {
75 /* A four-byte version identifier, used in pack indices. */
76 uint32_t format_id;
77
72 - /* The size of a hash context (e.g. git_SHA_CTX). */
73 - size_t ctxsz;
74 -
78 /* The length of the hash in binary. */
79 size_t rawsz;
80
sha1_file.c
+9 -11
@@ -39,32 +39,32 @@ const struct object_id empty_blob_oid = {
39 EMPTY_BLOB_SHA1_BIN_LITERAL
40 };
41
42 -static void git_hash_sha1_init(void *ctx)
42 +static void git_hash_sha1_init(git_hash_ctx *ctx)
43 {
44 - git_SHA1_Init((git_SHA_CTX *)ctx);
44 + git_SHA1_Init(&ctx->sha1);
45 }
46
47 -static void git_hash_sha1_update(void *ctx, const void *data, size_t len)
47 +static void git_hash_sha1_update(git_hash_ctx *ctx, const void *data, size_t len)
48 {
49 - git_SHA1_Update((git_SHA_CTX *)ctx, data, len);
49 + git_SHA1_Update(&ctx->sha1, data, len);
50 }
51
52 -static void git_hash_sha1_final(unsigned char *hash, void *ctx)
52 +static void git_hash_sha1_final(unsigned char *hash, git_hash_ctx *ctx)
53 {
54 - git_SHA1_Final(hash, (git_SHA_CTX *)ctx);
54 + git_SHA1_Final(hash, &ctx->sha1);
55 }
56
57 -static void git_hash_unknown_init(void *ctx)
57 +static void git_hash_unknown_init(git_hash_ctx *ctx)
58 {
59 die("trying to init unknown hash");
60 }
61
62 -static void git_hash_unknown_update(void *ctx, const void *data, size_t len)
62 +static void git_hash_unknown_update(git_hash_ctx *ctx, const void *data, size_t len)
63 {
64 die("trying to update unknown hash");
65 }
66
67 -static void git_hash_unknown_final(unsigned char *hash, void *ctx)
67 +static void git_hash_unknown_final(unsigned char *hash, git_hash_ctx *ctx)
68 {
69 die("trying to finalize unknown hash");
70 }
@@ -75,7 +75,6 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
75 0x00000000,
76 0,
77 0,
78 - 0,
78 git_hash_unknown_init,
79 git_hash_unknown_update,
80 git_hash_unknown_final,
@@ -86,7 +85,6 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
85 "sha-1",
86 /* "sha1", big-endian */
87 0x73686131,
89 - sizeof(git_SHA_CTX),
88 GIT_SHA1_RAWSZ,
89 GIT_SHA1_HEXSZ,
90 git_hash_sha1_init,