Skip to content

Commit 917cb99

Browse files
committed
Update charater converter steams to funnel statefull logic, including windows console implementation and fix cat_ext exmaple, tested on Windows
1 parent f0b9125 commit 917cb99

18 files changed

Lines changed: 499 additions & 318 deletions

File tree

‎examples/cat_ext/cat_ext.cbp‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
<Option compiler="gcc" />
1414
<Option parameters="utf8-bom.txt" />
1515
<Compiler>
16-
<Add option="-std=gnu++23" />
17-
<Add option="-ggdb" />
18-
<Add option="-Og" />
16+
<Add option="-std=gnu++26" />
1917
<Add option="-g" />
2018
<Add option="-fexceptions" />
2119
<Add option="-D_WIN32_WINNT=0x0A00" />

‎examples/cat_ext/main.cpp‎

Lines changed: 65 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,118 @@
11
/*
2-
*
3-
* Copyright (c) 2016-2023
2+
* Copyright (c) 2016-2026
43
* Viktor Gubin
54
*
65
* Use, modification and distribution are subject to the
76
* Boost Software License, Version 1.0. (See accompanying file
87
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
98
*/
109

11-
/*
12-
* This example demonstrate IO library text API possibilities
13-
* It works as POSIX utility cat https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/cat.html
14-
* and in the same time auto-detect input file character set and convert it to system UNCODE before printing to console
15-
*/
16-
1710
#include <vector>
18-
1911
#include <io/core/files.hpp>
2012
#include <io/console/console.hpp>
21-
2213
#include <io/textapi/charset_detector.hpp>
2314
#include <io/textapi/charset_converter.hpp>
2415

25-
void print_error(io::console_error_stream& err,const char* reason, const char* f, const char* what);
26-
void file_to_console(std::error_code& ec,io::file&& f, io::console_out_writer& out);
16+
/// Prints an error into console if any
17+
void print_error(io::console_error_stream& err, const char* reason, const char* f, const char* what);
18+
/// Prints a text file into console, detect character set automatically and reconvert into system UNICODE
19+
void file_to_console(std::error_code& ec, io::file&& f, io::console_out_writer& out);
2720

