2 * Copyright (c) 2011 Bryan O'Sullivan <bos@serpentine.com>.
4 * Portions copyright (c) 2008-2010 Björn Höhrmann <bjoern@hoehrmann.de>.
6 * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
12#include "text_cbits.h"
14void _hs_text_memcpy(void *dest, size_t doff, const void *src, size_t soff,
17 memcpy(dest + (doff<<1), src + (soff<<1), n<<1);
20int _hs_text_memcmp(const void *a, size_t aoff, const void *b, size_t boff,
23 return memcmp(a + (aoff<<1), b + (boff<<1), n<<1);
29static const uint8_t utf8d[] = {
31 * The first part of the table maps bytes to character classes that
32 * to reduce the size of the transition table and create bitmasks.
34 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
35 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 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, 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, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
38 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
39 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
40 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
41 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
44 * The second part is a transition table that maps a combination of
45 * a state of the automaton and a character class to a state.
47 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
48 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
49 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
50 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
51 12,36,12,12,12,12,12,12,12,12,12,12,
55decode(uint32_t *state, uint32_t* codep, uint32_t byte) {
56 uint32_t type = utf8d[byte];
58 *codep = (*state != UTF8_ACCEPT) ?
59 (byte & 0x3fu) | (*codep << 6) :
60 (0xff >> type) & (byte);
62 return *state = utf8d[256 + *state + type];
66 * The ISO 8859-1 (aka latin-1) code points correspond exactly to the first 256 unicode
67 * code-points, therefore we can trivially convert from a latin-1 encoded bytestring to
71_hs_text_decode_latin1(uint16_t *dest, const uint8_t *src,
72 const uint8_t *srcend)
74 const uint8_t *p = src;
76#if defined(__i386__) || defined(__x86_64__)
77 /* This optimization works on a little-endian systems by using
78 (aligned) 32-bit loads instead of 8-bit loads
81 /* consume unaligned prefix */
82 while (p != srcend && (uintptr_t)p & 0x3)
85 /* iterate over 32-bit aligned loads */
86 while (p < srcend - 3) {
87 const uint32_t w = *((const uint32_t *)p);
90 *dest++ = (w >> 8) & 0xff;
91 *dest++ = (w >> 16) & 0xff;
92 *dest++ = (w >> 24) & 0xff;
98 /* handle unaligned suffix */
104 * A best-effort decoder. Runs until it hits either end of input or
105 * the start of an invalid byte sequence.
107 * At exit, we update *destoff with the next offset to write to, *src
108 * with the next source location past the last one successfully
109 * decoded, and return the next source location to read from.
111 * Moreover, we expose the internal decoder state (state0 and
112 * codepoint0), allowing one to restart the decoder after it
113 * terminates (say, due to a partial codepoint).
115 * In particular, there are a few possible outcomes,
117 * 1) We decoded the buffer entirely:
118 * In this case we return srcend
119 * state0 == UTF8_ACCEPT
121 * 2) We met an invalid encoding
122 * In this case we return the address of the first invalid byte
123 * state0 == UTF8_REJECT
125 * 3) We reached the end of the buffer while decoding a codepoint
126 * In this case we return a pointer to the first byte of the partial codepoint
127 * state0 != UTF8_ACCEPT, UTF8_REJECT
130#if defined(__GNUC__) || defined(__clang__)
131static inline uint8_t const *
132_hs_text_decode_utf8_int(uint16_t *const dest, size_t *destoff,
133 const uint8_t **src, const uint8_t *srcend,
134 uint32_t *codepoint0, uint32_t *state0)
135 __attribute((always_inline));
138static inline uint8_t const *
139_hs_text_decode_utf8_int(uint16_t *const dest, size_t *destoff,
140 const uint8_t **src, const uint8_t *srcend,
141 uint32_t *codepoint0, uint32_t *state0)
143 uint16_t *d = dest + *destoff;
144 const uint8_t *s = *src, *last = *src;
145 uint32_t state = *state0;
146 uint32_t codepoint = *codepoint0;
149#if defined(__i386__) || defined(__x86_64__)
151 * This code will only work on a little-endian system that
152 * supports unaligned loads.
154 * It gives a substantial speed win on data that is purely or
155 * partly ASCII (e.g. HTML), at only a slight cost on purely
159 if (state == UTF8_ACCEPT) {
160 while (s < srcend - 4) {
161 codepoint = *((uint32_t *) s);
162 if ((codepoint & 0x80808080) != 0)
167 * Tried 32-bit stores here, but the extra bit-twiddling
168 * slowed the code down.
171 *d++ = (uint16_t) (codepoint & 0xff);
172 *d++ = (uint16_t) ((codepoint >> 8) & 0xff);
173 *d++ = (uint16_t) ((codepoint >> 16) & 0xff);
174 *d++ = (uint16_t) ((codepoint >> 24) & 0xff);
180 if (decode(&state, &codepoint, *s++) != UTF8_ACCEPT) {
181 if (state != UTF8_REJECT)
186 if (codepoint <= 0xffff)
187 *d++ = (uint16_t) codepoint;
189 *d++ = (uint16_t) (0xD7C0 + (codepoint >> 10));
190 *d++ = (uint16_t) (0xDC00 + (codepoint & 0x3FF));
196 *codepoint0 = codepoint;
204_hs_text_decode_utf8_state(uint16_t *const dest, size_t *destoff,
206 const uint8_t *srcend,
207 uint32_t *codepoint0, uint32_t *state0)
209 uint8_t const *ret = _hs_text_decode_utf8_int(dest, destoff, src, srcend,
211 if (*state0 == UTF8_REJECT)
217 * Helper to decode buffer and discard final decoder state
220_hs_text_decode_utf8(uint16_t *const dest, size_t *destoff,
221 const uint8_t *src, const uint8_t *const srcend)
224 uint32_t state = UTF8_ACCEPT;
225 uint8_t const *ret = _hs_text_decode_utf8_int(dest, destoff, &src, srcend,
227 /* Back up if we have an incomplete or invalid encoding */
228 if (state != UTF8_ACCEPT)
234_hs_text_encode_utf8(uint8_t **destp, const uint16_t *src, size_t srcoff,
237 const uint16_t *srcend;
238 uint8_t *dest = *destp;
241 srcend = src + srclen;
244#if defined(__x86_64__)
245 while (srcend - src >= 4) {
246 uint64_t w = *((uint64_t *) src);
248 if (w & 0xFF80FF80FF80FF80ULL) {
249 if (!(w & 0x000000000000FF80ULL)) {
250 *dest++ = w & 0xFFFF;
252 if (!(w & 0x00000000FF800000ULL)) {
253 *dest++ = (w >> 16) & 0xFFFF;
255 if (!(w & 0x0000FF8000000000ULL)) {
256 *dest++ = (w >> 32) & 0xFFFF;
263 *dest++ = w & 0xFFFF;
264 *dest++ = (w >> 16) & 0xFFFF;
265 *dest++ = (w >> 32) & 0xFFFF;
272 while (srcend - src >= 2) {
273 uint32_t w = *((uint32_t *) src);
277 *dest++ = w & 0xFFFF;
283 while (src < srcend) {
288 /* An ASCII byte is likely to begin a run of ASCII bytes.
289 Falling back into the fast path really helps performance. */
292 else if (w <= 0x7FF) {
293 *dest++ = (w >> 6) | 0xC0;
294 *dest++ = (w & 0x3f) | 0x80;
296 else if (w < 0xD800 || w > 0xDBFF) {
297 *dest++ = (w >> 12) | 0xE0;
298 *dest++ = ((w >> 6) & 0x3F) | 0x80;
299 *dest++ = (w & 0x3F) | 0x80;
301 uint32_t c = ((((uint32_t) w) - 0xD800) << 10) +
302 (((uint32_t) *src++) - 0xDC00) + 0x10000;
303 *dest++ = (c >> 18) | 0xF0;
304 *dest++ = ((c >> 12) & 0x3F) | 0x80;
305 *dest++ = ((c >> 6) & 0x3F) | 0x80;
306 *dest++ = (c & 0x3F) | 0x80;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list