st

st fork
git clone git://git.rr3.xyz/st
Log | Files | Refs | README | LICENSE

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 }