diff options
| author | David Faulkner <[email protected]> | 2026-08-07 23:40:47 -0500 |
|---|---|---|
| committer | David Faulkner <[email protected]> | 2026-08-07 23:40:47 -0500 |
| commit | b3e9e62599532050fc776c5e8f076915b56c2235 (patch) | |
| tree | af252346106a61b18cc6fc6fdbd32e962d096f1c /analyze-utf8.c | |
Import official C23 code examples for Modern C (Jens Gustedt, 2024)HEADupstream-importmain
- Add official C source files, Makefile, c23-fallback.h, and LICENSE
- Update README.md with study mirror notice
Diffstat (limited to 'analyze-utf8.c')
| -rw-r--r-- | analyze-utf8.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/analyze-utf8.c b/analyze-utf8.c new file mode 100644 index 0000000..8e8f881 --- /dev/null +++ b/analyze-utf8.c @@ -0,0 +1,57 @@ +#include "mbstrings.h" +#include <uchar.h> +#include <stdio.h> +#include <locale.h> + +int main(void) { + // Make sure to have the platform's mb encoding on input. + setlocale(LC_CTYPE, ""); + // Holds the state of input/output buffering. + mbstate_t st = { }; + // collects the input mb sequence + char ib[23]; + // collects the current UTF-8 mb sequence + char8_t ob[5] = { }; + // the number of input characters for the current code point + size_t in = 0; + while (fgets(ib, sizeof(ib), stdin)) { + // Run through the current line. The last character is + // always reserved for the string terminator. + for (char* p = ib; (p-ib) < sizeof(ib)-1;) { + size_t const n = sizeof(ib)-1-(p-ib); + size_t const r = mbrtoc8(ob, p, n, &st); + switch (r) { // Handle the special cases. + case mbincomplete: p += n; in += n; continue; + case 0: case mbstored: case mbinvalid: goto INVAL; + } + p += r; in += r; + char8_t* cont = ob+1; // first character is already stored + while (mbrtoc8(cont, "", 1, &st) == mbstored) { + cont++; + } + // Now we have the whole UTF-8. Analyze the result. + printf("%s", ((cont-ob) == 1) ? "ASCII\t" : "UTF-8\t"); + for (char8_t* o = ob; o < cont; ++o) { + printf("|%02hhx", *o); + } + // fgets stopped at an end of a line + if (*ob == u8'\n') { + puts("|\t~ eol"); + in = 0; + break; + } else if (in == (cont-ob)) { + printf("|\t~ '%s'\n", ob); + } else { + printf("|\t%zu→%tu\n", in, (cont-ob)); + } + in = 0; + } + if (*ob != u8'\n') { + fputs("incomplete line\n", stderr); + } + } + return EXIT_SUCCESS; + INVAL: + fputs("input error, exiting\n", stderr); + return EXIT_FAILURE; +} |
