NetworkCacheKey.cpp [plain text]
#include "config.h"
#include "NetworkCacheKey.h"
#if ENABLE(NETWORK_CACHE)
#include "NetworkCacheCoders.h"
#include <wtf/ASCIICType.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
namespace WebKit {
namespace NetworkCache {
Key::Key(const Key& o)
: m_method(o.m_method.isolatedCopy())
, m_partition(o.m_partition.isolatedCopy())
, m_identifier(o.m_identifier.isolatedCopy())
, m_range(o.m_range.isolatedCopy())
, m_hash(o.m_hash)
{
}
Key::Key(const String& method, const String& partition, const String& range, const String& identifier)
: m_method(method.isolatedCopy())
, m_partition(partition.isolatedCopy())
, m_identifier(identifier.isolatedCopy())
, m_range(range.isolatedCopy())
, m_hash(computeHash())
{
}
Key& Key::operator=(const Key& other)
{
m_method = other.m_method.isolatedCopy();
m_partition = other.m_partition.isolatedCopy();
m_identifier = other.m_identifier.isolatedCopy();
m_range = other.m_range.isolatedCopy();
m_hash = other.m_hash;
return *this;
}
static void hashString(SHA1& sha1, const String& string)
{
if (string.isNull())
return;
if (string.is8Bit() && string.containsOnlyASCII()) {
const uint8_t nullByte = 0;
sha1.addBytes(string.characters8(), string.length());
sha1.addBytes(&nullByte, 1);
return;
}
auto cString = string.utf8();
sha1.addBytes(reinterpret_cast<const uint8_t*>(cString.data()), cString.length() + 1);
}
Key::HashType Key::computeHash() const
{
SHA1 sha1;
hashString(sha1, m_method);
hashString(sha1, m_partition);
hashString(sha1, m_identifier);
hashString(sha1, m_range);
SHA1::Digest hash;
sha1.computeHash(hash);
return hash;
}
String Key::hashAsString() const
{
StringBuilder builder;
builder.reserveCapacity(hashStringLength());
for (auto byte : m_hash) {
builder.append(upperNibbleToASCIIHexDigit(byte));
builder.append(lowerNibbleToASCIIHexDigit(byte));
}
return builder.toString();
}
template <typename CharType> bool hexDigitsToHash(CharType* characters, Key::HashType& hash)
{
for (unsigned i = 0; i < sizeof(hash); ++i) {
auto high = characters[2 * i];
auto low = characters[2 * i + 1];
if (!isASCIIHexDigit(high) || !isASCIIHexDigit(low))
return false;
hash[i] = toASCIIHexValue(high, low);
}
return true;
}
bool Key::stringToHash(const String& string, HashType& hash)
{
if (string.length() != hashStringLength())
return false;
if (string.is8Bit())
return hexDigitsToHash(string.characters8(), hash);
return hexDigitsToHash(string.characters16(), hash);
}
bool Key::operator==(const Key& other) const
{
return m_hash == other.m_hash && m_method == other.m_method && m_partition == other.m_partition && m_identifier == other.m_identifier && m_range == other.m_range;
}
void Key::encode(Encoder& encoder) const
{
encoder << m_method;
encoder << m_partition;
encoder << m_identifier;
encoder << m_range;
encoder << m_hash;
}
bool Key::decode(Decoder& decoder, Key& key)
{
return decoder.decode(key.m_method) && decoder.decode(key.m_partition) && decoder.decode(key.m_identifier) && decoder.decode(key.m_range) && decoder.decode(key.m_hash);
}
}
}
#endif