← Back to davo.co
summaryrefslogtreecommitdiffstats
path: root/analyze-utf8.c
diff options
context:
space:
mode:
authorDavid Faulkner <[email protected]>2026-08-07 23:40:47 -0500
committerDavid Faulkner <[email protected]>2026-08-07 23:40:47 -0500
commitb3e9e62599532050fc776c5e8f076915b56c2235 (patch)
treeaf252346106a61b18cc6fc6fdbd32e962d096f1c /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.c57
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;
+}