fmt.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. #define HL_NAME(n) fmt_##n
  2. #include <png.h>
  3. #include <hl.h>
  4. #if defined(HL_CONSOLE) && !defined(HL_XBO)
  5. extern bool sys_jpg_decode( vbyte *data, int dataLen, vbyte *out, int width, int height, int stride, int format, int flags );
  6. #else
  7. # include <turbojpeg.h>
  8. #endif
  9. #include <zlib.h>
  10. #include <vorbis/vorbisfile.h>
  11. /* ------------------------------------------------- IMG --------------------------------------------------- */
  12. typedef struct {
  13. unsigned char a,r,g,b;
  14. } pixel;
  15. HL_PRIM bool HL_NAME(jpg_decode)( vbyte *data, int dataLen, vbyte *out, int width, int height, int stride, int format, int flags ) {
  16. #if defined(HL_CONSOLE) && !defined(HL_XBO)
  17. hl_blocking(true);
  18. bool b = sys_jpg_decode(data, dataLen, out, width, height, stride, format, flags);
  19. hl_blocking(false);
  20. return b;
  21. #else
  22. hl_blocking(true);
  23. tjhandle h = tjInitDecompress();
  24. int result;
  25. result = tjDecompress2(h,data,dataLen,out,width,stride,height,format,(flags & 1 ? TJFLAG_BOTTOMUP : 0));
  26. tjDestroy(h);
  27. hl_blocking(false);
  28. return result == 0;
  29. #endif
  30. }
  31. HL_PRIM bool HL_NAME(png_decode)( vbyte *data, int dataLen, vbyte *out, int width, int height, int stride, int format, int flags ) {
  32. # ifdef PNG_IMAGE_VERSION
  33. png_image img;
  34. hl_blocking(true);
  35. memset(&img, 0, sizeof(img));
  36. img.version = PNG_IMAGE_VERSION;
  37. if( png_image_begin_read_from_memory(&img,data,dataLen) == 0 ) {
  38. hl_blocking(false);
  39. png_image_free(&img);
  40. return false;
  41. }
  42. switch( format ) {
  43. case 0:
  44. img.format = PNG_FORMAT_RGB;
  45. break;
  46. case 1:
  47. img.format = PNG_FORMAT_BGR;
  48. break;
  49. case 7:
  50. img.format = PNG_FORMAT_RGBA;
  51. break;
  52. case 8:
  53. img.format = PNG_FORMAT_BGRA;
  54. break;
  55. case 9:
  56. img.format = PNG_FORMAT_ABGR;
  57. break;
  58. case 10:
  59. img.format = PNG_FORMAT_ARGB;
  60. break;
  61. default:
  62. hl_blocking(false);
  63. png_image_free(&img);
  64. hl_error("Unsupported format");
  65. break;
  66. }
  67. if( img.width != width || img.height != height ) {
  68. hl_blocking(false);
  69. png_image_free(&img);
  70. return false;
  71. }
  72. if( png_image_finish_read(&img,NULL,out,stride * (flags & 1 ? -1 : 1),NULL) == 0 ) {
  73. hl_blocking(false);
  74. png_image_free(&img);
  75. return false;
  76. }
  77. hl_blocking(false);
  78. png_image_free(&img);
  79. # else
  80. hl_error("PNG support is missing for this libPNG version");
  81. # endif
  82. return true;
  83. }
  84. HL_PRIM void HL_NAME(img_scale)( vbyte *out, int outPos, int outStride, int outWidth, int outHeight, vbyte *in, int inPos, int inStride, int inWidth, int inHeight, int flags ) {
  85. int x, y;
  86. float scaleX = outWidth <= 1 ? 0.0f : (float)((inWidth - 1.001f) / (outWidth - 1));
  87. float scaleY = outHeight <= 1 ? 0.0f : (float)((inHeight - 1.001f) / (outHeight - 1));
  88. out += outPos;
  89. in += inPos;
  90. hl_blocking(true);
  91. for(y=0;y<outHeight;y++) {
  92. for(x=0;x<outWidth;x++) {
  93. float fx = x * scaleX;
  94. float fy = y * scaleY;
  95. int ix = (int)fx;
  96. int iy = (int)fy;
  97. if( (flags & 1) == 0 ) {
  98. // nearest
  99. vbyte *rin = in + iy * inStride;
  100. *(pixel*)out = *(pixel*)(rin + (ix<<2));
  101. out += 4;
  102. } else {
  103. // bilinear
  104. float rx = fx - ix;
  105. float ry = fy - iy;
  106. float rx1 = 1.0f - rx;
  107. float ry1 = 1.0f - ry;
  108. int w1 = (int)(rx1 * ry1 * 256.0f);
  109. int w2 = (int)(rx * ry1 * 256.0f);
  110. int w3 = (int)(rx1 * ry * 256.0f);
  111. int w4 = (int)(rx * ry * 256.0f);
  112. vbyte *rin = in + iy * inStride;
  113. pixel p1 = *(pixel*)(rin + (ix<<2));
  114. pixel p2 = *(pixel*)(rin + ((ix + 1)<<2));
  115. pixel p3 = *(pixel*)(rin + inStride + (ix<<2));
  116. pixel p4 = *(pixel*)(rin + inStride + ((ix + 1)<<2));
  117. *out++ = (unsigned char)((p1.a * w1 + p2.a * w2 + p3.a * w3 + p4.a * w4 + 128)>>8);
  118. *out++ = (unsigned char)((p1.r * w1 + p2.r * w2 + p3.r * w3 + p4.r * w4 + 128)>>8);
  119. *out++ = (unsigned char)((p1.g * w1 + p2.g * w2 + p3.g * w3 + p4.g * w4 + 128)>>8);
  120. *out++ = (unsigned char)((p1.b * w1 + p2.b * w2 + p3.b * w3 + p4.b * w4 + 128)>>8);
  121. }
  122. }
  123. out += outStride - (outWidth << 2);
  124. }
  125. hl_blocking(false);
  126. }
  127. DEFINE_PRIM(_BOOL, jpg_decode, _BYTES _I32 _BYTES _I32 _I32 _I32 _I32 _I32);
  128. DEFINE_PRIM(_BOOL, png_decode, _BYTES _I32 _BYTES _I32 _I32 _I32 _I32 _I32);
  129. DEFINE_PRIM(_VOID, img_scale, _BYTES _I32 _I32 _I32 _I32 _BYTES _I32 _I32 _I32 _I32 _I32);
  130. /* ------------------------------------------------- ZLIB --------------------------------------------------- */
  131. typedef struct _fmt_zip fmt_zip;
  132. struct _fmt_zip {
  133. void (*finalize)( fmt_zip * );
  134. z_stream *z;
  135. int flush;
  136. bool inflate;
  137. };
  138. static void free_stream_inf( fmt_zip *v ) {
  139. if( v->inflate )
  140. inflateEnd(v->z); // no error
  141. else
  142. deflateEnd(v->z);
  143. free(v->z);
  144. v->z = NULL;
  145. v->finalize = NULL;
  146. }
  147. static void zlib_error( z_stream *z, int err ) {
  148. hl_buffer *b = hl_alloc_buffer();
  149. vdynamic *d;
  150. hl_buffer_cstr(b, "ZLib Error : ");
  151. if( z && z->msg ) {
  152. hl_buffer_cstr(b,z->msg);
  153. hl_buffer_cstr(b," (");
  154. }
  155. d = hl_alloc_dynamic(&hlt_i32);
  156. d->v.i = err;
  157. hl_buffer_val(b,d);
  158. if( z && z->msg )
  159. hl_buffer_char(b,')');
  160. d = hl_alloc_dynamic(&hlt_bytes);
  161. d->v.ptr = hl_buffer_content(b,NULL);
  162. hl_throw(d);
  163. }
  164. HL_PRIM fmt_zip *HL_NAME(inflate_init)( int wbits ) {
  165. z_stream *z;
  166. int err;
  167. fmt_zip *s;
  168. if( wbits == 0 )
  169. wbits = MAX_WBITS;
  170. z = (z_stream*)malloc(sizeof(z_stream));
  171. memset(z,0,sizeof(z_stream));
  172. if( (err = inflateInit2(z,wbits)) != Z_OK ) {
  173. free(z);
  174. zlib_error(NULL,err);
  175. }
  176. s = (fmt_zip*)hl_gc_alloc_finalizer(sizeof(fmt_zip));
  177. s->finalize = free_stream_inf;
  178. s->flush = Z_NO_FLUSH;
  179. s->z = z;
  180. s->inflate = true;
  181. return s;
  182. }
  183. HL_PRIM fmt_zip *HL_NAME(deflate_init)( int level ) {
  184. z_stream *z;
  185. int err;
  186. fmt_zip *s;
  187. z = (z_stream*)malloc(sizeof(z_stream));
  188. memset(z,0,sizeof(z_stream));
  189. if( (err = deflateInit(z,level)) != Z_OK ) {
  190. free(z);
  191. zlib_error(NULL,err);
  192. }
  193. s = (fmt_zip*)hl_gc_alloc_finalizer(sizeof(fmt_zip));
  194. s->finalize = free_stream_inf;
  195. s->flush = Z_NO_FLUSH;
  196. s->z = z;
  197. s->inflate = false;
  198. return s;
  199. }
  200. HL_PRIM void HL_NAME(zip_end)( fmt_zip *z ) {
  201. free_stream_inf(z);
  202. }
  203. HL_PRIM void HL_NAME(zip_flush_mode)( fmt_zip *z, int flush ) {
  204. switch( flush ) {
  205. case 0:
  206. z->flush = Z_NO_FLUSH;
  207. break;
  208. case 1:
  209. z->flush = Z_SYNC_FLUSH;
  210. break;
  211. case 2:
  212. z->flush = Z_FULL_FLUSH;
  213. break;
  214. case 3:
  215. z->flush = Z_FINISH;
  216. break;
  217. case 4:
  218. z->flush = Z_BLOCK;
  219. break;
  220. default:
  221. hl_error("Invalid flush mode %d",flush);
  222. break;
  223. }
  224. }
  225. HL_PRIM bool HL_NAME(inflate_buffer)( fmt_zip *zip, vbyte *src, int srcpos, int srclen, vbyte *dst, int dstpos, int dstlen, int *read, int *write ) {
  226. int slen, dlen, err;
  227. z_stream *z = zip->z;
  228. slen = srclen - srcpos;
  229. dlen = dstlen - dstpos;
  230. if( srcpos < 0 || dstpos < 0 || slen < 0 || dlen < 0 )
  231. hl_error("Out of range");
  232. hl_blocking(true);
  233. z->next_in = (Bytef*)(src + srcpos);
  234. z->next_out = (Bytef*)(dst + dstpos);
  235. z->avail_in = slen;
  236. z->avail_out = dlen;
  237. if( (err = inflate(z,zip->flush)) < 0 ) {
  238. hl_blocking(false);
  239. zlib_error(z,err);
  240. }
  241. z->next_in = NULL;
  242. z->next_out = NULL;
  243. *read = slen - z->avail_in;
  244. *write = dlen - z->avail_out;
  245. hl_blocking(false);
  246. return err == Z_STREAM_END;
  247. }
  248. HL_PRIM bool HL_NAME(deflate_buffer)( fmt_zip *zip, vbyte *src, int srcpos, int srclen, vbyte *dst, int dstpos, int dstlen, int *read, int *write ) {
  249. int slen, dlen, err;
  250. z_stream *z = zip->z;
  251. slen = srclen - srcpos;
  252. dlen = dstlen - dstpos;
  253. if( srcpos < 0 || dstpos < 0 || slen < 0 || dlen < 0 )
  254. hl_error("Out of range");
  255. hl_blocking(true);
  256. z->next_in = (Bytef*)(src + srcpos);
  257. z->next_out = (Bytef*)(dst + dstpos);
  258. z->avail_in = slen;
  259. z->avail_out = dlen;
  260. if( (err = deflate(z,zip->flush)) < 0 ) {
  261. hl_blocking(false);
  262. zlib_error(z,err);
  263. }
  264. z->next_in = NULL;
  265. z->next_out = NULL;
  266. *read = slen - z->avail_in;
  267. *write = dlen - z->avail_out;
  268. hl_blocking(false);
  269. return err == Z_STREAM_END;
  270. }
  271. HL_PRIM int HL_NAME(deflate_bound)( fmt_zip *zip, int size ) {
  272. return deflateBound(zip->z,size);
  273. }
  274. #define _ZIP _ABSTRACT(fmt_zip)
  275. DEFINE_PRIM(_ZIP, inflate_init, _I32);
  276. DEFINE_PRIM(_ZIP, deflate_init, _I32);
  277. DEFINE_PRIM(_I32, deflate_bound, _ZIP _I32);
  278. DEFINE_PRIM(_VOID, zip_end, _ZIP);
  279. DEFINE_PRIM(_VOID, zip_flush_mode, _ZIP _I32);
  280. DEFINE_PRIM(_BOOL, inflate_buffer, _ZIP _BYTES _I32 _I32 _BYTES _I32 _I32 _REF(_I32) _REF(_I32));
  281. DEFINE_PRIM(_BOOL, deflate_buffer, _ZIP _BYTES _I32 _I32 _BYTES _I32 _I32 _REF(_I32) _REF(_I32));
  282. /* ------------------------------------------------- SOUND --------------------------------------------------- */
  283. typedef struct _fmt_ogg fmt_ogg;
  284. struct _fmt_ogg {
  285. void (*finalize)( fmt_ogg * );
  286. OggVorbis_File f;
  287. char *bytes;
  288. int pos;
  289. int size;
  290. int section;
  291. };
  292. static void ogg_finalize( fmt_ogg *o ) {
  293. ov_clear(&o->f);
  294. }
  295. static size_t ogg_memread( void *ptr, int size, int count, fmt_ogg *o ) {
  296. int len = size * count;
  297. if( o->pos + len > o->size )
  298. len = o->size - o->pos;
  299. memcpy(ptr, o->bytes + o->pos, len);
  300. o->pos += len;
  301. return len;
  302. }
  303. static int ogg_memseek( fmt_ogg *o, ogg_int64_t _offset, int mode ) {
  304. int offset = (int)_offset;
  305. switch( mode ) {
  306. case SEEK_SET:
  307. if( offset < 0 || offset > o->size ) return 1;
  308. o->pos = offset;
  309. break;
  310. case SEEK_CUR:
  311. if( o->pos + offset < 0 || o->pos + offset > o->size ) return 1;
  312. o->pos += offset;
  313. break;
  314. case SEEK_END:
  315. if( offset < 0 || offset > o->size ) return 1;
  316. o->pos = o->size - offset;
  317. break;
  318. }
  319. return 0;
  320. }
  321. static long ogg_memtell( fmt_ogg *o ) {
  322. return o->pos;
  323. }
  324. static ov_callbacks OV_CALLBACKS_MEMORY = {
  325. (size_t (*)(void *, size_t, size_t, void *)) ogg_memread,
  326. (int (*)(void *, ogg_int64_t, int)) ogg_memseek,
  327. (int (*)(void *)) NULL,
  328. (long (*)(void *)) ogg_memtell
  329. };
  330. HL_PRIM fmt_ogg *HL_NAME(ogg_open)( char *bytes, int size ) {
  331. fmt_ogg *o = (fmt_ogg*)hl_gc_alloc_finalizer(sizeof(fmt_ogg));
  332. o->finalize = NULL;
  333. o->bytes = bytes;
  334. o->size = size;
  335. o->pos = 0;
  336. if( ov_open_callbacks(o,&o->f,NULL,0,OV_CALLBACKS_MEMORY) != 0 )
  337. return NULL;
  338. o->finalize = ogg_finalize;
  339. return o;
  340. }
  341. HL_PRIM void HL_NAME(ogg_info)( fmt_ogg *o, int *bitrate, int *freq, int *samples, int *channels ) {
  342. vorbis_info *i = ov_info(&o->f,-1);
  343. *bitrate = i->bitrate_nominal;
  344. *freq = i->rate;
  345. *channels = i->channels;
  346. *samples = (int)ov_pcm_total(&o->f, -1);
  347. }
  348. HL_PRIM int HL_NAME(ogg_tell)( fmt_ogg *o ) {
  349. return (int)ov_pcm_tell(&o->f); // overflow at 12 hours @48 Khz
  350. }
  351. HL_PRIM bool HL_NAME(ogg_seek)( fmt_ogg *o, int sample ) {
  352. return ov_pcm_seek(&o->f,sample) == 0;
  353. }
  354. #define OGGFMT_I8 1
  355. #define OGGFMT_I16 2
  356. //#define OGGFMT_F32 3
  357. #define OGGFMT_BIGENDIAN 128
  358. #define OGGFMT_UNSIGNED 256
  359. HL_PRIM int HL_NAME(ogg_read)( fmt_ogg *o, char *output, int size, int format ) {
  360. int ret = -1;
  361. hl_blocking(true);
  362. switch( format&127 ) {
  363. case OGGFMT_I8:
  364. case OGGFMT_I16:
  365. ret = ov_read(&o->f, output, size, (format & OGGFMT_BIGENDIAN) != 0, format&3, (format & OGGFMT_UNSIGNED) == 0, &o->section);
  366. break;
  367. // case OGGFMT_F32:
  368. // -- this decodes separates channels instead of mixed single buffer one
  369. // return ov_read_float(&o->f, output, size, (format & OGGFMT_BIGENDIAN) != 0, format&3, (format & OGGFMT_UNSIGNED) == 0, &o->section);
  370. default:
  371. break;
  372. }
  373. hl_blocking(false);
  374. return ret;
  375. }
  376. #define _OGG _ABSTRACT(fmt_ogg)
  377. DEFINE_PRIM(_OGG, ogg_open, _BYTES _I32);
  378. DEFINE_PRIM(_VOID, ogg_info, _OGG _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32));
  379. DEFINE_PRIM(_I32, ogg_tell, _OGG);
  380. DEFINE_PRIM(_BOOL, ogg_seek, _OGG _I32);
  381. DEFINE_PRIM(_I32, ogg_read, _OGG _BYTES _I32 _I32);
  382. /* ------------------------------------------------- CRYPTO --------------------------------------------------- */
  383. typedef unsigned int uint32;
  384. typedef unsigned char uint8;
  385. typedef struct {
  386. uint32 total[2];
  387. uint32 state[4];
  388. uint8 buffer[64];
  389. } md5_context;
  390. #define GET_UINT32(n,b,i) \
  391. { \
  392. (n) = ( (uint32) (b)[(i) ] ) \
  393. | ( (uint32) (b)[(i) + 1] << 8 ) \
  394. | ( (uint32) (b)[(i) + 2] << 16 ) \
  395. | ( (uint32) (b)[(i) + 3] << 24 ); \
  396. }
  397. #define PUT_UINT32(n,b,i) \
  398. { \
  399. (b)[(i) ] = (uint8) ( (n) ); \
  400. (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
  401. (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
  402. (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
  403. }
  404. static void md5_starts( md5_context *ctx ) {
  405. ctx->total[0] = 0;
  406. ctx->total[1] = 0;
  407. ctx->state[0] = 0x67452301;
  408. ctx->state[1] = 0xEFCDAB89;
  409. ctx->state[2] = 0x98BADCFE;
  410. ctx->state[3] = 0x10325476;
  411. }
  412. static void md5_process( md5_context *ctx, uint8 data[64] ) {
  413. uint32 X[16], A, B, C, D;
  414. GET_UINT32( X[0], data, 0 );
  415. GET_UINT32( X[1], data, 4 );
  416. GET_UINT32( X[2], data, 8 );
  417. GET_UINT32( X[3], data, 12 );
  418. GET_UINT32( X[4], data, 16 );
  419. GET_UINT32( X[5], data, 20 );
  420. GET_UINT32( X[6], data, 24 );
  421. GET_UINT32( X[7], data, 28 );
  422. GET_UINT32( X[8], data, 32 );
  423. GET_UINT32( X[9], data, 36 );
  424. GET_UINT32( X[10], data, 40 );
  425. GET_UINT32( X[11], data, 44 );
  426. GET_UINT32( X[12], data, 48 );
  427. GET_UINT32( X[13], data, 52 );
  428. GET_UINT32( X[14], data, 56 );
  429. GET_UINT32( X[15], data, 60 );
  430. #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
  431. #define P(a,b,c,d,k,s,t) \
  432. { \
  433. a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
  434. }
  435. A = ctx->state[0];
  436. B = ctx->state[1];
  437. C = ctx->state[2];
  438. D = ctx->state[3];
  439. #define F(x,y,z) (z ^ (x & (y ^ z)))
  440. P( A, B, C, D, 0, 7, 0xD76AA478 );
  441. P( D, A, B, C, 1, 12, 0xE8C7B756 );
  442. P( C, D, A, B, 2, 17, 0x242070DB );
  443. P( B, C, D, A, 3, 22, 0xC1BDCEEE );
  444. P( A, B, C, D, 4, 7, 0xF57C0FAF );
  445. P( D, A, B, C, 5, 12, 0x4787C62A );
  446. P( C, D, A, B, 6, 17, 0xA8304613 );
  447. P( B, C, D, A, 7, 22, 0xFD469501 );
  448. P( A, B, C, D, 8, 7, 0x698098D8 );
  449. P( D, A, B, C, 9, 12, 0x8B44F7AF );
  450. P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
  451. P( B, C, D, A, 11, 22, 0x895CD7BE );
  452. P( A, B, C, D, 12, 7, 0x6B901122 );
  453. P( D, A, B, C, 13, 12, 0xFD987193 );
  454. P( C, D, A, B, 14, 17, 0xA679438E );
  455. P( B, C, D, A, 15, 22, 0x49B40821 );
  456. #undef F
  457. #define F(x,y,z) (y ^ (z & (x ^ y)))
  458. P( A, B, C, D, 1, 5, 0xF61E2562 );
  459. P( D, A, B, C, 6, 9, 0xC040B340 );
  460. P( C, D, A, B, 11, 14, 0x265E5A51 );
  461. P( B, C, D, A, 0, 20, 0xE9B6C7AA );
  462. P( A, B, C, D, 5, 5, 0xD62F105D );
  463. P( D, A, B, C, 10, 9, 0x02441453 );
  464. P( C, D, A, B, 15, 14, 0xD8A1E681 );
  465. P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
  466. P( A, B, C, D, 9, 5, 0x21E1CDE6 );
  467. P( D, A, B, C, 14, 9, 0xC33707D6 );
  468. P( C, D, A, B, 3, 14, 0xF4D50D87 );
  469. P( B, C, D, A, 8, 20, 0x455A14ED );
  470. P( A, B, C, D, 13, 5, 0xA9E3E905 );
  471. P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
  472. P( C, D, A, B, 7, 14, 0x676F02D9 );
  473. P( B, C, D, A, 12, 20, 0x8D2A4C8A );
  474. #undef F
  475. #define F(x,y,z) (x ^ y ^ z)
  476. P( A, B, C, D, 5, 4, 0xFFFA3942 );
  477. P( D, A, B, C, 8, 11, 0x8771F681 );
  478. P( C, D, A, B, 11, 16, 0x6D9D6122 );
  479. P( B, C, D, A, 14, 23, 0xFDE5380C );
  480. P( A, B, C, D, 1, 4, 0xA4BEEA44 );
  481. P( D, A, B, C, 4, 11, 0x4BDECFA9 );
  482. P( C, D, A, B, 7, 16, 0xF6BB4B60 );
  483. P( B, C, D, A, 10, 23, 0xBEBFBC70 );
  484. P( A, B, C, D, 13, 4, 0x289B7EC6 );
  485. P( D, A, B, C, 0, 11, 0xEAA127FA );
  486. P( C, D, A, B, 3, 16, 0xD4EF3085 );
  487. P( B, C, D, A, 6, 23, 0x04881D05 );
  488. P( A, B, C, D, 9, 4, 0xD9D4D039 );
  489. P( D, A, B, C, 12, 11, 0xE6DB99E5 );
  490. P( C, D, A, B, 15, 16, 0x1FA27CF8 );
  491. P( B, C, D, A, 2, 23, 0xC4AC5665 );
  492. #undef F
  493. #define F(x,y,z) (y ^ (x | ~z))
  494. P( A, B, C, D, 0, 6, 0xF4292244 );
  495. P( D, A, B, C, 7, 10, 0x432AFF97 );
  496. P( C, D, A, B, 14, 15, 0xAB9423A7 );
  497. P( B, C, D, A, 5, 21, 0xFC93A039 );
  498. P( A, B, C, D, 12, 6, 0x655B59C3 );
  499. P( D, A, B, C, 3, 10, 0x8F0CCC92 );
  500. P( C, D, A, B, 10, 15, 0xFFEFF47D );
  501. P( B, C, D, A, 1, 21, 0x85845DD1 );
  502. P( A, B, C, D, 8, 6, 0x6FA87E4F );
  503. P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
  504. P( C, D, A, B, 6, 15, 0xA3014314 );
  505. P( B, C, D, A, 13, 21, 0x4E0811A1 );
  506. P( A, B, C, D, 4, 6, 0xF7537E82 );
  507. P( D, A, B, C, 11, 10, 0xBD3AF235 );
  508. P( C, D, A, B, 2, 15, 0x2AD7D2BB );
  509. P( B, C, D, A, 9, 21, 0xEB86D391 );
  510. #undef F
  511. ctx->state[0] += A;
  512. ctx->state[1] += B;
  513. ctx->state[2] += C;
  514. ctx->state[3] += D;
  515. }
  516. static void md5_update( md5_context *ctx, uint8 *input, uint32 length ) {
  517. uint32 left, fill;
  518. if( !length )
  519. return;
  520. left = ctx->total[0] & 0x3F;
  521. fill = 64 - left;
  522. ctx->total[0] += length;
  523. ctx->total[0] &= 0xFFFFFFFF;
  524. if( ctx->total[0] < length )
  525. ctx->total[1]++;
  526. if( left && length >= fill ) {
  527. memcpy( (void *) (ctx->buffer + left),
  528. (void *) input, fill );
  529. md5_process( ctx, ctx->buffer );
  530. length -= fill;
  531. input += fill;
  532. left = 0;
  533. }
  534. while( length >= 64 ) {
  535. md5_process( ctx, input );
  536. length -= 64;
  537. input += 64;
  538. }
  539. if( length ) {
  540. memcpy( (void *) (ctx->buffer + left),
  541. (void *) input, length );
  542. }
  543. }
  544. static uint8 md5_padding[64] =
  545. {
  546. 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  547. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  548. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  549. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  550. };
  551. static void md5_finish( md5_context *ctx, uint8 digest[16] ) {
  552. uint32 last, padn;
  553. uint32 high, low;
  554. uint8 msglen[8];
  555. high = ( ctx->total[0] >> 29 )
  556. | ( ctx->total[1] << 3 );
  557. low = ( ctx->total[0] << 3 );
  558. PUT_UINT32( low, msglen, 0 );
  559. PUT_UINT32( high, msglen, 4 );
  560. last = ctx->total[0] & 0x3F;
  561. padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
  562. md5_update( ctx, md5_padding, padn );
  563. md5_update( ctx, msglen, 8 );
  564. PUT_UINT32( ctx->state[0], digest, 0 );
  565. PUT_UINT32( ctx->state[1], digest, 4 );
  566. PUT_UINT32( ctx->state[2], digest, 8 );
  567. PUT_UINT32( ctx->state[3], digest, 12 );
  568. }
  569. #include "sha1.h"
  570. HL_PRIM void HL_NAME(digest)( vbyte *out, vbyte *in, int length, int format ) {
  571. if( format & 256 ) {
  572. in = (vbyte*)hl_to_utf8((uchar*)in);
  573. length = (int)strlen((char*)in);
  574. }
  575. hl_blocking(true);
  576. switch( format & 0xFF ) {
  577. case 0:
  578. {
  579. md5_context ctx;
  580. md5_starts(&ctx);
  581. md5_update(&ctx,in,(uint32)length);
  582. md5_finish(&ctx,out);
  583. }
  584. break;
  585. case 1:
  586. {
  587. SHA1_CTX ctx;
  588. sha1_init(&ctx);
  589. sha1_update(&ctx,in,length);
  590. sha1_final(&ctx,out);
  591. }
  592. break;
  593. case 2:
  594. *((int*)out) = crc32(*(int*)out, in, length);
  595. break;
  596. case 3:
  597. *((int*)out) = adler32(*(int*)out, in, length);
  598. break;
  599. default:
  600. hl_blocking(false);
  601. hl_error("Unknown digest format %d",format&0xFF);
  602. break;
  603. }
  604. hl_blocking(false);
  605. }
  606. DEFINE_PRIM(_VOID, digest, _BYTES _BYTES _I32 _I32);