载入中...
搜索中...
未找到
HashFunction.cpp
浏览该文件的文档.
1
2
3#include "HashFunction.h"
4#include "common/Exception.h"
5
6#include <cstring>
7
8// FIXME: Probably trivial by having tole and tobe functions, which can be ifdeffed to being identity functions
9#ifdef LOVE_BIG_ENDIAN
10# error Hashing not yet implemented for big endian
11#endif
12
13namespace eve
14{
15namespace data
16{
17
18namespace
19{
20namespace impl
21{
22
23inline uint32_t leftrot(uint32_t x, uint8_t amount)
24{
25 return (x << amount) | (x >> (32 - amount));
26}
27
28inline uint32_t rightrot(uint32_t x, uint8_t amount)
29{
30 return (x >> amount) | (x << (32 - amount));
31}
32
33inline uint64_t rightrot(uint64_t x, uint8_t amount)
34{
35 return (x >> amount) | (x << (64 - amount));
36}
37
45class MD5 : public HashFunction
46{
47private:
48 static const uint8_t shifts[64];
49 static const uint32_t constants[64];
50
51public:
52 bool isSupported(std::string function) const override
53 {
54 return function == "md5";
55 }
56
57 void hash(std::string function, const char *input, uint64_t length, Value &output) const override
58 {
59 if (function != "md5")
60 throw eve::Exception("Hash function not supported by MD5 implementation");
61
62 uint32_t a0 = 0x67452301;
63 uint32_t b0 = 0xefcdab89;
64 uint32_t c0 = 0x98badcfe;
65 uint32_t d0 = 0x10325476;
66
67 //Do the required padding (MD5, SHA1 and SHA2 use the same padding)
68 uint64_t paddedLength = length + 1; //Consider the appended bit
69 if (paddedLength % 64 < 56)
70 paddedLength += 56 - paddedLength % 64;
71 if (paddedLength % 64 > 56)
72 paddedLength += 120 - paddedLength % 64;
73
74 uint8_t *padded = new uint8_t[paddedLength + 8];
75 if (length != 0)
76 memcpy(padded, input, length);
77 memset(padded + length, 0, paddedLength - length);
78 padded[length] = 0x80;
79
80 //Now we need the length in bits
81 *((uint64_t*) &padded[paddedLength]) = length * 8;
82 paddedLength += 8;
83
84 for (uint64_t i = 0; i < paddedLength; i += 64)
85 {
86 uint32_t *chunk = (uint32_t*) &padded[i];
87
88 uint32_t A = a0;
89 uint32_t B = b0;
90 uint32_t C = c0;
91 uint32_t D = d0;
92 uint32_t F;
93 uint32_t g;
94
95 for (int j = 0; j < 64; j++)
96 {
97 if (j < 16)
98 {
99 F = (B & C) | (~B & D);
100 g = j;
101 }
102 else if (j < 32)
103 {
104 F = (D & B) | (~D & C);
105 g = (5*j + 1) % 16;
106 }
107 else if (j < 48)
108 {
109 F = B ^ C ^ D;
110 g = (3*j + 5) % 16;
111 }
112 else
113 {
114 F = C ^ (B | ~D);
115 g = (7*j) % 16;
116 }
117
118 uint32_t temp = D;
119 D = C;
120 C = B;
121 B += leftrot(A + F + constants[j] + chunk[g], shifts[j]);
122 A = temp;
123 }
124
125 a0 += A;
126 b0 += B;
127 c0 += C;
128 d0 += D;
129 }
130
131 delete[] padded;
132
133 memcpy(&output.data[ 0], &a0, 4);
134 memcpy(&output.data[ 4], &b0, 4);
135 memcpy(&output.data[ 8], &c0, 4);
136 memcpy(&output.data[12], &d0, 4);
137 output.size = 16;
138 }
139} md5;
140
141const uint8_t MD5::shifts[64] = {
142 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
143 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
144 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
145 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
146};
147
148const uint32_t MD5::constants[64] = {
149 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
150 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
151 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
152 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
153 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
154 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
155 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
156 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
157 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
158 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
159 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
160 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
161 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
162 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
163 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
164 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
165};
166
172class SHA1 : public HashFunction
173{
174public:
175 bool isSupported(std::string function) const override
176 {
177 return function == "sha1";
178 }
179
180 void hash(std::string function, const char *input, uint64_t length, Value &output) const override
181 {
182 if (function != "sha1")
183 throw eve::Exception("Hash function not supported by SHA1 implementation");
184
185 uint32_t intermediate[5] = {
186 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
187 };
188
189 //Do the required padding (MD5, SHA1 and SHA2 use the same padding)
190 uint64_t paddedLength = length + 1; //Consider the appended bit
191 if (paddedLength % 64 < 56)
192 paddedLength += 56 - paddedLength % 64;
193 if (paddedLength % 64 > 56)
194 paddedLength += 120 - paddedLength % 64;
195
196 uint8_t *padded = new uint8_t[paddedLength + 8];
197 if (length != 0)
198 memcpy(padded, input, length);
199 memset(padded + length, 0, paddedLength - length);
200 padded[length] = 0x80;
201
202 // Now we need the length in bits (big endian)
203 length *= 8;
204 for (int i = 0; i < 8; ++i, ++paddedLength)
205 padded[paddedLength] = (length >> (56 - i * 8)) & 0xFF;
206
207 // Allocate our extended words
208 uint32_t words[80];
209
210 for (uint64_t i = 0; i < paddedLength; i += 64)
211 {
212 uint32_t *chunk = (uint32_t*) &padded[i];
213 for (int j = 0; j < 16; j++)
214 {
215 char *c = (char*) &words[j];
216 c[0] = (chunk[j] >> 24) & 0xFF;
217 c[1] = (chunk[j] >> 16) & 0xFF;
218 c[2] = (chunk[j] >> 8) & 0xFF;
219 c[3] = (chunk[j] >> 0) & 0xFF;
220 }
221 for (int j = 16; j < 80; j++)
222 words[j] = leftrot(words[j-3] ^ words[j-8] ^ words[j-14] ^ words[j-16], 1);
223
224 uint32_t A = intermediate[0];
225 uint32_t B = intermediate[1];
226 uint32_t C = intermediate[2];
227 uint32_t D = intermediate[3];
228 uint32_t E = intermediate[4];
229
230 for (int j = 0; j < 80; j++)
231 {
232 uint32_t temp = leftrot(A, 5) + E + words[j];
233
234 if (j < 20)
235 temp += 0x5A827999 + ((B & C) | (~B & D));
236 else if (j < 40)
237 temp += 0x6ED9EBA1 + (B ^ C ^ D);
238 else if (j < 60)
239 temp += 0x8F1BBCDC + ((B & C) | (B & D) | (C & D));
240 else
241 temp += 0xCA62C1D6 + (B ^ C ^ D);
242
243 E = D;
244 D = C;
245 C = leftrot(B, 30);
246 B = A;
247 A = temp;
248 }
249
250 intermediate[0] += A;
251 intermediate[1] += B;
252 intermediate[2] += C;
253 intermediate[3] += D;
254 intermediate[4] += E;
255 }
256
257 delete[] padded;
258
259 for (int i = 0; i < 20; i += 4)
260 {
261 output.data[i+0] = (intermediate[i/4] >> 24) & 0xFF;
262 output.data[i+1] = (intermediate[i/4] >> 16) & 0xFF;
263 output.data[i+2] = (intermediate[i/4] >> 8) & 0xFF;
264 output.data[i+3] = (intermediate[i/4] >> 0) & 0xFF;
265 }
266
267 output.size = 20;
268 }
269} sha1;
270
274// SHA-2: SHA-224 and SHA-256
275class SHA256 : public HashFunction
276{
277private:
278 static const uint32_t initial224[8];
279 static const uint32_t initial256[8];
280 static const uint32_t constants[64];
281
282public:
283 bool isSupported(std::string function) const override
284 {
285 return function == "sha224" || function == "sha256";
286 }
287
288 void hash(std::string function, const char *input, uint64_t length, Value &output) const override
289 {
290 if (!isSupported(function))
291 throw eve::Exception("Hash function not supported by SHA-224/SHA-256 implementation");
292
293 //Do the required padding (MD5, SHA1 and SHA2 use the same padding)
294 uint64_t paddedLength = length + 1; //Consider the appended bit
295 if (paddedLength % 64 < 56)
296 paddedLength += 56 - paddedLength % 64;
297 if (paddedLength % 64 > 56)
298 paddedLength += 120 - paddedLength % 64;
299
300 uint8_t *padded = new uint8_t[paddedLength + 8];
301 if (length != 0)
302 memcpy(padded, input, length);
303 memset(padded + length, 0, paddedLength - length);
304 padded[length] = 0x80;
305
306 // Now we need the length in bits (big endian)
307 length *= 8;
308 for (int i = 0; i < 8; ++i, ++paddedLength)
309 padded[paddedLength] = (length >> (56 - i * 8)) & 0xFF;
310
311 uint32_t intermediate[8];
312 if (function == "sha224")
313 memcpy(intermediate, initial224, sizeof(intermediate));
314 else
315 memcpy(intermediate, initial256, sizeof(intermediate));
316
317 // Allocate our extended words
318 uint32_t words[64];
319
320 for (uint64_t i = 0; i < paddedLength; i += 64)
321 {
322 uint32_t *chunk = (uint32_t*) &padded[i];
323 for (int j = 0; j < 16; j++)
324 {
325 char *c = (char*) &words[j];
326 c[0] = (chunk[j] >> 24) & 0xFF;
327 c[1] = (chunk[j] >> 16) & 0xFF;
328 c[2] = (chunk[j] >> 8) & 0xFF;
329 c[3] = (chunk[j] >> 0) & 0xFF;
330 }
331 for (int j = 16; j < 64; j++)
332 {
333 words[j] = rightrot(words[j-2], 17) ^ rightrot(words[j-2], 19) ^ (words[j-2] >> 10);
334 words[j] += rightrot(words[j-15], 7) ^ rightrot(words[j-15], 18) ^ (words[j-15] >> 3);
335 words[j] += words[j-7] + words[j-16];
336 }
337
338 uint32_t A = intermediate[0];
339 uint32_t B = intermediate[1];
340 uint32_t C = intermediate[2];
341 uint32_t D = intermediate[3];
342 uint32_t E = intermediate[4];
343 uint32_t F = intermediate[5];
344 uint32_t G = intermediate[6];
345 uint32_t H = intermediate[7];
346
347 for (int j = 0; j < 64; j++)
348 {
349 uint32_t temp1 = H + constants[j] + words[j];
350 temp1 += rightrot(E, 6) ^ rightrot(E, 11) ^ rightrot(E, 25);
351 temp1 += (E & F) ^ (~E & G);
352 uint32_t temp2 = rightrot(A, 2) ^ rightrot(A, 13) ^ rightrot(A, 22);
353 temp2 += (A & B) ^ (A & C) ^ (B & C);
354
355 H = G;
356 G = F;
357 F = E;
358 E = D + temp1;
359 D = C;
360 C = B;
361 B = A;
362 A = temp1 + temp2;
363 }
364
365 intermediate[0] += A;
366 intermediate[1] += B;
367 intermediate[2] += C;
368 intermediate[3] += D;
369 intermediate[4] += E;
370 intermediate[5] += F;
371 intermediate[6] += G;
372 intermediate[7] += H;
373 }
374
375 delete[] padded;
376
377 int hashlength = 32;
378 if (function == "sha224")
379 hashlength = 28;
380
381 for (int i = 0; i < hashlength; i += 4)
382 {
383 output.data[i+0] = (intermediate[i/4] >> 24) & 0xFF;
384 output.data[i+1] = (intermediate[i/4] >> 16) & 0xFF;
385 output.data[i+2] = (intermediate[i/4] >> 8) & 0xFF;
386 output.data[i+3] = (intermediate[i/4] >> 0) & 0xFF;
387 }
388
389 output.size = hashlength;
390 }
391} sha256;
392
393const uint32_t SHA256::initial224[8] = {
394 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
395 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
396};
397
398const uint32_t SHA256::initial256[8] = {
399 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
400 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
401};
402
403const uint32_t SHA256::constants[64] = {
404 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
405 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
406 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
407 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
408 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
409 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
410 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
411 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
412 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
413 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
414 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
415 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
416 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
417 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
418 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
419 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
420};
421
425// SHA-2: SHA-384 and SHA-512
426class SHA512 : public HashFunction
427{
428private:
429 static const uint64_t initial384[8];
430 static const uint64_t initial512[8];
431 static const uint64_t constants[80];
432
433public:
434 bool isSupported(std::string function) const override
435 {
436 return function == "sha384" || function == "sha512";
437 }
438
439 void hash(std::string function, const char *input, uint64_t length, Value &output) const override
440 {
441 if (!isSupported(function))
442 throw eve::Exception("Hash function not supported by SHA-384/SHA-512 implementation");
443
444 uint64_t intermediates[8];
445 if (function == "sha384")
446 memcpy(intermediates, initial384, sizeof(intermediates));
447 else
448 memcpy(intermediates, initial512, sizeof(intermediates));
449
450 //Do the required padding
451 uint64_t paddedLength = length + 1; //Consider the appended bit
452 if (paddedLength % 128 < 112)
453 paddedLength += 112 - paddedLength % 128;
454 if (paddedLength % 128 > 112)
455 paddedLength += 240 - paddedLength % 128;
456
457 uint8_t *padded = new uint8_t[paddedLength + 16];
458 paddedLength += 8;
459 if (length != 0)
460 memcpy(padded, input, length);
461 memset(padded + length, 0, paddedLength - length);
462 padded[length] = 0x80;
463
464 // Now we need the length in bits (big endian), note we only write a 64-bit int, so
465 // we have filled the first 8 bytes with zeroes
466 length *= 8;
467 for (int i = 0; i < 8; ++i, ++paddedLength)
468 padded[paddedLength] = (length >> (56 - i * 8)) & 0xFF;
469
470 // Allocate our extended words
471 uint64_t words[80];
472
473 for (uint64_t i = 0; i < paddedLength; i += 128)
474 {
475 uint64_t *chunk = (uint64_t*) &padded[i];
476 for (int j = 0; j < 16; ++j)
477 {
478 char *c = (char*) &words[j];
479 c[0] = (chunk[j] >> 56) & 0xFF;
480 c[1] = (chunk[j] >> 48) & 0xFF;
481 c[2] = (chunk[j] >> 40) & 0xFF;
482 c[3] = (chunk[j] >> 32) & 0xFF;
483 c[4] = (chunk[j] >> 24) & 0xFF;
484 c[5] = (chunk[j] >> 16) & 0xFF;
485 c[6] = (chunk[j] >> 8) & 0xFF;
486 c[7] = (chunk[j] >> 0) & 0xFF;
487 }
488 for (int j = 16; j < 80; ++j)
489 {
490 words[j] = words[j-7] + words[j-16];
491 words[j] += rightrot(words[j-2], 19) ^ rightrot(words[j-2], 61) ^ (words[j-2] >> 6);
492 words[j] += rightrot(words[j-15], 1) ^ rightrot(words[j-15], 8) ^ (words[j-15] >> 7);
493 }
494
495 uint64_t A = intermediates[0];
496 uint64_t B = intermediates[1];
497 uint64_t C = intermediates[2];
498 uint64_t D = intermediates[3];
499 uint64_t E = intermediates[4];
500 uint64_t F = intermediates[5];
501 uint64_t G = intermediates[6];
502 uint64_t H = intermediates[7];
503
504 for (int j = 0; j < 80; ++j)
505 {
506 uint64_t temp1 = H + constants[j] + words[j];
507 temp1 += rightrot(E, 14) ^ rightrot(E, 18) ^ rightrot(E, 41);
508 temp1 += (E & F) ^ (~E & G);
509 uint64_t temp2 = rightrot(A, 28) ^ rightrot(A, 34) ^ rightrot(A, 39);
510 temp2 += (A & B) ^ (A & C) ^ (B & C);
511 H = G;
512 G = F;
513 F = E;
514 E = D + temp1;
515 D = C;
516 C = B;
517 B = A;
518 A = temp1 + temp2;
519 }
520
521 intermediates[0] += A;
522 intermediates[1] += B;
523 intermediates[2] += C;
524 intermediates[3] += D;
525 intermediates[4] += E;
526 intermediates[5] += F;
527 intermediates[6] += G;
528 intermediates[7] += H;
529 }
530
531 delete[] padded;
532
533 int hashlength = 64;
534 if (function == "sha384")
535 hashlength = 48;
536
537 for (int i = 0; i < hashlength; i += 8)
538 {
539 output.data[i+0] = (intermediates[i/8] >> 56) & 0xFF;
540 output.data[i+1] = (intermediates[i/8] >> 48) & 0xFF;
541 output.data[i+2] = (intermediates[i/8] >> 40) & 0xFF;
542 output.data[i+3] = (intermediates[i/8] >> 32) & 0xFF;
543 output.data[i+4] = (intermediates[i/8] >> 24) & 0xFF;
544 output.data[i+5] = (intermediates[i/8] >> 16) & 0xFF;
545 output.data[i+6] = (intermediates[i/8] >> 8) & 0xFF;
546 output.data[i+7] = (intermediates[i/8] >> 0) & 0xFF;
547 }
548
549 output.size = hashlength;
550 }
551} sha512;
552
553const uint64_t SHA512::initial384[8] = {
554 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
555 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4,
556};
557
558const uint64_t SHA512::initial512[8] = {
559 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
560 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
561};
562
563const uint64_t SHA512::constants[80] = {
564 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
565 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
566 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
567 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
568 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
569 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
570 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
571 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
572 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
573 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
574 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
575 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
576 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
577 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
578 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
579 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
580 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
581 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
582 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
583 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
584};
585
586} // impl
587}
588
590{
591 if (function == "md5")
592 return &impl::md5;
593 if (function == "sha1")
594 return &impl::sha1;
595 if (function == "sha224" || function == "sha256")
596 return &impl::sha256;
597 if (function == "sha384" || function == "sha512")
598 return &impl::sha512;
599 return nullptr;
600}
601
602} // data
603} // eve
float x
Definition AnimClip.cpp:738
std::string output
void * impl
float length
Definition CaveMesh.cpp:94
std::array< std::uint8_t, 32 > hash
Definition Evpack.cpp:172
EvpackChunkInput input
Definition Evpack.cpp:170
tensor::Graph g
Definition GpuGraph.cpp:7
std::int32_t c
MigrationFunction function
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
EVENGINE_API_FOUNDATION public API.
static HashFunction * getHashFunction(std::string function)
Get a HashFunction instance for the given function.
Build metadata (engine git commit, build time, third-party version).
Definition Build.cpp:16