HTTP Digest 認証の credential デコーダ

credential のデコーダを正攻法のトライで作ってみました。ちゃんと動作しますが、やりすぎ感が漂っていて微妙です。

struct authdigest_credential_type {
    enum {
        MARK_ALGORITHM =   2, MARK_CNONCE   =   4, MARK_NC  =   8,
        MARK_NONCE    =   16, MARK_OPAQUE   =  32, MARK_QOP =  64,
        MARK_REALM    =  128, MARK_RESPONSE = 256, MARK_URI = 512,
        MARK_USERNAME = 1024,
    };
    std::string algorithm;
    std::string cnonce;
    std::string nc;
    std::string nonce;
    std::string opaque;
    std::string qop;
    std::string realm;
    std::string response;
    std::string uri;
    std::string username;
    bool decode (std::string const& str);
    bool good () const { return 70 == next_state; }
private:
    int next_state;
    uint32_t mark;
};

bool
authdigest_credential_type::decode (std::string const& str)
{
    static const int CCLS[128] = {
    //                                     \t  \n          \r
        0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    //      !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
        2, 24,  5, 24, 24, 24, 24, 24, 25, 25, 24, 24,  4, 24, 24, 25,
    //  0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
       24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,  3, 25, 25,
    //  @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
       25,  7, 24,  8,  9, 10, 24, 11, 12, 13, 24, 24, 14, 15, 16, 17,
    //  P   Q   R   S   T   U   V   W   X   Y   Z   [  \\   ]   ^   _
       18, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 25,  6, 25, 24, 24,
    //  `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
       24,  7, 24,  8,  9, 10, 24, 11, 12, 13, 24, 24, 14, 15, 16, 17,
    //  p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~
       18, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 25, 24, 25, 24,  0,
    };      // END_STRING 26
    static const int SHIFT[71][27] = {
    //     \t \s  =  ,  "  \  a  c  d  e  g  h  i  l  m  n  o  p  q  r  s  t  u \T \Q  $
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//1
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//2
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//3
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//4
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0},//5
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0},//6
        {0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//7
        {0, 0, 8, 0, 9, 0, 0,10,19,61,61,61,61,61,61,61,25,31,61,37,40,61,61,51,61, 0, 0},//8
        {0, 9, 9, 0, 9, 0, 0,10,19,61,61,61,61,61,61,61,25,31,61,37,40,61,61,51,61, 0, 0},//9
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,11,61,61,61,61,61,61,61,61,61,61, 0, 0},//10
        {0,62,62,63,61,61,61,61,61,61,61,12,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//11
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,13,61,61,61,61,61,61,61, 0, 0},//12
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,14,61,61,61,61, 0, 0},//13
        {0,62,62,63,61,61,61,61,61,61,61,61,61,15,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//14
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,16,61,61, 0, 0},//15
        {0,62,62,63,61,61,61,61,61,61,61,61,17,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//16
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,18,61,61,61,61,61,61,61,61,61, 0, 0},//17
        {1,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//18
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,20,61,61,61,61,61,61,61,61, 0, 0},//19
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,21,61,61,61,61,61,61,61, 0, 0},//20
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,22,61,61,61,61,61,61,61,61, 0, 0},//21
        {0,62,62,63,61,61,61,61,23,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//22
        {0,62,62,63,61,61,61,61,61,61,24,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//23
        {2,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//24
        {0,62,62,63,61,61,61,61,26,61,61,61,61,61,61,61,61,27,61,61,61,61,61,61,61, 0, 0},//25
        {3,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//26
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,28,61,61,61,61,61,61,61,61, 0, 0},//27
        {0,62,62,63,61,61,61,61,29,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//28
        {0,62,62,63,61,61,61,61,61,61,30,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//29
        {4,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//30
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,32,61,61,61,61,61,61, 0, 0},//31
        {0,62,62,63,61,61,61,33,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//32
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,34,61,61,61,61,61, 0, 0},//33
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,35,61, 0, 0},//34
        {0,62,62,63,61,61,61,61,61,61,36,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//35
        {5,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//36
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,38,61,61,61,61,61,61,61, 0, 0},//37
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,39,61,61,61,61,61,61, 0, 0},//38
        {6,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//39
        {0,62,62,63,61,61,61,61,61,61,41,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//40
        {0,62,62,63,61,61,61,42,61,61,61,61,61,61,61,61,61,61,61,61,61,45,61,61,61, 0, 0},//41
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,43,61,61,61,61,61,61,61,61,61,61, 0, 0},//42
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,44,61,61,61,61,61,61,61,61,61, 0, 0},//43
        {7,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//44
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,46,61,61,61,61,61,61, 0, 0},//45
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,47,61,61,61,61,61,61,61, 0, 0},//46
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,48,61,61,61,61,61,61,61,61, 0, 0},//47
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,49,61,61,61, 0, 0},//48
        {0,62,62,63,61,61,61,61,61,61,50,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//49
        {8,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//50
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,52,54,61,61,61, 0, 0},//51
        {0,62,62,63,61,61,61,61,61,61,61,61,61,53,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//52
        {9,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//53
        {0,62,62,63,61,61,61,61,61,61,55,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//54
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,56,61,61,61,61, 0, 0},//55
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,57,61,61,61,61,61,61,61,61, 0, 0},//56
        {0,62,62,63,61,61,61,58,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//57
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,59,61,61,61,61,61,61,61,61,61, 0, 0},//58
        {0,62,62,63,61,61,61,61,61,61,60,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//59
       {10,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//60
        {0,62,62,63,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 0, 0},//61
       {16,62,62,63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//62
       {16,63,63, 0, 0,65, 0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 0, 0},//63
       {32,68,68, 0,69, 0, 0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 0,70},//64
        {0,67,67,67,67,68,66,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, 0},//65
        {0,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, 0},//66
       {32,67,67,67,67,68,66,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, 0},//67
        {0,68,68, 0,69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,70},//68
        {0,69,69, 0,69, 0, 0,10,19,61,61,61,61,61,61,61,25,31,61,37,40,61,61,51,61, 0,70},//69
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//70
    };
    int directive = 0;
    std::string value;
    next_state = 1;
    mark = 0;
    std::string::const_iterator s = str.cbegin ();
    std::string::const_iterator const e = str.cend ();
    for (; s <= e && next_state > 0; ++s) {
        int ch = s < e ? *s : '\0';
        int cls = s == e ? 26 : ch < 128 ? CCLS[ch] : 0;
        int prev_state = next_state;
        next_state = cls == 0 ? 0 : SHIFT[prev_state][cls];
        if ((16 & SHIFT[next_state][0]) && (15 & SHIFT[prev_state][0]) > 0)
            directive = 15 & SHIFT[prev_state][0];
        if (32 & SHIFT[next_state][0])
            value.push_back (ch);
        if (next_state >= 68 && (32 & SHIFT[prev_state][0])) {
            if (mark & (1U << directive)) {
                next_state = 0;
                break;
            }
            mark |= 1U << directive;
            switch (directive) {
            case  1: algorithm = value; break;
            case  2: cnonce = value; break;
            case  3: nc = value; break;
            case  4: nonce = value; break;
            case  5: opaque = value; break;
            case  6: qop = value; break;
            case  7: realm = value; break;
            case  8: response = value; break;
            case  9: uri = value; break;
            case 10: username = value; break;
            }
            directive = 0;
            value.clear ();
        }
    }
    return good ();
}