linenoise/utf8.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
/** * UTF-8 utility functions * * (c) 2010 Steve Bennett <steveb@workware.net.au> * * See LICENCE for licence details. */ #include <ctype.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include "utf8.h" #ifdef USE_UTF8 int utf8_fromunicode(char *p, unsigned short uc) { if (uc <= 0x7f) { *p = uc; return 1; } else if (uc <= 0x7ff) { *p++ = 0xc0 | ((uc & 0x7c0) >> 6); *p = 0x80 | (uc & 0x3f); return 2; } else { *p++ = 0xe0 | ((uc & 0xf000) >> 12); *p++ = 0x80 | ((uc & 0xfc0) >> 6); *p = 0x80 | (uc & 0x3f); return 3; } } int utf8_charlen(int c) { if ((c & 0x80) == 0) { return 1; } if ((c & 0xe0) == 0xc0) { return 2; } if ((c & 0xf0) == 0xe0) { return 3; } if ((c & 0xf8) == 0xf0) { return 4; } /* Invalid sequence */ return -1; } int utf8_strlen(const char *str, int bytelen) { int charlen = 0; if (bytelen < 0) { bytelen = strlen(str); } while (bytelen) { int c; int l = utf8_tounicode(str, &c); charlen++; str += l; bytelen -= l; } return charlen; } int utf8_index(const char *str, int index) { const char *s = str; while (index--) { int c; s += utf8_tounicode(s, &c); } return s - str; } int utf8_charequal(const char *s1, const char *s2) { int c1, c2; utf8_tounicode(s1, &c1); utf8_tounicode(s2, &c2); return c1 == c2; } int utf8_tounicode(const char *str, int *uc) { unsigned const char *s = (unsigned const char *)str; if (s[0] < 0xc0) { *uc = s[0]; return 1; } if (s[0] < 0xe0) { if ((s[1] & 0xc0) == 0x80) { *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80); return 2; } } else if (s[0] < 0xf0) { if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) { *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80); return 3; } } /* Invalid sequence, so just return the byte */ *uc = *s; return 1; } #endif |