Skip to content

Commit 8001518

Browse files
authored
Add files via upload
0 parents  commit 8001518

File tree

2 files changed

+296
-0
lines changed

2 files changed

+296
-0
lines changed

FileToCArray.hpp

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
#include <nana/gui.hpp>
2+
#include <nana/gui/widgets/label.hpp>
3+
#include <nana/gui/filebox.hpp>
4+
#include <nana/gui/widgets/button.hpp>
5+
#include <nana/gui/widgets/progress.hpp>
6+
#include <nana/gui/msgbox.hpp>
7+
8+
#include <iostream>
9+
#include <fstream>
10+
#include <thread>
11+
#include <atomic>
12+
13+
using std::cout;
14+
using std::endl;
15+
16+
class ftca_form : public nana::form
17+
{
18+
nana::label l_in, l_inpath, l_out, l_outpath;
19+
nana::button btn_in, btn_out, btn_gen;
20+
nana::progress prog;
21+
22+
std::filesystem::path inpath, outpath;
23+
int line_chars_max{120};
24+
std::atomic<bool> working{false}, abort{false};
25+
const char *gen_text{"Generate C array"};
26+
27+
public:
28+
29+
ftca_form() : nana::form(nana::API::make_center(600, 185), appear::decorate<appear::minimize>())
30+
{
31+
nana::place &plc{get_place()};
32+
const auto bg{nana::colors::white};
33+
34+
nana::API::track_window_size(handle(), {600, 185}, false);
35+
caption("File To C Array");
36+
bgcolor(bg);
37+
38+
div("vert margin=15 < weight=20 <l_in weight=70><weight=15><l_inpath><weight=15><btn_in weight=20> >"
39+
"<weight=15> < weight=20 <l_out weight=70><weight=15><l_outpath><weight=15><btn_out weight=20> >"
40+
"<weight=15> <prog weight=30> <weight=15> <btn_gen weight=40>"
41+
);
42+
43+
l_in.create(handle(), true);
44+
l_in.caption("Input file:");
45+
l_in.bgcolor(bg);
46+
l_in.text_align(nana::align::right, nana::align_v::center);
47+
plc["l_in"] << l_in;
48+
49+
l_inpath.create(handle(), true);
50+
l_inpath.bgcolor(nana::color{"#eef6ee"});
51+
l_inpath.text_align(nana::align::center, nana::align_v::center);
52+
l_inpath.caption("Select a file you want to make a C array out of.");
53+
plc["l_inpath"] << l_inpath;
54+
55+
btn_in.create(handle(), true);
56+
btn_in.caption("...");
57+
btn_in.bgcolor(bg);
58+
plc["btn_in"] << btn_in;
59+
60+
l_out.create(handle(), true);
61+
l_out.caption("Output file:");
62+
l_out.bgcolor(bg);
63+
l_out.text_align(nana::align::right, nana::align_v::center);
64+
plc["l_out"] << l_out;
65+
66+
l_outpath.create(handle(), true);
67+
l_outpath.bgcolor(nana::color{"#eef6ee"});
68+
l_outpath.text_align(nana::align::center, nana::align_v::center);
69+
l_outpath.caption("Choose which file you want to save the C array to.");
70+
plc["l_outpath"] << l_outpath;
71+
72+
btn_out.create(handle(), true);
73+
btn_out.caption("...");
74+
btn_out.bgcolor(bg);
75+
plc["btn_out"] << btn_out;
76+
77+
btn_gen.create(handle(), true);
78+
btn_gen.caption(gen_text);
79+
btn_gen.bgcolor(nana::colors::white);
80+
btn_gen.fgcolor(nana::color{"#406080"});
81+
btn_gen.typeface({typeface().name(), 15, nana::paint::font::font_style{800}});
82+
btn_gen.events().mouse_enter([this] { btn_gen.fgcolor(nana::color{"#557799"}); });
83+
btn_gen.events().mouse_leave([this] { btn_gen.fgcolor(nana::color{"#406080"}); });
84+
btn_gen.enabled(false);
85+
plc["btn_gen"] << btn_gen;
86+
87+
prog.create(handle(), true);
88+
prog.scheme().gradient_bgcolor = nana::color{"#f5f5f5"};
89+
prog.scheme().gradient_fgcolor = nana::color{"#b7d3db"};
90+
prog.scheme().background = nana::color{"#e4e4e4"};
91+
prog.scheme().foreground = nana::color{"#64a3b5"};
92+
plc["prog"] << prog;
93+
94+
collocate();
95+
96+
btn_in.events().click([this]
97+
{
98+
nana::filebox fb{handle(), true};
99+
fb.title("Select a file you want to make a C array out of");
100+
auto res = fb.show();
101+
if(!res.empty())
102+
{
103+
inpath = res.front();
104+
if(inpath == outpath)
105+
{
106+
outpath.replace_filename(std::wstring{L"arr_"} + outpath.filename().c_str());
107+
outpath.replace_extension(L"hpp");
108+
label_path_caption(l_outpath, outpath);
109+
}
110+
label_path_caption(l_inpath, inpath);
111+
btn_gen.enabled(!inpath.empty() && !outpath.empty());
112+
}
113+
});
114+
115+
btn_out.events().click([this]
116+
{
117+
nana::filebox fb{handle(), false};
118+
fb.title("Choose which file you want to save the C array to.");
119+
fb.init_file("out.hpp");
120+
auto res = fb.show();
121+
if(!res.empty())
122+
{
123+
outpath = res.front();
124+
if(inpath == outpath)
125+
{
126+
outpath.replace_filename(std::wstring{L"arr_"} + outpath.filename().c_str());
127+
outpath.replace_extension(L"hpp");
128+
label_path_caption(l_outpath, outpath);
129+
}
130+
label_path_caption(l_outpath, outpath);
131+
btn_gen.enabled(!inpath.empty() && !outpath.empty());
132+
}
133+
});
134+
135+
btn_gen.events().click([this]
136+
{
137+
if(working)
138+
{
139+
abort = true;
140+
while(working) std::this_thread::sleep_for(std::chrono::milliseconds{75});
141+
abort = false;
142+
std::filesystem::remove(outpath);
143+
btn_gen.caption(gen_text);
144+
prog.value(0);
145+
}
146+
else
147+
{
148+
btn_gen.caption("Abort");
149+
nana::API::refresh_window(btn_gen);
150+
std::thread([this]
151+
{
152+
try { file_to_c_array(); }
153+
catch(std::exception &e)
154+
{
155+
btn_gen.caption(gen_text);
156+
working = false;
157+
nana::msgbox mbox{handle(), "Error"};
158+
mbox << e.what();
159+
mbox.icon(nana::msgbox::icon_t::icon_error);
160+
mbox.show();
161+
}
162+
}).detach();
163+
}
164+
});
165+
166+
events().unload([this]
167+
{
168+
if(working)
169+
{
170+
abort = true;
171+
while(working) std::this_thread::sleep_for(std::chrono::milliseconds{75});
172+
}
173+
});
174+
}
175+
176+
private:
177+
178+
std::string make_valstr(char *buf, unsigned width) const
179+
{
180+
union uint_t
181+
{
182+
uint8_t uint8;
183+
uint16_t uint16;
184+
uint32_t uint32;
185+
uint64_t uint64;
186+
};
187+
188+
auto pval = reinterpret_cast<uint_t*>(buf);
189+
std::stringstream ss;
190+
191+
switch(width)
192+
{
193+
case 8:
194+
if(pval->uint64 > 999'999'999'999u)
195+
ss << std::hex << std::showbase << pval->uint64;
196+
else ss << pval->uint64;
197+
break;
198+
199+
case 4:
200+
ss << pval->uint32;
201+
break;
202+
203+
case 2:
204+
ss << pval->uint16;
205+
break;
206+
207+
case 1:
208+
ss << std::to_string(pval->uint8);
209+
break;
210+
}
211+
212+
return ss.str();
213+
}
214+
215+
void file_to_c_array()
216+
{
217+
working = true;
218+
if(!std::filesystem::exists(inpath))
219+
throw(std::exception{"Input file does not exist!"});
220+
auto insize = std::filesystem::file_size(inpath);
221+
unsigned width = sizeof(uint64_t);
222+
while(insize % width) width /= 2;
223+
auto buf{std::make_unique<char[]>(width)};
224+
const int prog_steps{568};
225+
prog.amount(prog_steps);
226+
prog.value(0);
227+
uintmax_t prog_step{0}, step_treshold{0};
228+
if(insize >= 10000)
229+
{
230+
prog_step = insize / prog_steps;
231+
step_treshold = prog_step;
232+
}
233+
234+
std::ifstream infile{inpath, std::ios::binary};
235+
if(!infile.good()) throw(std::exception{"Failed to open the input file!"});
236+
std::ofstream outfile{outpath};
237+
if(!outfile.good()) throw(std::exception{"Failed to open the output file!"});
238+
239+
auto name{"arr_" + inpath.filename().generic_u8string()};
240+
for(auto &c : name) if(!isalnum(c)) c = '_';
241+
242+
outfile << "#include <cstdint>\n\n";
243+
if(width > 1) outfile << "// length in bytes: " << insize << "\n";
244+
outfile << "const uint" << std::to_string(width*8) << "_t " << name << '[' << std::to_string(insize/width) << "] = {";
245+
if(line_chars_max) outfile << "\n\t";
246+
size_t line_chars{0};
247+
248+
while(infile.read(buf.get(), width))
249+
{
250+
auto elstr{make_valstr(buf.get(), width) + ','};
251+
if(line_chars_max)
252+
{
253+
line_chars += elstr.size();
254+
if(line_chars > line_chars_max)
255+
{
256+
line_chars = elstr.size();
257+
outfile << "\n\t";
258+
}
259+
}
260+
outfile << elstr;
261+
if(prog_step && infile.tellg() >= step_treshold)
262+
{
263+
step_treshold += prog_step;
264+
prog.inc();
265+
}
266+
if(abort) { working = false; return; }
267+
}
268+
269+
if(infile.bad()) throw(std::exception{"Failed trying to read the input file!"});
270+
271+
outfile.seekp(static_cast<std::streamoff>(outfile.tellp())-1);
272+
if(line_chars_max) outfile << '\n';
273+
outfile << "};";
274+
btn_gen.caption(gen_text);
275+
working = false;
276+
}
277+
278+
void label_path_caption(nana::label &l, const std::filesystem::path &p)
279+
{
280+
l.caption(p);
281+
int offset = 0;
282+
while(l.measure(1234).width > l.size().width)
283+
{
284+
offset += 6;
285+
l.caption(L"..." + std::wstring{p.c_str()}.substr(offset));
286+
}
287+
}
288+
};

FileToCArray_main.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include "FileToCArray.hpp"
2+
3+
int main()
4+
{
5+
ftca_form fm;
6+
fm.show();
7+
nana::exec();
8+
}

0 commit comments

Comments
 (0)