util.c (4997B)
1 #include <ctype.h> 2 #include <errno.h> 3 #include <unistd.h> 4 #include <stdarg.h> 5 #include <stdint.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <wchar.h> 10 #include <X11/Xlib.h> 11 12 #include "util.h" 13 #include "config.h" 14 15 static Rune utf8decbyte(char, size_t *); 16 static char utf8encbyte(Rune, size_t); 17 static size_t utf8validate(Rune *, size_t); 18 static char base64dec_getc(const char **); 19 static uint termkeymod(uint xmod); 20 21 static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; 22 static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; 23 static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; 24 static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; 25 26 static const char base64_digits[] = { 27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 30 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 31 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 32 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 33 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 34 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43 }; 44 45 void 46 die(const char *errstr, ...) 47 { 48 va_list ap; 49 50 va_start(ap, errstr); 51 vfprintf(stderr, errstr, ap); 52 va_end(ap); 53 exit(1); 54 } 55 56 void * 57 xmalloc(size_t len) 58 { 59 void *p; 60 61 if ((p = malloc(len)) == NULL) 62 die("malloc: %s\n", strerror(errno)); 63 64 return p; 65 } 66 67 void * 68 xrealloc(void *p, size_t len) 69 { 70 if ((p = realloc(p, len)) == NULL) 71 die("realloc: %s\n", strerror(errno)); 72 73 return p; 74 } 75 76 char * 77 xstrdup(const char *s) 78 { 79 char *p; 80 81 if ((p = strdup(s)) == NULL) 82 die("strdup: %s\n", strerror(errno)); 83 84 return p; 85 } 86 87 ssize_t 88 xwrite(int fd, const char *s, size_t len) 89 { 90 size_t aux = len; 91 ssize_t r; 92 93 while (len > 0) { 94 r = write(fd, s, len); 95 if (r < 0) 96 return r; 97 len -= r; 98 s += r; 99 } 100 101 return aux; 102 } 103 104 size_t 105 utf8dec(const char *c, Rune *u, size_t clen) 106 { 107 size_t i, j, len, type; 108 Rune udecoded; 109 110 *u = UTF_INVALID; 111 if (!clen) 112 return 0; 113 udecoded = utf8decbyte(c[0], &len); 114 if (!BETWEEN(len, 1, UTF_SIZ)) 115 return 1; 116 for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { 117 udecoded = (udecoded << 6) | utf8decbyte(c[i], &type); 118 if (type != 0) 119 return j; 120 } 121 if (j < len) 122 return 0; 123 *u = udecoded; 124 utf8validate(u, len); 125 126 return len; 127 } 128 129 Rune 130 utf8decbyte(char c, size_t *i) 131 { 132 for (*i = 0; *i < LEN(utfmask); ++(*i)) { 133 if (((uchar)c & utfmask[*i]) == utfbyte[*i]) 134 return (uchar)c & ~utfmask[*i]; 135 } 136 137 return 0; 138 } 139 140 size_t 141 utf8enc(Rune u, char *c) 142 { 143 size_t len, i; 144 145 len = utf8validate(&u, 0); 146 if (len > UTF_SIZ) 147 return 0; 148 149 for (i = len - 1; i != 0; --i) { 150 c[i] = utf8encbyte(u, 0); 151 u >>= 6; 152 } 153 c[0] = utf8encbyte(u, len); 154 155 return len; 156 } 157 158 char 159 utf8encbyte(Rune u, size_t i) 160 { 161 return utfbyte[i] | (u & ~utfmask[i]); 162 } 163 164 size_t 165 utf8validate(Rune *u, size_t i) 166 { 167 if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) 168 *u = UTF_INVALID; 169 for (i = 1; *u > utfmax[i]; ++i) 170 ; 171 172 return i; 173 } 174 175 char * 176 base64dec(const char *src) 177 { 178 size_t in_len = strlen(src); 179 char *result, *dst; 180 181 if (in_len % 4) 182 in_len += 4 - (in_len % 4); 183 result = dst = xmalloc(in_len / 4 * 3 + 1); 184 while (*src) { 185 int a = base64_digits[(uchar) base64dec_getc(&src)]; 186 int b = base64_digits[(uchar) base64dec_getc(&src)]; 187 int c = base64_digits[(uchar) base64dec_getc(&src)]; 188 int d = base64_digits[(uchar) base64dec_getc(&src)]; 189 190 /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ 191 if (a == -1 || b == -1) 192 break; 193 194 *dst++ = (a << 2) | ((b & 0x30) >> 4); 195 if (c == -1) 196 break; 197 *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); 198 if (d == -1) 199 break; 200 *dst++ = ((c & 0x03) << 6) | d; 201 } 202 *dst = '\0'; 203 return result; 204 } 205 206 char 207 base64dec_getc(const char **src) 208 { 209 while (**src && !isprint(**src)) 210 (*src)++; 211 return **src ? *((*src)++) : '='; /* emulate padding if string ends */ 212 } 213 214 size_t 215 csienc(char *buf, size_t len, uint state, uint n, uint m, char c) 216 { 217 uint mod; 218 219 mod = termkeymod(state & ~m); 220 if (mod > 1) 221 return snprintf(buf, len, "\033[%d;%d%c", n, mod, c); 222 else if (n > 1) 223 return snprintf(buf, len, "\033[%d%c", n, c); 224 else 225 return snprintf(buf, len, "\033[%c", c); 226 } 227 228 uint 229 termkeymod(uint xmod) 230 { 231 return 1 + ((xmod&SHFT ? 1<<0 : 0) 232 | (xmod&ALT ? 1<<1 : 0) 233 | (xmod&CTRL ? 1<<2 : 0)); 234 }