1 module cmd;
2 
3 
4 private static import core.memory;
5 private static import core.stdc.locale;
6 private static import core.stdc.stdio;
7 private static import core.stdc.stdlib;
8 private static import core.stdc.string;
9 private static import core.stdc.wchar_;
10 private static import std.string;
11 private static import wcwidth_cjk_compat.wcwidth;
12 
13 nothrow @nogc @live
14 private void dump_bigendian(core.stdc.stdio.FILE* fp, scope const void* p_in, size_t size)
15 
16 	do
17 	{
18 		size_t i = 0;
19 
20 		for (ubyte* p = cast(ubyte*)(p_in); i < size; i++) {
21 			core.stdc.stdio.fprintf(fp, " %02X", *(p + i));
22 		}
23 	}
24 
25 nothrow @nogc @live
26 private void dump_littleendian(core.stdc.stdio.FILE* fp, scope const void* p_in, size_t size)
27 
28 	do
29 	{
30 		int i = cast(int)(size) - 1;
31 
32 		for (ubyte* p = cast(ubyte*)(p_in); i >= 0; i--) {
33 			core.stdc.stdio.fprintf(fp, " %02X", *(p + i));
34 		}
35 	}
36 
37 int main(string[] argv)
38 
39 	do
40 	{
41 		if (argv.length < 2) {
42 			core.stdc.stdio.printf("Usage: %s STRING [...]\n", std..string.toStringz(argv[0]));
43 
44 			return 1;
45 		}
46 
47 		core.stdc.locale.setlocale(core.stdc.locale.LC_ALL, "");
48 		core.stdc.stdlib.mbtowc(null, null, 0);
49 
50 		char* mb_buf = cast(char*)(core.memory.pureMalloc(core.stdc.stdlib.MB_CUR_MAX + 1));
51 
52 		if (mb_buf == null) {
53 			core.stdc.stdio.fputs("allocation error.\n", core.stdc.stdio.stderr);
54 
55 			return 1;
56 		}
57 
58 		scope (exit) {
59 			assert(mb_buf != null);
60 			core.memory.pureFree(mb_buf);
61 			mb_buf = null;
62 		}
63 
64 		uint wc = void;
65 
66 		for (size_t i = 1; i < argv.length; i++) {
67 			immutable (char)* mb_p = std..string.toStringz(argv[i]);
68 			size_t mb_len = core.stdc..string.strlen(mb_p);
69 
70 			while (mb_len > 0) {
71 				core.stdc.wchar_.wchar_t wc_temp = void;
72 				int mb_consumed = core.stdc.stdlib.mbtowc(&wc_temp, mb_p, mb_len);
73 
74 				if (mb_consumed == -1) {
75 					core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "%s: ERROR: Invalid multibyte sequence: argv=%zd, index=%d, bytes:", std..string.toStringz(argv[0]), i, cast(int)(mb_p - std..string.toStringz(argv[i])));
76 					.dump_bigendian(core.stdc.stdio.stderr, mb_p, mb_len);
77 					core.stdc.stdio.fputs("\n", core.stdc.stdio.stderr);
78 
79 					return 1;
80 				}
81 
82 				wc = wc_temp;
83 				int wc_width = wcwidth_cjk_compat.wcwidth.wcwidth_cjk(wc);
84 
85 				core.stdc..string.strncpy(mb_buf, mb_p, mb_consumed);
86 				mb_buf[mb_consumed] = '\0';
87 
88 				core.stdc.stdio.printf("%d", wc_width);
89 
90 				version (BigEndian) {
91 					.dump_bigendian(core.stdc.stdio.stdout, &wc, uint.sizeof);
92 				} else {
93 					.dump_littleendian(core.stdc.stdio.stdout, &wc, uint.sizeof);
94 				}
95 
96 				core.stdc.stdio.printf("\t%s\n", mb_buf);
97 
98 				mb_p += mb_consumed;
99 				mb_len -= mb_consumed;
100 			}
101 		}
102 
103 		return 0;
104 	}