bool Qca2ByteArrayChecksumAlgorithm::calculateChecksum( QString* result,
                                                        const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range ) const
{
    QCA::Hash hash( mType );

    // TODO: find a way without needing to copy, perhaps by smart iterator which can return spans of original data
    // TODO: see if buffer size could be a value which matches the algorithm and qca2

    char buffer[CalculatedByteCountSignalLimit];
    int bufferLength = CalculatedByteCountSignalLimit;
    Okteta::Address nextBlockEnd = range.start() + CalculatedByteCountSignalLimit;
    for( Okteta::Address i = range.start(); i<=range.end(); i+=CalculatedByteCountSignalLimit )
    {
        if( range.end() < i+CalculatedByteCountSignalLimit )
            bufferLength = range.end() - i + 1;
        model->copyTo( reinterpret_cast<Okteta::Byte*>(buffer), i, bufferLength );
        hash.update( buffer, bufferLength );

        if( i >= nextBlockEnd )
        {
            nextBlockEnd += CalculatedByteCountSignalLimit;
            emit calculatedBytes( range.localIndex(i)+1 );
        }
    }

    const QByteArray hashResult = hash.final().toByteArray();

    *result = QCA::arrayToHex( hashResult );
    return true;
}
bool Adler32ByteArrayChecksumAlgorithm::calculateChecksum( QString* result,
                                                           const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range ) const
{
    quint32 a = 1;
    quint32 b = 0;

    // TODO: this is the "inefficient but straightforward implementation" from the Wikipedia entry, search for improved
    Okteta::Address nextBlockEnd = range.start() + CalculatedByteCountSignalLimit;
    for( Okteta::Address i = range.start(); i<=range.end(); ++i )
    {
        a = (a + model->byte( i )) % MOD_ADLER;
        b = (b + a) % MOD_ADLER;

        if( i >= nextBlockEnd )
        {
            nextBlockEnd += CalculatedByteCountSignalLimit;
            emit calculatedBytes( range.localIndex(i)+1 );
        }
    }

    const quint32 sum = (b << 16) | a;
    *result = QString::fromLatin1("%1").arg( sum, 8, 16, QChar::fromLatin1('0') );

    return true;
}
quint16 ModSum16ByteArrayChecksumAlgorithm::calculateModSumWithBigEndian( const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range ) const
{
    quint16 modSum = 0x0000;
    Okteta::Address nextBlockEnd = range.start() + CalculatedByteCountSignalLimit;

    // TODO: move padding checks into extra code before and after loop
    for( Okteta::Address i = range.start(); i<=range.end(); ++i )
    {
        quint16 value = (quint16)( (quint8)(model->byte( i )) ) << 8;
        ++i;
        if( i<=range.end() )
            value |= (quint16)( (quint8)(model->byte( i )) );

        modSum += value;
#if 0
        const uchar value = (crcBits & 0xFF) + model->byte( i );
        crcBits >>= 8;
        crcBits ^= lookupTable[value];
#endif
        if( i >= nextBlockEnd )
        {
            nextBlockEnd += CalculatedByteCountSignalLimit;
            emit calculatedBytes( range.localIndex(i)+1 );
        }
    }

    return modSum;
}