18

Is there any way to create a hash of string at compile time using the C/C++ preprocessor (or even template-metaprogramming)?

e.g. UNIQUE_SALT("HelloWord", 3DES);

The idea is that HelloWorld will not be present in the compiled binary, just a hash.

Edit: There are many of these declarations spread over a large codebase.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Ash
  • 1,266
  • 4
  • 14
  • 24

9 Answers9

15

While this is not a proper answer to the question, see this blog entry for an example of a hash function for strings of up to 256 characters implemented purely as a C macro:

http://lolengine.net/blog/2011/12/20/cpp-constant-string-hash

Here is the actual code from the blog:

#include <string.h>
#include <stdint.h>
#include <stdio.h>

#define H1(s,i,x)   (x*65599u+(uint8_t)s[(i)<strlen(s)?strlen(s)-1-(i):strlen(s)])
#define H4(s,i,x)   H1(s,i,H1(s,i+1,H1(s,i+2,H1(s,i+3,x))))
#define H16(s,i,x)  H4(s,i,H4(s,i+4,H4(s,i+8,H4(s,i+12,x))))
#define H64(s,i,x)  H16(s,i,H16(s,i+16,H16(s,i+32,H16(s,i+48,x))))
#define H256(s,i,x) H64(s,i,H64(s,i+64,H64(s,i+128,H64(s,i+192,x))))

#define HASH(s)    ((uint32_t)(H256(s,0,0)^(H256(s,0,0)>>16)))

If you know ahead of time that you will only use it for static strings you could replace strlen() with sizeof().

michaeljt
  • 1,106
  • 8
  • 17
12

Why not make generating the hash part of your build process? You can write a simple batch file to generate the hash (assuming you have a program to do such a thing - if not, write one) and have it output a preprocessor directive something like:

#define MY_HASH 123456789 

to a .h file that then gets #included in your application.

  • My problem isn't generating a hash, it's finding and replacing these strings with their hashes at compile-time. The only way I can think of doing this is using a pre-processor hack. There are many of these UNIQUE_SALT("Some string", xxx) declarations in the source control. – Ash May 13 '10 at 12:32
  • 2
    @Ashirus Well, I still think the best way to deal with them is to centralise them, and then generate the required definitions somehow. –  May 13 '10 at 12:41
  • A prebuild step is easy! After all, it's just some pattern matching / replace. Any scripting language will allow you do it, and it'll become as transparent as the use of the preprocessor. – Matthieu M. May 13 '10 at 13:57
  • @Neil. They can't be centralised. They are spread all over the source code (which is over 1M LOC and not under my control). Such is the problem space. – Ash May 14 '10 at 10:06
  • @Matthieu: But then I would be require the codebase's 10,000 developers to run a specific extra tool before compilation - it's got to be part of the standard toolchain. – Ash May 14 '10 at 10:08
  • 1
    @All I appreciate these alternative approaches but really, you're asking me to redefine the problem space and assuming I have a level of contorl over the codebase and toolchain that I simply do not have, but thanks anyway. – Ash May 14 '10 at 10:09
12

With C++0x, this is possible as covered by answers in #1 and #2.

In C++03 there was no compile time string processing. With the preprocessor you can't seperate the string into tokens, with templates you can't access single characters. There was however a discussion on the speculated approach using C++0x.

What you could do for C++03 is to pass the string character-wise (possible using multi-character literals):

foo = hash<3DES, str<'a','b','c'> >::result;
// or:
foo = hash<3DES, str<'abc','def'> >::result;

... or simply do it as a pre-build step.

