]> git.gir.st - base65536.git/blob - main.c
Code Import
[base65536.git] / main.c
1 /* base65536 en- and decoder with usage similar to GNU's base64.
2 (C) 2016 Tobias Girstmair, http://isticktoit.net/
3 Released under the GNU GPL v3. See LICENSE for details. */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include "base65536.h"
9
10 #define VERSION "0.1"
11
12 #define DEFAULT_WRAP 72
13 enum OPERATIONS {
14 ENCODE,
15 DECODE
16 };
17
18 void do_encode (FILE* in, FILE* out, int wrap_column);
19 void do_decode (FILE* in, FILE* out, int ignore_garbage);
20
21 int main (int argc, char** argv) {
22 int operation = ENCODE;
23 int wrap = DEFAULT_WRAP;
24 int garb_ignore = 0;
25 FILE* file_to_op = stdin;
26
27 for (int i = 1; i < argc; i++) {
28 //TODO: not efficient and ugly
29 if (strcmp (argv[i], "-d") == 0 || strcmp (argv[i], "--decode") == 0) {
30 operation = DECODE;
31 } else if (strcmp (argv[i], "-i") == 0 || strcmp (argv[i], "--ignore-garbage") == 0) {
32 garb_ignore = 1;
33 } else if (strcmp (argv[i], "-w") == 0) {
34 if (i == argc-1) {
35 fputs ("option required for argument -w", stderr);
36 return EXIT_FAILURE;
37 } else {
38 for (int j = 0; argv[i+1][j] != '\0'; j++)
39 if (argv[i+1][j] < '0' || argv[i+1][j] > '9') {
40 fputs ("option required for argument -w", stderr);
41 return EXIT_FAILURE;
42 }
43
44 wrap = atoi (argv[++i]);
45 }
46 } else if (strcmp (argv[i], "--help") == 0) {
47 fprintf (stderr, "help. ");
48 return EXIT_SUCCESS;
49 } else if (strcmp (argv[i], "--version") == 0) {
50 fprintf (stderr, "base65536 version %s", VERSION);
51 return EXIT_SUCCESS;
52 } else {
53 if (argv[i][0] == '-') {
54 fprintf (stderr, "%s is not a valid argument.\n", argv[i]);
55 return EXIT_FAILURE;
56 } else if (file_to_op == stdin) {
57 file_to_op = fopen (argv[i], "rb");
58 } else {
59 fputs ("cannot give more than one file.\n", stderr);
60 return EXIT_FAILURE;
61 }
62 }
63 }
64
65 if (operation == DECODE) {
66 do_decode (file_to_op, stdout, garb_ignore);
67 } else {
68 do_encode (file_to_op, stdout, wrap);
69 }
70
71 if (file_to_op != stdin) fclose (file_to_op);
72
73 return 0;
74 }
75
76
77 void do_encode (FILE* in, FILE* out, int wrap_column) {
78 int in_char[2];
79 char out_utf8[5];
80 int unicode_cp;
81 long cnt = 0;
82
83 while (1) {
84 if ((in_char[0] = getc(in)) == EOF) break;
85 in_char[1] = getc(in);
86
87 unicode_cp = base65536_encode_char (in_char);
88 codepoint_to_utf8 (unicode_cp, out_utf8);
89 fprintf (out, "%s%s", wrap_column&&!(cnt%wrap_column)&&cnt?"\n":"", out_utf8);
90 cnt++;
91 if (in_char[1] == EOF) break;
92 }
93 printf ("\n");
94 }
95
96 void do_decode (FILE* in, FILE* out, int ignore_garbage) {
97 int out_char[2];
98 char in_utf8[5];
99 int unicode_cp;
100
101 while (1) {
102 for (int i = 0; i < 5; i++) {
103 int c = getc (in);
104 if (c == EOF) {
105 return;
106 } else if (i != 0 && c < 0x80) { //start of new asciichar
107 ungetc (c, in);
108 in_utf8[i] = '\0';
109 break;
110 } else if (i != 0 && c >= 0xc0) { //start of new utf8char
111 ungetc (c, in);
112 in_utf8[i] = '\0';
113 break;
114 }
115 in_utf8[i] = c;
116 }
117 unicode_cp = utf8_to_codepoint (in_utf8);
118 //ignore ascii-chars, because base65k won't map to those (but
119 //whitespace may be added by the encoder / medium)
120 if (unicode_cp < 0x80) continue;
121
122 if (base65536_decode_char (unicode_cp, out_char) > 0) {
123 fputc (out_char[0], out);
124 fputc (out_char[1], out);
125 } else {
126 if (!ignore_garbage) {
127 fprintf (stderr, "Unrecognized glyph %s\n", in_utf8);
128 return;
129 }
130 }
131 }
132 }
Imprint / Impressum