slweb

Једноставни генератор статичких веб страна
git clone https://git.sr.ht/~strahinja/slweb
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

utf8.c (3524B)


      1 /* This program is licensed under the terms of GNU GPL v3 or (at your option)
      2  * any later version. Copyright (C) 2020-2026  Страхиња Радић.
      3  * See the file LICENSE for exact copyright and license details. */
      4 
      5 #include "utf8.h"
      6 
      7 /*
      8  *	00000000 -- 0000007F: 	0xxxxxxx
      9  *		(2^7 = 128 chars)
     10  *	00000080 -- 000007FF: 	110xxxxx 10xxxxxx
     11  *		(2^5 = 32 chars)
     12  *	00000800 -- 0000FFFF: 	1110xxxx 10xxxxxx 10xxxxxx
     13  *		(2^4 = 16 chars)
     14  *	00010000 -- 001FFFFF: 	11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
     15  *		(2^3 = 8 chars)
     16  *	00200000 -- 007FFFFF: 	111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
     17  *		(2^2 = 4 chars)
     18  *	00800000 -- 00FFFFFF: 	1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
     19  *								10xxxxxx
     20  *		(2^1 = 2 chars)
     21  */
     22 
     23 /* clang-format off */
     24 const int utf_length_table[256] = {
     25 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     26 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 32 */
     27 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     28 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64 */
     29 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     30 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96 */
     31 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     32 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 128 */
     33 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     34 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 160 */
     35 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     36 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 192 */
     37 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     38 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 224 */
     39 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
     40 	4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1, /* 256 */
     41 };
     42 /* clang-format on */
     43 
     44 const int extract_masks[6] = {XMASK1, XMASK2, XMASK3, XMASK4, XMASK5, XMASK6};
     45 
     46 int
     47 u8_rune_to_u32(u32* to, const u8* from, size_t* from_delta)
     48 {
     49 	const u8* pfrom = from;
     50 	if (!from)
     51 		return 1;
     52 	*from_delta = 0;
     53 	int len	    = utf_length_table[*from];
     54 	*to	    = *from & extract_masks[len - 1];
     55 	for (int i = 1; i < len; i++)
     56 	{
     57 		pfrom = from + i;
     58 		if (!*pfrom)
     59 			return 1;
     60 		*to <<= 6;
     61 		*to |= *pfrom & XMASKR;
     62 	}
     63 	*from_delta = len;
     64 
     65 	return 0;
     66 }
     67 
     68 int
     69 u32_rune_to_u8(u8* to, const u32 from)
     70 {
     71 	u32 cfrom = from;
     72 	u8 start  = 0;
     73 	int len	  = 0;
     74 	if (from >= BOUND6)
     75 	{
     76 		start = START6;
     77 		len   = 6;
     78 	}
     79 	else if (from >= BOUND5)
     80 	{
     81 		start = START5;
     82 		len   = 5;
     83 	}
     84 	else if (from >= BOUND4)
     85 	{
     86 		start = START4;
     87 		len   = 4;
     88 	}
     89 	else if (from >= BOUND3)
     90 	{
     91 		start = START3;
     92 		len   = 3;
     93 	}
     94 	else if (from >= BOUND2)
     95 	{
     96 		start = START2;
     97 		len   = 2;
     98 	}
     99 	else
    100 	{
    101 		start = START1;
    102 		len   = 1;
    103 	}
    104 	for (int i = len - 1; i > 0; i--)
    105 	{
    106 		to[i] = STARTR | (cfrom & XMASKR);
    107 		cfrom >>= 6;
    108 	}
    109 	to[0] = start | cfrom;
    110 	return len;
    111 }
    112 
    113 int
    114 u8_to_u32(u32* to, const u8* from, const ssize_t max, size_t* from_delta)
    115 {
    116 	const u8* pfrom = from;
    117 	u32* pto	= to;
    118 	if (!from)
    119 		return 1;
    120 	size_t delta = 0;
    121 	*from_delta  = 0;
    122 	while (pfrom - from < max && *pfrom)
    123 	{
    124 		int result = u8_rune_to_u32(pto, pfrom, &delta);
    125 		if (result)
    126 			return result;
    127 		pto++;
    128 		pfrom += delta;
    129 		*from_delta += delta;
    130 	}
    131 	*pto = 0;
    132 	return 0;
    133 }
    134 
    135 int
    136 u32_to_u8(u8* to, const u32* from, const ssize_t max)
    137 {
    138 	const u32* pfrom = from;
    139 	u8* pto		 = to;
    140 	int len		 = 0;
    141 	if (!from)
    142 		return 0;
    143 	while (pfrom - from < max && *pfrom)
    144 	{
    145 		size_t delta = u32_rune_to_u8(pto, *pfrom);
    146 		pto += delta;
    147 		len += delta;
    148 		pfrom++;
    149 	}
    150 	return len;
    151 }
    152 
    153 size_t
    154 u32_strlen(const u32* s, const ssize_t max)
    155 {
    156 	const u32* ps = s;
    157 	while (ps && ps - s < max && *ps)
    158 		ps++;
    159 	return ps - s;
    160 }