Community
  • 1
  • 1
Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
  • how does "hash<3DES, str<'abc','def'> >::result" work and why can't you do "hash<3DES, str<'verylong string','even longer string'> >::result"? – Ash May 14 '10 at 10:17
  • @Ashirus: These are *multicharacter literals*, have type `int` and *"implementation defined value"*. Longer values simply wouldn't fit into an `int` and you still have to get the seperate character values out manually. – Georg Fritzsche May 14 '10 at 10:31
  • Sorry for stirring up an old post, but yes it is possible in C++. C++0X makes the following method cleaner, but with meta template programming you can do it, albeit, character by character, as in my example below. While, as you pointed out, in C++0x you can process more characters at a time. – leetNightshade Dec 23 '11 at 17:14
  • @leet: What i already said above is that you can't have compile-time processing of strings or string literals, but that you can process lists of characters. That's exactly what you did and my example shows. – Georg Fritzsche Jan 03 '12 at 03:14
  • @Georg Sorry, I misinterpreted your wording, I wasn't being quite so literal; you're right, as far as you can't process a "string", you can only process individual 'c','h','a','r','s'. At the time I was thinking in a general sense, not as a programmer, that it is possible to process strings, you just have to manually break it up for compile time processing. – leetNightshade Jan 04 '12 at 16:17
  • This answer is simply incorrect. Compile-time string literals can be parsed by functions declared constexpr. The trick is that you can't allow them to decay into pointers; you have to keep them as references to arrays of a defined size, which usually means making them template functions so the string size can be deduced. – Ian Ni-Lewis Apr 06 '16 at 19:40
  • @IanNi-Lewis: Have you noticed the date of the answer? Feel free to suggest edits/updates/... instead. – Georg Fritzsche Apr 07 '16 at 09:03
  • @GeorgFritzsche Not sure why the date would matter. Sure, the answer is two years old, but it's four years younger than this thread: http://www.ogre3d.org/forums/viewtopic.php?f=10&t=48471. The links are broken now, but the TL;DR is that you can parse string literals using recursive templates. I posted working code in an answer below. – Ian Ni-Lewis Apr 11 '16 at 13:54
  • @IanNi-Lewis: This discussion was pre-C++0x and is 6 years old. – Georg Fritzsche Apr 12 '16 at 09:30
6

This can be done with Boost.MPL but it might not be the type of hash you are after.

http://arcticinteractive.com/2009/04/18/compile-time-string-hashing-boost-mpl/

Eddy Pronk
  • 6,527
  • 5
  • 33
  • 57
  • Thanks, that about as close as it gets however I guess as per Georg's answer current C++ simply isn't capable. I guess other similar questions here on SO should have alerted me to that. If I could accept two answers I'd accept yours too. – Ash May 14 '10 at 10:15
3

Even if this can't be (reasonably) done with the preprocessor, if you used a string literal or declared it as static const and did not create any lasting references to it the compiler will likely go ahead and do all of the math to generate the result and omit the string in the object file if you compile with optimizations. The hardest part of this is that you can't make the code to initialize a global or static variable too complicated or the compiler will say "hey, you! Don't you know you can't use a for loop outside of a function?".

nategoose
  • 12,054
  • 27
  • 42
  • That's a good point, however I need to be certain that there are no references as there are many declarations and binary size is very important. – Ash May 17 '10 at 11:13
  • 1
    I really don't think your compiler is going to optimise a hash algorithm out of existence even if all the data is const - they are clever but not even nearly that clever. – Elemental May 19 '10 at 16:01
3

I stumbled across a solution using the good 'ol C++ standard (I'm not sure what version it's considered, but let's just say this solution works in Visual Studio). Here's the link: link.

Also, here's a short version of a JSHash function using the above technique. The shown one here supports up to 4 characters, though you can add as many as you want.

template<const char A = 0, const char B = 0, const char C = 0, const char D = 0>
struct cHash
{
    template<const char C, size_t hash = 1315423911>
    struct HashCalc
    {
        enum { value = (C == 0) ? hash : hash ^ ((hash << 5) + C + (hash >> 2)) };
    };

    enum { value = HashCalc<D,HashCalc<C,HashCalc<B,HashCalc<A>::value>::value>::value>::value };
};

As noted, because this is a compile time hash, you can do something like this:

namespace Section
{
    enum Enum
    {
        Player = cHash<'p','l','a','y'>::value
    };
}

It's not the most elegant solution, so I plan on doing more research in this area, however as this is the only thing I've gotten to work in VisualStudio2010 I'm a little limited as far as my current project is concerned.

leetNightshade
  • 2,673
  • 2
  • 36
  • 47
2

Answers claiming that strings cannot be parsed at compile time are wrong. Character pointers can't be parsed at compile time, but string literals are not character pointers; they are arrays of characters whose length is part of the type. It's easy to forget that, because in most cases it's far more useful to let them decay into a char*. But they don't start out that way.

Ah, but how to actually define a function that takes a fixed-length character array, especially if we'd really rather use it on strings of arbitrary length? That's where template argument deduction comes in super handy:

template<size_t L>
constexpr int hash(const char (&str)[L], int n = L - 1) {
    // hash goes here. You can define recursively as a
    // function of str[n] and hash(str, n-1). Remember to
    // treat 0 as a special case.
}

That should get you started. Obviously the hash itself needs to be simple enough for compile-time computation, but that's probably ok.

Ian Ni-Lewis
  • 2,377
  • 20
  • 20
1

This is how I do this compile-time string hash with C++0x:

class StringHash
{
public:
    template <unsigned N, unsigned I>
    struct HashHelper
    {
        constexpr static unsigned Calculate(const char (&str)[N])
        {
            return (HashHelper<N, I - 1>::Calculate(str) ^ (str[I - 1] & 0xFF)) * StringHash::PRIME;
        }
    };

