blind

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

blind-to-portable.c (4415B)


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