ArrayRef-ize MD5 and clean up a few variable names.

Add a stringize method to make dumping a bit easier, and add a testcase
exercising a few different paths.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182692 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Christopher 2013-05-24 23:08:17 +00:00
parent 80d10ded8c
commit f7306f224e
3 changed files with 85 additions and 24 deletions

View File

@ -28,10 +28,13 @@
#ifndef LLVM_SYSTEM_MD5_H
#define LLVM_SYSTEM_MD5_H
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
template <typename T> class ArrayRef;
class MD5 {
// Any 32-bit or wider unsigned integer data type will do.
typedef uint32_t MD5_u32plus;
@ -41,17 +44,21 @@ class MD5 {
unsigned char buffer[64];
MD5_u32plus block[16];
public:
public:
typedef unsigned char MD5Result[16];
MD5();
/// \brief Updates the hash for arguments provided.
void Update(void *data, unsigned long size);
void update(ArrayRef<unsigned char> Data);
/// \brief Finishes off the hash and puts the result in result.
void Final(unsigned char *result);
void final(MD5Result &result);
static void stringifyResult(MD5Result &Res, SmallString<32> &Str);
private:
void *body(void *data, unsigned long size);
const unsigned char *body(ArrayRef<unsigned char> Data);
};
}

View File

@ -37,7 +37,10 @@
* compile-time configuration.
*/
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
// The basic MD5 functions.
@ -69,12 +72,13 @@ namespace llvm {
/// \brief This processes one or more 64-byte data blocks, but does NOT update
///the bit counters. There are no alignment requirements.
void *MD5::body(void *data, unsigned long size) {
unsigned char *ptr;
const unsigned char *MD5::body(ArrayRef<unsigned char> Data) {
const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
unsigned long Size = Data.size();
ptr = (unsigned char *)data;
ptr = Data.data();
a = this->a;
b = this->b;
@ -165,7 +169,7 @@ void *MD5::body(void *data, unsigned long size) {
d += saved_d;
ptr += 64;
} while (size -= 64);
} while (Size -= 64);
this->a = a;
this->b = b;
@ -180,42 +184,44 @@ MD5::MD5()
}
/// Incrementally add \p size of \p data to the hash.
void MD5::Update(void *data, unsigned long size) {
void MD5::update(ArrayRef<unsigned char> Data) {
MD5_u32plus saved_lo;
unsigned long used, free;
const unsigned char *Ptr = Data.data();
unsigned long Size = Data.size();
saved_lo = lo;
if ((lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
if ((lo = (saved_lo + Size) & 0x1fffffff) < saved_lo)
hi++;
hi += size >> 29;
hi += Size >> 29;
used = saved_lo & 0x3f;
if (used) {
free = 64 - used;
if (size < free) {
memcpy(&buffer[used], data, size);
if (Size < free) {
memcpy(&buffer[used], Ptr, Size);
return;
}
memcpy(&buffer[used], data, free);
data = (unsigned char *)data + free;
size -= free;
body(buffer, 64);
memcpy(&buffer[used], Ptr, free);
Ptr = Ptr + free;
Size -= free;
body(ArrayRef<unsigned char>(buffer, 64));
}
if (size >= 64) {
data = body(data, size & ~(unsigned long) 0x3f);
size &= 0x3f;
if (Size >= 64) {
Ptr = body(ArrayRef<unsigned char>(Ptr, Size & ~(unsigned long) 0x3f));
Size &= 0x3f;
}
memcpy(buffer, data, size);
memcpy(buffer, Ptr, Size);
}
/// \brief Finish the hash and place the resulting hash into \p result.
/// \param result is assumed to be a minimum of 16-bytes in size.
void MD5::Final(unsigned char *result) {
void MD5::final(MD5Result &result) {
unsigned long used, free;
used = lo & 0x3f;
@ -226,7 +232,7 @@ void MD5::Final(unsigned char *result) {
if (free < 8) {
memset(&buffer[used], 0, free);
body(buffer, 64);
body(ArrayRef<unsigned char>(buffer, 64));
used = 0;
free = 64;
}
@ -243,7 +249,7 @@ void MD5::Final(unsigned char *result) {
buffer[62] = hi >> 16;
buffer[63] = hi >> 24;
body(buffer, 64);
body(ArrayRef<unsigned char>(buffer, 64));
result[0] = a;
result[1] = a >> 8;
@ -263,4 +269,10 @@ void MD5::Final(unsigned char *result) {
result[15] = d >> 24;
}
void MD5::stringifyResult(MD5Result &result, SmallString<32> &Str) {
raw_svector_ostream Res(Str);
for (int i = 0; i < 16; ++i)
Res << format("%.2x", result[i]);
}
}

View File

@ -0,0 +1,42 @@
//===- llvm/unittest/Support/MD5Test.cpp - MD5 tests ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements unit tests for the MD5 functions.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MD5.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
void TestMD5Sum(ArrayRef<unsigned char> Input, StringRef Final) {
MD5 Hash;
Hash.update(Input);
MD5::MD5Result MD5Res;
Hash.final(MD5Res);
SmallString<32> Res;
MD5::stringifyResult(MD5Res, Res);
EXPECT_EQ(Res, Final);
}
TEST(MD5Test, MD5) {
TestMD5Sum(ArrayRef<unsigned char>((const unsigned char *)"", (size_t) 0),
"d41d8cd98f00b204e9800998ecf8427e");
TestMD5Sum(ArrayRef<unsigned char>((const unsigned char *)"a", (size_t) 1),
"0cc175b9c0f1b6a831c399e269772661");
TestMD5Sum(ArrayRef<unsigned char>(
(const unsigned char *)"abcdefghijklmnopqrstuvwxyz",
(size_t) 26),
"c3fcd3d76192e4007dfb496cca67e13b");
}
}