2821
int main(int argc, const char** argv)
2922
{
3023
int ret = ERROR_SUCCESS;
3124

3225
io::console cons;
3326
io::console_error_stream cerr(cons);
34-
3527
io::console_out_writer out(cons);
3628

37-
if(argc < 2) {
38-
cerr << io::cclr::light_red << "No files to display." << io::cclr::reset << std::endl << std::endl;
29+
if (argc < 2) {
30+
cerr << io::cclr::light_red << "No files to display." << io::cclr::reset << std::endl << std::endl;
3931
cerr << "\tCommand usage : ";
40-
cerr << io::cclr::navy_green << "cat_ext " << io::cclr::reset;
32+
cerr << io::cclr::navy_green << "cat_ext " << io::cclr::reset;
4133
cerr << '[' << io::cclr::magenta << "file..." << io::cclr::reset << ']' << std::endl;
42-
ret = EINVAL;
34+
return EINVAL;
4335
}
4436

4537
std::error_code ec;
46-
for(std::size_t i =1; i < static_cast<std::size_t>(argc); i++) {
38+
for (std::size_t i = 1; i < static_cast<std::size_t>(argc); i++) {
4739
io::file src_file(argv[i]);
48-
if( !src_file.exist() ) {
40+
if (!src_file.exist()) {
4941
ret = ENOENT;
50-
print_error(cerr,"Requested",argv[i],"not found");
42+
print_error(cerr, "Requested", argv[i], "not found");
5143
break;
5244
}
53-
file_to_console(ec,std::move(src_file), out);
54-
if(ec) {
45+
46+
file_to_console(ec, std::move(src_file), out);
47+
if (ec) {
5548
ret = ec.value();
56-
print_error(cerr,"Issue with",argv[i], ec.message().data() );
49+
print_error(cerr, "Issue with", argv[i], ec.message().data());
5750
break;
5851
}
5952
}
6053

6154
return ret;
6255
}
6356

64-
65-
void print_error(io::console_error_stream& err,const char* reason, const char* f, const char* what)
57+
void print_error(io::console_error_stream& err, const char* reason, const char* f, const char* what)
6658
{
67-
err << io::cclr::light_red << "Error" << io::cclr::reset << ": ";
59+
err << io::cclr::light_red << "Error" << io::cclr::reset << ": ";
6860
err << reason << " file ";
6961
err << io::cclr::yellow << f << io::cclr::reset;
7062
err << ' ' << what << io::cclr::reset << std::endl;
7163
}
7264

73-
#ifdef __IO_WINDOWS_BACKEND__
74-
static const char* WENDL = "\r\n";
75-
#else
76-
static const char* WENDL = "\n";
77-
#endif // __IO_WINDOWS_BACKEND__
78-
79-
80-
io::s_pump data_pump_for_charset(std::error_code& ec,const io::s_read_channel& rch, const io::charset* chst, io::byte_buffer&& buff)
65+
io::s_pump data_pump_for_charset(std::error_code& ec, const io::s_read_channel& rch, const io::charset* chst, io::byte_buffer&& buff)
8166
{
82-
io::s_pump ret;
83-
if(io::code_pages::utf8() == chst)
84-
ret = io::buffered_channel_pump::create(ec, rch, std::forward<io::byte_buffer>(buff) );
85-
else
86-
ret = io::charset_converting_channel_pump::create(ec, rch, chst, io::code_pages::utf8(), std::forward<io::byte_buffer>(buff) );
87-
return ret;
67+
if (io::code_pages::utf8() == chst) {
68+
return io::buffered_channel_pump::create(ec, rch, std::move(buff));
69+
}
70+
return io::charset_converting_channel_pump::create(ec, rch, chst, io::code_pages::utf8(), std::move(buff));
8871
}
8972

90-
void file_to_console(std::error_code& ec,io::file&& f, io::console_out_writer& out)
73+
void file_to_console(std::error_code& ec, io::file&& f, io::console_out_writer& out)
9174
{
9275
io::s_read_channel rch = f.open_for_read(ec);
93-
if(!ec) {
94-
// detect character set
95-
io::byte_buffer buff = io::byte_buffer::allocate(ec, 1024);
96-
if(!ec) {
97-
std::size_t read = rch->read(ec, const_cast<uint8_t*>(buff.position().get()), buff.capacity());
98-
if(!ec && read > 0 ) {
99-
io::s_charset_detector chdet = io::charset_detector::create(ec);
100-
buff.move(read);
101-
buff.flip();
102-
auto detect_status = chdet->detect( ec, buff.position().get(), read );
103-
if(!ec) {
104-
if(!detect_status) {
105-
ec = std::make_error_code(std::errc::illegal_byte_sequence);
106-
}
107-
else {
108-
out.write("Detected : ");
109-
out.write(detect_status.character_set()->name());
110-
out.write(WENDL);
111-
io::s_pump pmp = data_pump_for_charset(ec, rch, detect_status.character_set(), std::move(buff) );
112-
if(!ec) {
113-
io::reader in( std::move(pmp) );
114-
char tmp[1024] = {'\0'};
115-
std::size_t read = 0;
116-
do {
117-
read = in.read(ec, tmp, 1024);
118-
if(read > 0 && !ec)
119-
out.write(tmp, read);
120-
} while(read > 0 && !ec);
121-
}
122-
}
123-
}
124-
}
125-
}
76+
if (ec)
77+
return;
78+
79+
io::byte_buffer buff = io::byte_buffer::allocate(ec, 1024);
80+
if (ec)
81+
return;
82+
83+
// Read initial block to detect character set
84+
std::size_t bytes_read = rch->read(ec, const_cast<uint8_t*>(buff.position().get()), buff.capacity());
85+
if (ec || bytes_read == 0)
86+
return;
87+
88+
io::s_charset_detector chdet = io::charset_detector::create(ec);
89+
if (ec)
90+
return;
91+
92+
buff.move(bytes_read);
93+
buff.flip();
94+
95+
auto detect_status = chdet->detect(ec, buff.position().get(), bytes_read);
96+
if (ec)
97+
return;
98+
99+
if (!detect_status) {
100+
ec = std::make_error_code(std::errc::illegal_byte_sequence);
101+
return;
102+
}
103+
104+
// Print detected charset
105+
out.write("Detected : ");
106+
out.writeln(detect_status.character_set()->name());
107+
108+
io::s_pump pmp = data_pump_for_charset(ec, rch, detect_status.character_set(), std::move(buff));
109+
if (ec)
110+
return;
111+
112+
// Stream the converted content directly to the console
113+
io::reader in(std::move(pmp));
114+
char tmp[1024];
115+
while ((bytes_read = in.read(ec, tmp, sizeof(tmp))) > 0 && !ec) {
116+
out.write(tmp, bytes_read);
126117
}
127118
}

‎libio/include/io/config/compiler/gcc.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@
149149
# define io_snprintf __builtin_snprintf
150150
#endif
151151
152-
// in case of intel compiler
152+
// in case of Intel compiler
153153
#ifdef __ICC
154154
# define io_clz(__x) _lzcnt_u32((__x))
155155
# ifdef __LP64__

0 commit comments

Comments
 (0)