]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-charset: test-charset can now be used to convert input file
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 21 May 2018 21:22:42 +0000 (00:22 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 25 May 2018 07:25:08 +0000 (07:25 +0000)
Usage: test-charset <charset> [<input path>]

If <input path> isn't specified, read input from stdin.  The input is
converted to UTF-8 and written to stdout.

src/lib-charset/test-charset.c

index 16985f5a2907440bee2f7905f251b4975fe863ef..2f9ba2b26ac509794da4b03c1744feedaa2df466 100644 (file)
@@ -1,10 +1,13 @@
 /* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "istream.h"
 #include "str.h"
 #include "test-common.h"
 #include "charset-utf8.h"
 
+#include <unistd.h>
+
 static void test_charset_is_utf8(void)
 {
        test_begin("charset_is_utf8");
@@ -154,7 +157,60 @@ static void test_charset_iconv_utf7_state(void)
 }
 #endif
 
-int main(void)
+static int convert(const char *charset, const char *path)
+{
+       struct istream *input;
+       const unsigned char *data;
+       size_t size;
+       struct charset_translation *trans;
+       buffer_t *buf = buffer_create_dynamic(default_pool, IO_BLOCK_SIZE);
+       enum charset_result last_ret = CHARSET_RET_OK;
+       bool seen_invalid_input = FALSE;
+
+       input = path == NULL ? i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE) :
+               i_stream_create_file(path, IO_BLOCK_SIZE);
+
+       if (charset_to_utf8_begin(charset, NULL, &trans) < 0)
+               i_fatal("Failed to initialize charset '%s'", charset);
+
+       size_t need = 1;
+       while (i_stream_read_bytes(input, &data, &size, need) > 0) {
+               last_ret = charset_to_utf8(trans, data, &size, buf);
+               if (size > 0)
+                       need = 1;
+               i_stream_skip(input, size);
+               switch (last_ret) {
+               case CHARSET_RET_OK:
+                       break;
+               case CHARSET_RET_INCOMPLETE_INPUT:
+                       need++;
+                       break;
+               case CHARSET_RET_INVALID_INPUT:
+                       seen_invalid_input = TRUE;
+                       break;
+               }
+               if (write(STDOUT_FILENO, buf->data, buf->used) != (ssize_t)buf->used)
+                       i_fatal("write(stdout) failed: %m");
+               buffer_set_used_size(buf, 0);
+       }
+       if (input->stream_errno != 0)
+               i_error("read() failed: %s", i_stream_get_error(input));
+       charset_to_utf8_end(&trans);
+       i_stream_destroy(&input);
+       buffer_free(&buf);
+
+       if (seen_invalid_input) {
+               i_error("Seen invalid input");
+               return 1;
+       }
+       if (last_ret == CHARSET_RET_INCOMPLETE_INPUT) {
+               i_error("Incomplete input");
+               return 2;
+       }
+       return 0;
+}
+
+int main(int argc, char *argv[])
 {
        static void (*const test_functions[])(void) = {
                test_charset_is_utf8,
@@ -167,5 +223,9 @@ int main(void)
                NULL
        };
 
+       if (argc >= 2) {
+               /* <charset> [<input path>] */
+               return convert(argv[1], argv[2]);
+       }
        return test_run(test_functions);
 }