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 }