    template <unsigned N>
    struct HashHelper<N, 1>
    {
        constexpr static unsigned Calculate(const char (&str)[N])
        {
            return (StringHash::OFFSET ^ (str[0] & 0xFF)) * StringHash::PRIME;
        }
    };

    template<unsigned N>
    constexpr static unsigned StaticHash(const char (&str)[N])
    {
        return HashHelper<N, N>::Calculate(str);
    }

    static const unsigned OFFSET = 0x01234567;
    static const unsigned PRIME = 0x89ABCDEF;
}

Usage:

static hash = StringHash::StaticHash("Hello"); // You may even use this expression in `switch case`
jayatubi
  • 1,972
  • 1
  • 21
  • 51
0

The answer from michaeljt didn't work for me, I was getting:

Error C2131 expression did not evaluate to a constant

Instead I came up with this, it works for me (up to length of 254, only constant char arrays):

#define CT 65599u
#define H2(s) (CT * s[0] + s[1])
#define H4(s) (CT * (CT * H2(s) + s[2]) + s[3])
#define H6(s) (CT * (CT * H4(s) + s[4]) + s[5])
#define H8(s) (CT * (CT * H6(s) + s[6]) + s[7])
#define H10(s) (CT * (CT * H8(s) + s[8]) + s[9])
#define H12(s) (CT * (CT * H10(s) + s[10]) + s[11])
#define H14(s) (CT * (CT * H12(s) + s[12]) + s[13])
#define H16(s) (CT * (CT * H14(s) + s[14]) + s[15])
#define H18(s) (CT * (CT * H16(s) + s[16]) + s[17])
#define H20(s) (CT * (CT * H18(s) + s[18]) + s[19])
#define H22(s) (CT * (CT * H20(s) + s[20]) + s[21])
#define H24(s) (CT * (CT * H22(s) + s[22]) + s[23])
#define H26(s) (CT * (CT * H24(s) + s[24]) + s[25])
#define H28(s) (CT * (CT * H26(s) + s[26]) + s[27])
#define H30(s) (CT * (CT * H28(s) + s[28]) + s[29])
#define H32(s) (CT * (CT * H30(s) + s[30]) + s[31])
#define H34(s) (CT * (CT * H32(s) + s[32]) + s[33])
#define H36(s) (CT * (CT * H34(s) + s[34]) + s[35])
#define H38(s) (CT * (CT * H36(s) + s[36]) + s[37])
#define H40(s) (CT * (CT * H38(s) + s[38]) + s[39])
#define H42(s) (CT * (CT * H40(s) + s[40]) + s[41])
#define H44(s) (CT * (CT * H42(s) + s[42]) + s[43])
#define H46(s) (CT * (CT * H44(s) + s[44]) + s[45])
#define H48(s) (CT * (CT * H46(s) + s[46]) + s[47])
#define H50(s) (CT * (CT * H48(s) + s[48]) + s[49])
#define H52(s) (CT * (CT * H50(s) + s[50]) + s[51])
#define H54(s) (CT * (CT * H52(s) + s[52]) + s[53])
#define H56(s) (CT * (CT * H54(s) + s[54]) + s[55])
#define H58(s) (CT * (CT * H56(s) + s[56]) + s[57])
#define H60(s) (CT * (CT * H58(s) + s[58]) + s[59])
#define H62(s) (CT * (CT * H60(s) + s[60]) + s[61])
#define H64(s) (CT * (CT * H62(s) + s[62]) + s[63])
#define H66(s) (CT * (CT * H64(s) + s[64]) + s[65])
#define H68(s) (CT * (CT * H66(s) + s[66]) + s[67])
#define H70(s) (CT * (CT * H68(s) + s[68]) + s[69])
#define H72(s) (CT * (CT * H70(s) + s[70]) + s[71])
#define H74(s) (CT * (CT * H72(s) + s[72]) + s[73])
#define H76(s) (CT * (CT * H74(s) + s[74]) + s[75])
#define H78(s) (CT * (CT * H76(s) + s[76]) + s[77])
#define H80(s) (CT * (CT * H78(s) + s[78]) + s[79])
#define H82(s) (CT * (CT * H80(s) + s[80]) + s[81])
#define H84(s) (CT * (CT * H82(s) + s[82]) + s[83])
#define H86(s) (CT * (CT * H84(s) + s[84]) + s[85])
#define H88(s) (CT * (CT * H86(s) + s[86]) + s[87])
#define H90(s) (CT * (CT * H88(s) + s[88]) + s[89])
#define H92(s) (CT * (CT * H90(s) + s[90]) + s[91])
#define H94(s) (CT * (CT * H92(s) + s[92]) + s[93])
#define H96(s) (CT * (CT * H94(s) + s[94]) + s[95])
#define H98(s) (CT * (CT * H96(s) + s[96]) + s[97])
#define H100(s) (CT * (CT * H98(s) + s[98]) + s[99])
#define H102(s) (CT * (CT * H100(s) + s[100]) + s[101])
#define H104(s) (CT * (CT * H102(s) + s[102]) + s[103])
#define H106(s) (CT * (CT * H104(s) + s[104]) + s[105])
#define H108(s) (CT * (CT * H106(s) + s[106]) + s[107])
#define H110(s) (CT * (CT * H108(s) + s[108]) + s[109])
#define H112(s) (CT * (CT * H110(s) + s[110]) + s[111])
#define H114(s) (CT * (CT * H112(s) + s[112]) + s[113])
#define H116(s) (CT * (CT * H114(s) + s[114]) + s[115])
#define H118(s) (CT * (CT * H116(s) + s[116]) + s[117])
#define H120(s) (CT * (CT * H118(s) + s[118]) + s[119])
#define H122(s) (CT * (CT * H120(s) + s[120]) + s[121])
#define H124(s) (CT * (CT * H122(s) + s[122]) + s[123])
#define H126(s) (CT * (CT * H124(s) + s[124]) + s[125])
#define H128(s) (CT * (CT * H126(s) + s[126]) + s[127])
#define H130(s) (CT * (CT * H128(s) + s[128]) + s[129])
#define H132(s) (CT * (CT * H130(s) + s[130]) + s[131])
#define H134(s) (CT * (CT * H132(s) + s[132]) + s[133])
#define H136(s) (CT * (CT * H134(s) + s[134]) + s[135])
#define H138(s) (CT * (CT * H136(s) + s[136]) + s[137])
#define H140(s) (CT * (CT * H138(s) + s[138]) + s[139])
#define H142(s) (CT * (CT * H140(s) + s[140]) + s[141])
#define H144(s) (CT * (CT * H142(s) + s[142]) + s[143])
#define H146(s) (CT * (CT * H144(s) + s[144]) + s[145])
#define H148(s) (CT * (CT * H146(s) + s[146]) + s[147])
#define H150(s) (CT * (CT * H148(s) + s[148]) + s[149])
#define H152(s) (CT * (CT * H150(s) + s[150]) + s[151])
#define H154(s) (CT * (CT * H152(s) + s[152]) + s[153])
#define H156(s) (CT * (CT * H154(s) + s[154]) + s[155])
#define H158(s) (CT * (CT * H156(s) + s[156]) + s[157])
#define H160(s) (CT * (CT * H158(s) + s[158]) + s[159])
#define H162(s) (CT * (CT * H160(s) + s[160]) + s[161])
#define H164(s) (CT * (CT * H162(s) + s[162]) + s[163])
#define H166(s) (CT * (CT * H164(s) + s[164]) + s[165])
#define H168(s) (CT * (CT * H166(s) + s[166]) + s[167])
#define H170(s) (CT * (CT * H168(s) + s[168]) + s[169])
#define H172(s) (CT * (CT * H170(s) + s[170]) + s[171])
#define H174(s) (CT * (CT * H172(s) + s[172]) + s[173])
#define H176(s) (CT * (CT * H174(s) + s[174]) + s[175])
#define H178(s) (CT * (CT * H176(s) + s[176]) + s[177])
#define H180(s) (CT * (CT * H178(s) + s[178]) + s[179])
#define H182(s) (CT * (CT * H180(s) + s[180]) + s[181])
#define H184(s) (CT * (CT * H182(s) + s[182]) + s[183])
#define H186(s) (CT * (CT * H184(s) + s[184]) + s[185])
#define H188(s) (CT * (CT * H186(s) + s[186]) + s[187])
#define H190(s) (CT * (CT * H188(s) + s[188]) + s[189])
#define H192(s) (CT * (CT * H190(s) + s[190]) + s[191])
#define H194(s) (CT * (CT * H192(s) + s[192]) + s[193])
#define H196(s) (CT * (CT * H194(s) + s[194]) + s[195])
#define H198(s) (CT * (CT * H196(s) + s[196]) + s[197])
#define H200(s) (CT * (CT * H198(s) + s[198]) + s[199])
#define H202(s) (CT * (CT * H200(s) + s[200]) + s[201])
#define H204(s) (CT * (CT * H202(s) + s[202]) + s[203])
#define H206(s) (CT * (CT * H204(s) + s[204]) + s[205])
#define H208(s) (CT * (CT * H206(s) + s[206]) + s[207])
#define H210(s) (CT * (CT * H208(s) + s[208]) + s[209])
#define H212(s) (CT * (CT * H210(s) + s[210]) + s[211])
#define H214(s) (CT * (CT * H212(s) + s[212]) + s[213])
#define H216(s) (CT * (CT * H214(s) + s[214]) + s[215])
#define H218(s) (CT * (CT * H216(s) + s[216]) + s[217])
#define H220(s) (CT * (CT * H218(s) + s[218]) + s[219])
#define H222(s) (CT * (CT * H220(s) + s[220]) + s[221])
#define H224(s) (CT * (CT * H222(s) + s[222]) + s[223])
#define H226(s) (CT * (CT * H224(s) + s[224]) + s[225])
#define H228(s) (CT * (CT * H226(s) + s[226]) + s[227])
#define H230(s) (CT * (CT * H228(s) + s[228]) + s[229])
#define H232(s) (CT * (CT * H230(s) + s[230]) + s[231])
#define H234(s) (CT * (CT * H232(s) + s[232]) + s[233])
#define H236(s) (CT * (CT * H234(s) + s[234]) + s[235])
#define H238(s) (CT * (CT * H236(s) + s[236]) + s[237])
#define H240(s) (CT * (CT * H238(s) + s[238]) + s[239])
#define H242(s) (CT * (CT * H240(s) + s[240]) + s[241])
#define H244(s) (CT * (CT * H242(s) + s[242]) + s[243])
#define H246(s) (CT * (CT * H244(s) + s[244]) + s[245])
#define H248(s) (CT * (CT * H246(s) + s[246]) + s[247])
#define H250(s) (CT * (CT * H248(s) + s[248]) + s[249])
#define H252(s) (CT * (CT * H250(s) + s[250]) + s[251])
#define H254(s) (CT * (CT * H252(s) + s[252]) + s[253])
#define STRHASH(s) ((unsigned int)\
( \
sizeof(s) == 1 ? s[0] \
: sizeof(s) == 2 ? H2(s) \
: sizeof(s) == 3 ? (CT * H2(s) + s[2]) \
: sizeof(s) == 4 ? H4(s) \
: sizeof(s) == 5 ? (CT * H4(s) + s[4]) \
: sizeof(s) == 6 ? H6(s) \
: sizeof(s) == 7 ? (CT * H6(s) + s[6]) \
: sizeof(s) == 8 ? H8(s) \
: sizeof(s) == 9 ? (CT * H8(s) + s[8]) \
: sizeof(s) == 10 ? H10(s) \
: sizeof(s) == 11 ? (CT * H10(s) + s[10]) \
: sizeof(s) == 12 ? H12(s) \
: sizeof(s) == 13 ? (CT * H12(s) + s[12]) \
: sizeof(s) == 14 ? H14(s) \
: sizeof(s) == 15 ? (CT * H14(s) + s[14]) \
: sizeof(s) == 16 ? H16(s) \
: sizeof(s) == 17 ? (CT * H16(s) + s[16]) \
: sizeof(s) == 18 ? H18(s) \
: sizeof(s) == 19 ? (CT * H18(s) + s[18]) \
: sizeof(s) == 20 ? H20(s) \
: sizeof(s) == 21 ? (CT * H20(s) + s[20]) \
: sizeof(s) == 22 ? H22(s) \
: sizeof(s) == 23 ? (CT * H22(s) + s[22]) \
: sizeof(s) == 24 ? H24(s) \
: sizeof(s) == 25 ? (CT * H24(s) + s[24]) \
: sizeof(s) == 26 ? H26(s) \
: sizeof(s) == 27 ? (CT * H26(s) + s[26]) \
: sizeof(s) == 28 ? H28(s) \
: sizeof(s) == 29 ? (CT * H28(s) + s[28]) \
: sizeof(s) == 30 ? H30(s) \
: sizeof(s) == 31 ? (CT * H30(s) + s[30]) \
: sizeof(s) == 32 ? H32(s) \
: sizeof(s) == 33 ? (CT * H32(s) + s[32]) \
: sizeof(s) == 34 ? H34(s) \
: sizeof(s) == 35 ? (CT * H34(s) + s[34]) \
: sizeof(s) == 36 ? H36(s) \
: sizeof(s) == 37 ? (CT * H36(s) + s[36]) \
: sizeof(s) == 38 ? H38(s) \
: sizeof(s) == 39 ? (CT * H38(s) + s[38]) \
: sizeof(s) == 40 ? H40(s) \
: sizeof(s) == 41 ? (CT * H40(s) + s[40]) \
: sizeof(s) == 42 ? H42(s) \
: sizeof(s) == 43 ? (CT * H42(s) + s[42]) \
: sizeof(s) == 44 ? H44(s) \
: sizeof(s) == 45 ? (CT * H44(s) + s[44]) \
: sizeof(s) == 46 ? H46(s) \
: sizeof(s) == 47 ? (CT * H46(s) + s[46]) \
: sizeof(s) == 48 ? H48(s) \
: sizeof(s) == 49 ? (CT * H48(s) + s[48]) \
: sizeof(s) == 50 ? H50(s) \
: sizeof(s) == 51 ? (CT * H50(s) + s[50]) \
: sizeof(s) == 52 ? H52(s) \
: sizeof(s) == 53 ? (CT * H52(s) + s[52]) \
: sizeof(s) == 54 ? H54(s) \
: sizeof(s) == 55 ? (CT * H54(s) + s[54]) \
: sizeof(s) == 56 ? H56(s) \
: sizeof(s) == 57 ? (CT * H56(s) + s[56]) \
: sizeof(s) == 58 ? H58(s) \
: sizeof(s) == 59 ? (CT * H58(s) + s[58]) \
: sizeof(s) == 60 ? H60(s) \
: sizeof(s) == 61 ? (CT * H60(s) + s[60]) \
: sizeof(s) == 62 ? H62(s) \
: sizeof(s) == 63 ? (CT * H62(s) + s[62]) \
: sizeof(s) == 64 ? H64(s) \
: sizeof(s) == 65 ? (CT * H64(s) + s[64]) \
: sizeof(s) == 66 ? H66(s) \
: sizeof(s) == 67 ? (CT * H66(s) + s[66]) \
: sizeof(s) == 68 ? H68(s) \
: sizeof(s) == 69 ? (CT * H68(s) + s[68]) \
: sizeof(s) == 70 ? H70(s) \
: sizeof(s) == 71 ? (CT * H70(s) + s[70]) \
: sizeof(s) == 72 ? H72(s) \
: sizeof(s) == 73 ? (CT * H72(s) + s[72]) \
: sizeof(s) == 74 ? H74(s) \
: sizeof(s) == 75 ? (CT * H74(s) + s[74]) \
: sizeof(s) == 76 ? H76(s) \
: sizeof(s) == 77 ? (CT * H76(s) + s[76]) \
: sizeof(s) == 78 ? H78(s) \
: sizeof(s) == 79 ? (CT * H78(s) + s[78]) \
: sizeof(s) == 80 ? H80(s) \
: sizeof(s) == 81 ? (CT * H80(s) + s[80]) \
: sizeof(s) == 82 ? H82(s) \
: sizeof(s) == 83 ? (CT * H82(s) + s[82]) \
: sizeof(s) == 84 ? H84(s) \
: sizeof(s) == 85 ? (CT * H84(s) + s[84]) \
: sizeof(s) == 86 ? H86(s) \
: sizeof(s) == 87 ? (CT * H86(s) + s[86]) \
: sizeof(s) == 88 ? H88(s) \
: sizeof(s) == 89 ? (CT * H88(s) + s[88]) \
: sizeof(s) == 90 ? H90(s) \
: sizeof(s) == 91 ? (CT * H90(s) + s[90]) \
: sizeof(s) == 92 ? H92(s) \
: sizeof(s) == 93 ? (CT * H92(s) + s[92]) \
: sizeof(s) == 94 ? H94(s) \
: sizeof(s) == 95 ? (CT * H94(s) + s[94]) \
: sizeof(s) == 96 ? H96(s) \
: sizeof(s) == 97 ? (CT * H96(s) + s[96]) \
: sizeof(s) == 98 ? H98(s) \
: sizeof(s) == 99 ? (CT * H98(s) + s[98]) \
: sizeof(s) == 100 ? H100(s) \
: sizeof(s) == 101 ? (CT * H100(s) + s[100]) \
: sizeof(s) == 102 ? H102(s) \
: sizeof(s) == 103 ? (CT * H102(s) + s[102]) \
: sizeof(s) == 104 ? H104(s) \
: sizeof(s) == 105 ? (CT * H104(s) + s[104]) \
: sizeof(s) == 106 ? H106(s) \
: sizeof(s) == 107 ? (CT * H106(s) + s[106]) \
: sizeof(s) == 108 ? H108(s) \
: sizeof(s) == 109 ? (CT * H108(s) + s[108]) \
: sizeof(s) == 110 ? H110(s) \
: sizeof(s) == 111 ? (CT * H110(s) + s[110]) \
: sizeof(s) == 112 ? H112(s) \
: sizeof(s) == 113 ? (CT * H112(s) + s[112]) \
: sizeof(s) == 114 ? H114(s) \
: sizeof(s) == 115 ? (CT * H114(s) + s[114]) \
: sizeof(s) == 116 ? H116(s) \
: sizeof(s) == 117 ? (CT * H116(s) + s[116]) \
: sizeof(s) == 118 ? H118(s) \
: sizeof(s) == 119 ? (CT * H118(s) + s[118]) \
: sizeof(s) == 120 ? H120(s) \
: sizeof(s) == 121 ? (CT * H120(s) + s[120]) \
: sizeof(s) == 122 ? H122(s) \
: sizeof(s) == 123 ? (CT * H122(s) + s[122]) \
: sizeof(s) == 124 ? H124(s) \
: sizeof(s) == 125 ? (CT * H124(s) + s[124]) \
: sizeof(s) == 126 ? H126(s) \
: sizeof(s) == 127 ? (CT * H126(s) + s[126]) \
: sizeof(s) == 128 ? H128(s) \
: sizeof(s) == 129 ? (CT * H128(s) + s[128]) \
: sizeof(s) == 130 ? H130(s) \
: sizeof(s) == 131 ? (CT * H130(s) + s[130]) \
: sizeof(s) == 132 ? H132(s) \
: sizeof(s) == 133 ? (CT * H132(s) + s[132]) \
: sizeof(s) == 134 ? H134(s) \
: sizeof(s) == 135 ? (CT * H134(s) + s[134]) \
: sizeof(s) == 136 ? H136(s) \
: sizeof(s) == 137 ? (CT * H136(s) + s[136]) \
: sizeof(s) == 138 ? H138(s) \
: sizeof(s) == 139 ? (CT * H138(s) + s[138]) \
: sizeof(s) == 140 ? H140(s) \
: sizeof(s) == 141 ? (CT * H140(s) + s[140]) \
: sizeof(s) == 142 ? H142(s) \
: sizeof(s) == 143 ? (CT * H142(s) + s[142]) \
: sizeof(s) == 144 ? H144(s) \
: sizeof(s) == 145 ? (CT * H144(s) + s[144]) \
: sizeof(s) == 146 ? H146(s) \
: sizeof(s) == 147 ? (CT * H146(s) + s[146]) \
: sizeof(s) == 148 ? H148(s) \
: sizeof(s) == 149 ? (CT * H148(s) + s[148]) \
: sizeof(s) == 150 ? H150(s) \
: sizeof(s) == 151 ? (CT * H150(s) + s[150]) \
: sizeof(s) == 152 ? H152(s) \
: sizeof(s) == 153 ? (CT * H152(s) + s[152]) \
: sizeof(s) == 154 ? H154(s) \
: sizeof(s) == 155 ? (CT * H154(s) + s[154]) \
: sizeof(s) == 156 ? H156(s) \
: sizeof(s) == 157 ? (CT * H156(s) + s[156]) \
: sizeof(s) == 158 ? H158(s) \
: sizeof(s) == 159 ? (CT * H158(s) + s[158]) \
: sizeof(s) == 160 ? H160(s) \
: sizeof(s) == 161 ? (CT * H160(s) + s[160]) \
: sizeof(s) == 162 ? H162(s) \
: sizeof(s) == 163 ? (CT * H162(s) + s[162]) \
: sizeof(s) == 164 ? H164(s) \
: sizeof(s) == 165 ? (CT * H164(s) + s[164]) \
: sizeof(s) == 166 ? H166(s) \
: sizeof(s) == 167 ? (CT * H166(s) + s[166]) \
: sizeof(s) == 168 ? H168(s) \
: sizeof(s) == 169 ? (CT * H168(s) + s[168]) \
: sizeof(s) == 170 ? H170(s) \
: sizeof(s) == 171 ? (CT * H170(s) + s[170]) \
: sizeof(s) == 172 ? H172(s) \
: sizeof(s) == 173 ? (CT * H172(s) + s[172]) \
: sizeof(s) == 174 ? H174(s) \
: sizeof(s) == 175 ? (CT * H174(s) + s[174]) \
: sizeof(s) == 176 ? H176(s) \
: sizeof(s) == 177 ? (CT * H176(s) + s[176]) \
: sizeof(s) == 178 ? H178(s) \
: sizeof(s) == 179 ? (CT * H178(s) + s[178]) \
: sizeof(s) == 180 ? H180(s) \
: sizeof(s) == 181 ? (CT * H180(s) + s[180]) \
: sizeof(s) == 182 ? H182(s) \
: sizeof(s) == 183 ? (CT * H182(s) + s[182]) \
: sizeof(s) == 184 ? H184(s) \
: sizeof(s) == 185 ? (CT * H184(s) + s[184]) \
: sizeof(s) == 186 ? H186(s) \
: sizeof(s) == 187 ? (CT * H186(s) + s[186]) \
: sizeof(s) == 188 ? H188(s) \
: sizeof(s) == 189 ? (CT * H188(s) + s[188]) \
: sizeof(s) == 190 ? H190(s) \
: sizeof(s) == 191 ? (CT * H190(s) + s[190]) \
: sizeof(s) == 192 ? H192(s) \
: sizeof(s) == 193 ? (CT * H192(s) + s[192]) \
: sizeof(s) == 194 ? H194(s) \
: sizeof(s) == 195 ? (CT * H194(s) + s[194]) \
: sizeof(s) == 196 ? H196(s) \
: sizeof(s) == 197 ? (CT * H196(s) + s[196]) \
: sizeof(s) == 198 ? H198(s) \
: sizeof(s) == 199 ? (CT * H198(s) + s[198]) \
: sizeof(s) == 200 ? H200(s) \
: sizeof(s) == 201 ? (CT * H200(s) + s[200]) \
: sizeof(s) == 202 ? H202(s) \
: sizeof(s) == 203 ? (CT * H202(s) + s[202]) \
: sizeof(s) == 204 ? H204(s) \
: sizeof(s) == 205 ? (CT * H204(s) + s[204]) \
: sizeof(s) == 206 ? H206(s) \
: sizeof(s) == 207 ? (CT * H206(s) + s[206]) \
: sizeof(s) == 208 ? H208(s) \
: sizeof(s) == 209 ? (CT * H208(s) + s[208]) \
: sizeof(s) == 210 ? H210(s) \
: sizeof(s) == 211 ? (CT * H210(s) + s[210]) \
: sizeof(s) == 212 ? H212(s) \
: sizeof(s) == 213 ? (CT * H212(s) + s[212]) \
: sizeof(s) == 214 ? H214(s) \
: sizeof(s) == 215 ? (CT * H214(s) + s[214]) \
: sizeof(s) == 216 ? H216(s) \
: sizeof(s) == 217 ? (CT * H216(s) + s[216]) \
: sizeof(s) == 218 ? H218(s) \
: sizeof(s) == 219 ? (CT * H218(s) + s[218]) \
: sizeof(s) == 220 ? H220(s) \
: sizeof(s) == 221 ? (CT * H220(s) + s[220]) \
: sizeof(s) == 222 ? H222(s) \
: sizeof(s) == 223 ? (CT * H222(s) + s[222]) \
: sizeof(s) == 224 ? H224(s) \
: sizeof(s) == 225 ? (CT * H224(s) + s[224]) \
: sizeof(s) == 226 ? H226(s) \
: sizeof(s) == 227 ? (CT * H226(s) + s[226]) \
: sizeof(s) == 228 ? H228(s) \
: sizeof(s) == 229 ? (CT * H228(s) + s[228]) \
: sizeof(s) == 230 ? H230(s) \
: sizeof(s) == 231 ? (CT * H230(s) + s[230]) \
: sizeof(s) == 232 ? H232(s) \
: sizeof(s) == 233 ? (CT * H232(s) + s[232]) \
: sizeof(s) == 234 ? H234(s) \
: sizeof(s) == 235 ? (CT * H234(s) + s[234]) \
: sizeof(s) == 236 ? H236(s) \
: sizeof(s) == 237 ? (CT * H236(s) + s[236]) \
: sizeof(s) == 238 ? H238(s) \
: sizeof(s) == 239 ? (CT * H238(s) + s[238]) \
: sizeof(s) == 240 ? H240(s) \
: sizeof(s) == 241 ? (CT * H240(s) + s[240]) \
: sizeof(s) == 242 ? H242(s) \
: sizeof(s) == 243 ? (CT * H242(s) + s[242]) \
: sizeof(s) == 244 ? H244(s) \
: sizeof(s) == 245 ? (CT * H244(s) + s[244]) \
: sizeof(s) == 246 ? H246(s) \
: sizeof(s) == 247 ? (CT * H246(s) + s[246]) \
: sizeof(s) == 248 ? H248(s) \
: sizeof(s) == 249 ? (CT * H248(s) + s[248]) \
: sizeof(s) == 250 ? H250(s) \
: sizeof(s) == 251 ? (CT * H250(s) + s[250]) \
: sizeof(s) == 252 ? H252(s) \
: sizeof(s) == 253 ? (CT * H252(s) + s[252]) \
: sizeof(s) == 254 ? H254(s) \
: -1 \
))