blind-from-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-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 }