From ff6baf89ae46837223717601e00ebc1060753fbb Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 17 May 2017 21:05:14 +0200 Subject: [PATCH 1/3] Use C++ range-based iterations in slic3r.cpp and remove unused variables --- src/slic3r.cpp | 80 ++++++++++++++++---------------- xs/src/libslic3r/PrintObject.cpp | 2 - 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/slic3r.cpp b/src/slic3r.cpp index e194117b3..4a5de42d1 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -10,7 +10,7 @@ #include #include #include -#include "boost/filesystem.hpp" +#include using namespace Slic3r; @@ -34,16 +34,15 @@ main(const int argc, const char **argv) DynamicPrintConfig print_config; // load config files supplied via --load - for (std::vector::const_iterator file = cli_config.load.values.begin(); - file != cli_config.load.values.end(); ++file) { - if (!boost::filesystem::exists(*file)) { - std::cout << "No such file: " << *file << std::endl; + for (const std::string &file : cli_config.load.values) { + if (!boost::filesystem::exists(file)) { + std::cout << "No such file: " << file << std::endl; exit(1); } DynamicPrintConfig c; try { - c.load(*file); + c.load(file); } catch (std::exception &e) { std::cout << "Error while reading config file: " << e.what() << std::endl; exit(1); @@ -62,85 +61,85 @@ main(const int argc, const char **argv) // read input file(s) if any std::vector models; - for (t_config_option_keys::const_iterator it = input_files.begin(); it != input_files.end(); ++it) { - if (!boost::filesystem::exists(*it)) { - std::cout << "No such file: " << *it << std::endl; + for (const t_config_option_key &file : input_files) { + if (!boost::filesystem::exists(file)) { + std::cerr << "No such file: " << file << std::endl; exit(1); } Model model; try { - model = Model::read_from_file(*it); + model = Model::read_from_file(file); } catch (std::exception &e) { - std::cout << *it << ": " << e.what() << std::endl; + std::cerr << file << ": " << e.what() << std::endl; exit(1); } if (model.objects.empty()) { - printf("Error: file is empty: %s\n", it->c_str()); + std::cerr << "Error: file is empty: " << file << std::endl; continue; } model.add_default_instances(); // apply command line transform options - for (ModelObjectPtrs::iterator o = model.objects.begin(); o != model.objects.end(); ++o) { + for (ModelObject* o : model.objects) { if (cli_config.scale_to_fit.is_positive_volume()) - (*o)->scale_to_fit(cli_config.scale_to_fit.value); + o->scale_to_fit(cli_config.scale_to_fit.value); // TODO: honor option order? - (*o)->scale(cli_config.scale.value); - (*o)->rotate(Geometry::deg2rad(cli_config.rotate_x.value), X); - (*o)->rotate(Geometry::deg2rad(cli_config.rotate_y.value), Y); - (*o)->rotate(Geometry::deg2rad(cli_config.rotate.value), Z); + o->scale(cli_config.scale.value); + o->rotate(Geometry::deg2rad(cli_config.rotate_x.value), X); + o->rotate(Geometry::deg2rad(cli_config.rotate_y.value), Y); + o->rotate(Geometry::deg2rad(cli_config.rotate.value), Z); } // TODO: handle --merge models.push_back(model); } - for (std::vector::iterator model = models.begin(); model != models.end(); ++model) { + for (Model &model : models) { if (cli_config.info) { // --info works on unrepaired model - model->print_info(); + model.print_info(); } else if (cli_config.export_obj) { std::string outfile = cli_config.output.value; - if (outfile.empty()) outfile = model->objects.front()->input_file + ".obj"; + if (outfile.empty()) outfile = model.objects.front()->input_file + ".obj"; - TriangleMesh mesh = model->mesh(); + TriangleMesh mesh = model.mesh(); mesh.repair(); IO::OBJ::write(mesh, outfile); - printf("File exported to %s\n", outfile.c_str()); + std::cout << "File exported to " << outfile << std::endl; } else if (cli_config.export_pov) { std::string outfile = cli_config.output.value; - if (outfile.empty()) outfile = model->objects.front()->input_file + ".pov"; + if (outfile.empty()) outfile = model.objects.front()->input_file + ".pov"; - TriangleMesh mesh = model->mesh(); + TriangleMesh mesh = model.mesh(); mesh.repair(); IO::POV::write(mesh, outfile); - printf("File exported to %s\n", outfile.c_str()); + std::cout << "File exported to " << outfile << std::endl; } else if (cli_config.export_svg) { std::string outfile = cli_config.output.value; - if (outfile.empty()) outfile = model->objects.front()->input_file + ".svg"; + if (outfile.empty()) outfile = model.objects.front()->input_file + ".svg"; - SLAPrint print(&*model); + SLAPrint print(&model); print.config.apply(print_config, true); print.slice(); print.write_svg(outfile); - printf("SVG file exported to %s\n", outfile.c_str()); + std::cout << "SVG file exported to " << outfile << std::endl; } else if (cli_config.cut_x > 0 || cli_config.cut_y > 0 || cli_config.cut > 0) { - model->repair(); - model->translate(0, 0, -model->bounding_box().min.z); + model.repair(); + model.translate(0, 0, -model.bounding_box().min.z); - if (!model->objects.empty()) { + if (!model.objects.empty()) { // FIXME: cut all objects Model out; if (cli_config.cut_x > 0) { - model->objects.front()->cut(X, cli_config.cut_x, &out); + model.objects.front()->cut(X, cli_config.cut_x, &out); } else if (cli_config.cut_y > 0) { - model->objects.front()->cut(Y, cli_config.cut_y, &out); + model.objects.front()->cut(Y, cli_config.cut_y, &out); } else { - model->objects.front()->cut(Z, cli_config.cut, &out); + model.objects.front()->cut(Z, cli_config.cut, &out); } ModelObject &upper = *out.objects[0]; @@ -156,15 +155,16 @@ main(const int argc, const char **argv) } } } else if (cli_config.cut_grid.value.x > 0 && cli_config.cut_grid.value.y > 0) { - TriangleMesh mesh = model->mesh(); + TriangleMesh mesh = model.mesh(); mesh.repair(); TriangleMeshPtrs meshes = mesh.cut_by_grid(cli_config.cut_grid.value); - for (TriangleMeshPtrs::iterator m = meshes.begin(); m != meshes.end(); ++m) { + size_t i = 0; + for (TriangleMesh* m : meshes) { std::ostringstream ss; - ss << model->objects.front()->input_file << "_" << (m - meshes.begin()) << ".stl"; - IO::STL::write(**m, ss.str()); - delete *m; + ss << model.objects.front()->input_file << "_" << i++ << ".stl"; + IO::STL::write(*m, ss.str()); + delete m; } } else { std::cerr << "error: command not supported" << std::endl; diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 5e841b637..ff87345eb 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -625,8 +625,6 @@ void PrintObject::_slice() { coordf_t raft_height = 0; - coordf_t print_z = 0; - coordf_t height = 0; coordf_t first_layer_height = this->config.first_layer_height.get_abs_value(this->config.layer_height.value); From 31115e0369747b1e1c45cbe3f2a90f6dff66666a Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 18 May 2017 01:11:09 +0200 Subject: [PATCH 2/3] Use UTF-8 in libslic3r. Future-proof portable solution for non-ASCII files. #2955 --- lib/Slic3r/Config.pm | 4 +- lib/Slic3r/GUI/BedShapeDialog.pm | 2 +- lib/Slic3r/GUI/MainFrame.pm | 6 +- lib/Slic3r/GUI/Plater.pm | 4 +- lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm | 2 +- slic3r.pl | 11 +- src/slic3r.cpp | 26 +- src/utils/extrude-tin.cpp | 10 +- xs/src/admesh/shared.c | 31 +- xs/src/admesh/stl.h | 31 +- xs/src/admesh/stl_io.c | 55 +- xs/src/admesh/stlinit.c | 25 +- xs/src/boost/nowide/args.hpp | 167 ++++++ xs/src/boost/nowide/cenv.hpp | 126 +++++ xs/src/boost/nowide/config.hpp | 54 ++ xs/src/boost/nowide/convert.hpp | 154 ++++++ xs/src/boost/nowide/cstdio.hpp | 101 ++++ xs/src/boost/nowide/cstdlib.hpp | 16 + xs/src/boost/nowide/filebuf.hpp | 415 +++++++++++++++ xs/src/boost/nowide/fstream.hpp | 283 ++++++++++ .../boost/nowide/integration/filesystem.hpp | 28 + xs/src/boost/nowide/iostream.cpp | 261 +++++++++ xs/src/boost/nowide/iostream.hpp | 99 ++++ xs/src/boost/nowide/stackstring.hpp | 154 ++++++ xs/src/boost/nowide/system.hpp | 46 ++ xs/src/boost/nowide/utf8_codecvt.hpp | 499 ++++++++++++++++++ xs/src/boost/nowide/windows.hpp | 39 ++ xs/src/libslic3r/Config.cpp | 18 +- xs/src/libslic3r/Config.hpp | 2 +- xs/src/libslic3r/IO/AMF.cpp | 21 +- xs/src/libslic3r/TriangleMesh.cpp | 19 + xs/xsp/my.map | 4 +- 32 files changed, 2571 insertions(+), 142 deletions(-) create mode 100755 xs/src/boost/nowide/args.hpp create mode 100755 xs/src/boost/nowide/cenv.hpp create mode 100755 xs/src/boost/nowide/config.hpp create mode 100755 xs/src/boost/nowide/convert.hpp create mode 100755 xs/src/boost/nowide/cstdio.hpp create mode 100755 xs/src/boost/nowide/cstdlib.hpp create mode 100755 xs/src/boost/nowide/filebuf.hpp create mode 100755 xs/src/boost/nowide/fstream.hpp create mode 100755 xs/src/boost/nowide/integration/filesystem.hpp create mode 100755 xs/src/boost/nowide/iostream.cpp create mode 100755 xs/src/boost/nowide/iostream.hpp create mode 100755 xs/src/boost/nowide/stackstring.hpp create mode 100755 xs/src/boost/nowide/system.hpp create mode 100755 xs/src/boost/nowide/utf8_codecvt.hpp create mode 100755 xs/src/boost/nowide/windows.hpp diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 930917dfd..0ba05cf23 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -95,7 +95,7 @@ sub load { # legacy syntax of load() my $config = $class->new; - $config->_load(Slic3r::encode_path($file)); + $config->_load($file); return $config; } @@ -103,7 +103,7 @@ sub save { my $self = shift; my ($file) = @_; - return $self->_save(Slic3r::encode_path($file)); + return $self->_save($file); } # Deserialize a perl hash into the underlying C++ Slic3r::DynamicConfig class, diff --git a/lib/Slic3r/GUI/BedShapeDialog.pm b/lib/Slic3r/GUI/BedShapeDialog.pm index a336b40e7..1ef787e70 100644 --- a/lib/Slic3r/GUI/BedShapeDialog.pm +++ b/lib/Slic3r/GUI/BedShapeDialog.pm @@ -289,7 +289,7 @@ sub _load_stl { my $input_file = Slic3r::decode_path($dialog->GetPaths); $dialog->Destroy; - my $model = Slic3r::Model->read_from_file(Slic3r::encode_path($input_file)); + my $model = Slic3r::Model->read_from_file($input_file); my $mesh = $model->raw_mesh; my $expolygons = $mesh->horizontal_projection; diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index dc04b39d5..fc7aef322 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -384,7 +384,7 @@ sub quick_slice { ); # keep model around - my $model = Slic3r::Model->read_from_file(Slic3r::encode_path($input_file)); + my $model = Slic3r::Model->read_from_file($input_file); $sprint->apply_config($config); $sprint->set_model($model); @@ -469,9 +469,9 @@ sub repair_stl { } my $tmesh = Slic3r::TriangleMesh->new; - $tmesh->ReadSTLFile(Slic3r::encode_path($input_file)); + $tmesh->ReadSTLFile($input_file); $tmesh->repair; - $tmesh->WriteOBJFile(Slic3r::encode_path($output_file)); + $tmesh->WriteOBJFile($output_file); Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair"); } diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 4d2ce292d..2cd8e52af 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -816,7 +816,7 @@ sub add_tin { return if $offset < 0; foreach my $input_file (@input_files) { - my $model = eval { Slic3r::Model->read_from_file(Slic3r::encode_path($input_file)) }; + my $model = eval { Slic3r::Model->read_from_file($input_file) }; Slic3r::GUI::show_error($self, $@) if $@; next if !$model; @@ -847,7 +847,7 @@ sub load_file { local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); - my $model = eval { Slic3r::Model->read_from_file(Slic3r::encode_path($input_file)) }; + my $model = eval { Slic3r::Model->read_from_file($input_file) }; Slic3r::GUI::show_error($self, $@) if $@; my @obj_idx = (); diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index bc3c7d0b8..e0fe90f6e 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -350,7 +350,7 @@ sub on_btn_load { my @input_files = wxTheApp->open_model($self); foreach my $input_file (@input_files) { - my $model = eval { Slic3r::Model->read_from_file(Slic3r::encode_path($input_file)) }; + my $model = eval { Slic3r::Model->read_from_file($input_file) }; if ($@) { Slic3r::GUI::show_error($self, $@); next; diff --git a/slic3r.pl b/slic3r.pl index a97dcca81..abef041d2 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -18,6 +18,7 @@ use Slic3r::Geometry qw(epsilon X Y Z deg2rad); use Time::HiRes qw(gettimeofday tv_interval); $|++; binmode STDOUT, ':utf8'; +binmode STDERR, ':utf8'; our %opt = (); my %cli_options = (); @@ -154,7 +155,7 @@ if (@ARGV) { # slicing from command line if ($opt{cut}) { foreach my $file (@ARGV) { $file = Slic3r::decode_path($file); - my $model = Slic3r::Model->read_from_file(Slic3r::encode_path($file)); + my $model = Slic3r::Model->read_from_file($file); $model->add_default_instances; my $mesh = $model->mesh; $mesh->translate(0, 0, -$mesh->bounding_box->z_min); @@ -175,7 +176,7 @@ if (@ARGV) { # slicing from command line my ($grid_x, $grid_y) = split /[,x]/, $opt{cut_grid}, 2; foreach my $file (@ARGV) { $file = Slic3r::decode_path($file); - my $model = Slic3r::Model->read_from_file(Slic3r::encode_path($file)); + my $model = Slic3r::Model->read_from_file($file); $model->add_default_instances; my $mesh = $model->mesh; my $bb = $mesh->bounding_box; @@ -217,7 +218,7 @@ if (@ARGV) { # slicing from command line if ($opt{split}) { foreach my $file (@ARGV) { $file = Slic3r::decode_path($file); - my $model = Slic3r::Model->read_from_file(Slic3r::encode_path($file)); + my $model = Slic3r::Model->read_from_file($file); $model->add_default_instances; my $mesh = $model->mesh; $mesh->repair; @@ -236,10 +237,10 @@ if (@ARGV) { # slicing from command line $input_file = Slic3r::decode_path($input_file); my $model; if ($opt{merge}) { - my @models = map Slic3r::Model->read_from_file($_), Slic3r::encode_path($input_file), (splice @ARGV, 0); + my @models = map Slic3r::Model->read_from_file($_), $input_file, (splice @ARGV, 0); $model = Slic3r::Model->merge(@models); } else { - $model = Slic3r::Model->read_from_file(Slic3r::encode_path($input_file)); + $model = Slic3r::Model->read_from_file($input_file); } $model->repair; diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 4a5de42d1..bdbe9abfd 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -11,14 +11,20 @@ #include #include #include +#include +#include using namespace Slic3r; void confess_at(const char *file, int line, const char *func, const char *pat, ...){} int -main(const int argc, const char **argv) +main(int argc, char **argv) { + // Convert arguments to UTF-8 (needed on Windows). + // argv then points to memory owned by a. + boost::nowide::args a(argc, argv); + // parse all command line options into a DynamicConfig ConfigDef config_def; config_def.merge(cli_config_def); @@ -36,7 +42,7 @@ main(const int argc, const char **argv) // load config files supplied via --load for (const std::string &file : cli_config.load.values) { if (!boost::filesystem::exists(file)) { - std::cout << "No such file: " << file << std::endl; + boost::nowide::cout << "No such file: " << file << std::endl; exit(1); } @@ -44,7 +50,7 @@ main(const int argc, const char **argv) try { c.load(file); } catch (std::exception &e) { - std::cout << "Error while reading config file: " << e.what() << std::endl; + boost::nowide::cout << "Error while reading config file: " << e.what() << std::endl; exit(1); } c.normalize(); @@ -63,7 +69,7 @@ main(const int argc, const char **argv) std::vector models; for (const t_config_option_key &file : input_files) { if (!boost::filesystem::exists(file)) { - std::cerr << "No such file: " << file << std::endl; + boost::nowide::cerr << "No such file: " << file << std::endl; exit(1); } @@ -71,12 +77,12 @@ main(const int argc, const char **argv) try { model = Model::read_from_file(file); } catch (std::exception &e) { - std::cerr << file << ": " << e.what() << std::endl; + boost::nowide::cerr << file << ": " << e.what() << std::endl; exit(1); } if (model.objects.empty()) { - std::cerr << "Error: file is empty: " << file << std::endl; + boost::nowide::cerr << "Error: file is empty: " << file << std::endl; continue; } @@ -109,7 +115,7 @@ main(const int argc, const char **argv) TriangleMesh mesh = model.mesh(); mesh.repair(); IO::OBJ::write(mesh, outfile); - std::cout << "File exported to " << outfile << std::endl; + boost::nowide::cout << "File exported to " << outfile << std::endl; } else if (cli_config.export_pov) { std::string outfile = cli_config.output.value; if (outfile.empty()) outfile = model.objects.front()->input_file + ".pov"; @@ -117,7 +123,7 @@ main(const int argc, const char **argv) TriangleMesh mesh = model.mesh(); mesh.repair(); IO::POV::write(mesh, outfile); - std::cout << "File exported to " << outfile << std::endl; + boost::nowide::cout << "File exported to " << outfile << std::endl; } else if (cli_config.export_svg) { std::string outfile = cli_config.output.value; if (outfile.empty()) outfile = model.objects.front()->input_file + ".svg"; @@ -126,7 +132,7 @@ main(const int argc, const char **argv) print.config.apply(print_config, true); print.slice(); print.write_svg(outfile); - std::cout << "SVG file exported to " << outfile << std::endl; + boost::nowide::cout << "SVG file exported to " << outfile << std::endl; } else if (cli_config.cut_x > 0 || cli_config.cut_y > 0 || cli_config.cut > 0) { model.repair(); model.translate(0, 0, -model.bounding_box().min.z); @@ -167,7 +173,7 @@ main(const int argc, const char **argv) delete m; } } else { - std::cerr << "error: command not supported" << std::endl; + boost::nowide::cerr << "error: command not supported" << std::endl; return 1; } } diff --git a/src/utils/extrude-tin.cpp b/src/utils/extrude-tin.cpp index 0043b42e8..d5ad91625 100644 --- a/src/utils/extrude-tin.cpp +++ b/src/utils/extrude-tin.cpp @@ -3,14 +3,20 @@ #include "IO.hpp" #include "TriangleMesh.hpp" #include "libslic3r.h" +#include +#include using namespace Slic3r; void confess_at(const char *file, int line, const char *func, const char *pat, ...){} int -main(const int argc, const char **argv) +main(int argc, char **argv) { + // Convert arguments to UTF-8 (needed on Windows). + // argv then points to memory owned by a. + boost::nowide::args a(argc, argv); + // read config ConfigDef config_def; { @@ -40,7 +46,7 @@ main(const int argc, const char **argv) if (outfile.empty()) outfile = *it + "_extruded.stl"; Slic3r::IO::STL::write(mesh, outfile); - printf("Extruded mesh written to %s\n", outfile.c_str()); + boost::nowide::cout << "Extruded mesh written to " << outfile << std::endl; } return 0; diff --git a/xs/src/admesh/shared.c b/xs/src/admesh/shared.c index 19c7da70e..667aefc1e 100644 --- a/xs/src/admesh/shared.c +++ b/xs/src/admesh/shared.c @@ -141,7 +141,7 @@ stl_generate_shared_vertices(stl_file *stl) { } void -stl_write_off(stl_file *stl, char *file) { +stl_write_off(stl_file *stl, ADMESH_CHAR *file) { int i; FILE *fp; char *error_msg; @@ -149,14 +149,9 @@ stl_write_off(stl_file *stl, char *file) { if (stl->error) return; /* Open the file */ - fp = fopen(file, "w"); + fp = stl_fopen(file, "w"); if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); + perror("stl_write_ascii: Couldn't open file for writing"); stl->error = 1; return; } @@ -177,7 +172,7 @@ stl_write_off(stl_file *stl, char *file) { } void -stl_write_vrml(stl_file *stl, char *file) { +stl_write_vrml(stl_file *stl, ADMESH_CHAR *file) { int i; FILE *fp; char *error_msg; @@ -185,14 +180,9 @@ stl_write_vrml(stl_file *stl, char *file) { if (stl->error) return; /* Open the file */ - fp = fopen(file, "w"); + fp = stl_fopen(file, "w"); if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); + perror("stl_write_ascii: Couldn't open file for writing"); stl->error = 1; return; } @@ -234,19 +224,16 @@ stl_write_vrml(stl_file *stl, char *file) { fclose(fp); } -void stl_write_obj (stl_file *stl, const char *file) { +void stl_write_obj (stl_file *stl, const ADMESH_CHAR *file) { int i; FILE* fp; if (stl->error) return; /* Open the file */ - fp = fopen(file, "w"); + fp = stl_fopen(file, "w"); if (fp == NULL) { - char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file); - perror(error_msg); - free(error_msg); + perror("stl_write_ascii: Couldn't open file for writing"); stl->error = 1; return; } diff --git a/xs/src/admesh/stl.h b/xs/src/admesh/stl.h index 99fc61eed..f86f9940b 100644 --- a/xs/src/admesh/stl.h +++ b/xs/src/admesh/stl.h @@ -32,6 +32,15 @@ #error "admesh works correctly on little endian machines only!" #endif +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + #include "windows.h" + #define ADMESH_CHAR wchar_t + #define stl_fopen(file, mode) _wfopen(file, L##mode) +#else + #define ADMESH_CHAR char + #define stl_fopen(file, mode) fopen(file, mode) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -163,15 +172,15 @@ typedef struct { } stl_file; -extern void stl_open(stl_file *stl, const char *file); +extern void stl_open(stl_file *stl, const ADMESH_CHAR *file); extern void stl_close(stl_file *stl); extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file); extern void stl_print_edges(stl_file *stl, FILE *file); -extern void stl_print_neighbors(stl_file *stl, char *file); +extern void stl_print_neighbors(stl_file *stl, ADMESH_CHAR *file); extern void stl_put_little_int(FILE *fp, int value_in); extern void stl_put_little_float(FILE *fp, float value_in); -extern void stl_write_ascii(stl_file *stl, const char *file, const char *label); -extern void stl_write_binary(stl_file *stl, const char *file, const char *label); +extern void stl_write_ascii(stl_file *stl, const ADMESH_CHAR *file, const char *label); +extern void stl_write_binary(stl_file *stl, const ADMESH_CHAR *file, const char *label); extern void stl_write_binary_block(stl_file *stl, FILE *fp); extern void stl_check_facets_exact(stl_file *stl); extern void stl_check_facets_nearby(stl_file *stl, float tolerance); @@ -180,7 +189,7 @@ extern void stl_write_vertex(stl_file *stl, int facet, int vertex); extern void stl_write_facet(stl_file *stl, char *label, int facet); extern void stl_write_edge(stl_file *stl, char *label, stl_hash_edge edge); extern void stl_write_neighbor(stl_file *stl, int facet); -extern void stl_write_quad_object(stl_file *stl, char *file); +extern void stl_write_quad_object(stl_file *stl, ADMESH_CHAR *file); extern void stl_verify_neighbors(stl_file *stl); extern void stl_fill_holes(stl_file *stl); extern void stl_fix_normal_directions(stl_file *stl); @@ -198,13 +207,13 @@ extern void stl_mirror_xy(stl_file *stl); extern void stl_mirror_yz(stl_file *stl); extern void stl_mirror_xz(stl_file *stl); extern void stl_transform(stl_file *stl, float *trafo3x4); -extern void stl_open_merge(stl_file *stl, char *file); +extern void stl_open_merge(stl_file *stl, ADMESH_CHAR *file); extern void stl_invalidate_shared_vertices(stl_file *stl); extern void stl_generate_shared_vertices(stl_file *stl); -extern void stl_write_obj(stl_file *stl, const char *file); -extern void stl_write_off(stl_file *stl, char *file); -extern void stl_write_dxf(stl_file *stl, char *file, char *label); -extern void stl_write_vrml(stl_file *stl, char *file); +extern void stl_write_obj(stl_file *stl, const ADMESH_CHAR *file); +extern void stl_write_off(stl_file *stl, ADMESH_CHAR *file); +extern void stl_write_dxf(stl_file *stl, ADMESH_CHAR *file, char *label); +extern void stl_write_vrml(stl_file *stl, ADMESH_CHAR *file); extern void stl_calculate_normal(float normal[], stl_facet *facet); extern void stl_normalize_vector(float v[]); extern void stl_calculate_volume(stl_file *stl); @@ -212,7 +221,7 @@ extern void stl_calculate_volume(stl_file *stl); extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int tolerance_flag, float tolerance, int increment_flag, float increment, int nearby_flag, int iterations, int remove_unconnected_flag, int fill_holes_flag, int normal_directions_flag, int normal_values_flag, int reverse_all_flag, int verbose_flag); extern void stl_initialize(stl_file *stl); -extern void stl_count_facets(stl_file *stl, const char *file); +extern void stl_count_facets(stl_file *stl, const ADMESH_CHAR *file); extern void stl_allocate(stl_file *stl); extern void stl_read(stl_file *stl, int first_facet, int first); extern void stl_facet_stats(stl_file *stl, stl_facet facet, int first); diff --git a/xs/src/admesh/stl_io.c b/xs/src/admesh/stl_io.c index 7d8e4eab8..b51eae819 100644 --- a/xs/src/admesh/stl_io.c +++ b/xs/src/admesh/stl_io.c @@ -124,7 +124,7 @@ Normals fixed : %5d\n", stl->stats.normals_fixed); } void -stl_write_ascii(stl_file *stl, const char *file, const char *label) { +stl_write_ascii(stl_file *stl, const ADMESH_CHAR *file, const char *label) { int i; FILE *fp; char *error_msg; @@ -132,14 +132,9 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) { if (stl->error) return; /* Open the file */ - fp = fopen(file, "w"); + fp = stl_fopen(file, "w"); if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); + perror("stl_write_ascii: Couldn't open file for writing"); stl->error = 1; return; } @@ -170,7 +165,7 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) { } void -stl_print_neighbors(stl_file *stl, char *file) { +stl_print_neighbors(stl_file *stl, ADMESH_CHAR *file) { int i; FILE *fp; char *error_msg; @@ -178,14 +173,9 @@ stl_print_neighbors(stl_file *stl, char *file) { if (stl->error) return; /* Open the file */ - fp = fopen(file, "w"); + fp = stl_fopen(file, "w"); if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_print_neighbors: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); + perror("stl_print_neighbors: Couldn't open file for writing"); stl->error = 1; return; } @@ -204,7 +194,7 @@ stl_print_neighbors(stl_file *stl, char *file) { } void -stl_write_binary(stl_file *stl, const char *file, const char *label) { +stl_write_binary(stl_file *stl, const ADMESH_CHAR *file, const char *label) { FILE *fp; int i; char *error_msg; @@ -212,14 +202,9 @@ stl_write_binary(stl_file *stl, const char *file, const char *label) { if (stl->error) return; /* Open the file */ - fp = fopen(file, "wb"); + fp = stl_fopen(file, "wb"); if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_binary: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); + perror("stl_write_binary: Couldn't open file for writing"); stl->error = 1; return; } @@ -278,7 +263,7 @@ stl_write_neighbor(stl_file *stl, int facet) { } void -stl_write_quad_object(stl_file *stl, char *file) { +stl_write_quad_object(stl_file *stl, ADMESH_CHAR *file) { FILE *fp; int i; int j; @@ -292,14 +277,9 @@ stl_write_quad_object(stl_file *stl, char *file) { if (stl->error) return; /* Open the file */ - fp = fopen(file, "w"); + fp = stl_fopen(file, "w"); if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_quad_object: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); + perror("stl_write_quad_object: Couldn't open file for writing"); stl->error = 1; return; } @@ -352,7 +332,7 @@ stl_write_quad_object(stl_file *stl, char *file) { } void -stl_write_dxf(stl_file *stl, char *file, char *label) { +stl_write_dxf(stl_file *stl, ADMESH_CHAR *file, char *label) { int i; FILE *fp; char *error_msg; @@ -360,14 +340,9 @@ stl_write_dxf(stl_file *stl, char *file, char *label) { if (stl->error) return; /* Open the file */ - fp = fopen(file, "w"); + fp = stl_fopen(file, "w"); if(fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", - file); - perror(error_msg); - free(error_msg); + perror("stl_write_ascii: Couldn't open file for writing"); stl->error = 1; return; } diff --git a/xs/src/admesh/stlinit.c b/xs/src/admesh/stlinit.c index f83056621..7ec56e795 100644 --- a/xs/src/admesh/stlinit.c +++ b/xs/src/admesh/stlinit.c @@ -33,7 +33,7 @@ #endif void -stl_open(stl_file *stl, const char *file) { +stl_open(stl_file *stl, const ADMESH_CHAR *file) { stl_initialize(stl); stl_count_facets(stl, file); stl_allocate(stl); @@ -66,7 +66,7 @@ stl_initialize(stl_file *stl) { } void -stl_count_facets(stl_file *stl, const char *file) { +stl_count_facets(stl_file *stl, const ADMESH_CHAR *file) { long file_size; int header_num_facets; int num_facets; @@ -79,14 +79,9 @@ stl_count_facets(stl_file *stl, const char *file) { if (stl->error) return; /* Open the file in binary mode first */ - stl->fp = fopen(file, "rb"); + stl->fp = stl_fopen(file, "rb"); if(stl->fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_initialize: Couldn't open %s for reading", - file); - perror(error_msg); - free(error_msg); + perror("stl_initialize: Couldn't open file for reading"); stl->error = 1; return; } @@ -144,16 +139,12 @@ stl_count_facets(stl_file *stl, const char *file) { /* Reopen the file in text mode (for getting correct newlines on Windows) */ // fix to silence a warning about unused return value. // obviously if it fails we have problems.... - stl->fp = freopen(file, "r", stl->fp); + fclose(stl->fp); + stl->fp = stl_fopen(file, "r"); // do another null check to be safe if(stl->fp == NULL) { - error_msg = (char*) - malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ - sprintf(error_msg, "stl_initialize: Couldn't open %s for reading", - file); - perror(error_msg); - free(error_msg); + perror("stl_initialize: Couldn't open file for reading"); stl->error = 1; return; } @@ -201,7 +192,7 @@ stl_allocate(stl_file *stl) { } void -stl_open_merge(stl_file *stl, char *file_to_merge) { +stl_open_merge(stl_file *stl, ADMESH_CHAR *file_to_merge) { int num_facets_so_far; stl_type origStlType; FILE *origFp; diff --git a/xs/src/boost/nowide/args.hpp b/xs/src/boost/nowide/args.hpp new file mode 100755 index 000000000..bb806d02e --- /dev/null +++ b/xs/src/boost/nowide/args.hpp @@ -0,0 +1,167 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_ARGS_HPP_INCLUDED +#define BOOST_NOWIDE_ARGS_HPP_INCLUDED + +#include +#include +#include +#ifdef BOOST_WINDOWS +#include +#endif + +namespace boost { +namespace nowide { + #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) + class args { + public: + args(int &,char **&) {} + args(int &,char **&,char **&){} + ~args() {} + }; + + #else + + /// + /// \brief args is a class that fixes standard main() function arguments and changes them to UTF-8 under + /// Microsoft Windows. + /// + /// The class uses \c GetCommandLineW(), \c CommandLineToArgvW() and \c GetEnvironmentStringsW() + /// in order to obtain the information. It does not relates to actual values of argc,argv and env + /// under Windows. + /// + /// It restores the original values in its destructor + /// + /// \note the class owns the memory of the newly allocated strings + /// + class args { + public: + + /// + /// Fix command line agruments + /// + args(int &argc,char **&argv) : + old_argc_(argc), + old_argv_(argv), + old_env_(0), + old_argc_ptr_(&argc), + old_argv_ptr_(&argv), + old_env_ptr_(0) + { + fix_args(argc,argv); + } + /// + /// Fix command line agruments and environment + /// + args(int &argc,char **&argv,char **&en) : + old_argc_(argc), + old_argv_(argv), + old_env_(en), + old_argc_ptr_(&argc), + old_argv_ptr_(&argv), + old_env_ptr_(&en) + { + fix_args(argc,argv); + fix_env(en); + } + /// + /// Restore original argc,argv,env values, if changed + /// + ~args() + { + if(old_argc_ptr_) + *old_argc_ptr_ = old_argc_; + if(old_argv_ptr_) + *old_argv_ptr_ = old_argv_; + if(old_env_ptr_) + *old_env_ptr_ = old_env_; + } + private: + void fix_args(int &argc,char **&argv) + { + int wargc; + wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc); + if(!wargv) { + argc = 0; + static char *dummy = 0; + argv = &dummy; + return; + } + try{ + args_.resize(wargc+1,0); + arg_values_.resize(wargc); + for(int i=0;i args_; + std::vector arg_values_; + stackstring env_; + std::vector envp_; + + int old_argc_; + char **old_argv_; + char **old_env_; + + int *old_argc_ptr_; + char ***old_argv_ptr_; + char ***old_env_ptr_; + }; + + #endif + +} // nowide +} // namespace boost +#endif + +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/cenv.hpp b/xs/src/boost/nowide/cenv.hpp new file mode 100755 index 000000000..5f6d084af --- /dev/null +++ b/xs/src/boost/nowide/cenv.hpp @@ -0,0 +1,126 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_CENV_H_INCLUDED +#define BOOST_NOWIDE_CENV_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_WINDOWS +#include +#endif + +namespace boost { +namespace nowide { + #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) + using ::getenv; + using ::setenv; + using ::unsetenv; + using ::putenv; + #else + /// + /// \brief UTF-8 aware getenv. Returns 0 if the variable is not set. + /// + /// This function is not thread safe or reenterable as defined by the standard library + /// + inline char *getenv(char const *key) + { + static stackstring value; + + wshort_stackstring name; + if(!name.convert(key)) + return 0; + + static const size_t buf_size = 64; + wchar_t buf[buf_size]; + std::vector tmp; + wchar_t *ptr = buf; + size_t n = GetEnvironmentVariableW(name.c_str(),buf,buf_size); + if(n == 0 && GetLastError() == 203) // ERROR_ENVVAR_NOT_FOUND + return 0; + if(n >= buf_size) { + tmp.resize(n+1,L'\0'); + n = GetEnvironmentVariableW(name.c_str(),&tmp[0],static_cast(tmp.size() - 1)); + // The size may have changed + if(n >= tmp.size() - 1) + return 0; + ptr = &tmp[0]; + } + if(!value.convert(ptr)) + return 0; + return value.c_str(); + } + /// + /// \brief UTF-8 aware setenv, \a key - the variable name, \a value is a new UTF-8 value, + /// + /// if override is not 0, that the old value is always overridded, otherwise, + /// if the variable exists it remains unchanged + /// + inline int setenv(char const *key,char const *value,int override) + { + wshort_stackstring name; + if(!name.convert(key)) + return -1; + if(!override) { + wchar_t unused[2]; + if(!(GetEnvironmentVariableW(name.c_str(),unused,2)==0 && GetLastError() == 203)) // ERROR_ENVVAR_NOT_FOUND + return 0; + } + wstackstring wval; + if(!wval.convert(value)) + return -1; + if(SetEnvironmentVariableW(name.c_str(),wval.c_str())) + return 0; + return -1; + } + /// + /// \brief Remove enviroment variable \a key + /// + inline int unsetenv(char const *key) + { + wshort_stackstring name; + if(!name.convert(key)) + return -1; + if(SetEnvironmentVariableW(name.c_str(),0)) + return 0; + return -1; + } + /// + /// \brief UTF-8 aware putenv implementation, expects string in format KEY=VALUE + /// + inline int putenv(char *string) + { + char const *key = string; + char const *key_end = string; + while(*key_end!='=' && key_end!='\0') + key_end++; + if(*key_end == '\0') + return -1; + wshort_stackstring wkey; + if(!wkey.convert(key,key_end)) + return -1; + + wstackstring wvalue; + if(!wvalue.convert(key_end+1)) + return -1; + + if(SetEnvironmentVariableW(wkey.c_str(),wvalue.c_str())) + return 0; + return -1; + } + #endif +} // nowide +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/config.hpp b/xs/src/boost/nowide/config.hpp new file mode 100755 index 000000000..d983109f3 --- /dev/null +++ b/xs/src/boost/nowide/config.hpp @@ -0,0 +1,54 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_CONFIG_HPP_INCLUDED +#define BOOST_NOWIDE_CONFIG_HPP_INCLUDED + +#include + +#ifndef BOOST_SYMBOL_VISIBLE +# define BOOST_SYMBOL_VISIBLE +#endif + +#ifdef BOOST_HAS_DECLSPEC +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_NOWIDE_DYN_LINK) +# ifdef BOOST_NOWIDE_SOURCE +# define BOOST_NOWIDE_DECL BOOST_SYMBOL_EXPORT +# else +# define BOOST_NOWIDE_DECL BOOST_SYMBOL_IMPORT +# endif // BOOST_NOWIDE_SOURCE +# endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC + +#ifndef BOOST_NOWIDE_DECL +# define BOOST_NOWIDE_DECL +#endif + +// +// Automatically link to the correct build variant where possible. +// +#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_NOWIDE_NO_LIB) && !defined(BOOST_NOWIDE_SOURCE) +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_nowide +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_NOWIDE_DYN_LINK) +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include +#endif // auto-linking disabled + + +#endif // boost/nowide/config.hpp +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 \ No newline at end of file diff --git a/xs/src/boost/nowide/convert.hpp b/xs/src/boost/nowide/convert.hpp new file mode 100755 index 000000000..89b8871d0 --- /dev/null +++ b/xs/src/boost/nowide/convert.hpp @@ -0,0 +1,154 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_CONVERT_H_INCLUDED +#define BOOST_NOWIDE_CONVERT_H_INCLUDED + +#include +#include + +namespace boost { +namespace nowide { + /// + /// \brief Template function that converts a buffer of UTF sequences in range [source_begin,source_end) + /// to the output \a buffer of size \a buffer_size. + /// + /// In case of success a NULL terminated string is returned (buffer), otherwise 0 is returned. + /// + /// If there is not enough room in the buffer or the source sequence contains invalid UTF, + /// 0 is returned, and the contents of the buffer are undefined. + /// + template + CharOut *basic_convert(CharOut *buffer,size_t buffer_size,CharIn const *source_begin,CharIn const *source_end) + { + CharOut *rv = buffer; + if(buffer_size == 0) + return 0; + buffer_size --; + while(source_begin!=source_end) { + using namespace boost::locale::utf; + code_point c = utf_traits::template decode(source_begin,source_end); + if(c==illegal || c==incomplete) { + rv = 0; + break; + } + size_t width = utf_traits::width(c); + if(buffer_size < width) { + rv=0; + break; + } + buffer = utf_traits::template encode(c,buffer); + buffer_size -= width; + } + *buffer++ = 0; + return rv; + } + + /// \cond INTERNAL + namespace details { + // + // wcslen defined only in C99... So we will not use it + // + template + Char const *basic_strend(Char const *s) + { + while(*s) + s++; + return s; + } + } + /// \endcond + + /// + /// Convert NULL terminated UTF source string to NULL terminated \a output string of size at + /// most output_size (including NULL) + /// + /// In case of success output is returned, if the input sequence is illegal, + /// or there is not enough room NULL is returned + /// + inline char *narrow(char *output,size_t output_size,wchar_t const *source) + { + return basic_convert(output,output_size,source,details::basic_strend(source)); + } + /// + /// Convert UTF text in range [begin,end) to NULL terminated \a output string of size at + /// most output_size (including NULL) + /// + /// In case of success output is returned, if the input sequence is illegal, + /// or there is not enough room NULL is returned + /// + inline char *narrow(char *output,size_t output_size,wchar_t const *begin,wchar_t const *end) + { + return basic_convert(output,output_size,begin,end); + } + /// + /// Convert NULL terminated UTF source string to NULL terminated \a output string of size at + /// most output_size (including NULL) + /// + /// In case of success output is returned, if the input sequence is illegal, + /// or there is not enough room NULL is returned + /// + inline wchar_t *widen(wchar_t *output,size_t output_size,char const *source) + { + return basic_convert(output,output_size,source,details::basic_strend(source)); + } + /// + /// Convert UTF text in range [begin,end) to NULL terminated \a output string of size at + /// most output_size (including NULL) + /// + /// In case of success output is returned, if the input sequence is illegal, + /// or there is not enough room NULL is returned + /// + inline wchar_t *widen(wchar_t *output,size_t output_size,char const *begin,char const *end) + { + return basic_convert(output,output_size,begin,end); + } + + + /// + /// Convert between Wide - UTF-16/32 string and UTF-8 string. + /// + /// boost::locale::conv::conversion_error is thrown in a case of a error + /// + inline std::string narrow(wchar_t const *s) + { + return boost::locale::conv::utf_to_utf(s); + } + /// + /// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform + /// + /// boost::locale::conv::conversion_error is thrown in a case of a error + /// + inline std::wstring widen(char const *s) + { + return boost::locale::conv::utf_to_utf(s); + } + /// + /// Convert between Wide - UTF-16/32 string and UTF-8 string + /// + /// boost::locale::conv::conversion_error is thrown in a case of a error + /// + inline std::string narrow(std::wstring const &s) + { + return boost::locale::conv::utf_to_utf(s); + } + /// + /// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform + /// + /// boost::locale::conv::conversion_error is thrown in a case of a error + /// + inline std::wstring widen(std::string const &s) + { + return boost::locale::conv::utf_to_utf(s); + } + +} // nowide +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/cstdio.hpp b/xs/src/boost/nowide/cstdio.hpp new file mode 100755 index 000000000..d0bda97a0 --- /dev/null +++ b/xs/src/boost/nowide/cstdio.hpp @@ -0,0 +1,101 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_CSTDIO_H_INCLUDED +#define BOOST_NOWIDE_CSTDIO_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4996) +#endif + + +namespace boost { +namespace nowide { +#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) + using std::fopen; + using std::freopen; + using std::remove; + using std::rename; +#else + +/// +/// \brief Same as freopen but file_name and mode are UTF-8 strings +/// +/// If invalid UTF-8 given, NULL is returned and errno is set to EINVAL +/// +inline FILE *freopen(char const *file_name,char const *mode,FILE *stream) +{ + wstackstring wname; + wshort_stackstring wmode; + if(!wname.convert(file_name) || !wmode.convert(mode)) { + errno = EINVAL; + return 0; + } + return _wfreopen(wname.c_str(),wmode.c_str(),stream); +} +/// +/// \brief Same as fopen but file_name and mode are UTF-8 strings +/// +/// If invalid UTF-8 given, NULL is returned and errno is set to EINVAL +/// +inline FILE *fopen(char const *file_name,char const *mode) +{ + wstackstring wname; + wshort_stackstring wmode; + if(!wname.convert(file_name) || !wmode.convert(mode)) { + errno = EINVAL; + return 0; + } + return _wfopen(wname.c_str(),wmode.c_str()); +} +/// +/// \brief Same as rename but old_name and new_name are UTF-8 strings +/// +/// If invalid UTF-8 given, -1 is returned and errno is set to EINVAL +/// +inline int rename(char const *old_name,char const *new_name) +{ + wstackstring wold,wnew; + if(!wold.convert(old_name) || !wnew.convert(new_name)) { + errno = EINVAL; + return -1; + } + return _wrename(wold.c_str(),wnew.c_str()); +} +/// +/// \brief Same as rename but name is UTF-8 string +/// +/// If invalid UTF-8 given, -1 is returned and errno is set to EINVAL +/// +inline int remove(char const *name) +{ + wstackstring wname; + if(!wname.convert(name)) { + errno = EINVAL; + return -1; + } + return _wremove(wname.c_str()); +} +#endif +} // nowide +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/cstdlib.hpp b/xs/src/boost/nowide/cstdlib.hpp new file mode 100755 index 000000000..27e20610a --- /dev/null +++ b/xs/src/boost/nowide/cstdlib.hpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED +#define BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED + +#include +#include + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/filebuf.hpp b/xs/src/boost/nowide/filebuf.hpp new file mode 100755 index 000000000..2d6f4a443 --- /dev/null +++ b/xs/src/boost/nowide/filebuf.hpp @@ -0,0 +1,415 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_FILEBUF_HPP +#define BOOST_NOWIDE_FILEBUF_HPP + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4996 4244 4800) +#endif + + +namespace boost { +namespace nowide { +#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_NOWIDE_DOXYGEN) + using std::basic_filebuf; + using std::filebuf; +#else // Windows + + /// + /// \brief This forward declaration defined the basic_filebuf type. + /// + /// it is implemented and specialized for CharType = char, it behaves + /// implements std::filebuf over standard C I/O + /// + template > + class basic_filebuf; + + /// + /// \brief This is implementation of std::filebuf + /// + /// it is implemented and specialized for CharType = char, it behaves + /// implements std::filebuf over standard C I/O + /// + template<> + class basic_filebuf : public std::basic_streambuf { + public: + /// + /// Creates new filebuf + /// + basic_filebuf() : + buffer_size_(4), + buffer_(0), + file_(0), + own_(true), + mode_(std::ios::in | std::ios::out) + { + setg(0,0,0); + setp(0,0); + } + + virtual ~basic_filebuf() + { + if(file_) { + ::fclose(file_); + file_ = 0; + } + if(own_ && buffer_) + delete [] buffer_; + } + + /// + /// Same as std::filebuf::open but s is UTF-8 string + /// + basic_filebuf *open(std::string const &s,std::ios_base::openmode mode) + { + return open(s.c_str(),mode); + } + /// + /// Same as std::filebuf::open but s is UTF-8 string + /// + basic_filebuf *open(char const *s,std::ios_base::openmode mode) + { + if(file_) { + sync(); + ::fclose(file_); + file_ = 0; + } + bool ate = bool(mode & std::ios_base::ate); + if(ate) + mode = mode ^ std::ios_base::ate; + wchar_t const *smode = get_mode(mode); + if(!smode) + return 0; + wstackstring name; + if(!name.convert(s)) + return 0; + #ifdef BOOST_NOWIDE_FSTREAM_TESTS + FILE *f = ::fopen(s,boost::nowide::convert(smode).c_str()); + #else + FILE *f = ::_wfopen(name.c_str(),smode); + #endif + if(!f) + return 0; + if(ate && fseek(f,0,SEEK_END)!=0) { + fclose(f); + return 0; + } + file_ = f; + return this; + } + /// + /// Same as std::filebuf::close() + /// + basic_filebuf *close() + { + bool res = sync() == 0; + if(file_) { + if(::fclose(file_)!=0) + res = false; + file_ = 0; + } + return res ? this : 0; + } + /// + /// Same as std::filebuf::is_open() + /// + bool is_open() const + { + return file_ != 0; + } + + private: + void make_buffer() + { + if(buffer_) + return; + if(buffer_size_ > 0) { + buffer_ = new char [buffer_size_]; + own_ = true; + } + } + protected: + + virtual std::streambuf *setbuf(char *s,std::streamsize n) + { + if(!buffer_ && n>=0) { + buffer_ = s; + buffer_size_ = n; + own_ = false; + } + return this; + } + +#ifdef BOOST_NOWIDE_DEBUG_FILEBUF + + void print_buf(char *b,char *p,char *e) + { + std::cerr << "-- Is Null: " << (b==0) << std::endl;; + if(b==0) + return; + if(e != 0) + std::cerr << "-- Total: " << e - b <<" offset from start " << p - b << std::endl; + else + std::cerr << "-- Total: " << p - b << std::endl; + + std::cerr << "-- ["; + for(char *ptr = b;ptrprint_state(); + } + ~print_guard() + { + std::cerr << "Out: " << f << std::endl; + self->print_state(); + } + basic_filebuf *self; + char const *f; + }; +#else +#endif + + int overflow(int c) + { +#ifdef BOOST_NOWIDE_DEBUG_FILEBUF + print_guard g(this,__FUNCTION__); +#endif + if(!file_) + return EOF; + + if(fixg() < 0) + return EOF; + + size_t n = pptr() - pbase(); + if(n > 0) { + if(::fwrite(pbase(),1,n,file_) < n) + return -1; + fflush(file_); + } + + if(buffer_size_ > 0) { + make_buffer(); + setp(buffer_,buffer_+buffer_size_); + if(c!=EOF) + sputc(c); + } + else if(c!=EOF) { + if(::fputc(c,file_)==EOF) + return EOF; + fflush(file_); + } + return 0; + } + + + int sync() + { + return overflow(EOF); + } + + int underflow() + { +#ifdef BOOST_NOWIDE_DEBUG_FILEBUF + print_guard g(this,__FUNCTION__); +#endif + if(!file_) + return EOF; + if(fixp() < 0) + return EOF; + if(buffer_size_ == 0) { + int c = ::fgetc(file_); + if(c==EOF) { + return EOF; + } + last_char_ = c; + setg(&last_char_,&last_char_,&last_char_ + 1); + return c; + } + make_buffer(); + size_t n = ::fread(buffer_,1,buffer_size_,file_); + setg(buffer_,buffer_,buffer_+n); + if(n == 0) + return EOF; + return std::char_traits::to_int_type(*gptr()); + } + + int pbackfail(int) + { + return pubseekoff(-1,std::ios::cur); + } + + std::streampos seekoff(std::streamoff off, + std::ios_base::seekdir seekdir, + std::ios_base::openmode /*m*/) + { +#ifdef BOOST_NOWIDE_DEBUG_FILEBUF + print_guard g(this,__FUNCTION__); +#endif + if(!file_) + return EOF; + if(fixp() < 0 || fixg() < 0) + return EOF; + if(seekdir == std::ios_base::cur) { + if( ::fseek(file_,off,SEEK_CUR) < 0) + return EOF; + } + else if(seekdir == std::ios_base::beg) { + if( ::fseek(file_,off,SEEK_SET) < 0) + return EOF; + } + else if(seekdir == std::ios_base::end) { + if( ::fseek(file_,off,SEEK_END) < 0) + return EOF; + } + else + return -1; + return ftell(file_); + } + std::streampos seekpos(std::streampos off,std::ios_base::openmode m) + { + return seekoff(std::streamoff(off),std::ios_base::beg,m); + } + private: + int fixg() + { + if(gptr()!=egptr()) { + std::streamsize off = gptr() - egptr(); + setg(0,0,0); + if(fseek(file_,off,SEEK_CUR) != 0) + return -1; + } + setg(0,0,0); + return 0; + } + + int fixp() + { + if(pptr()!=0) { + int r = sync(); + setp(0,0); + return r; + } + return 0; + } + + void reset(FILE *f = 0) + { + sync(); + if(file_) { + fclose(file_); + file_ = 0; + } + file_ = f; + } + + + static wchar_t const *get_mode(std::ios_base::openmode mode) + { + // + // done according to n2914 table 106 27.9.1.4 + // + + // note can't use switch case as overload operator can't be used + // in constant expression + if(mode == (std::ios_base::out)) + return L"w"; + if(mode == (std::ios_base::out | std::ios_base::app)) + return L"a"; + if(mode == (std::ios_base::app)) + return L"a"; + if(mode == (std::ios_base::out | std::ios_base::trunc)) + return L"w"; + if(mode == (std::ios_base::in)) + return L"r"; + if(mode == (std::ios_base::in | std::ios_base::out)) + return L"r+"; + if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc)) + return L"w+"; + if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app)) + return L"a+"; + if(mode == (std::ios_base::in | std::ios_base::app)) + return L"a+"; + if(mode == (std::ios_base::binary | std::ios_base::out)) + return L"wb"; + if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app)) + return L"ab"; + if(mode == (std::ios_base::binary | std::ios_base::app)) + return L"ab"; + if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc)) + return L"wb"; + if(mode == (std::ios_base::binary | std::ios_base::in)) + return L"rb"; + if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out)) + return L"r+b"; + if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc)) + return L"w+b"; + if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app)) + return L"a+b"; + if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app)) + return L"a+b"; + return 0; + } + + size_t buffer_size_; + char *buffer_; + FILE *file_; + bool own_; + char last_char_; + std::ios::openmode mode_; + }; + + /// + /// \brief Convinience typedef + /// + typedef basic_filebuf filebuf; + + #endif // windows + +} // nowide +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + + +#endif + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/fstream.hpp b/xs/src/boost/nowide/fstream.hpp new file mode 100755 index 000000000..b0824a51b --- /dev/null +++ b/xs/src/boost/nowide/fstream.hpp @@ -0,0 +1,283 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_FSTREAM_INCLUDED_HPP +#define BOOST_NOWIDE_FSTREAM_INCLUDED_HPP + +//#include +#include +#include +#include +#include +#include +#include + +namespace boost { +/// +/// \brief This namespace includes implementation of the standard library functios +/// such that they accept UTF-8 strings on Windows. On other platforms it is just an alias +/// of std namespace (i.e. not on Windows) +/// +namespace nowide { +#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_NOWIDE_DOXYGEN) + + using std::basic_ifstream; + using std::basic_ofstream; + using std::basic_fstream; + using std::ifstream; + using std::ofstream; + using std::fstream; + +#else + /// + /// \brief Same as std::basic_ifstream but accepts UTF-8 strings under Windows + /// + template > + class basic_ifstream : public std::basic_istream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_istream internal_stream_type; + + basic_ifstream() : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + } + + explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + + explicit basic_ifstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::in) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + + + void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::in) + { + open(file_name.c_str(),mode); + } + void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) + { + if(!buf_->open(file_name,mode | std::ios_base::in)) { + this->setstate(std::ios_base::failbit); + } + else { + this->clear(); + } + } + bool is_open() + { + return buf_->is_open(); + } + bool is_open() const + { + return buf_->is_open(); + } + void close() + { + if(!buf_->close()) + this->setstate(std::ios_base::failbit); + else + this->clear(); + } + + internal_buffer_type *rdbuf() const + { + return buf_.get(); + } + ~basic_ifstream() + { + buf_->close(); + } + + private: + boost::scoped_ptr buf_; + }; + + /// + /// \brief Same as std::basic_ofstream but accepts UTF-8 strings under Windows + /// + + template > + class basic_ofstream : public std::basic_ostream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_ostream internal_stream_type; + + basic_ofstream() : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + } + explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + explicit basic_ofstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out) + { + open(file_name.c_str(),mode); + } + void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) + { + if(!buf_->open(file_name,mode | std::ios_base::out)) { + this->setstate(std::ios_base::failbit); + } + else { + this->clear(); + } + } + bool is_open() + { + return buf_->is_open(); + } + bool is_open() const + { + return buf_->is_open(); + } + void close() + { + if(!buf_->close()) + this->setstate(std::ios_base::failbit); + else + this->clear(); + } + + internal_buffer_type *rdbuf() const + { + return buf_.get(); + } + ~basic_ofstream() + { + buf_->close(); + } + + private: + boost::scoped_ptr buf_; + }; + + /// + /// \brief Same as std::basic_fstream but accepts UTF-8 strings under Windows + /// + + template > + class basic_fstream : public std::basic_iostream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_iostream internal_stream_type; + + basic_fstream() : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + } + explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + explicit basic_fstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) : + internal_stream_type(0) + { + buf_.reset(new internal_buffer_type()); + std::ios::rdbuf(buf_.get()); + open(file_name,mode); + } + void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out) + { + open(file_name.c_str(),mode); + } + void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out) + { + if(!buf_->open(file_name,mode)) { + this->setstate(std::ios_base::failbit); + } + else { + this->clear(); + } + } + bool is_open() + { + return buf_->is_open(); + } + bool is_open() const + { + return buf_->is_open(); + } + void close() + { + if(!buf_->close()) + this->setstate(std::ios_base::failbit); + else + this->clear(); + } + + internal_buffer_type *rdbuf() const + { + return buf_.get(); + } + ~basic_fstream() + { + buf_->close(); + } + + private: + boost::scoped_ptr buf_; + }; + + + /// + /// \brief Same as std::filebuf but accepts UTF-8 strings under Windows + /// + typedef basic_filebuf filebuf; + /// + /// Same as std::ifstream but accepts UTF-8 strings under Windows + /// + typedef basic_ifstream ifstream; + /// + /// Same as std::ofstream but accepts UTF-8 strings under Windows + /// + typedef basic_ofstream ofstream; + /// + /// Same as std::fstream but accepts UTF-8 strings under Windows + /// + typedef basic_fstream fstream; + +#endif +} // nowide +} // namespace boost + + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/integration/filesystem.hpp b/xs/src/boost/nowide/integration/filesystem.hpp new file mode 100755 index 000000000..c2a44b4ee --- /dev/null +++ b/xs/src/boost/nowide/integration/filesystem.hpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED +#define BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED + +#include +#include +namespace boost { + namespace nowide { + /// + /// Instal utf8_codecvt facet into boost::filesystem::path such all char strings are interpreted as utf-8 strings + /// + inline void nowide_filesystem() + { + std::locale tmp = std::locale(std::locale(),new boost::nowide::utf8_codecvt()); + boost::filesystem::path::imbue(tmp); + } + } // nowide +} // boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/iostream.cpp b/xs/src/boost/nowide/iostream.cpp new file mode 100755 index 000000000..6b9099110 --- /dev/null +++ b/xs/src/boost/nowide/iostream.cpp @@ -0,0 +1,261 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_NOWIDE_SOURCE +#include +#include +#include +#include + +#ifdef BOOST_WINDOWS + +#ifndef NOMINMAX +# define NOMINMAX +#endif + + +#include + +namespace boost { +namespace nowide { +namespace details { + class console_output_buffer : public std::streambuf { + public: + console_output_buffer(HANDLE h) : + handle_(h), + isatty_(false) + { + if(handle_) { + DWORD dummy; + isatty_ = GetConsoleMode(handle_,&dummy) == TRUE; + } + } + protected: + int sync() + { + return overflow(EOF); + } + int overflow(int c) + { + if(!handle_) + return -1; + int n = pptr() - pbase(); + int r = 0; + + if(n > 0 && (r=write(pbase(),n)) < 0) + return -1; + if(r < n) { + memmove(pbase(),pbase() + r,n-r); + } + setp(buffer_, buffer_ + buffer_size); + pbump(n-r); + if(c!=EOF) + sputc(c); + return 0; + } + private: + + int write(char const *p,int n) + { + namespace uf = boost::locale::utf; + char const *b = p; + char const *e = p+n; + DWORD size=0; + if(!isatty_) { + if(!WriteFile(handle_,p,n,&size,0) || static_cast(size) != n) + return -1; + return n; + } + if(n > buffer_size) + return -1; + wchar_t *out = wbuffer_; + uf::code_point c; + size_t decoded = 0; + while(p < e && (c = uf::utf_traits::decode(p,e))!=uf::illegal && c!=uf::incomplete) { + out = uf::utf_traits::encode(c,out); + decoded = p-b; + } + if(c==uf::illegal) + return -1; + if(!WriteConsoleW(handle_,wbuffer_,out - wbuffer_,&size,0)) + return -1; + return decoded; + } + + static const int buffer_size = 1024; + char buffer_[buffer_size]; + wchar_t wbuffer_[buffer_size]; // for null + HANDLE handle_; + bool isatty_; + }; + + class console_input_buffer: public std::streambuf { + public: + console_input_buffer(HANDLE h) : + handle_(h), + isatty_(false), + wsize_(0) + { + if(handle_) { + DWORD dummy; + isatty_ = GetConsoleMode(handle_,&dummy) == TRUE; + } + } + + protected: + int pbackfail(int c) + { + if(c==EOF) + return EOF; + + if(gptr()!=eback()) { + gbump(-1); + *gptr() = c; + return 0; + } + + if(pback_buffer_.empty()) { + pback_buffer_.resize(4); + char *b = &pback_buffer_[0]; + char *e = b + pback_buffer_.size(); + setg(b,e-1,e); + *gptr() = c; + } + else { + size_t n = pback_buffer_.size(); + std::vector tmp; + tmp.resize(n*2); + memcpy(&tmp[n],&pback_buffer_[0],n); + tmp.swap(pback_buffer_); + char *b = &pback_buffer_[0]; + char *e = b + n * 2; + char *p = b+n-1; + *p = c; + setg(b,p,e); + } + + return 0; + } + + int underflow() + { + if(!handle_) + return -1; + if(!pback_buffer_.empty()) + pback_buffer_.clear(); + + size_t n = read(); + setg(buffer_,buffer_,buffer_+n); + if(n == 0) + return EOF; + return std::char_traits::to_int_type(*gptr()); + } + + private: + + size_t read() + { + namespace uf = boost::locale::utf; + if(!isatty_) { + DWORD read_bytes = 0; + if(!ReadFile(handle_,buffer_,buffer_size,&read_bytes,0)) + return 0; + return read_bytes; + } + DWORD read_wchars = 0; + size_t n = wbuffer_size - wsize_; + if(!ReadConsoleW(handle_,wbuffer_,n,&read_wchars,0)) + return 0; + wsize_ += read_wchars; + char *out = buffer_; + wchar_t *b = wbuffer_; + wchar_t *e = b + wsize_; + wchar_t *p = b; + uf::code_point c; + wsize_ = e-p; + while(p < e && (c = uf::utf_traits::decode(p,e))!=uf::illegal && c!=uf::incomplete) { + out = uf::utf_traits::encode(c,out); + wsize_ = e-p; + } + + if(c==uf::illegal) + return -1; + + + if(c==uf::incomplete) { + memmove(b,e-wsize_,sizeof(wchar_t)*wsize_); + } + + return out - buffer_; + } + + static const size_t buffer_size = 1024 * 3; + static const size_t wbuffer_size = 1024; + char buffer_[buffer_size]; + wchar_t wbuffer_[buffer_size]; // for null + HANDLE handle_; + bool isatty_; + int wsize_; + std::vector pback_buffer_; + }; + + winconsole_ostream::winconsole_ostream(int fd) : std::ostream(0) + { + HANDLE h = 0; + switch(fd) { + case 1: + h = GetStdHandle(STD_OUTPUT_HANDLE); + break; + case 2: + h = GetStdHandle(STD_ERROR_HANDLE); + break; + } + d.reset(new console_output_buffer(h)); + std::ostream::rdbuf(d.get()); + } + + winconsole_ostream::~winconsole_ostream() + { + } + + winconsole_istream::winconsole_istream() : std::istream(0) + { + HANDLE h = GetStdHandle(STD_INPUT_HANDLE); + d.reset(new console_input_buffer(h)); + std::istream::rdbuf(d.get()); + } + + winconsole_istream::~winconsole_istream() + { + } + +} // details + +BOOST_NOWIDE_DECL details::winconsole_istream cin; +BOOST_NOWIDE_DECL details::winconsole_ostream cout(1); +BOOST_NOWIDE_DECL details::winconsole_ostream cerr(2); +BOOST_NOWIDE_DECL details::winconsole_ostream clog(2); + +namespace { + struct initialize { + initialize() + { + boost::nowide::cin.tie(&boost::nowide::cout); + boost::nowide::cerr.tie(&boost::nowide::cout); + boost::nowide::clog.tie(&boost::nowide::cout); + } + } inst; +} + + + +} // nowide +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/iostream.hpp b/xs/src/boost/nowide/iostream.hpp new file mode 100755 index 000000000..6ab004a25 --- /dev/null +++ b/xs/src/boost/nowide/iostream.hpp @@ -0,0 +1,99 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED +#define BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4251) +#endif + + +namespace boost { +namespace nowide { + #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) + using std::cout; + using std::cerr; + using std::cin; + using std::clog; + #else + + /// \cond INTERNAL + namespace details { + class console_output_buffer; + class console_input_buffer; + + class BOOST_NOWIDE_DECL winconsole_ostream : public std::ostream { + winconsole_ostream(winconsole_ostream const &); + void operator=(winconsole_ostream const &); + public: + winconsole_ostream(int fd); + ~winconsole_ostream(); + private: + boost::scoped_ptr d; + }; + + class BOOST_NOWIDE_DECL winconsole_istream : public std::istream { + winconsole_istream(winconsole_istream const &); + void operator=(winconsole_istream const &); + public: + + winconsole_istream(); + ~winconsole_istream(); + private: + struct data; + boost::scoped_ptr d; + }; + } // details + + /// \endcond + + /// + /// \brief Same as std::cin, but uses UTF-8 + /// + /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio + /// + extern BOOST_NOWIDE_DECL details::winconsole_istream cin; + /// + /// \brief Same as std::cout, but uses UTF-8 + /// + /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio + /// + extern BOOST_NOWIDE_DECL details::winconsole_ostream cout; + /// + /// \brief Same as std::cerr, but uses UTF-8 + /// + /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio + /// + extern BOOST_NOWIDE_DECL details::winconsole_ostream cerr; + /// + /// \brief Same as std::clog, but uses UTF-8 + /// + /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio + /// + extern BOOST_NOWIDE_DECL details::winconsole_ostream clog; + + #endif + +} // nowide +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/stackstring.hpp b/xs/src/boost/nowide/stackstring.hpp new file mode 100755 index 000000000..948a22f7f --- /dev/null +++ b/xs/src/boost/nowide/stackstring.hpp @@ -0,0 +1,154 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_DETAILS_WIDESTR_H_INCLUDED +#define BOOST_NOWIDE_DETAILS_WIDESTR_H_INCLUDED +#include +#include +#include + +namespace boost { +namespace nowide { + +/// +/// \brief A class that allows to create a temporary wide or narrow UTF strings from +/// wide or narrow UTF source. +/// +/// It uses on stack buffer of the string is short enough +/// and allocated a buffer on the heap if the size of the buffer is too small +/// +template +class basic_stackstring { +public: + + static const size_t buffer_size = BufferSize; + typedef CharOut output_char; + typedef CharIn input_char; + + basic_stackstring(basic_stackstring const &other) : + mem_buffer_(0) + { + clear(); + if(other.mem_buffer_) { + size_t len = 0; + while(other.mem_buffer_[len]) + len ++; + mem_buffer_ = new output_char[len + 1]; + memcpy(mem_buffer_,other.mem_buffer_,sizeof(output_char) * (len+1)); + } + else { + memcpy(buffer_,other.buffer_,buffer_size * sizeof(output_char)); + } + } + + void swap(basic_stackstring &other) + { + std::swap(mem_buffer_,other.mem_buffer_); + for(size_t i=0;i wstackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring stackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring wshort_stackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring short_stackstring; + + +} // nowide +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/system.hpp b/xs/src/boost/nowide/system.hpp new file mode 100755 index 000000000..a1fc97505 --- /dev/null +++ b/xs/src/boost/nowide/system.hpp @@ -0,0 +1,46 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_CSTDLIB_HPP +#define BOOST_NOWIDE_CSTDLIB_HPP + +#include +#include +#include +namespace boost { +namespace nowide { + +#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) + +using ::system; + +#else // Windows + +/// +/// Same as std::system but cmd is UTF-8. +/// +/// If the input is not valid UTF-8, -1 returned and errno set to EINVAL +/// +inline int system(char const *cmd) +{ + if(!cmd) + return _wsystem(0); + wstackstring wcmd; + if(!wcmd.convert(cmd)) { + errno = EINVAL; + return -1; + } + return _wsystem(wcmd.c_str()); +} + +#endif +} // nowide +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/utf8_codecvt.hpp b/xs/src/boost/nowide/utf8_codecvt.hpp new file mode 100755 index 000000000..2d8d393ad --- /dev/null +++ b/xs/src/boost/nowide/utf8_codecvt.hpp @@ -0,0 +1,499 @@ +// +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_NOWIDE_UTF8_CODECVT_HPP +#define BOOST_NOWIDE_UTF8_CODECVT_HPP + +#include +#include +#include +#include + +namespace boost { +namespace nowide { + +// +// Make sure that mbstate can keep 16 bit of UTF-16 sequence +// +BOOST_STATIC_ASSERT(sizeof(std::mbstate_t)>=2); + +#ifdef _MSC_VER +// MSVC do_length is non-standard it counts wide characters instead of narrow and does not change mbstate +#define BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST +#endif + +template +class utf8_codecvt; + +template +class utf8_codecvt : public std::codecvt +{ +public: + utf8_codecvt(size_t refs = 0) : std::codecvt(refs) + { + } +protected: + + typedef CharType uchar; + + virtual std::codecvt_base::result do_unshift(std::mbstate_t &s,char *from,char * /*to*/,char *&next) const + { + boost::uint16_t &state = *reinterpret_cast(&s); +#ifdef DEBUG_CODECVT + std::cout << "Entering unshift " << std::hex << state << std::dec << std::endl; +#endif + if(state != 0) + return std::codecvt_base::error; + next=from; + return std::codecvt_base::ok; + } + virtual int do_encoding() const throw() + { + return 0; + } + virtual int do_max_length() const throw() + { + return 4; + } + virtual bool do_always_noconv() const throw() + { + return false; + } + + virtual int + do_length( std::mbstate_t + #ifdef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + const + #endif + &std_state, + char const *from, + char const *from_end, + size_t max) const + { + #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + char const *save_from = from; + boost::uint16_t &state = *reinterpret_cast(&std_state); + #else + size_t save_max = max; + boost::uint16_t state = *reinterpret_cast(&std_state); + #endif + while(max > 0 && from < from_end){ + char const *prev_from = from; + boost::uint32_t ch=boost::locale::utf::utf_traits::decode(from,from_end); + if(ch==boost::locale::utf::incomplete || ch==boost::locale::utf::illegal) { + from = prev_from; + break; + } + max --; + if(ch > 0xFFFF) { + if(state == 0) { + from = prev_from; + state = 1; + } + else { + state = 0; + } + } + } + #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + return from - save_from; + #else + return save_max - max; + #endif + } + + + virtual std::codecvt_base::result + do_in( std::mbstate_t &std_state, + char const *from, + char const *from_end, + char const *&from_next, + uchar *to, + uchar *to_end, + uchar *&to_next) const + { + std::codecvt_base::result r=std::codecvt_base::ok; + + // mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT()) + // according to standard. We use it to keep a flag 0/1 for surrogate pair writing + // + // if 0 no code above >0xFFFF observed, of 1 a code above 0xFFFF observerd + // and first pair is written, but no input consumed + boost::uint16_t &state = *reinterpret_cast(&std_state); + while(to < to_end && from < from_end) + { +#ifdef DEBUG_CODECVT + std::cout << "Entering IN--------------" << std::endl; + std::cout << "State " << std::hex << state <::decode(from,from_end); + + if(ch==boost::locale::utf::illegal) { + from = from_saved; + r=std::codecvt_base::error; + break; + } + if(ch==boost::locale::utf::incomplete) { + from = from_saved; + r=std::codecvt_base::partial; + break; + } + // Normal codepoints go direcly to stream + if(ch <= 0xFFFF) { + *to++=ch; + } + else { + // for other codepoints we do following + // + // 1. We can't consume our input as we may find ourselfs + // in state where all input consumed but not all output written,i.e. only + // 1st pair is written + // 2. We only write first pair and mark this in the state, we also revert back + // the from pointer in order to make sure this codepoint would be read + // once again and then we would consume our input together with writing + // second surrogate pair + ch-=0x10000; + boost::uint16_t vh = ch >> 10; + boost::uint16_t vl = ch & 0x3FF; + boost::uint16_t w1 = vh + 0xD800; + boost::uint16_t w2 = vl + 0xDC00; + if(state == 0) { + from = from_saved; + *to++ = w1; + state = 1; + } + else { + *to++ = w2; + state = 0; + } + } + } + from_next=from; + to_next=to; + if(r == std::codecvt_base::ok && (from!=from_end || state!=0)) + r = std::codecvt_base::partial; +#ifdef DEBUG_CODECVT + std::cout << "Returning "; + switch(r) { + case std::codecvt_base::ok: + std::cout << "ok" << std::endl; + break; + case std::codecvt_base::partial: + std::cout << "partial" << std::endl; + break; + case std::codecvt_base::error: + std::cout << "error" << std::endl; + break; + default: + std::cout << "other" << std::endl; + break; + } + std::cout << "State " << std::hex << state <=2 in order + // to be able to store first observerd surrogate pair + // + // State: state!=0 - a first surrogate pair was observerd (state = first pair), + // we expect the second one to come and then zero the state + /// + boost::uint16_t &state = *reinterpret_cast(&std_state); + while(to < to_end && from < from_end) + { +#ifdef DEBUG_CODECVT + std::cout << "Entering OUT --------------" << std::endl; + std::cout << "State " << std::hex << state <::width(ch); + if(to_end - to < len) { + r=std::codecvt_base::partial; + break; + } + to = boost::locale::utf::utf_traits::encode(ch,to); + state = 0; + from++; + } + from_next=from; + to_next=to; + if(r==std::codecvt_base::ok && from!=from_end) + r = std::codecvt_base::partial; +#ifdef DEBUG_CODECVT + std::cout << "Returning "; + switch(r) { + case std::codecvt_base::ok: + std::cout << "ok" << std::endl; + break; + case std::codecvt_base::partial: + std::cout << "partial" << std::endl; + break; + case std::codecvt_base::error: + std::cout << "error" << std::endl; + break; + default: + std::cout << "other" << std::endl; + break; + } + std::cout << "State " << std::hex << state < +class utf8_codecvt : public std::codecvt +{ +public: + utf8_codecvt(size_t refs = 0) : std::codecvt(refs) + { + } +protected: + + typedef CharType uchar; + + virtual std::codecvt_base::result do_unshift(std::mbstate_t &/*s*/,char *from,char * /*to*/,char *&next) const + { + next=from; + return std::codecvt_base::ok; + } + virtual int do_encoding() const throw() + { + return 0; + } + virtual int do_max_length() const throw() + { + return 4; + } + virtual bool do_always_noconv() const throw() + { + return false; + } + + virtual int + do_length( std::mbstate_t + #ifdef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + const + #endif + &/*state*/, + char const *from, + char const *from_end, + size_t max) const + { + #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + char const *start_from = from; + #else + size_t save_max = max; + #endif + + while(max > 0 && from < from_end){ + char const *save_from = from; + boost::uint32_t ch=boost::locale::utf::utf_traits::decode(from,from_end); + if(ch==boost::locale::utf::incomplete || ch==boost::locale::utf::illegal) { + from = save_from; + break; + } + max--; + } + #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + return from - start_from; + #else + return save_max - max; + #endif + } + + + virtual std::codecvt_base::result + do_in( std::mbstate_t &/*state*/, + char const *from, + char const *from_end, + char const *&from_next, + uchar *to, + uchar *to_end, + uchar *&to_next) const + { + std::codecvt_base::result r=std::codecvt_base::ok; + + // mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT()) + // according to standard. We use it to keep a flag 0/1 for surrogate pair writing + // + // if 0 no code above >0xFFFF observed, of 1 a code above 0xFFFF observerd + // and first pair is written, but no input consumed + while(to < to_end && from < from_end) + { +#ifdef DEBUG_CODECVT + std::cout << "Entering IN--------------" << std::endl; + std::cout << "State " << std::hex << state <::decode(from,from_end); + + if(ch==boost::locale::utf::illegal) { + r=std::codecvt_base::error; + from = from_saved; + break; + } + if(ch==boost::locale::utf::incomplete) { + r=std::codecvt_base::partial; + from=from_saved; + break; + } + *to++=ch; + } + from_next=from; + to_next=to; + if(r == std::codecvt_base::ok && from!=from_end) + r = std::codecvt_base::partial; +#ifdef DEBUG_CODECVT + std::cout << "Returning "; + switch(r) { + case std::codecvt_base::ok: + std::cout << "ok" << std::endl; + break; + case std::codecvt_base::partial: + std::cout << "partial" << std::endl; + break; + case std::codecvt_base::error: + std::cout << "error" << std::endl; + break; + default: + std::cout << "other" << std::endl; + break; + } + std::cout << "State " << std::hex << state <::width(ch); + if(to_end - to < len) { + r=std::codecvt_base::partial; + break; + } + to = boost::locale::utf::utf_traits::encode(ch,to); + from++; + } + from_next=from; + to_next=to; + if(r==std::codecvt_base::ok && from!=from_end) + r = std::codecvt_base::partial; +#ifdef DEBUG_CODECVT + std::cout << "Returning "; + switch(r) { + case std::codecvt_base::ok: + std::cout << "ok" << std::endl; + break; + case std::codecvt_base::partial: + std::cout << "partial" << std::endl; + break; + case std::codecvt_base::error: + std::cout << "error" << std::endl; + break; + default: + std::cout << "other" << std::endl; + break; + } + std::cout << "State " << std::hex << state < + +#ifdef BOOST_NOWIDE_USE_WINDOWS_H +#include +#else + +// +// These are function prototypes... Allow to to include windows.h +// +extern "C" { + +__declspec(dllimport) wchar_t* __stdcall GetEnvironmentStringsW(void); +__declspec(dllimport) int __stdcall FreeEnvironmentStringsW(wchar_t *); +__declspec(dllimport) wchar_t* __stdcall GetCommandLineW(void); +__declspec(dllimport) wchar_t** __stdcall CommandLineToArgvW(wchar_t const *,int *); +__declspec(dllimport) unsigned long __stdcall GetLastError(); +__declspec(dllimport) void* __stdcall LocalFree(void *); +__declspec(dllimport) int __stdcall SetEnvironmentVariableW(wchar_t const *,wchar_t const *); +__declspec(dllimport) unsigned long __stdcall GetEnvironmentVariableW(wchar_t const *,wchar_t *,unsigned long); + +} + +#endif + + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index 68d4837c1..51a24c055 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -1,5 +1,4 @@ #include "Config.hpp" -#include // for setenv() #include #include #include @@ -13,14 +12,11 @@ #include #include #include +#include #include #include #include -#if defined(_WIN32) && !defined(setenv) && defined(_putenv_s) -#define setenv(k, v, o) _putenv_s(k, v) -#endif - namespace Slic3r { std::string escape_string_cstyle(const std::string &str) @@ -360,7 +356,6 @@ ConfigBase::get_abs_value(const t_config_option_key &opt_key, double ratio_over) void ConfigBase::setenv_() { -#ifdef setenv t_config_option_keys opt_keys = this->keys(); for (t_config_option_keys::const_iterator it = opt_keys.begin(); it != opt_keys.end(); ++it) { // prepend the SLIC3R_ prefix @@ -373,9 +368,8 @@ ConfigBase::setenv_() for (size_t i = 0; i < envname.size(); ++i) envname[i] = (envname[i] <= 'z' && envname[i] >= 'a') ? envname[i]-('a'-'A') : envname[i]; - setenv(envname.c_str(), this->serialize(*it).c_str(), 1); + boost::nowide::setenv(envname.c_str(), this->serialize(*it).c_str(), 1); } -#endif } const ConfigOption* @@ -527,19 +521,19 @@ DynamicConfig::empty() const { void DynamicConfig::read_cli(const std::vector &tokens, t_config_option_keys* extra) { - std::vector _argv; + std::vector _argv; // push a bogus executable name (argv[0]) - _argv.push_back(""); + _argv.push_back(const_cast("")); for (size_t i = 0; i < tokens.size(); ++i) - _argv.push_back(const_cast(tokens[i].c_str())); + _argv.push_back(const_cast(tokens[i].c_str())); this->read_cli(_argv.size(), &_argv[0], extra); } void -DynamicConfig::read_cli(const int argc, const char** argv, t_config_option_keys* extra) +DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra) { // cache the CLI option => opt_key mapping std::map opts; diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp index 39e8f2f68..63b335a64 100644 --- a/xs/src/libslic3r/Config.hpp +++ b/xs/src/libslic3r/Config.hpp @@ -685,7 +685,7 @@ class DynamicConfig : public virtual ConfigBase void clear(); bool empty() const; void read_cli(const std::vector &tokens, t_config_option_keys* extra); - void read_cli(const int argc, const char **argv, t_config_option_keys* extra); + void read_cli(int argc, char** argv, t_config_option_keys* extra); private: typedef std::map t_options_map; diff --git a/xs/src/libslic3r/IO/AMF.cpp b/xs/src/libslic3r/IO/AMF.cpp index f0bb7a60a..f0f1c8853 100644 --- a/xs/src/libslic3r/IO/AMF.cpp +++ b/xs/src/libslic3r/IO/AMF.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace Slic3r { namespace IO { @@ -453,10 +454,10 @@ AMF::read(std::string input_file, Model* model) printf("Couldn't allocate memory for parser\n"); return false; } - - FILE *pFile = ::fopen(input_file.c_str(), "rt"); - if (pFile == NULL) { - printf("Cannot open file %s\n", input_file.c_str()); + + std::fstream fin(input_file.c_str(), std::ios::in); + if (!fin.is_open()) { + boost::nowide::cerr << "Cannot open file: " << input_file << std::endl; return false; } @@ -467,27 +468,25 @@ AMF::read(std::string input_file, Model* model) char buff[8192]; bool result = false; - for (;;) { - int len = (int)fread(buff, 1, 8192, pFile); - if (ferror(pFile)) { + while (fin.read(buff, sizeof(buff))) { + if (fin.fail()) { printf("AMF parser: Read error\n"); break; } - int done = feof(pFile); - if (XML_Parse(parser, buff, len, done) == XML_STATUS_ERROR) { + if (XML_Parse(parser, buff, fin.gcount(), fin.eof()) == XML_STATUS_ERROR) { printf("AMF parser: Parse error at line %lu:\n%s\n", XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); break; } - if (done) { + if (fin.eof()) { result = true; break; } } XML_ParserFree(parser); - ::fclose(pFile); + fin.close(); if (result) ctx.endDocument(); diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index cba0a7977..429a5fff4 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #ifdef SLIC3R_DEBUG #include "SVG.hpp" @@ -110,20 +112,32 @@ TriangleMesh::~TriangleMesh() { void TriangleMesh::ReadSTLFile(const std::string &input_file) { + #ifdef BOOST_WINDOWS + stl_open(&stl, boost::nowide::widen(input_file).c_str()); + #else stl_open(&stl, input_file.c_str()); + #endif if (this->stl.error != 0) throw std::runtime_error("Failed to read STL file"); } void TriangleMesh::write_ascii(const std::string &output_file) { + #ifdef BOOST_WINDOWS + stl_write_ascii(&this->stl, boost::nowide::widen(output_file).c_str(), ""); + #else stl_write_ascii(&this->stl, output_file.c_str(), ""); + #endif } void TriangleMesh::write_binary(const std::string &output_file) { + #ifdef BOOST_WINDOWS + stl_write_binary(&this->stl, boost::nowide::widen(output_file).c_str(), ""); + #else stl_write_binary(&this->stl, output_file.c_str(), ""); + #endif } void @@ -234,7 +248,12 @@ TriangleMesh::facets_count() const void TriangleMesh::WriteOBJFile(const std::string &output_file) { stl_generate_shared_vertices(&stl); + + #ifdef BOOST_WINDOWS + stl_write_obj(&stl, boost::nowide::widen(output_file).c_str()); + #else stl_write_obj(&stl, output_file.c_str()); + #endif } void TriangleMesh::scale(float factor) diff --git a/xs/xsp/my.map b/xs/xsp/my.map index b1f026eaa..89025f078 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -275,7 +275,7 @@ INPUT T_STD_STRING { size_t len; - const char * c = SvPV($arg, len); + const char * c = SvPVutf8($arg, len); $var = std::string(c, len); } @@ -290,7 +290,7 @@ T_STD_VECTOR_STD_STRING for (unsigned int i = 0; i < alen; i++) { elem = av_fetch(av, i, 0); if (elem != NULL) { - tmp = SvPV(*elem, len); + tmp = SvPVutf8(*elem, len); ${var}[i] = std::string(tmp, len); } else From 2ad26fc6a7b8870961d47c8c9d068ceead1fa3f3 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 19 May 2017 17:25:53 +0200 Subject: [PATCH 3/3] Fixes for Windows --- lib/Slic3r/Config.pm | 1 + xs/src/libslic3r/Config.cpp | 9 ++++++--- xs/src/libslic3r/IO.cpp | 7 ++++--- xs/src/libslic3r/IO/AMF.cpp | 14 ++++++++------ 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 0ba05cf23..52d67bfee 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -95,6 +95,7 @@ sub load { # legacy syntax of load() my $config = $class->new; + $config->_load($file); return $config; } diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index 51a24c055..da33b2fcd 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -10,9 +10,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -387,7 +389,8 @@ ConfigBase::load(const std::string &file) { namespace pt = boost::property_tree; pt::ptree tree; - pt::read_ini(file, tree); + boost::nowide::ifstream ifs(file); + pt::read_ini(ifs, tree); BOOST_FOREACH(const pt::ptree::value_type &v, tree) { try { t_config_option_key opt_key = v.first; @@ -403,8 +406,8 @@ void ConfigBase::save(const std::string &file) const { using namespace std; - ofstream c; - c.open(file.c_str(), ios::out | ios::trunc); + boost::nowide::ofstream c; + c.open(file, ios::out | ios::trunc); { time_t now; diff --git a/xs/src/libslic3r/IO.cpp b/xs/src/libslic3r/IO.cpp index bdb892373..5b7c77d2d 100644 --- a/xs/src/libslic3r/IO.cpp +++ b/xs/src/libslic3r/IO.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #define TINYOBJLOADER_IMPLEMENTATION #include "tiny_obj_loader.h" @@ -12,7 +13,6 @@ namespace Slic3r { namespace IO { bool STL::read(std::string input_file, TriangleMesh* mesh) { - // TODO: encode file name // TODO: check that file exists try { @@ -81,7 +81,8 @@ OBJ::read(std::string input_file, Model* model) std::vector shapes; std::vector materials; std::string err; - bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, input_file.c_str()); + boost::nowide::ifstream ifs(input_file); + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, &ifs); if (!err.empty()) { // `err` may contain warning message. std::cerr << err << std::endl; @@ -153,7 +154,7 @@ POV::write(TriangleMesh& mesh, std::string output_file) mesh2.center_around_origin(); using namespace std; - ofstream pov; + boost::nowide::ofstream pov; pov.open(output_file.c_str(), ios::out | ios::trunc); for (int i = 0; i < mesh2.stl.stats.number_of_facets; ++i) { const stl_facet &f = mesh2.stl.facet_start[i]; diff --git a/xs/src/libslic3r/IO/AMF.cpp b/xs/src/libslic3r/IO/AMF.cpp index f0f1c8853..7433762ee 100644 --- a/xs/src/libslic3r/IO/AMF.cpp +++ b/xs/src/libslic3r/IO/AMF.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -455,7 +456,7 @@ AMF::read(std::string input_file, Model* model) return false; } - std::fstream fin(input_file.c_str(), std::ios::in); + boost::nowide::ifstream fin(input_file, std::ios::in); if (!fin.is_open()) { boost::nowide::cerr << "Cannot open file: " << input_file << std::endl; return false; @@ -468,8 +469,9 @@ AMF::read(std::string input_file, Model* model) char buff[8192]; bool result = false; - while (fin.read(buff, sizeof(buff))) { - if (fin.fail()) { + while (!fin.eof()) { + fin.read(buff, sizeof(buff)); + if (fin.bad()) { printf("AMF parser: Read error\n"); break; } @@ -498,12 +500,12 @@ AMF::write(Model& model, std::string output_file) { using namespace std; - ofstream file; + boost::nowide::ofstream file; file.open(output_file, ios::out | ios::trunc); file << "" << endl << "" << endl - << "Slic3r " << SLIC3R_VERSION << "" << endl; + << " Slic3r " << SLIC3R_VERSION << "" << endl; for (const auto &material : model.materials) { if (material.first.empty()) @@ -597,7 +599,7 @@ AMF::write(Model& model, std::string output_file) << " " << endl << " " << instance->offset.x + object->origin_translation.x << "" << endl << " " << instance->offset.y + object->origin_translation.y << "" << endl - << " %" << instance->rotation << "" << endl + << " " << instance->rotation << "" << endl << " " << instance->scaling_factor << "" << endl << " " << endl; }