8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 23:23:04 +01:00

Refactor introducing HashContext and WeakHashContext.

This commit is contained in:
Adriano dos Santos Fernandes 2017-07-19 18:55:28 +00:00
parent 8c5c9bdc61
commit 7fe1fbbae3
3 changed files with 61 additions and 26 deletions

View File

@ -108,3 +108,26 @@ unsigned int InternalHash::hash(unsigned int length, const UCHAR* value)
{
return internalHash(length, value);
}
void WeakHashContext::update(const void* data, FB_SIZE_T length)
{
const UCHAR* p = static_cast<const UCHAR*>(data);
for (const UCHAR* end = p + length; p != end; ++p)
{
hashNumber = (hashNumber << 4) + *p;
const SINT64 n = hashNumber & FB_CONST64(0xF000000000000000);
if (n)
hashNumber ^= n >> 56;
hashNumber &= ~n;
}
}
void WeakHashContext::finish(Buffer& result)
{
UCHAR* resultBuffer = result.getBuffer(sizeof(hashNumber));
memcpy(resultBuffer, &hashNumber, sizeof(hashNumber));
}

View File

@ -28,7 +28,7 @@
#ifndef CLASSES_HASH_H
#define CLASSES_HASH_H
#include "../common/classes/vector.h"
#include "../common/classes/array.h"
namespace Firebird
{
@ -341,7 +341,31 @@ namespace Firebird
}
};
class HashContext
{
public:
typedef HalfStaticArray<UCHAR, 256> Buffer;
public:
virtual ~HashContext()
{
}
public:
virtual void update(const void* data, FB_SIZE_T length) = 0;
virtual void finish(Buffer& result) = 0;
};
class WeakHashContext FB_FINAL : public HashContext
{
public:
virtual void update(const void* data, FB_SIZE_T length);
virtual void finish(Buffer& result);
private:
SINT64 hashNumber = 0;
};
} // namespace Firebird
#endif // CLASSES_HASH_H

View File

@ -30,6 +30,7 @@
#include "firebird.h"
#include "../common/classes/VaryStr.h"
#include "../common/classes/Hash.h"
#include "../jrd/SysFunction.h"
#include "../jrd/DataTypeUtil.h"
#include "../include/fb_blk.h"
@ -2647,10 +2648,9 @@ dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
if (request->req_flags & req_null) // return NULL if value is NULL
return NULL;
WeakHashContext hashContext;
impure->vlu_misc.vlu_int64 = 0;
UCHAR* address;
if (value->isBlob())
{
UCHAR buffer[BUFFER_LARGE];
@ -2659,38 +2659,26 @@ dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
while (!(blob->blb_flags & BLB_eof))
{
address = buffer;
const ULONG length = blob->BLB_get_data(tdbb, address, sizeof(buffer), false);
for (const UCHAR* end = address + length; address < end; ++address)
{
impure->vlu_misc.vlu_int64 = (impure->vlu_misc.vlu_int64 << 4) + *address;
const SINT64 n = impure->vlu_misc.vlu_int64 & FB_CONST64(0xF000000000000000);
if (n)
impure->vlu_misc.vlu_int64 ^= n >> 56;
impure->vlu_misc.vlu_int64 &= ~n;
}
const ULONG length = blob->BLB_get_data(tdbb, buffer, sizeof(buffer), false);
hashContext.update(buffer, length);
}
blob->BLB_close(tdbb);
}
else
{
UCHAR* address;
MoveBuffer buffer;
const ULONG length = MOV_make_string2(tdbb, value, value->getTextType(), &address, buffer, false);
for (const UCHAR* end = address + length; address < end; ++address)
{
impure->vlu_misc.vlu_int64 = (impure->vlu_misc.vlu_int64 << 4) + *address;
const SINT64 n = impure->vlu_misc.vlu_int64 & FB_CONST64(0xF000000000000000);
if (n)
impure->vlu_misc.vlu_int64 ^= n >> 56;
impure->vlu_misc.vlu_int64 &= ~n;
}
hashContext.update(address, length);
}
HashContext::Buffer resultBuffer;
hashContext.finish(resultBuffer);
fb_assert(resultBuffer.getCount() == sizeof(SINT64));
memcpy(&impure->vlu_misc.vlu_int64, resultBuffer.begin(), sizeof(SINT64));
// make descriptor for return value
impure->vlu_desc.makeInt64(0, &impure->vlu_misc.vlu_int64);