blind-to-portable.c - blind - suckless command-line video editing utility
(HTM) git clone git://git.suckless.org/blind
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) 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 }