blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

blind-from-portable.c (3967B)


      1 /* See LICENSE file for copyright and license details. */
      2 #define INCLUDE_UINT16
      3 #include "common.h"
      4 
      5 USAGE("[-s]")
      6 
      7 static int strict = 1;
      8 
      9 #define CONV(ITYPE, SITYPE, OTYPE, EXPONENT, HA2EXPONENT, FRACTION)\
     10 	do {\
     11 		static int cache_i = 0;\
     12 		static ITYPE cache_in[] = {0, 0, 0, 0};\
     13 		static OTYPE cache_out[] = {0, 0, 0, 0};\
     14 		ITYPE exponent, fraction, signb;\
     15 		SITYPE sexponent;\
     16 		OTYPE ret, dexponent;\
     17 		if (portable == cache_in[cache_i]) {\
     18 			ret = cache_out[cache_i++];\
     19 			cache_i &= 3;\
     20 			return ret;\
     21 		}\
     22 		cache_in[cache_i] = portable;\
     23 		signb = portable >> (EXPONENT + FRACTION);\
     24 		exponent = (portable >> FRACTION) ^ (signb << EXPONENT);\
     25 		fraction = portable & (((ITYPE)1 << FRACTION) - 1);\
     26 		if (!exponent) {\
     27 			if (!fraction) {\
     28 				ret = (OTYPE)0.0;\
     29 			} else {\
     30 				sexponent = 1 - HA2EXPONENT - FRACTION;\
     31 				dexponent = (OTYPE)sexponent;\
     32 				ret = (OTYPE)fraction;\
     33 				ret *= pow((OTYPE)2.0, dexponent);\
     34 			}\
     35 		} else if (exponent + 1 == (ITYPE)1 << EXPONENT) {\
     36 			ret = (OTYPE)(fraction ? NAN : INFINITY);\
     37 		} else {\
     38 			fraction |= (ITYPE)1 << FRACTION;\
     39 			sexponent = (SITYPE)exponent;\
     40 			sexponent -= HA2EXPONENT + FRACTION;\
     41 			dexponent = (OTYPE)sexponent;\
     42 			ret = (OTYPE)fraction;\
     43 			ret *= pow((OTYPE)2.0, dexponent);\
     44 		}\
     45 		ret = signb ? -ret : ret;\
     46 		cache_out[cache_i++] = ret;\
     47 		cache_i &= 3;\
     48 		return ret;\
     49 	} while (0)
     50 
     51 #define PROCESS_FLOAT(ITYPE, OTYPE, BITS)\
     52 	do {\
     53 		size_t i, n;\
     54 		ITYPE *ibuf = (ITYPE *)(stream->buf);\
     55 		OTYPE *obuf = sizeof(ITYPE) == sizeof(OTYPE) ? (OTYPE *)(stream->buf)\
     56 			: alloca(sizeof(stream->buf) / sizeof(ITYPE) * sizeof(OTYPE));\
     57 		strict *= !USING_BINARY##BITS;\
     58 		if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\
     59 			eprintf("-s is supported not on this machine\n");\
     60 		if (stream->endian == HOST && !strict) {\
     61 			esend_stream(stream, STDOUT_FILENO, "<stdout>");\
     62 			break;\
     63 		}\
     64 		do {\
     65 			n = stream->ptr / sizeof(ITYPE);\
     66 			if (strict) {\
     67 				for (i = 0; i < n; i++)\
     68 					obuf[i] = conv_##OTYPE(letoh(ibuf[i]));\
     69 			} else {\
     70 				for (i = 0; i < n; i++)\
     71 					obuf[i] = *(OTYPE *)&(ITYPE){letoh(ibuf[i])};\
     72 			}\
     73 			ewriteall(STDOUT_FILENO, obuf, n * sizeof(OTYPE), "<stdout>");\
     74 			n *= sizeof(ITYPE);\
     75 			memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
     76 		} while (eread_stream(stream, SIZE_MAX));\
     77 		if (stream->ptr)\
     78 			eprintf("%s: incomplete frame\n", stream->file);\
     79 	} while (0)
     80 
     81 #define PROCESS_INTEGER(TYPE)\
     82 	do {\
     83 		size_t i, n;\
     84 		TYPE *buf = (TYPE *)(stream->buf);\
     85 		if (stream->endian == HOST) {\
     86 			esend_stream(stream, STDOUT_FILENO, "<stdout>");\
     87 			break;\
     88 		}\
     89 		do {\
     90 			n = stream->ptr / sizeof(TYPE);\
     91 			for (i = 0; i < n; i++)\
     92 				buf[i] = letoh(buf[i]);\
     93 			n *= sizeof(TYPE);\
     94 			ewriteall(STDOUT_FILENO, buf, n, "<stdout>");\
     95 			memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
     96 		} while (eread_stream(stream, SIZE_MAX));\
     97 		if (stream->ptr)\
     98 			eprintf("%s: incomplete frame\n", stream->file);\
     99 	} while (0)
    100 
    101 static double conv_double(uint64_t portable) {CONV(uint64_t, int64_t, double, 11, 1023, 52);}
    102 static float  conv_float (uint32_t portable) {CONV(uint32_t, int32_t, float,   8,  127, 23);}
    103 
    104 static void process_lf (struct stream *stream) {PROCESS_FLOAT(uint64_t, double, 64);}
    105 static void process_f  (struct stream *stream) {PROCESS_FLOAT(uint32_t, float,  32);}
    106 static void process_u16(struct stream *stream) {PROCESS_INTEGER(uint16_t);}
    107 
    108 int
    109 main(int argc, char *argv[])
    110 {
    111 	struct stream stream;
    112 	void (*process)(struct stream *stream);
    113 
    114 	ARGBEGIN {
    115 	case 's':
    116 		strict = 0;
    117 		break;
    118 	default:
    119 		usage();
    120 	} ARGEND;
    121 
    122 	if (argc)
    123 		usage();
    124 
    125 	eopen_stream(&stream, NULL);
    126 #if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN)
    127 	if (stream.endian == LITTLE)
    128 		stream.endian = HOST;
    129 #elif defined(HOST_ENDIAN_IS_BIG_ENDIAN)
    130 	if (stream.endian == BIG)
    131 		stream.endian = HOST;
    132 #endif
    133 
    134 	SELECT_PROCESS_FUNCTION(&stream);
    135 	fprint_stream_head(stdout, &stream);
    136 	efflush(stdout, "<stdout>");
    137 	process(&stream);
    138 	return 0;
    139 }