git の sha1_to_hex のやつ
すこし調べた。
Linus が普通に Mailing List で明言していた。
Nothing magical, it's just "rounded up from 40 + NUL character".
単に、40バイト+NUL文字用の1バイトで切り上げて50バイトらしい。
が、masterのやつを見たら全然違うので、もう少し歴史を見てみる。
最初のは read-cache.c にあった。initial commitですね。
char * sha1_to_hex(unsigned char *sha1) { static char buffer[50]; static const char hex[] = "0123456789abcdef"; char *buf = buffer; int i; for (i = 0; i < 20; i++) { unsigned int val = *sha1++; *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } return buffer; }
sha1_file.cに移動されたあと、ちゃんと毎回 NUL terminate されるようになる。commitは@1e80e0。
char * sha1_to_hex(const unsigned char *sha1) { static char buffer[50]; static const char hex[] = "0123456789abcdef"; char *buf = buffer; int i; for (i = 0; i < 20; i++) { unsigned int val = *sha1++; *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } *buf = '\0'; return buffer; }
static 領域のアドレスを返すためにエラーメッセージ作るのが面倒だとかそんな感じの文句が出たのか、簡易LRUキャッシュが導入される。commitは@dcb345。
char * sha1_to_hex(const unsigned char *sha1) { static int bufno; static char hexbuffer[4][50]; static const char hex[] = "0123456789abcdef"; char *buffer = hexbuffer[3 & ++bufno], *buf = buffer; int i; for (i = 0; i < 20; i++) { unsigned int val = *sha1++; *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } *buf = '\0'; return buffer; }
さらに hex.c に移動して、マジックナンバーをマクロで置き換え、バッファサイズも変更。commit は @aa1c6f。
char *sha1_to_hex(const unsigned char *sha1) { static int bufno; static char hexbuffer[4][GIT_SHA1_HEXSZ + 1]; static const char hex[] = "0123456789abcdef"; char *buffer = hexbuffer[3 & ++bufno], *buf = buffer; int i; for (i = 0; i < GIT_SHA1_RAWSZ; i++) { unsigned int val = *sha1++; *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } *buf = '\0'; return buffer; }
#define GIT_SHA1_RAWSZ 20 #define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
で、reentrant版の sha1_to_hex_r と非reentrant版のsha1_to_hexに分離して、だいたい今の形になっている。commitは@af49c6。
char *sha1_to_hex_r(char *buffer, const unsigned char *sha1) { static const char hex[] = "0123456789abcdef"; char *buf = buffer; int i; for (i = 0; i < GIT_SHA1_RAWSZ; i++) { unsigned int val = *sha1++; *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } *buf = '\0'; return buffer; } char *sha1_to_hex(const unsigned char *sha1) { static int bufno; static char hexbuffer[4][GIT_SHA1_HEXSZ + 1]; return sha1_to_hex_r(hexbuffer[3 & ++bufno], sha1); }
こんな小さな関数でも結構変わっているもんですな。