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 }