Skip to content

Commit cac9db8

Browse files
authored
Merge pull request #5699 from mvieth/better_locale_invariance
Make io more locale invariant
2 parents 2acc695 + 07d3cb9 commit cac9db8

File tree

4 files changed

+77
-19
lines changed

4 files changed

+77
-19
lines changed

io/include/pcl/io/file_io.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ namespace pcl
342342
}
343343
else {
344344
is.str(st);
345+
is.clear(); // clear error state flags
345346
if (!(is >> value))
346347
value = static_cast<Type>(atof(st.c_str()));
347348
}
@@ -364,6 +365,7 @@ namespace pcl
364365
std::int8_t value;
365366
int val;
366367
is.str(st);
368+
is.clear(); // clear error state flags
367369
// is >> val; -- unfortunately this fails on older GCC versions and CLANG on MacOS
368370
if (!(is >> val)) {
369371
val = static_cast<int>(atof(st.c_str()));
@@ -388,6 +390,7 @@ namespace pcl
388390
std::uint8_t value;
389391
int val;
390392
is.str(st);
393+
is.clear(); // clear error state flags
391394
// is >> val; -- unfortunately this fails on older GCC versions and CLANG on
392395
// MacOS
393396
if (!(is >> val)) {

io/src/ply_io.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ pcl::PLYWriter::generateHeader (const pcl::PCLPointCloud2 &cloud,
787787
int valid_points)
788788
{
789789
std::ostringstream oss;
790+
oss.imbue (std::locale::classic ()); // mostly to make sure that no thousands separator is printed
790791
// Begin header
791792
oss << "ply";
792793
if (!binary)

test/io/test_io.cpp

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,27 +1519,29 @@ TEST (PCL, LZFInMem)
15191519
TEST (PCL, Locale)
15201520
{
15211521
#ifndef __APPLE__
1522+
PointCloud<PointXYZ> cloud, cloud2, cloud3;
1523+
cloud.width = 640;
1524+
cloud.height = 480;
1525+
cloud.resize (cloud.width * cloud.height);
1526+
cloud.is_dense = true;
1527+
1528+
srand (static_cast<unsigned int> (time (nullptr)));
1529+
const auto nr_p = cloud.size ();
1530+
// Randomly create a new point cloud
1531+
cloud[0].x = std::numeric_limits<float>::quiet_NaN ();
1532+
cloud[0].y = std::numeric_limits<float>::quiet_NaN ();
1533+
cloud[0].z = std::numeric_limits<float>::quiet_NaN ();
1534+
1535+
for (std::size_t i = 1; i < nr_p; ++i)
1536+
{
1537+
cloud[i].x = static_cast<float> (1024 * rand () / (RAND_MAX + 1.0));
1538+
cloud[i].y = static_cast<float> (1024 * rand () / (RAND_MAX + 1.0));
1539+
cloud[i].z = static_cast<float> (1024 * rand () / (RAND_MAX + 1.0));
1540+
}
1541+
1542+
// First write with German locale, then read with English locale
15221543
try
15231544
{
1524-
PointCloud<PointXYZ> cloud, cloud2;
1525-
cloud.width = 640;
1526-
cloud.height = 480;
1527-
cloud.resize (cloud.width * cloud.height);
1528-
cloud.is_dense = true;
1529-
1530-
srand (static_cast<unsigned int> (time (nullptr)));
1531-
const auto nr_p = cloud.size ();
1532-
// Randomly create a new point cloud
1533-
cloud[0].x = std::numeric_limits<float>::quiet_NaN ();
1534-
cloud[0].y = std::numeric_limits<float>::quiet_NaN ();
1535-
cloud[0].z = std::numeric_limits<float>::quiet_NaN ();
1536-
1537-
for (std::size_t i = 1; i < nr_p; ++i)
1538-
{
1539-
cloud[i].x = static_cast<float> (1024 * rand () / (RAND_MAX + 1.0));
1540-
cloud[i].y = static_cast<float> (1024 * rand () / (RAND_MAX + 1.0));
1541-
cloud[i].z = static_cast<float> (1024 * rand () / (RAND_MAX + 1.0));
1542-
}
15431545
PCDWriter writer;
15441546
try
15451547
{
@@ -1592,6 +1594,56 @@ TEST (PCL, Locale)
15921594
}
15931595

15941596
remove ("test_pcl_io_ascii_locale.pcd");
1597+
1598+
// Now write with English locale, then read with German locale
1599+
try
1600+
{
1601+
#ifdef _WIN32
1602+
std::locale::global (std::locale ("English_US"));
1603+
#else
1604+
std::locale::global (std::locale ("en_US.UTF-8"));
1605+
#endif
1606+
}
1607+
catch (const std::runtime_error&)
1608+
{
1609+
PCL_WARN ("Failed to set locale, skipping test.\n");
1610+
}
1611+
PCDWriter writer;
1612+
int res = writer.writeASCII<PointXYZ> ("test_pcl_io_ascii_locale.pcd", cloud);
1613+
EXPECT_EQ (res, 0);
1614+
1615+
PCDReader reader;
1616+
try
1617+
{
1618+
#ifdef _WIN32
1619+
std::locale::global (std::locale ("German_germany"));
1620+
#else
1621+
std::locale::global (std::locale ("de_DE.UTF-8"));
1622+
#endif
1623+
}
1624+
catch (const std::runtime_error&)
1625+
{
1626+
PCL_WARN ("Failed to set locale, skipping test.\n");
1627+
}
1628+
reader.read<PointXYZ> ("test_pcl_io_ascii_locale.pcd", cloud3);
1629+
std::locale::global (std::locale::classic ());
1630+
1631+
EXPECT_EQ (cloud3.width, cloud.width);
1632+
EXPECT_EQ (cloud3.height, cloud.height);
1633+
EXPECT_FALSE (cloud3.is_dense);
1634+
EXPECT_EQ (cloud3.size (), cloud.size ());
1635+
1636+
EXPECT_TRUE (std::isnan(cloud3[0].x));
1637+
EXPECT_TRUE (std::isnan(cloud3[0].y));
1638+
EXPECT_TRUE (std::isnan(cloud3[0].z));
1639+
for (std::size_t i = 1; i < cloud3.size (); ++i)
1640+
{
1641+
ASSERT_FLOAT_EQ (cloud3[i].x, cloud[i].x);
1642+
ASSERT_FLOAT_EQ (cloud3[i].y, cloud[i].y);
1643+
ASSERT_FLOAT_EQ (cloud3[i].z, cloud[i].z);
1644+
}
1645+
1646+
remove ("test_pcl_io_ascii_locale.pcd");
15951647
#endif
15961648
}
15971649

test/io/test_ply_io.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ TEST (PCL, PLYReaderWriter)
105105
EXPECT_FLOAT_EQ (cloud[counter].z, cloud2[counter].z); // test for fromPCLPointCloud2 ()
106106
EXPECT_FLOAT_EQ (cloud[counter].intensity, cloud2[counter].intensity); // test for fromPCLPointCloud2 ()
107107
}
108+
remove ("test_pcl_io.ply");
108109
}
109110

110111
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -567,6 +568,7 @@ TEST_F (PLYTest, Float64Cloud)
567568

568569
// create file
569570
std::ofstream fs;
571+
fs.imbue (std::locale::classic ()); // make sure that floats are printed with decimal point
570572
fs.open (mesh_file_ply_.c_str ());
571573
fs << "ply\n"
572574
"format ascii 1.0\n"

0 commit comments

Comments
 (0)