On 21 Feb, 09:20, "Alf P. Steinbach" <al...@start.no> wrote:
* ke...@bytebrothers.co.uk:
Now this seems from my reading to be the sort of thing that templates
are probably good at, but I can't for the life of me see how to do it,
without first creating a separate class for each of AAA, BBB, and CCC.
Each of group AAA, BBB and CCC essentially constitute a functor object.
Hi again. I'm going to try my luck one more time and ask for some
more advice on this!
Alf's suggestions upthread all worked swimmingly, but I'm left with
one thing that I can't quite work out.
The actual template is intended as a wrapper for the ciphers in
LibTomCrypt[1], and one of the things I need to do is find out the
'index' of a particular cipher by passing the cipher name as a string
to a helper function. Here's what I've got so far with Alf's help:
//--------------------- ltc.h START------------------------
#include "tomcrypt.h"
/* Our abstract base class */
class AbstractCipher
{
public:
virtual ~AbstractCipher() {}
virtual int setup (const uint8_t* key, int keylen) = 0;
virtual int ecb_encrypt (const uint8_t *ptext, uint8_t* ctext) = 0;
virtual int ecb_decrypt (const uint8_t *ctext, uint8_t* ptext) = 0;
virtual int test () = 0;
virtual int keysize (int* keysize) = 0;
virtual void done () = 0;
virtual int index () = 0;
};
/* Our functors */
struct CFunctionTypes
{
typedef int (*Setup)
(const uint_8t* key, int keylen, int rounds, symmetric_key* skey);
typedef int (*ECBencrypt)
(const uint8_t *ptext, uint8_t* ctext, symmetric_key* skey);
typedef int (*ECBdecrypt)
(const uint8_t *ctext, uint8_t* ptext, symmetric_key* skey);
typedef int (*Test)
();
typedef int (*Keysize)
(int* keysize);
typedef void (*Done)
(symmetric_key* skey);
};
/* Now specialise the functors for each cipher */
struct AESCipher:CFunctionTypes
{
static Setup const setup;
static ECBencrypt const ecb_encrypt;
static ECBdecrypt const ecb_decrypt;
static Test const test;
static Keysize const keysize;
static Done const done;
AESCipher() { register_cipher(&aes_desc); index =
find_cipher("aes");}
~AESCipher() { unregister_cipher(&aes_desc); }
int index;
};
CFunctionTypes::Setup const AESCipher::setup = &aes_setup;
CFunctionTypes::ECBencrypt const AESCipher::ecb_encrypt =
&aes_ecb_encrypt;
CFunctionTypes::ECBdecrypt const AESCipher::ecb_decrypt =
&aes_ecb_decrypt;
CFunctionTypes::Test const AESCipher::test = &aes_test;
CFunctionTypes::Keysize const AESCipher::keysize =
&aes_keysize;
CFunctionTypes::Done const AESCipher::done = &aes_done;
struct TwofishCipher:CFunctionTypes
{
static Setup const setup;
static ECBencrypt const ecb_encrypt;
static ECBdecrypt const ecb_decrypt;
static Test const test;
static Keysize const keysize;
static Done const done;
TwofishCipher() { register_cipher(&twofish_desc); index =
find_cipher("twofish");}
~TwofishCipher() { unregister_cipher(&twofish_desc); }
int index;
};
CFunctionTypes::Setup const TwofishCipher::setup =
&twofish_setup;
CFunctionTypes::ECBencrypt const TwofishCipher::ecb_encrypt =
&twofish_ecb_encrypt;
CFunctionTypes::ECBdecrypt const TwofishCipher::ecb_decrypt =
&twofish_ecb_decrypt;
CFunctionTypes::Test const TwofishCipher::test =
&twofish_test;
CFunctionTypes::Keysize const TwofishCipher::keysize =
&twofish_keysize;
CFunctionTypes::Done const TwofishCipher::done =
&twofish_done;
template < class CFunctions > class Cipher : public AbstractCipher
{
public:
Cipher () : skey() {}
virtual int setup (const uint_8t* key, int keylen)
{ return CFunctions::setup (key, keylen, 0, &skey); }
virtual int ecb_encrypt (const uint8_t *ptext, uint8_t* ctext)
{ return CFunctions::ecb_encrypt (ptext, ctext, &skey); }
virtual int ecb_decrypt (const uint8_t *ctext, uint8_t* ptext)
{ return CFunctions::ecb_decrypt (ctext, ptext, &skey); }
virtual int test ()
{ return CFunctions::test(); }
virtual int keysize (int* keysize)
{ return CFunctions::keysize(keysize); }
virtual int index()
{ return CFunctions::index; }
virtual ~Cipher ()
{ CFunctions::done (&skey); }
protected:
symmetric_key skey;
};
typedef Cipher < AESCipher > AES;
typedef Cipher < TwofishCipher > Twofish;
//--------------------- ltc.h END------------------------
//--------------------- x.cc BEGIN-----------------------
#include <iostream>
#include "ltc.h"
int main()
{
AES aes;
std::cerr << "AES.index() = " << aes.index();
return 0;
}
//--------------------- x.cc END-------------------------
Now you can probably see what I'm trying to do with this 'index' call;
it has to return the result of find_cipher("ciphername"). The problem
is that at compile time, I get the following error:
ltc.h: In member function 'int Cipher<CFunctions>::index() [with
CFunctions = AESCipher]':
x.cc:47: instantiated from here
ltc.h:40: error: object missing in reference to 'AESCipher::index'
ltc.h:93: error: from this location
I can't see what it is that's missing. If someone can clarify, or
even better, show me a better way to do what I'm trying to do, I'd be
grateful. Meanwhile, I'm learning a _lot_ doing this stuff!
exists in instances of AESCipher, one per instance.
types should probably all be 'extern "C"', but that's just a nit).
constructors, and all cleanup calls in destructors. That is, no "setup"
or "cleanup" functions visible to client code at the C++ level. Of
cleanup: it automates the calls, and makes for better exception safety.
A: Because it messes up the order in which people normally read text.
A: Top-posting.