yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
17.8 KiB620 linesraw
1/*
2 * MD5 implementation is based on:
3 * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
4 * Original file header is at the bottom of this file.
5 *
6 * SHA1 implementation is based on:
7 * https://github.com/983/SHA1
8 * Original LICENSE is at the bottom of this file.
9 */
10
11#include "slang-crypto.h"
12
13#include "../core/slang-char-util.h"
14
15namespace Slang
16{
17
18// DigestUtil
19
20/*static*/ String DigestUtil::digestToString(const void* digest, SlangInt digestSize)
21{
22    SLANG_ASSERT(digest && digestSize >= 0);
23
24    static const char* hex = "0123456789abcdef";
25
26    String str;
27    const uint8_t* data = reinterpret_cast<const uint8_t*>(digest);
28    for (SlangInt i = 0; i < digestSize; ++i)
29    {
30        str.append(hex[data[i] >> 4]);
31        str.append(hex[data[i] & 0xf]);
32    }
33    return str;
34}
35
36/*static*/ bool DigestUtil::stringToDigest(
37    const char* str,
38    SlangInt strLength,
39    void* digest,
40    SlangInt digestSize)
41{
42    SLANG_ASSERT(str && strLength >= 0 && digest && digestSize >= 0);
43
44    if (strLength != digestSize * 2)
45    {
46        ::memset(digest, 0, digestSize);
47        return false;
48    }
49
50    uint8_t* data = reinterpret_cast<uint8_t*>(digest);
51    for (SlangInt i = 0; i < digestSize; ++i)
52    {
53        int upper = CharUtil::getHexDigitValue(str[i * 2]);
54        int lower = CharUtil::getHexDigitValue(str[i * 2 + 1]);
55        if (upper == -1 || lower == -1)
56        {
57            ::memset(digest, 0, digestSize);
58            return false;
59        }
60        data[i] = uint8_t(lower | upper << 4);
61        ;
62    }
63
64    return true;
65}
66
67// MD5
68
69MD5::MD5()
70{
71    init();
72}
73
74void MD5::init()
75{
76    m_lo = 0;
77    m_hi = 0;
78    m_a = 0x67452301;
79    m_b = 0xefcdab89;
80    m_c = 0x98badcfe;
81    m_d = 0x10325476;
82}
83
84void MD5::update(const void* data, SlangSizeT size)
85{
86    uint32_t saved_lo;
87    uint32_t used;
88    uint32_t available;
89
90    saved_lo = m_lo;
91    if ((m_lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
92    {
93        m_hi++;
94    }
95    m_hi += (uint32_t)size >> 29;
96
97    used = saved_lo & 0x3f;
98
99    if (used)
100    {
101        available = 64 - used;
102
103        if (size < available)
104        {
105            ::memcpy(&m_buffer[used], data, size);
106            return;
107        }
108
109        ::memcpy(&m_buffer[used], data, available);
110        data = reinterpret_cast<const uint8_t*>(data) + available;
111        size -= available;
112        processBlock(m_buffer, 64);
113    }
114
115    if (size >= 64)
116    {
117        data = processBlock(data, size & ~(SlangInt)0x3f);
118        size &= 0x3f;
119    }
120
121    ::memcpy(m_buffer, data, size);
122}
123
124MD5::Digest MD5::finalize()
125{
126    uint32_t used, available;
127
128    used = m_lo & 0x3f;
129
130    m_buffer[used++] = 0x80;
131
132    available = 64 - used;
133
134    if (available < 8)
135    {
136        ::memset(&m_buffer[used], 0, available);
137        processBlock(m_buffer, 64);
138        used = 0;
139        available = 64;
140    }
141
142    ::memset(&m_buffer[used], 0, available - 8);
143
144    m_lo <<= 3;
145
146    m_buffer[56] = uint8_t(m_lo);
147    m_buffer[57] = uint8_t(m_lo >> 8);
148    m_buffer[58] = uint8_t(m_lo >> 16);
149    m_buffer[59] = uint8_t(m_lo >> 24);
150    m_buffer[60] = uint8_t(m_hi);
151    m_buffer[61] = uint8_t(m_hi >> 8);
152    m_buffer[62] = uint8_t(m_hi >> 16);
153    m_buffer[63] = uint8_t(m_hi >> 24);
154
155    processBlock(m_buffer, 64);
156
157    Digest digest;
158    digest.data[0] = m_a;
159    digest.data[1] = m_b;
160    digest.data[2] = m_c;
161    digest.data[3] = m_d;
162
163    return digest;
164}
165
166/*
167 * The basic MD5 functions.
168 *
169 * F and G are optimized compared to their RFC 1321 definitions for
170 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
171 * implementation.
172 */
173#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
174#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
175#define H(x, y, z) (((x) ^ (y)) ^ (z))
176#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
177#define I(x, y, z) ((y) ^ ((x) | ~(z)))
178
179/*
180 * The MD5 transformation for all four rounds.
181 */
182#define STEP(f, a, b, c, d, x, t, s)                           \
183    (a) += f((b), (c), (d)) + (x) + (t);                       \
184    (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
185    (a) += (b);
186
187/*
188 * SET reads 4 input bytes in little-endian byte order and stores them in a
189 * properly aligned word in host byte order.
190 */
191#define SET(n)                                                                   \
192    (m_block[(n)] = (uint32_t)ptr[(n) * 4] | ((uint32_t)ptr[(n) * 4 + 1] << 8) | \
193                    ((uint32_t)ptr[(n) * 4 + 2] << 16) | ((uint32_t)ptr[(n) * 4 + 3] << 24))
194#define GET(n) (m_block[(n)])
195
196const void* MD5::processBlock(const void* data, SlangInt size)
197{
198    const unsigned char* ptr;
199    ptr = (const unsigned char*)data;
200
201    uint32_t a = m_a;
202    uint32_t b = m_b;
203    uint32_t c = m_c;
204    uint32_t d = m_d;
205
206    do
207    {
208        uint32_t saved_a = a;
209        uint32_t saved_b = b;
210        uint32_t saved_c = c;
211        uint32_t saved_d = d;
212
213        /* Round 1 */
214        STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
215        STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
216        STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
217        STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
218        STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
219        STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
220        STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
221        STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
222        STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
223        STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
224        STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
225        STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
226        STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
227        STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
228        STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
229        STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
230
231        /* Round 2 */
232        STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
233        STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
234        STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
235        STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
236        STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
237        STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
238        STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
239        STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
240        STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
241        STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
242        STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
243        STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
244        STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
245        STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
246        STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
247        STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
248
249        /* Round 3 */
250        STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
251        STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
252        STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
253        STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
254        STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
255        STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
256        STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
257        STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
258        STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
259        STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
260        STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
261        STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
262        STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
263        STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
264        STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
265        STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
266
267        /* Round 4 */
268        STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
269        STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
270        STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
271        STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
272        STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
273        STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
274        STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
275        STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
276        STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
277        STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
278        STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
279        STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
280        STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
281        STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
282        STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
283        STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
284
285        a += saved_a;
286        b += saved_b;
287        c += saved_c;
288        d += saved_d;
289
290        ptr += 64;
291    } while (size -= 64);
292
293    m_a = a;
294    m_b = b;
295    m_c = c;
296    m_d = d;
297
298    return ptr;
299}
300
301#undef F
302#undef G
303#undef H
304#undef H2
305#undef I
306#undef STEP
307#undef SET
308#undef GET
309
310/*static*/ MD5::Digest MD5::compute(const void* data, SlangInt size)
311{
312    MD5 md5;
313    md5.update(data, size);
314    return md5.finalize();
315}
316
317// SHA1
318
319SHA1::SHA1()
320{
321    init();
322}
323
324void SHA1::init()
325{
326    m_index = 0;
327    m_bits = 0;
328    m_state[0] = 0x67452301;
329    m_state[1] = 0xefcdab89;
330    m_state[2] = 0x98badcfe;
331    m_state[3] = 0x10325476;
332    m_state[4] = 0xc3d2e1f0;
333}
334
335void SHA1::update(const void* data, SlangSizeT len)
336{
337    if (!data || len <= 0)
338    {
339        return;
340    }
341
342    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
343
344    // Fill up buffer if not full.
345    while (len > 0 && m_index != 0)
346    {
347        addByte(*ptr++);
348        m_bits += 8;
349        len--;
350    }
351
352    // Process full blocks.
353    while (len >= sizeof(m_buf))
354    {
355        processBlock(ptr);
356        ptr += sizeof(m_buf);
357        len -= sizeof(m_buf);
358        m_bits += sizeof(m_buf) * 8;
359    }
360
361    // Process remaining bytes.
362    while (len > 0)
363    {
364        addByte(*ptr++);
365        m_bits += 8;
366        len--;
367    }
368}
369
370SHA1::Digest SHA1::finalize()
371{
372    // Finalize with 0x80, some zero padding and the length in bits.
373    addByte(0x80);
374    while (m_index % 64 != 56)
375    {
376        addByte(0);
377    }
378    for (int i = 7; i >= 0; --i)
379    {
380        addByte(uint8_t(m_bits >> i * 8));
381    }
382
383    Digest digest;
384    uint8_t* data = reinterpret_cast<uint8_t*>(digest.data);
385    for (int i = 0; i < 5; i++)
386    {
387        for (int j = 3; j >= 0; j--)
388        {
389            data[i * 4 + j] = (m_state[i] >> ((3 - j) * 8)) & 0xff;
390        }
391    }
392
393    return digest;
394}
395
396void SHA1::addByte(uint8_t byte)
397{
398    m_buf[m_index++] = byte;
399
400    if (m_index >= sizeof(m_buf))
401    {
402        m_index = 0;
403        processBlock(m_buf);
404    }
405}
406
407void SHA1::processBlock(const uint8_t* ptr)
408{
409    auto rol32 = [](uint32_t x, uint32_t n) { return (x << n) | (x >> (32 - n)); };
410
411    auto makeWord = [](const uint8_t* p)
412    {
413        return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) |
414               (uint32_t)p[3];
415    };
416
417    const uint32_t c0 = 0x5a827999;
418    const uint32_t c1 = 0x6ed9eba1;
419    const uint32_t c2 = 0x8f1bbcdc;
420    const uint32_t c3 = 0xca62c1d6;
421
422    uint32_t a = m_state[0];
423    uint32_t b = m_state[1];
424    uint32_t c = m_state[2];
425    uint32_t d = m_state[3];
426    uint32_t e = m_state[4];
427
428    uint32_t w[16];
429
430    for (size_t i = 0; i < 16; i++)
431    {
432        w[i] = makeWord(ptr + i * 4);
433    }
434
435#define SHA1_LOAD(i) \
436    w[i & 15] = rol32(w[(i + 13) & 15] ^ w[(i + 8) & 15] ^ w[(i + 2) & 15] ^ w[i & 15], 1);
437#define SHA1_ROUND_0(v, u, x, y, z, i)                       \
438    z += ((u & (x ^ y)) ^ y) + w[i & 15] + c0 + rol32(v, 5); \
439    u = rol32(u, 30);
440#define SHA1_ROUND_1(v, u, x, y, z, i)                                    \
441    SHA1_LOAD(i) z += ((u & (x ^ y)) ^ y) + w[i & 15] + c0 + rol32(v, 5); \
442    u = rol32(u, 30);
443#define SHA1_ROUND_2(v, u, x, y, z, i)                            \
444    SHA1_LOAD(i) z += (u ^ x ^ y) + w[i & 15] + c1 + rol32(v, 5); \
445    u = rol32(u, 30);
446#define SHA1_ROUND_3(v, u, x, y, z, i)                                          \
447    SHA1_LOAD(i) z += (((u | x) & y) | (u & x)) + w[i & 15] + c2 + rol32(v, 5); \
448    u = rol32(u, 30);
449#define SHA1_ROUND_4(v, u, x, y, z, i)                            \
450    SHA1_LOAD(i) z += (u ^ x ^ y) + w[i & 15] + c3 + rol32(v, 5); \
451    u = rol32(u, 30);
452
453    SHA1_ROUND_0(a, b, c, d, e, 0);
454    SHA1_ROUND_0(e, a, b, c, d, 1);
455    SHA1_ROUND_0(d, e, a, b, c, 2);
456    SHA1_ROUND_0(c, d, e, a, b, 3);
457    SHA1_ROUND_0(b, c, d, e, a, 4);
458    SHA1_ROUND_0(a, b, c, d, e, 5);
459    SHA1_ROUND_0(e, a, b, c, d, 6);
460    SHA1_ROUND_0(d, e, a, b, c, 7);
461    SHA1_ROUND_0(c, d, e, a, b, 8);
462    SHA1_ROUND_0(b, c, d, e, a, 9);
463    SHA1_ROUND_0(a, b, c, d, e, 10);
464    SHA1_ROUND_0(e, a, b, c, d, 11);
465    SHA1_ROUND_0(d, e, a, b, c, 12);
466    SHA1_ROUND_0(c, d, e, a, b, 13);
467    SHA1_ROUND_0(b, c, d, e, a, 14);
468    SHA1_ROUND_0(a, b, c, d, e, 15);
469    SHA1_ROUND_1(e, a, b, c, d, 16);
470    SHA1_ROUND_1(d, e, a, b, c, 17);
471    SHA1_ROUND_1(c, d, e, a, b, 18);
472    SHA1_ROUND_1(b, c, d, e, a, 19);
473    SHA1_ROUND_2(a, b, c, d, e, 20);
474    SHA1_ROUND_2(e, a, b, c, d, 21);
475    SHA1_ROUND_2(d, e, a, b, c, 22);
476    SHA1_ROUND_2(c, d, e, a, b, 23);
477    SHA1_ROUND_2(b, c, d, e, a, 24);
478    SHA1_ROUND_2(a, b, c, d, e, 25);
479    SHA1_ROUND_2(e, a, b, c, d, 26);
480    SHA1_ROUND_2(d, e, a, b, c, 27);
481    SHA1_ROUND_2(c, d, e, a, b, 28);
482    SHA1_ROUND_2(b, c, d, e, a, 29);
483    SHA1_ROUND_2(a, b, c, d, e, 30);
484    SHA1_ROUND_2(e, a, b, c, d, 31);
485    SHA1_ROUND_2(d, e, a, b, c, 32);
486    SHA1_ROUND_2(c, d, e, a, b, 33);
487    SHA1_ROUND_2(b, c, d, e, a, 34);
488    SHA1_ROUND_2(a, b, c, d, e, 35);
489    SHA1_ROUND_2(e, a, b, c, d, 36);
490    SHA1_ROUND_2(d, e, a, b, c, 37);
491    SHA1_ROUND_2(c, d, e, a, b, 38);
492    SHA1_ROUND_2(b, c, d, e, a, 39);
493    SHA1_ROUND_3(a, b, c, d, e, 40);
494    SHA1_ROUND_3(e, a, b, c, d, 41);
495    SHA1_ROUND_3(d, e, a, b, c, 42);
496    SHA1_ROUND_3(c, d, e, a, b, 43);
497    SHA1_ROUND_3(b, c, d, e, a, 44);
498    SHA1_ROUND_3(a, b, c, d, e, 45);
499    SHA1_ROUND_3(e, a, b, c, d, 46);
500    SHA1_ROUND_3(d, e, a, b, c, 47);
501    SHA1_ROUND_3(c, d, e, a, b, 48);
502    SHA1_ROUND_3(b, c, d, e, a, 49);
503    SHA1_ROUND_3(a, b, c, d, e, 50);
504    SHA1_ROUND_3(e, a, b, c, d, 51);
505    SHA1_ROUND_3(d, e, a, b, c, 52);
506    SHA1_ROUND_3(c, d, e, a, b, 53);
507    SHA1_ROUND_3(b, c, d, e, a, 54);
508    SHA1_ROUND_3(a, b, c, d, e, 55);
509    SHA1_ROUND_3(e, a, b, c, d, 56);
510    SHA1_ROUND_3(d, e, a, b, c, 57);
511    SHA1_ROUND_3(c, d, e, a, b, 58);
512    SHA1_ROUND_3(b, c, d, e, a, 59);
513    SHA1_ROUND_4(a, b, c, d, e, 60);
514    SHA1_ROUND_4(e, a, b, c, d, 61);
515    SHA1_ROUND_4(d, e, a, b, c, 62);
516    SHA1_ROUND_4(c, d, e, a, b, 63);
517    SHA1_ROUND_4(b, c, d, e, a, 64);
518    SHA1_ROUND_4(a, b, c, d, e, 65);
519    SHA1_ROUND_4(e, a, b, c, d, 66);
520    SHA1_ROUND_4(d, e, a, b, c, 67);
521    SHA1_ROUND_4(c, d, e, a, b, 68);
522    SHA1_ROUND_4(b, c, d, e, a, 69);
523    SHA1_ROUND_4(a, b, c, d, e, 70);
524    SHA1_ROUND_4(e, a, b, c, d, 71);
525    SHA1_ROUND_4(d, e, a, b, c, 72);
526    SHA1_ROUND_4(c, d, e, a, b, 73);
527    SHA1_ROUND_4(b, c, d, e, a, 74);
528    SHA1_ROUND_4(a, b, c, d, e, 75);
529    SHA1_ROUND_4(e, a, b, c, d, 76);
530    SHA1_ROUND_4(d, e, a, b, c, 77);
531    SHA1_ROUND_4(c, d, e, a, b, 78);
532    SHA1_ROUND_4(b, c, d, e, a, 79);
533
534#undef SHA1_LOAD
535#undef SHA1_ROUND_0
536#undef SHA1_ROUND_1
537#undef SHA1_ROUND_2
538#undef SHA1_ROUND_3
539#undef SHA1_ROUND_4
540
541    m_state[0] += a;
542    m_state[1] += b;
543    m_state[2] += c;
544    m_state[3] += d;
545    m_state[4] += e;
546}
547
548/* static */ SHA1::Digest SHA1::compute(const void* data, SlangInt size)
549{
550    SHA1 sha1;
551    sha1.update(data, size);
552    return sha1.finalize();
553}
554
555} // namespace Slang
556
557
558/*
559 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
560 * MD5 Message-Digest Algorithm (RFC 1321).
561 *
562 * Homepage:
563 * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
564 *
565 * Author:
566 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
567 *
568 * This software was written by Alexander Peslyak in 2001.  No copyright is
569 * claimed, and the software is hereby placed in the public domain.
570 * In case this attempt to disclaim copyright and place the software in the
571 * public domain is deemed null and void, then the software is
572 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
573 * general public under the following terms:
574 *
575 * Redistribution and use in source and binary forms, with or without
576 * modification, are permitted.
577 *
578 * There's ABSOLUTELY NO WARRANTY, express or implied.
579 *
580 * (This is a heavily cut-down "BSD license".)
581 *
582 * This differs from Colin Plumb's older public domain implementation in that
583 * no exactly 32-bit integer data type is required (any 32-bit or wider
584 * unsigned integer data type will do), there's no compile-time endianness
585 * configuration, and the function prototypes match OpenSSL's.  No code from
586 * Colin Plumb's implementation has been reused; this comment merely compares
587 * the properties of the two independent implementations.
588 *
589 * The primary goals of this implementation are portability and ease of use.
590 * It is meant to be fast, but not as fast as possible.  Some known
591 * optimizations are not included to reduce source code size and avoid
592 * compile-time configuration.
593 */
594
595/*
596 * This is free and unencumbered software released into the public domain.
597 *
598 * Anyone is free to copy, modify, publish, use, compile, sell, or
599 * distribute this software, either in source code form or as a compiled
600 * binary, for any purpose, commercial or non-commercial, and by any
601 * means.
602 *
603 * In jurisdictions that recognize copyright laws, the author or authors
604 * of this software dedicate any and all copyright interest in the
605 * software to the public domain. We make this dedication for the benefit
606 * of the public at large and to the detriment of our heirs and
607 * successors. We intend this dedication to be an overt act of
608 * relinquishment in perpetuity of all present and future rights to this
609 * software under copyright law.
610 *
611 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
612 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
613 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
614 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
615 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
616 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
617 * OTHER DEALINGS IN THE SOFTWARE.
618 *
619 * For more information, please refer to <http://unlicense.org>
620 */