/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2022 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ │ above copyright notice and this permission notice appear in all copies. │ │ │ │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #ifndef __COSMOPOLITAN__ #include #include #endif #include "blc.h" #define ThomPikeCont(x) (0200 == (0300 & (x))) #define ThomPikeByte(x) ((x) & (((1 << ThomPikeMsb(x)) - 1) | 3)) #define ThomPikeLen(x) (7 - ThomPikeMsb(x)) #define ThomPikeMsb(x) ((255 & (x)) < 252 ? bsr(255 & ~(x)) : 1) #define ThomPikeMerge(x, y) ((x) << 6 | 077 & (y)) static inline int bsr(uint64_t x) { #if defined(__GNUC__) && !defined(__STRICT_ANSI__) return __builtin_clzll(x) ^ 63; #else static const char kDebruijn[64] = { 0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61, 54, 58, 35, 52, 50, 42, 21, 44, 38, 32, 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, 22, 10, 45, 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63, }; x |= x >> 1, x |= x >> 2; x |= x >> 4, x |= x >> 8; x |= x >> 16, x |= x >> 32; return kDebruijn[(x * 0x03f79d71b4cb0a89) >> 58]; #endif } wint_t fgetwc(FILE *f) { int c, n; wint_t b, x, y; if ((c = fgetc(f)) == EOF) return EOF; b = c; if (b < 0300) return b; n = ThomPikeLen(b); x = ThomPikeByte(b); while (--n) { if ((c = fgetc(f)) == EOF) return EOF; y = c; if (ThomPikeCont(y)) { x = ThomPikeMerge(x, y); } else { ungetc(y, f); return b; } } return x; }