⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hash.cpp

📁 Last change: 2008-02-03 This is the source code of KCeasy。
💻 CPP
字号:
/*
This file is part of KCeasy (http://www.kceasy.com)
Copyright (C) 2002-2004 Markus Kern <mkern@kceasy.com>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
*/
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Hash.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

namespace KCeasyEngine {

// List specifying urn encodings.
// Note that the names are in giFT capitalization while RFC 2141 specifies
// case insensitivity for URNs.
// We really shouldn't have to deal with this in the FE.
static const struct
{
    const char* AlgoName;
    THashEncoding Encoding;
} UrnEncodings[] =
{
    { "MD5",    HASHENC_BASE16 },
    { "SHA1",   HASHENC_BASE32 },
    { "FTH",    HASHENC_BASE64 },
    { "kzhash", HASHENC_BASE16 },
    { NULL, HASHENC_UNKNOWN }
};

// class THashAlgo

THashAlgo::THashAlgo(const THashAlgo* Algo)
{
    Name = Algo->Name;
    Encoding = Algo->Encoding;
}

THashAlgo::THashAlgo(const string& Name, THashEncoding Encoding)
{
    this->Name = Name;
    this->Encoding = Encoding;
}

// class THashAlgoSet

THashAlgoSet::THashAlgoSet()
{
}

THashAlgoSet::THashAlgoSet(const THashAlgoSet* org)
{
    *this = *org;
}

THashAlgoSet::~THashAlgoSet()
{
    Clear();
}

THashAlgo* THashAlgoSet::GetAlgo(const string& Name) const
{
    for(Iterator itr = Begin(); itr != End(); ++itr)
        if((*itr)->GetName() == Name)
            return (*itr);
    return NULL;
}

THashAlgo* THashAlgoSet::GetFirstAlgo() const
{
    if(Algos.empty())
        return NULL;
    return Algos.front();
}

void THashAlgoSet::AddAlgo(THashAlgo* Algo)
{
    RemoveAlgo(Algo->GetName());
    Algos.push_back(Algo);
}

bool THashAlgoSet::AddAlgo(const string Name, THashEncoding Encoding)
{
    RemoveAlgo(Name);

    THashAlgo* Algo;
    if((Algo = new THashAlgo(Name,Encoding)) != NULL) {
        Algos.push_back(Algo);
        return true;
    }
    return false;
}

bool THashAlgoSet::RemoveAlgo(const string& Name)
{
    list<THashAlgo*>::iterator itr = Algos.begin();
    for(; itr != Algos.end(); ++itr) {
        if((*itr)->GetName() == Name) {
            delete (*itr);
            list<THashAlgo*>::iterator end = itr;
            Algos.erase(itr,++end);
            return true;
        }
    }
    return false;
}

void THashAlgoSet::Clear()
{
    while(!Algos.empty()) {
        delete Algos.front();
        Algos.pop_front();
    }
}

bool THashAlgoSet::Equals(const THashAlgoSet* Cmp) const
{
    THashAlgo* CmpAlgo;

    for(Iterator itr = Begin(); itr != End(); ++itr) {
        if((CmpAlgo = Cmp->GetAlgo((*itr)->GetName())) != NULL) {
            if(CmpAlgo->Equals(*itr))
                return true;
        }
    }
    return false;
}

THashAlgoSet& THashAlgoSet::operator=(const THashAlgoSet& Org)
{
    Clear();

    for(Iterator itr = Org.Begin(); itr != Org.End(); ++itr)
        AddAlgo((*itr)->GetName(),(*itr)->GetEncoding());

    return *this;
}

// class THash

THash::THash()
:   Algo(NULL)
{
    Algo = new THashAlgo("",HASHENC_UNKNOWN);
}

THash::THash(const THash* org)
:   Algo(NULL)
{
    *this = *org;
}

THash::THash(const string& Name, THashEncoding Encoding, const string& EncStr)
:   Algo(NULL),
    EncodedHash(NULL)
{
    SetEncoded(Name, Encoding, EncStr);
}

THash::~THash()
{
    delete Algo;
}

string THash::GetEncoded() const
{
    return EncodedHash;
}

bool THash::SetEncoded(const string& Name, THashEncoding Encoding, const string& EncStr)
{
    delete Algo;

    if((Algo = new THashAlgo(Name,Encoding)) != NULL) {
        EncodedHash = EncStr;
        return true;
    }
    return false;
}

string THash::GetUrn() const
{
    string Urn("urn:");
    Urn += string_tolower(GetName()) + ":";
    Urn += EncodedHash;
    return Urn;
}

bool THash::SetUrn(const string& Urn)
{
    string Name;
    int pos, i;

    if(Urn.substr(0,4) != "urn:")
        return false;

    if((pos = Urn.find(':',4)) == -1)
        return false;
    Name = Urn.substr(4,pos - 4);
    pos++;

    // lookup encoding
    for(i=0; UrnEncodings[i].AlgoName; i++)
        if(Name == UrnEncodings[i].AlgoName)
            break;

    return SetEncoded(Name,UrnEncodings[i].Encoding,Urn.substr(pos).c_str());
}

string THash::GetGiftHash() const
{
    string GiftHash;
    int i;

    // lookup encoding for right name casing
    for(i=0; UrnEncodings[i].AlgoName; i++)
        if(GetName() == UrnEncodings[i].AlgoName)
            break;
    if(UrnEncodings[i].AlgoName == NULL)
        return "";

    GiftHash = UrnEncodings[i].AlgoName;
    GiftHash += string(":") + EncodedHash;
    return GiftHash;
}

bool THash::SetGiftHash(const string& GiftHash)
{
    string Name;
    int pos, i;

    if((pos = GiftHash.find(':')) == -1)
        return false;
    Name = GiftHash.substr(0,pos);
    pos++;

    // lookup encoding
    for(i=0; UrnEncodings[i].AlgoName; i++)
        if(Name == UrnEncodings[i].AlgoName)
            break;
    if(UrnEncodings[i].AlgoName == NULL)
        return false;

    return SetEncoded(UrnEncodings[i].AlgoName,
                      UrnEncodings[i].Encoding,
                      GiftHash.substr(pos).c_str());
}

bool THash::Equals(const THash* Cmp) const
{
    return (Algo->Equals(Cmp->Algo) &&
            EncodedHash == Cmp->EncodedHash);
}

THash& THash::operator=(const THash& Org)
{
    delete Algo;
    Algo = new THashAlgo(Org.Algo);
    EncodedHash = Org.EncodedHash;
    return *this;
}

// class THashSet

THashSet::THashSet()
{
}

THashSet::THashSet(const THashSet* org)
{
    *this = *org;
}

THashSet::~THashSet()
{
    Clear();
}

THash* THashSet::GetHash(const string& Name) const
{
    for(Iterator itr = Begin(); itr != End(); ++itr)
        if((*itr)->GetName() == Name)
            return (*itr);
    return NULL;
}

THash* THashSet::GetFirstHash() const
{
    if(Hashes.empty())
        return NULL;
    return Hashes.front();
}

void THashSet::AddHash(THash* Hash)
{
    RemoveHash(Hash->GetName());
    Hashes.push_back(Hash);
}

bool THashSet::AddGiftHash(const string& GiftHash)
{
    THash* Hash = new THash();

    if(Hash->SetGiftHash(GiftHash)) {
        AddHash(Hash);
        return true;
    }

    delete Hash;
    return false;
}

bool THashSet::RemoveHash(const string& Name)
{
    list<THash*>::iterator itr = Hashes.begin();
    for(; itr != Hashes.end(); ++itr) {
        if((*itr)->GetName() == Name) {
            delete (*itr);
            list<THash*>::iterator end = itr;
            Hashes.erase(itr,++end);
            return true;
        }
    }
    return false;
}

void THashSet::JoinHashSet(const THashSet* HashSet)
{
    Iterator itr = HashSet->Begin();
    for(;itr != HashSet->End(); ++itr) {
        // only add hashes if the algo is not yet present
        if(GetHash((*itr)->GetName()) == NULL)
            AddHash(new THash(*itr));
    }
}

void THashSet::Clear()
{
    while(!Hashes.empty()) {
        delete Hashes.front();
        Hashes.pop_front();
    }
}

// returns true if Hash is in set
bool THashSet::Contains(const THash* Hash) const
{
    THash* CmpHash;
    if((CmpHash = GetHash(Hash->GetName())) != NULL && CmpHash->Equals(Hash))
        return true;
    return false;
}

// return true of at least one hash matches and there are no others which contradict
bool THashSet::Equals(const THashSet* Cmp) const
{
    // optimize the common one-one case for search results
    if(Hashes.size() == 1 && Cmp->Hashes.size() == 1)
        return Hashes.front()->Equals(Cmp->Hashes.front());

    bool Match = false;
    THash* CmpHash;

    for(Iterator itr = Begin(); itr != End(); ++itr) {
        if((CmpHash = Cmp->GetHash((*itr)->GetName())) != NULL) {
            if(!(*itr)->Equals(CmpHash))
                return false;
            Match = true;
        }
    }
    return Match;
}

THashSet& THashSet::operator=(const THashSet& Org)
{
    Clear();

    for(Iterator itr = Org.Begin(); itr != Org.End(); ++itr)
        AddHash(new THash(*itr));

    return *this;
}

string THashSet::GetBitziUrl()
{
    THash* Hash = NULL;
    string Url = "";

    // create bitzi url with high lookup probability
    // best order according to http://bitzi.com/stat/tag seems to be:
    // sha1, kzhash, md5, sig2dat

    if ((Hash = GetHash("SHA1")) && Hash->GetEncoding() == HASHENC_BASE32) {
        Url = "http://bitzi.com/lookup/" + Hash->GetEncoded();
    } else if ((Hash = GetHash("kzhash")) && Hash->GetEncoding() == HASHENC_BASE16) {
        Url = "http://bitzi.com/lookup/kzhash:" + Hash->GetEncoded();
    } else if ((Hash = GetHash("MD5")) && Hash->GetEncoding() == HASHENC_BASE16) {
        Url = "http://bitzi.com/lookup/md5:" + Hash->GetEncoded();
    } else if ((Hash = GetHash("FTH")) && Hash->GetEncoding() == HASHENC_BASE64) {
        Url = "http://bitzi.com/lookup/sig2dat:" + Hash->GetEncoded();
    }

    return Url;
}

} // namespace KCeasyEngine

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -