Skip to content

Commit

Permalink
latest from coda-oss
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Smith committed Feb 23, 2022
1 parent 4ee8337 commit c08a0ce
Show file tree
Hide file tree
Showing 16 changed files with 167 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ class EncodedStringView final
// Convert whatever we're looking at to UTF-16 or UTF-32
std::u16string u16string() const; // c.f. std::filesystem::path::u8string()
std::u32string u32string() const; // c.f. std::filesystem::path::u8string()
// This is especially useful on Windows because the default for characters
// is WCHAR (char* is converted to UTF-16).
std::wstring wstring() const; // UTF-16 on Windows, UTF-32 on Linux

bool operator_eq(const EncodedStringView&) const;
Expand Down
11 changes: 11 additions & 0 deletions externals/coda-oss/modules/c++/str/include/str/Encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@

#include <string.h>
#include <wchar.h>
#include <stdint.h>

#include <memory>
#include <string>
#include <type_traits>

#include "coda_oss/string.h"
#include "gsl/gsl.h"
Expand Down Expand Up @@ -92,6 +94,15 @@ inline coda_oss::u8string fromUtf8(std::string::const_pointer s)

//////////////////////////////////////////////////////////////////////////////////////////

// We'll get strange errors, possibibly at link-time, if wchar_t is not a wchar_t type.
// MSVC has an option to control this: https://docs.microsoft.com/en-us/cpp/build/reference/zc-wchar-t-wchar-t-is-native-type
// https://en.cppreference.com/w/cpp/language/types
// "It has the same size, signedness, and alignment as one of the integer types, but is a distinct type."
static_assert(!std::is_same<wchar_t, uint16_t>::value, "wchar_t should not be the same as uint16_t");
static_assert(!std::is_same<wchar_t, int16_t>::value, "wchar_t should not be the same as int16_t");
static_assert(!std::is_same<wchar_t, uint32_t>::value, "wchar_t should not be the same as uint32_t");
static_assert(!std::is_same<wchar_t, int32_t>::value, "wchar_t should not be the same as int32_t");

// When the encoding is important, we want to "traffic" in coda_oss::u8string (UTF-8), not
// str::W1252string (Windows-1252) or std::string (unknown). Make it easy to get those from other encodings.
coda_oss::u8string to_u8string(std::string::const_pointer, size_t); // std::string is Windows-1252 or UTF-8 depending on platform
Expand Down
23 changes: 23 additions & 0 deletions externals/coda-oss/modules/c++/str/include/str/Manip.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,33 @@
#include <string>
#include <vector>

#include "config/compiler_extensions.h"
#include "coda_oss/CPlusPlus.h"
#include "str/Convert.h"

namespace str
{
// non-const overload for .data() in C++17
template<typename CharT>
inline CharT* data(std::basic_string<CharT>& s) noexcept
{
#if CODA_OSS_cpp17
return s.data();
#else
CODA_OSS_disable_warning_push
#if _MSC_VER
#pragma warning(disable : 26492) // Don't use const_cast to cast away const or volatile (type.3).
#endif
return const_cast <typename std::basic_string<CharT>::pointer>(s.data());
CODA_OSS_disable_warning_pop
#endif // CODA_OSS_cpp17
}
template <typename CharT>
inline const CharT* data(const std::basic_string<CharT>& s) noexcept // to make generic programming easier
{
return s.data();
}

/**
* Trim the white space off the back and front of a string
* @param s String to trim
Expand Down
2 changes: 1 addition & 1 deletion externals/coda-oss/modules/c++/str/source/Encoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ std::wstring str::details::to_wstring(std::string::const_pointer p, size_t sz, b
to_u16string(p, sz, is_utf8); // std::wstring is UTF-16 on Windows
#endif
#if !_WIN32
to_u32string(p, sz, is_utf8); // std::wstring is UTF-32 on Linux
to_u32string(p, sz, is_utf8); // std::wstring is UTF-32 on Linux
#endif
return str::c_str<std::wstring::const_pointer>(s); // copy
}
Expand Down
23 changes: 23 additions & 0 deletions externals/coda-oss/modules/c++/str/unittests/test_str.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
*
*/

#include <tuple> // std::ignore

#include <config/compiler_extensions.h>
#include <import/str.h>
#include "TestCase.h"

Expand Down Expand Up @@ -49,6 +52,25 @@ TEST_CASE(testStrip)
TEST_ASSERT_EQ(s5, "test");
}

TEST_CASE(testData)
{
std::string s;
// https://en.cppreference.com/w/cpp/string/basic_string/resize
s.resize(3); // "Resizes the string to contain count characters."

CODA_OSS_disable_warning_push
#if _MSC_VER
#pragma warning(disable : 4996) // '...': This function or variable may be unsafe. ...
#endif

// https://en.cppreference.com/w/cpp/string/basic_string/data
// "Modifying the past-the-end null terminator stored at data()+size() to any value other than CharT() has undefined behavior."
std::ignore = strcpy(str::data(s), "abc");

CODA_OSS_disable_warning_pop
TEST_ASSERT_EQ(s, "abc");
}

TEST_CASE(testUpper)
{
std::string s = "test-something1";
Expand Down Expand Up @@ -202,6 +224,7 @@ int main(int, char**)
{
TEST_CHECK(testTrim);
TEST_CHECK(testStrip);
TEST_CHECK(testData);
TEST_CHECK(testUpper);
TEST_CHECK(testLower);
TEST_CHECK(testReplace);
Expand Down
6 changes: 2 additions & 4 deletions externals/coda-oss/modules/c++/sys/source/sys_filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ fs::path::string_type fs::path::to_native(const std::string& s_)
#endif
}

static const fs::path empty_path;

fs::path::path() noexcept
{
}
Expand Down Expand Up @@ -141,7 +139,7 @@ fs::path fs::path::extension() const
const auto pathname = string();
if ((pathname == ".") || (pathname == ".."))
{
return empty_path;
return fs::path();
}

auto fn = filename().string();
Expand All @@ -150,7 +148,7 @@ fs::path fs::path::extension() const
// "If ... filename() does not contain the . character, then empty path is returned."
if (dot == std::string::npos)
{
return empty_path;
return fs::path();
}

// "If the first character in the filename is a period, that period is ignored
Expand Down
6 changes: 4 additions & 2 deletions externals/coda-oss/modules/c++/units/include/units/Angles.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@ using Degrees = Angle<tags::Degrees, T>;
//using Gradians = Angle<tags::Gradians, T>;

template <typename T, typename TResult = T>
inline constexpr void convert(Radians<T> v, Degrees<TResult>& result) noexcept
inline /*constexpr*/ Degrees<TResult>& convert(Radians<T> v, Degrees<TResult>& result) noexcept
{
result.value() = v.value() * math::Constants::radians_to_degrees<T>();
return result; // ICC doesn't like "constexpr void"
}
template <typename T, typename TResult = T>
inline constexpr void convert(Degrees<T> v, Radians<TResult>& result) noexcept
inline /*constexpr*/ Radians<TResult>& convert(Degrees<T> v, Radians<TResult>& result) noexcept
{
result.value() = v.value() * math::Constants::degrees_to_radians<T>();
return result; // ICC doesn't like "constexpr void"
}

template<typename Tag, typename T>
Expand Down
15 changes: 10 additions & 5 deletions externals/coda-oss/modules/c++/units/include/units/Lengths.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@ template <typename T>
using Meters = Length<tags::Meters, T>;

template <typename T, typename TResult = T>
inline constexpr void convert(Meters<T> v, Feet<TResult>& result) noexcept
inline /*constexpr*/ Feet<TResult>& convert(Meters<T> v, Feet<TResult>& result) noexcept
{
result.value() = v.value() * math::Constants::METERS_TO_FEET;
return result; // ICC doesn't like "constexpr void"
}
template <typename T, typename TResult = T>
inline constexpr void convert(Feet<T> v, Meters<TResult>& result) noexcept
inline /*constexpr*/ Meters<TResult>& convert(Feet<T> v, Meters<TResult>& result) noexcept
{
result.value() = v.value() * math::Constants::FEET_TO_METERS;
return result; // ICC doesn't like "constexpr void"
}

namespace tags
Expand All @@ -68,19 +70,22 @@ template <typename T>
using NauticalMiles = Length<tags::NauticalMiles, T>;

template <typename T, typename TResult = T>
inline constexpr void convert(NauticalMiles<T> v, Feet<TResult>& result) noexcept
inline /*constexpr*/ Feet<TResult>& convert(NauticalMiles<T> v, Feet<TResult>& result) noexcept
{
result.value() = v.value() * math::Constants::NAUTICAL_MILES_TO_FEET;
return result; // ICC doesn't like "constexpr void"
}
template <typename T, typename TResult = T>
inline constexpr void convert(NauticalMiles<T> v, Meters<TResult>& result) noexcept
inline /*constexpr*/ Meters<TResult>& convert(NauticalMiles<T> v, Meters<TResult>& result) noexcept
{
result.value() = v.value() * math::Constants::NAUTICAL_MILES_TO_METERS;
return result; // ICC doesn't like "constexpr void"
}
template <typename T, typename TResult = T>
inline constexpr void convert(Meters<T> v, NauticalMiles<TResult>& result) noexcept
inline /*constexpr*/ NauticalMiles<TResult>& convert(Meters<T> v, NauticalMiles<TResult>& result) noexcept
{
result.value() = v.value() * math::Constants::METERS_TO_NAUTICAL_MILES;
return result; // ICC doesn't like "constexpr void"
}
}

Expand Down
31 changes: 23 additions & 8 deletions externals/coda-oss/modules/c++/units/include/units/Unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,31 +56,46 @@ struct Unit final
return value_;
}

// Calls convert() to convert from Unit<int, feet> to Unit<double, meters>.
// The defaults ensure converting to oneself works.
template <typename ResultTag = Tag, typename TReturn = T>
constexpr Unit<TReturn, ResultTag> to() const noexcept;
/*constexpr*/ Unit<TReturn, ResultTag> to() const noexcept;
};

// Make a unit specifying only the tag, inferring the type T. Rather than
// units::Unit<int, my_tag_t> u(123);
// (T specified as "int"), you can do
// auto u = units::make_Unit<my_tag_t>(123);
// the type is inferred from "123".
template<typename Tag, typename T>
inline constexpr Unit<T, Tag> as(T v) noexcept
inline constexpr Unit<T, Tag> make_Unit(T v) noexcept
{
return Unit<T, Tag>(v);
}

// Allow Unit::to() (below) to compile; the routine below normally won't be used.
template <typename T, typename Tag, typename ResultTag = Tag, typename TResult = T>
inline constexpr void convert(Unit<T, Tag> v, Unit<TResult, ResultTag>& result) noexcept
inline /*constexpr*/ Unit<TResult, ResultTag>& convert(Unit<T, Tag> v, Unit<TResult, ResultTag>& result) noexcept
{
result = as<Tag, TResult>(v.value());
result = make_Unit<Tag, TResult>(v.value()); // or Unit<...>, this ensures make_Unit() works
return result; // ICC doesn't like "constexpr void"; want to use parameters for type deduction
}

// Now that "convert" is visble (above), implement the Unit::to() member function.
// convert() might be easier to use as the tag/type for each can be inferred;
// the template argument to to() is the raw tag. For example,
// constexpr units::Meters<double> meters_1 = 1.0;
// units::Feet<double> feet{0};
// convert(meters_1, feet);
// Using to() is a bit more awkward
// const auto meters = feet.to<units::tags::Meters>();
template <typename T, typename Tag>
template <typename ResultTag, typename TReturn>
constexpr Unit<TReturn, ResultTag> Unit<T, Tag>::to() const noexcept
inline /*constexpr*/ Unit<TReturn, ResultTag> Unit<T, Tag>::to() const noexcept
{
Unit<TReturn, ResultTag> retval{ 0 };
convert(*this, retval);
return retval;
return convert(*this, retval);
}

}

#endif // CODA_OSS_units_Unit_h_INCLUDED_
29 changes: 21 additions & 8 deletions externals/coda-oss/modules/c++/units/unittests/test_units.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,28 @@ TEST_CASE(test_degrees)

TEST_CASE(test_lengths)
{
constexpr units::Feet<double> feet_3 = 3;
units::Meters<double> meters { 0 };
convert(feet_3, meters);
TEST_ASSERT_ALMOST_EQ(meters.value(), 0.9144);
{
constexpr units::Feet<double> feet_3 = 3;
const auto same = feet_3.to();
TEST_ASSERT_EQ(same.value(), feet_3.value());

constexpr units::Meters<double> meters_1 = 1;
units::Feet<double> feet { 0 };
convert(meters_1, feet);
TEST_ASSERT_ALMOST_EQ(feet.value(), 3.2808398);
units::Meters<double> meters{0};
convert(feet_3, meters); // convert ...
TEST_ASSERT_ALMOST_EQ(meters.value(), 0.9144);
const auto feet = meters.to<units::tags::Feet>(); // ...and back
TEST_ASSERT_ALMOST_EQ(feet.value(), feet_3.value());
}
{
constexpr auto meters_1 = units::make_Unit<units::tags::Meters>(1.0);
const auto same = meters_1.to();
TEST_ASSERT_EQ(same.value(), meters_1.value());

units::Feet<double> feet{0};
convert(meters_1, feet); // convert ...
TEST_ASSERT_ALMOST_EQ(feet.value(), 3.2808398);
const auto meters = feet.to<units::tags::Meters>(); // ...and back
TEST_ASSERT_ALMOST_EQ(meters.value(), meters_1.value());
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ constexpr auto PlatformEncoding = sys::Platform == sys::PlatformType::Windows
? xml::lite::StringEncoding::Windows1252
: xml::lite::StringEncoding::Utf8;
// Could do the same for std::wstring, but there isn't any code needing it right now.
// Probably better to use std::u16string and std::u32string anyway.
#endif

/*!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
#ifndef __XML_LITE_UTILITIES_XERCES_H__
#define __XML_LITE_UTILITIES_XERCES_H__

#include <stdint.h>

#include <string>
#include <mutex>
#include <type_traits>

#include "xml/lite/xml_lite_config.h"

Expand Down Expand Up @@ -107,6 +111,7 @@ typedef xml::lite::AttributeNode LiteAttributesNode_T;
* non-const it takes ownership, and for const memory (assumed
* to be owned elsewhere) it makes a deep copy for its own use.
*/

class XercesLocalString
{
public:
Expand Down
30 changes: 3 additions & 27 deletions externals/coda-oss/modules/c++/xml.lite/source/MinidomHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,23 +108,6 @@ bool xml::lite::MinidomHandler::call_vcharacters() const
return storeEncoding();
}

inline std::string toUtf8(const char16_t* pChars16, const char32_t* pChars32, size_t length)
{
std::string result;
if (pChars16 != nullptr)
{
assert(pChars32 == nullptr);
return str::details::to_u8string(pChars16, length, result);
}
if (pChars32 != nullptr)
{
assert(pChars16 == nullptr);
return str::details::to_u8string(pChars32, length, result);
}
throw std::invalid_argument("Both pChars16 and pChars32 are NULL.");
}

// XMLCh could be either 16- or 32-bits, depending on platform and Xerces configuration
bool xml::lite::MinidomHandler::vcharacters(const void /*XMLCh*/* chars_, size_t length)
{
if (chars_ == nullptr)
Expand All @@ -136,21 +119,14 @@ bool xml::lite::MinidomHandler::vcharacters(const void /*XMLCh*/* chars_, size_t
throw std::invalid_argument("length is 0.");
}

constexpr auto XMLCh_is_16 = sizeof(XMLCh) == sizeof(char16_t);
constexpr auto XMLCh_is_32 = sizeof(XMLCh) == sizeof(char32_t);
static_assert(XMLCh_is_16 || XMLCh_is_32, "XMLCh should be 16- or 32-bits.");
auto pChars16 = XMLCh_is_16 ? static_cast<const char16_t*>(chars_) : nullptr;
auto pChars32 = XMLCh_is_32 ? static_cast<const char32_t*>(chars_) : nullptr;
if ((pChars16 == nullptr) && (pChars32 == nullptr))
{
throw std::invalid_argument("Wrong size for XMLCh");
}
static_assert(sizeof(XMLCh) == sizeof(char16_t), "XMLCh should be 16-bits.");
auto pChars16 = static_cast<const char16_t*>(chars_);

std::string chars;
auto platformEncoding = xml::lite::PlatformEncoding; // "conditional expression is constant"
if (platformEncoding == xml::lite::StringEncoding::Utf8)
{
chars = toUtf8(pChars16, pChars32, length);
str::details::to_u8string(pChars16, length, chars);
}
else if (platformEncoding == xml::lite::StringEncoding::Windows1252)
{
Expand Down
Loading

0 comments on commit c08a0ce

Please sign in to comment.