aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2024-06-24 00:06:25 +0800
committercrupest <crupest@outlook.com>2024-08-18 16:50:20 +0800
commit1b30150ab79ff1338f209a8ddb54b3dc60cfb599 (patch)
tree97e183587b293ecf768476da0edf3fdcf86e4543 /include
parentb756bf519cda0684ec46d0d9404cbc59741ec0cb (diff)
downloadcru-1b30150ab79ff1338f209a8ddb54b3dc60cfb599.tar.gz
cru-1b30150ab79ff1338f209a8ddb54b3dc60cfb599.tar.bz2
cru-1b30150ab79ff1338f209a8ddb54b3dc60cfb599.zip
fix(SubProcess): fix pipe fs close, add tests.
NEED TEST: BufferStream, AutoReadStream, SubProcess.
Diffstat (limited to 'include')
-rw-r--r--include/cru/common/Bitmask.h5
-rw-r--r--include/cru/common/Format.h59
-rw-r--r--include/cru/common/String.h32
-rw-r--r--include/cru/common/StringToNumberConverter.h88
-rw-r--r--include/cru/common/SubProcess.h2
-rw-r--r--include/cru/common/platform/unix/UnixPipe.h3
6 files changed, 114 insertions, 75 deletions
diff --git a/include/cru/common/Bitmask.h b/include/cru/common/Bitmask.h
index 23a3a069..9b6b8957 100644
--- a/include/cru/common/Bitmask.h
+++ b/include/cru/common/Bitmask.h
@@ -1,4 +1,5 @@
#pragma once
+
#include <functional>
namespace cru {
@@ -13,6 +14,8 @@ struct Bitmask final {
return Bitmask(static_cast<TUnderlying>(1u << offset));
}
+ constexpr bool Has(Bitmask rhs) const { return (value & rhs.value) != 0; }
+
Bitmask operator|(Bitmask rhs) const { return Bitmask(value | rhs.value); }
Bitmask operator&(Bitmask rhs) const { return Bitmask(value & rhs.value); }
Bitmask operator^(Bitmask rhs) const { return Bitmask(value ^ rhs.value); }
@@ -34,7 +37,7 @@ struct Bitmask final {
bool operator!=(Bitmask rhs) const { return this->value != rhs.value; }
explicit operator TUnderlying() const { return value; }
- explicit operator bool() const { return value != 0; }
+ operator bool() const { return value != 0; }
TUnderlying value;
};
diff --git a/include/cru/common/Format.h b/include/cru/common/Format.h
index e6935343..d5c5ed99 100644
--- a/include/cru/common/Format.h
+++ b/include/cru/common/Format.h
@@ -3,8 +3,10 @@
#include "Exception.h"
#include "String.h"
-#include <double-conversion/double-conversion.h>
-#include <charconv>
+#include <cassert>
+#include <cstdio>
+#include <type_traits>
+#include <vector>
namespace cru {
inline String ToString(bool value) {
@@ -12,31 +14,40 @@ inline String ToString(bool value) {
}
template <typename T>
-std::enable_if_t<std::is_integral_v<T>, String> ToString(T value) {
- std::array<char, 50> buffer;
- auto result =
- std::to_chars(buffer.data(), buffer.data() + buffer.size(), value);
-
- if (result.ec == std::errc{}) {
- } else {
- throw std::invalid_argument("Failed to convert value to chars.");
- }
+inline constexpr std::nullptr_t kPrintfFormatSpecifierOfType = nullptr;
+
+#define CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(type, specifier) \
+ template <> \
+ inline constexpr const char* kPrintfFormatSpecifierOfType<type> = specifier;
+
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed char, "%c")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned char, "%c")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed short, "%hd")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned short, "%hu")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed int, "%d")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned int, "%u")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed long, "%ld")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned long, "%lu")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed long long, "%lld")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned long long, "%llu")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(float, "%f")
+CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(double, "%f")
+
+#undef CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE
- auto size = result.ptr - buffer.data();
- auto b = new char16_t[size + 1];
- b[size] = 0;
- std::copy(buffer.data(), result.ptr, b);
- return String::FromBuffer(b, size, size);
+template <typename T>
+std::enable_if_t<
+ !std::is_null_pointer_v<decltype(kPrintfFormatSpecifierOfType<T>)>, String>
+ToString(T value) {
+ auto size = std::snprintf(nullptr, 0, kPrintfFormatSpecifierOfType<T>, value);
+ assert(size > 0);
+ std::vector<char> buffer(size + 1);
+ size = std::snprintf(buffer.data(), size + 1, kPrintfFormatSpecifierOfType<T>,
+ value);
+ assert(size > 0);
+ return String::FromUtf8(buffer.data(), size);
}
-extern double_conversion::DoubleToStringConverter
- kDefaultDoubleToStringConverter;
-
-String CRU_BASE_API ToString(float value, StringView option);
-String CRU_BASE_API ToString(double value, StringView option);
-inline String ToString(float value) { return ToString(value, u""); }
-inline String ToString(double value) { return ToString(value, u""); }
-
template <typename T>
String ToString(const T& value, StringView option) {
CRU_UNUSED(option)
diff --git a/include/cru/common/String.h b/include/cru/common/String.h
index 5d9fc549..21a3db51 100644
--- a/include/cru/common/String.h
+++ b/include/cru/common/String.h
@@ -6,7 +6,6 @@
#include "StringToNumberConverter.h"
#include "StringUtil.h"
-#include <double-conversion/double-conversion.h>
#include <filesystem>
#include <initializer_list>
#include <iterator>
@@ -221,16 +220,14 @@ class CRU_BASE_API String {
Index* processed_characters_count, unsigned flags, int base) const;
int ParseToInt(Index* processed_characters_count = nullptr,
- unsigned flags = StringToNumberFlags::kNoFlags,
- int base = 0) const;
+ StringToNumberFlag flags = {}, int base = 0) const;
long long ParseToLongLong(Index* processed_characters_count = nullptr,
- unsigned flags = StringToNumberFlags::kNoFlags,
- int base = 0) const;
+ StringToNumberFlag flags = {}, int base = 0) const;
float ParseToFloat(Index* processed_characters_count = nullptr,
- unsigned flags = StringToNumberFlags::kNoFlags) const;
+ StringToNumberFlag flags = {}) const;
double ParseToDouble(Index* processed_characters_count = nullptr,
- unsigned flags = StringToNumberFlags::kNoFlags) const;
+ StringToNumberFlag flags = {}) const;
std::vector<float> ParseToFloatList(value_type separator = u' ') const;
std::vector<double> ParseToDoubleList(value_type separator = u' ') const;
@@ -261,6 +258,8 @@ class CRU_BASE_API String {
Index capacity_ = 0; // always 1 smaller than real buffer size
};
+std::ostream& CRU_BASE_API operator<<(std::ostream& os, const String& value);
+
class CRU_BASE_API StringView {
public:
using value_type = char16_t;
@@ -357,23 +356,24 @@ class CRU_BASE_API StringView {
template <typename TInteger>
std::enable_if_t<std::is_signed_v<TInteger>, TInteger> ParseToInteger(
- Index* processed_characters_count, unsigned flags, int base) const {
- auto result = StringToIntegerConverterImpl(flags, base)
- .Parse(data(), size(), processed_characters_count);
+ Index* processed_characters_count, StringToNumberFlag flags,
+ int base) const {
+ auto utf8_string = ToUtf8();
+ auto result = StringToIntegerConverter(flags, base)
+ .Parse(utf8_string.data(), utf8_string.size(),
+ processed_characters_count);
return result.negate ? -result.value : result.value;
}
int ParseToInt(Index* processed_characters_count = nullptr,
- unsigned flags = StringToNumberFlags::kNoFlags,
- int base = 0) const;
+ StringToNumberFlag flags = {}, int base = 0) const;
long long ParseToLongLong(Index* processed_characters_count = nullptr,
- unsigned flags = StringToNumberFlags::kNoFlags,
- int base = 0) const;
+ StringToNumberFlag flags = {}, int base = 0) const;
float ParseToFloat(Index* processed_characters_count = nullptr,
- unsigned flags = StringToNumberFlags::kNoFlags) const;
+ StringToNumberFlag flags = {}) const;
double ParseToDouble(Index* processed_characters_count = nullptr,
- unsigned flags = StringToNumberFlags::kNoFlags) const;
+ StringToNumberFlag flags = {}) const;
std::vector<float> ParseToFloatList(value_type separator = u' ') const;
std::vector<double> ParseToDoubleList(value_type separator = u' ') const;
diff --git a/include/cru/common/StringToNumberConverter.h b/include/cru/common/StringToNumberConverter.h
index f1baafee..758b26c8 100644
--- a/include/cru/common/StringToNumberConverter.h
+++ b/include/cru/common/StringToNumberConverter.h
@@ -1,41 +1,63 @@
#pragma once
#include "Base.h"
+#include "Bitmask.h"
+#include <cstddef>
#include <ostream>
namespace cru {
-struct CRU_BASE_API StringToNumberFlags {
- constexpr static unsigned kNoFlags = 0;
- constexpr static unsigned kAllowLeadingSpaces = 1 << 0;
- constexpr static unsigned kAllowTrailingSpaces = 1 << 1;
- constexpr static unsigned kAllowTrailingJunk = 1 << 2;
- constexpr static unsigned kAllowLeadingZeroForInteger = 1 << 2;
- constexpr static unsigned kThrowOnError = 1 << 3;
+namespace details {
+struct StringToNumberFlagTag {};
+} // namespace details
+
+using StringToNumberFlag = Bitmask<details::StringToNumberFlagTag>;
+
+struct StringToNumberFlags {
+ constexpr static StringToNumberFlag kAllowLeadingSpaces =
+ StringToNumberFlag::FromOffset(0);
+ constexpr static StringToNumberFlag kAllowTrailingSpaces =
+ StringToNumberFlag::FromOffset(1);
+ constexpr static StringToNumberFlag kAllowTrailingJunk =
+ StringToNumberFlag::FromOffset(2);
+ constexpr static StringToNumberFlag kAllowLeadingZeroForInteger =
+ StringToNumberFlag::FromOffset(3);
+ constexpr static StringToNumberFlag kThrowOnError =
+ StringToNumberFlag::FromOffset(4);
};
-struct CRU_BASE_API StringToIntegerConverterImplResult {
- StringToIntegerConverterImplResult() = default;
- StringToIntegerConverterImplResult(bool negate, unsigned long long value)
+template <typename TResult>
+struct IStringToNumberConverter : virtual Interface {
+ virtual TResult Parse(const char* str, Index size,
+ Index* processed_characters_count) const = 0;
+
+ template <std::size_t Size>
+ TResult Parse(const char (&str)[Size],
+ Index* processed_characters_count) const {
+ return Parse(str, Size - 1, processed_characters_count);
+ }
+};
+
+struct CRU_BASE_API StringToIntegerResult {
+ StringToIntegerResult() = default;
+ StringToIntegerResult(bool negate, unsigned long long value)
: negate(negate), value(value) {}
bool negate;
unsigned long long value;
};
-inline bool CRU_BASE_API
-operator==(const StringToIntegerConverterImplResult& left,
- const StringToIntegerConverterImplResult& right) {
+inline bool CRU_BASE_API operator==(const StringToIntegerResult& left,
+ const StringToIntegerResult& right) {
return left.negate == right.negate && left.value == right.value;
}
-inline bool CRU_BASE_API
-operator!=(const StringToIntegerConverterImplResult& left,
- const StringToIntegerConverterImplResult& right) {
+inline bool CRU_BASE_API operator!=(const StringToIntegerResult& left,
+ const StringToIntegerResult& right) {
return !(left == right);
}
-inline std::ostream& operator<<(
- std::ostream& stream, const StringToIntegerConverterImplResult& result) {
+inline std::ostream& CRU_BASE_API
+operator<<(std::ostream& stream, const StringToIntegerResult& result) {
return stream << "StringToIntegerConverterImplResult("
<< (result.negate ? "-" : "") << result.value << ")";
}
@@ -43,9 +65,10 @@ inline std::ostream& operator<<(
/**
* \brief A converter that convert number into long long.
*/
-struct CRU_BASE_API StringToIntegerConverterImpl {
+struct CRU_BASE_API StringToIntegerConverter
+ : IStringToNumberConverter<StringToIntegerResult> {
public:
- explicit StringToIntegerConverterImpl(unsigned flags, int base = 0)
+ explicit StringToIntegerConverter(StringToNumberFlag flags, int base = 0)
: flags(flags), base(base) {}
bool CheckParams() const;
@@ -57,19 +80,11 @@ struct CRU_BASE_API StringToIntegerConverterImpl {
* \param processed_characters_count The number of characters that were
* processed. Or nullptr to not retrieve.
*/
- StringToIntegerConverterImplResult Parse(
- const char* str, Index size, Index* processed_characters_count) const;
-
- StringToIntegerConverterImplResult Parse(
- const char16_t* str, Index size, Index* processed_characters_count) const;
+ StringToIntegerResult Parse(const char* str, Index size,
+ Index* processed_characters_count) const override;
+ using IStringToNumberConverter<StringToIntegerResult>::Parse;
- template <std::size_t Size>
- StringToIntegerConverterImplResult Parse(
- const char (&str)[Size], Index* processed_characters_count) const {
- return Parse(str, Size - 1, processed_characters_count);
- }
-
- unsigned flags;
+ StringToNumberFlag flags;
/**
* \brief The base of the number used for parse or 0 for auto detect.
* \remarks Base can only be of range [2, 36] or 0. If base is 0, decimal is
@@ -80,4 +95,13 @@ struct CRU_BASE_API StringToIntegerConverterImpl {
*/
int base;
};
+
+struct CRU_BASE_API StringToFloatConverter {
+ StringToFloatConverter(StringToNumberFlag flags) : flags(flags) {}
+
+ double Parse(const char* str, Index size,
+ Index* processed_characters_count) const;
+
+ StringToNumberFlag flags;
+};
} // namespace cru
diff --git a/include/cru/common/SubProcess.h b/include/cru/common/SubProcess.h
index 98c272a3..fbe8ad2b 100644
--- a/include/cru/common/SubProcess.h
+++ b/include/cru/common/SubProcess.h
@@ -231,7 +231,7 @@ class CRU_BASE_API SubProcess : public Object {
SubProcess(SubProcess&& other) = default;
SubProcess& operator=(SubProcess&& other) = default;
- ~SubProcess();
+ ~SubProcess() override;
public:
void Wait(std::optional<std::chrono::milliseconds> wait_time = std::nullopt);
diff --git a/include/cru/common/platform/unix/UnixPipe.h b/include/cru/common/platform/unix/UnixPipe.h
index afe6024a..cf35fb11 100644
--- a/include/cru/common/platform/unix/UnixPipe.h
+++ b/include/cru/common/platform/unix/UnixPipe.h
@@ -43,7 +43,7 @@ class UnixPipe : public Object {
Receive,
};
- explicit UnixPipe(Usage usage, UnixPipeFlag flags = {});
+ explicit UnixPipe(Usage usage, bool auto_close, UnixPipeFlag flags = {});
CRU_DELETE_COPY(UnixPipe)
CRU_DELETE_MOVE(UnixPipe)
@@ -62,6 +62,7 @@ class UnixPipe : public Object {
private:
Usage usage_;
+ bool auto_close_;
UnixPipeFlag flags_;
int read_fd_;
int write_fd_;