mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-01 05:22:02 +08:00
Merge pull request #3963 from alexrj/utf8
Use UTF-8 in libslic3r. Future-proof portable solution for non-ASCII files
This commit is contained in:
commit
05a1024898
@ -95,7 +95,8 @@ sub load {
|
||||
|
||||
# legacy syntax of load()
|
||||
my $config = $class->new;
|
||||
$config->_load(Slic3r::encode_path($file));
|
||||
|
||||
$config->_load($file);
|
||||
return $config;
|
||||
}
|
||||
|
||||
@ -103,7 +104,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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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 = ();
|
||||
|
@ -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;
|
||||
|
11
slic3r.pl
11
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;
|
||||
|
||||
|
@ -11,14 +11,21 @@
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/args.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
|
||||
|
||||
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 +43,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 +51,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 +70,7 @@ main(const int argc, const char **argv)
|
||||
std::vector<Model> 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 +78,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 +116,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 +124,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 +133,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 +174,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;
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,20 @@
|
||||
#include "IO.hpp"
|
||||
#include "TriangleMesh.hpp"
|
||||
#include "libslic3r.h"
|
||||
#include <boost/nowide/args.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
167
xs/src/boost/nowide/args.hpp
Executable file
167
xs/src/boost/nowide/args.hpp
Executable file
@ -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 <boost/config.hpp>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
#include <vector>
|
||||
#ifdef BOOST_WINDOWS
|
||||
#include <boost/nowide/windows.hpp>
|
||||
#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<wargc;i++) {
|
||||
if(!arg_values_[i].convert(wargv[i])) {
|
||||
wargc = i;
|
||||
break;
|
||||
}
|
||||
args_[i] = arg_values_[i].c_str();
|
||||
}
|
||||
argc = wargc;
|
||||
argv = &args_[0];
|
||||
}
|
||||
catch(...) {
|
||||
LocalFree(wargv);
|
||||
throw;
|
||||
}
|
||||
LocalFree(wargv);
|
||||
}
|
||||
void fix_env(char **&en)
|
||||
{
|
||||
static char *dummy = 0;
|
||||
en = &dummy;
|
||||
wchar_t *wstrings = GetEnvironmentStringsW();
|
||||
if(!wstrings)
|
||||
return;
|
||||
try {
|
||||
wchar_t *wstrings_end = 0;
|
||||
int count = 0;
|
||||
for(wstrings_end = wstrings;*wstrings_end;wstrings_end+=wcslen(wstrings_end)+1)
|
||||
count++;
|
||||
if(env_.convert(wstrings,wstrings_end)) {
|
||||
envp_.resize(count+1,0);
|
||||
char *p=env_.c_str();
|
||||
int pos = 0;
|
||||
for(int i=0;i<count;i++) {
|
||||
if(*p!='=')
|
||||
envp_[pos++] = p;
|
||||
p+=strlen(p)+1;
|
||||
}
|
||||
en = &envp_[0];
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
FreeEnvironmentStringsW(wstrings);
|
||||
throw;
|
||||
}
|
||||
FreeEnvironmentStringsW(wstrings);
|
||||
|
||||
}
|
||||
|
||||
std::vector<char *> args_;
|
||||
std::vector<short_stackstring> arg_values_;
|
||||
stackstring env_;
|
||||
std::vector<char *> 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
|
126
xs/src/boost/nowide/cenv.hpp
Executable file
126
xs/src/boost/nowide/cenv.hpp
Executable file
@ -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 <string>
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
#include <vector>
|
||||
|
||||
#ifdef BOOST_WINDOWS
|
||||
#include <boost/nowide/windows.hpp>
|
||||
#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<wchar_t> 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<unsigned>(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
|
54
xs/src/boost/nowide/config.hpp
Executable file
54
xs/src/boost/nowide/config.hpp
Executable file
@ -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 <boost/config.hpp>
|
||||
|
||||
#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 <boost/config/auto_link.hpp>
|
||||
#endif // auto-linking disabled
|
||||
|
||||
|
||||
#endif // boost/nowide/config.hpp
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
154
xs/src/boost/nowide/convert.hpp
Executable file
154
xs/src/boost/nowide/convert.hpp
Executable file
@ -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 <string>
|
||||
#include <boost/locale/encoding_utf.hpp>
|
||||
|
||||
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<typename CharOut,typename CharIn>
|
||||
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<CharIn>::template decode<CharIn const *>(source_begin,source_end);
|
||||
if(c==illegal || c==incomplete) {
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
size_t width = utf_traits<CharOut>::width(c);
|
||||
if(buffer_size < width) {
|
||||
rv=0;
|
||||
break;
|
||||
}
|
||||
buffer = utf_traits<CharOut>::template encode<CharOut *>(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<typename Char>
|
||||
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<char>(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<wchar_t>(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<char>(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<wchar_t>(s);
|
||||
}
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
101
xs/src/boost/nowide/cstdio.hpp
Executable file
101
xs/src/boost/nowide/cstdio.hpp
Executable file
@ -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 <cstdio>
|
||||
#include <stdio.h>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#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
|
16
xs/src/boost/nowide/cstdlib.hpp
Executable file
16
xs/src/boost/nowide/cstdlib.hpp
Executable file
@ -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 <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/system.hpp>
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
415
xs/src/boost/nowide/filebuf.hpp
Executable file
415
xs/src/boost/nowide/filebuf.hpp
Executable file
@ -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 <iosfwd>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#include <stdio.h>
|
||||
|
||||
#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<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
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<char> : public std::basic_streambuf<char> {
|
||||
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;ptr<p;ptr++)
|
||||
std::cerr << *ptr;
|
||||
if(e!=0) {
|
||||
std::cerr << "|";
|
||||
for(char *ptr = p;ptr<e;ptr++)
|
||||
std::cerr << *ptr;
|
||||
}
|
||||
std::cerr << "]" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void print_state()
|
||||
{
|
||||
std::cerr << "- Output:" << std::endl;
|
||||
print_buf(pbase(),pptr(),0);
|
||||
std::cerr << "- Input:" << std::endl;
|
||||
print_buf(eback(),gptr(),egptr());
|
||||
std::cerr << "- fpos: " << (file_ ? ftell(file_) : -1L) << std::endl;
|
||||
}
|
||||
|
||||
struct print_guard
|
||||
{
|
||||
print_guard(basic_filebuf *p,char const *func)
|
||||
{
|
||||
self = p;
|
||||
f=func;
|
||||
std::cerr << "In: " << f << std::endl;
|
||||
self->print_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<char>::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<char> filebuf;
|
||||
|
||||
#endif // windows
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
283
xs/src/boost/nowide/fstream.hpp
Executable file
283
xs/src/boost/nowide/fstream.hpp
Executable file
@ -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 <iosfwd>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <boost/nowide/filebuf.hpp>
|
||||
|
||||
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<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_ifstream : public std::basic_istream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_istream<CharType,Traits> 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<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Same as std::basic_ofstream<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_ofstream : public std::basic_ostream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_ostream<CharType,Traits> 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<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Same as std::basic_fstream<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_fstream : public std::basic_iostream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_iostream<CharType,Traits> 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<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Same as std::filebuf but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_filebuf<char> filebuf;
|
||||
///
|
||||
/// Same as std::ifstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_ifstream<char> ifstream;
|
||||
///
|
||||
/// Same as std::ofstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_ofstream<char> ofstream;
|
||||
///
|
||||
/// Same as std::fstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_fstream<char> fstream;
|
||||
|
||||
#endif
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
28
xs/src/boost/nowide/integration/filesystem.hpp
Executable file
28
xs/src/boost/nowide/integration/filesystem.hpp
Executable file
@ -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 <boost/filesystem/path.hpp>
|
||||
#include <boost/nowide/utf8_codecvt.hpp>
|
||||
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<wchar_t>());
|
||||
boost::filesystem::path::imbue(tmp);
|
||||
}
|
||||
} // nowide
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
261
xs/src/boost/nowide/iostream.cpp
Executable file
261
xs/src/boost/nowide/iostream.cpp
Executable file
@ -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 <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef BOOST_WINDOWS
|
||||
|
||||
#ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
#endif
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
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<int>(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<char>::decode(p,e))!=uf::illegal && c!=uf::incomplete) {
|
||||
out = uf::utf_traits<wchar_t>::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<char> 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<char>::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<wchar_t>::decode(p,e))!=uf::illegal && c!=uf::incomplete) {
|
||||
out = uf::utf_traits<char>::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<char> 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
|
99
xs/src/boost/nowide/iostream.hpp
Executable file
99
xs/src/boost/nowide/iostream.hpp
Executable file
@ -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 <boost/nowide/config.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
|
||||
#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<console_output_buffer> 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<console_input_buffer> 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
|
154
xs/src/boost/nowide/stackstring.hpp
Executable file
154
xs/src/boost/nowide/stackstring.hpp
Executable file
@ -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 <boost/nowide/convert.hpp>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
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<typename CharOut=wchar_t,typename CharIn = char,size_t BufferSize = 256>
|
||||
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<buffer_size;i++)
|
||||
std::swap(buffer_[i],other.buffer_[i]);
|
||||
}
|
||||
basic_stackstring &operator=(basic_stackstring const &other)
|
||||
{
|
||||
if(this != &other) {
|
||||
basic_stackstring tmp(other);
|
||||
swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_stackstring() : mem_buffer_(0)
|
||||
{
|
||||
}
|
||||
bool convert(input_char const *input)
|
||||
{
|
||||
return convert(input,details::basic_strend(input));
|
||||
}
|
||||
bool convert(input_char const *begin,input_char const *end)
|
||||
{
|
||||
clear();
|
||||
|
||||
size_t space = get_space(sizeof(input_char),sizeof(output_char),end - begin) + 1;
|
||||
if(space <= buffer_size) {
|
||||
if(basic_convert(buffer_,buffer_size,begin,end))
|
||||
return true;
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
mem_buffer_ = new output_char[space];
|
||||
if(!basic_convert(mem_buffer_,space,begin,end)) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
output_char *c_str()
|
||||
{
|
||||
if(mem_buffer_)
|
||||
return mem_buffer_;
|
||||
return buffer_;
|
||||
}
|
||||
output_char const *c_str() const
|
||||
{
|
||||
if(mem_buffer_)
|
||||
return mem_buffer_;
|
||||
return buffer_;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
if(mem_buffer_) {
|
||||
delete [] mem_buffer_;
|
||||
mem_buffer_=0;
|
||||
}
|
||||
buffer_[0] = 0;
|
||||
}
|
||||
~basic_stackstring()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
private:
|
||||
static size_t get_space(size_t insize,size_t outsize,size_t in)
|
||||
{
|
||||
if(insize <= outsize)
|
||||
return in;
|
||||
else if(insize == 2 && outsize == 1)
|
||||
return 3 * in;
|
||||
else if(insize == 4 && outsize == 1)
|
||||
return 4 * in;
|
||||
else // if(insize == 4 && outsize == 2)
|
||||
return 2 * in;
|
||||
}
|
||||
output_char buffer_[buffer_size];
|
||||
output_char *mem_buffer_;
|
||||
}; //basic_stackstring
|
||||
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<wchar_t,char,256> wstackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<char,wchar_t,256> stackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<wchar_t,char,16> wshort_stackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<char,wchar_t,16> short_stackstring;
|
||||
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
46
xs/src/boost/nowide/system.hpp
Executable file
46
xs/src/boost/nowide/system.hpp
Executable file
@ -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 <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <boost/nowide/stackstring.hpp>
|
||||
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
|
499
xs/src/boost/nowide/utf8_codecvt.hpp
Executable file
499
xs/src/boost/nowide/utf8_codecvt.hpp
Executable file
@ -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 <boost/locale/utf.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <locale>
|
||||
|
||||
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<typename CharType,int CharSize=sizeof(CharType)>
|
||||
class utf8_codecvt;
|
||||
|
||||
template<typename CharType>
|
||||
class utf8_codecvt<CharType,2> : public std::codecvt<CharType,char,std::mbstate_t>
|
||||
{
|
||||
public:
|
||||
utf8_codecvt(size_t refs = 0) : std::codecvt<CharType,char,std::mbstate_t>(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<boost::uint16_t *>(&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<boost::uint16_t *>(&std_state);
|
||||
#else
|
||||
size_t save_max = max;
|
||||
boost::uint16_t state = *reinterpret_cast<boost::uint16_t const *>(&std_state);
|
||||
#endif
|
||||
while(max > 0 && from < from_end){
|
||||
char const *prev_from = from;
|
||||
boost::uint32_t ch=boost::locale::utf::utf_traits<char>::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<boost::uint16_t *>(&std_state);
|
||||
while(to < to_end && from < from_end)
|
||||
{
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Entering IN--------------" << std::endl;
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
char const *from_saved = from;
|
||||
|
||||
uint32_t ch=boost::locale::utf::utf_traits<char>::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 <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
virtual std::codecvt_base::result
|
||||
do_out( std::mbstate_t &std_state,
|
||||
uchar const *from,
|
||||
uchar const *from_end,
|
||||
uchar const *&from_next,
|
||||
char *to,
|
||||
char *to_end,
|
||||
char *&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 assume that sizeof(mbstate_t) >=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<boost::uint16_t *>(&std_state);
|
||||
while(to < to_end && from < from_end)
|
||||
{
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Entering OUT --------------" << std::endl;
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
boost::uint32_t ch=0;
|
||||
if(state != 0) {
|
||||
// if the state idecates that 1st surrogate pair was written
|
||||
// we should make sure that the second one that comes is actually
|
||||
// second surrogate
|
||||
boost::uint16_t w1 = state;
|
||||
boost::uint16_t w2 = *from;
|
||||
// we don't forward from as writing may fail to incomplete or
|
||||
// partial conversion
|
||||
if(0xDC00 <= w2 && w2<=0xDFFF) {
|
||||
boost::uint16_t vh = w1 - 0xD800;
|
||||
boost::uint16_t vl = w2 - 0xDC00;
|
||||
ch=((uint32_t(vh) << 10) | vl) + 0x10000;
|
||||
}
|
||||
else {
|
||||
// Invalid surrogate
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ch = *from;
|
||||
if(0xD800 <= ch && ch<=0xDBFF) {
|
||||
// if this is a first surrogate pair we put
|
||||
// it into the state and consume it, note we don't
|
||||
// go forward as it should be illegal so we increase
|
||||
// the from pointer manually
|
||||
state = ch;
|
||||
from++;
|
||||
continue;
|
||||
}
|
||||
else if(0xDC00 <= ch && ch<=0xDFFF) {
|
||||
// if we observe second surrogate pair and
|
||||
// first only may be expected we should break from the loop with error
|
||||
// as it is illegal input
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!boost::locale::utf::is_valid_codepoint(ch)) {
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
int len = boost::locale::utf::utf_traits<char>::width(ch);
|
||||
if(to_end - to < len) {
|
||||
r=std::codecvt_base::partial;
|
||||
break;
|
||||
}
|
||||
to = boost::locale::utf::utf_traits<char>::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 <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
class utf8_codecvt<CharType,4> : public std::codecvt<CharType,char,std::mbstate_t>
|
||||
{
|
||||
public:
|
||||
utf8_codecvt(size_t refs = 0) : std::codecvt<CharType,char,std::mbstate_t>(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<char>::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 <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
char const *from_saved = from;
|
||||
|
||||
uint32_t ch=boost::locale::utf::utf_traits<char>::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 <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
virtual std::codecvt_base::result
|
||||
do_out( std::mbstate_t &std_state,
|
||||
uchar const *from,
|
||||
uchar const *from_end,
|
||||
uchar const *&from_next,
|
||||
char *to,
|
||||
char *to_end,
|
||||
char *&to_next) const
|
||||
{
|
||||
std::codecvt_base::result r=std::codecvt_base::ok;
|
||||
while(to < to_end && from < from_end)
|
||||
{
|
||||
#ifdef DEBUG_CODECVT
|
||||
std::cout << "Entering OUT --------------" << std::endl;
|
||||
std::cout << "State " << std::hex << state <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
boost::uint32_t ch=0;
|
||||
ch = *from;
|
||||
if(!boost::locale::utf::is_valid_codepoint(ch)) {
|
||||
r=std::codecvt_base::error;
|
||||
break;
|
||||
}
|
||||
int len = boost::locale::utf::utf_traits<char>::width(ch);
|
||||
if(to_end - to < len) {
|
||||
r=std::codecvt_base::partial;
|
||||
break;
|
||||
}
|
||||
to = boost::locale::utf::utf_traits<char>::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 <<std::endl;
|
||||
std::cout << "Left in " << std::dec << from_end - from << " out " << to_end -to << std::endl;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
} // nowide
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
39
xs/src/boost/nowide/windows.hpp
Executable file
39
xs/src/boost/nowide/windows.hpp
Executable file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// 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_WINDOWS_HPP_INCLUDED
|
||||
#define BOOST_NOWIDE_WINDOWS_HPP_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef BOOST_NOWIDE_USE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#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
|
@ -1,5 +1,4 @@
|
||||
#include "Config.hpp"
|
||||
#include <stdlib.h> // for setenv()
|
||||
#include <assert.h>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
@ -11,16 +10,15 @@
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <string.h>
|
||||
|
||||
#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 +358,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 +370,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*
|
||||
@ -393,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;
|
||||
@ -409,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;
|
||||
@ -527,19 +524,19 @@ DynamicConfig::empty() const {
|
||||
void
|
||||
DynamicConfig::read_cli(const std::vector<std::string> &tokens, t_config_option_keys* extra)
|
||||
{
|
||||
std::vector<const char*> _argv;
|
||||
std::vector<char*> _argv;
|
||||
|
||||
// push a bogus executable name (argv[0])
|
||||
_argv.push_back("");
|
||||
_argv.push_back(const_cast<char*>(""));
|
||||
|
||||
for (size_t i = 0; i < tokens.size(); ++i)
|
||||
_argv.push_back(const_cast<const char*>(tokens[i].c_str()));
|
||||
_argv.push_back(const_cast<char *>(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<std::string,std::string> opts;
|
||||
|
@ -723,7 +723,7 @@ class DynamicConfig : public virtual ConfigBase
|
||||
void clear();
|
||||
bool empty() const;
|
||||
void read_cli(const std::vector<std::string> &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_config_option_key,ConfigOption*> t_options_map;
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
|
||||
#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<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> 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];
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <expat/expat.h>
|
||||
|
||||
namespace Slic3r { namespace IO {
|
||||
@ -453,10 +455,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());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -467,27 +469,26 @@ 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.eof()) {
|
||||
fin.read(buff, sizeof(buff));
|
||||
if (fin.bad()) {
|
||||
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();
|
||||
@ -499,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 << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl
|
||||
<< "<amf unit=\"millimeter\">" << endl
|
||||
<< "<metadata type=\"cad\">Slic3r " << SLIC3R_VERSION << "</metadata>" << endl;
|
||||
<< " <metadata type=\"cad\">Slic3r " << SLIC3R_VERSION << "</metadata>" << endl;
|
||||
|
||||
for (const auto &material : model.materials) {
|
||||
if (material.first.empty())
|
||||
@ -598,7 +599,7 @@ AMF::write(Model& model, std::string output_file)
|
||||
<< " <instance objectid=\"" << object_id << "\">" << endl
|
||||
<< " <deltax>" << instance->offset.x + object->origin_translation.x << "</deltax>" << endl
|
||||
<< " <deltay>" << instance->offset.y + object->origin_translation.y << "</deltay>" << endl
|
||||
<< " <rz>%" << instance->rotation << "</rz>" << endl
|
||||
<< " <rz>" << instance->rotation << "</rz>" << endl
|
||||
<< " <scale>" << instance->scaling_factor << "</scale>" << endl
|
||||
<< " </instance>" << endl;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <stdexcept>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
|
||||
#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)
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user