Port to macOS

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2023-09-12 16:55:16 +02:00
parent 1e993c8c65
commit 83d7fd844d
41 changed files with 1568 additions and 1324 deletions

View File

@ -7,8 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
F48105AD2AAF5FD4004DE682 /* math.hpp in Sources */ = {isa = PBXBuildFile; fileRef = F48105AC2AAF5FD4004DE682 /* math.hpp */; };
F4B7FBE02AAF49BC00C6BE9F /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4B7FBDF2AAF49BC00C6BE9F /* main.cpp */; };
F4C07F522AB059580044EDC0 /* pch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F512AB059580044EDC0 /* pch.cpp */; };
F4C07F552AB05B5B0044EDC0 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F542AB05B5B0044EDC0 /* main.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -24,10 +24,17 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
F48105AC2AAF5FD4004DE682 /* math.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = math.hpp; sourceTree = "<group>"; };
F48105AE2AAF64C7004DE682 /* common.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = common.hpp; sourceTree = "<group>"; };
F4B7FBDC2AAF49BC00C6BE9F /* UnitTests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = UnitTests; sourceTree = BUILT_PRODUCTS_DIR; };
F4B7FBDF2AAF49BC00C6BE9F /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
F4C07F4E2AB059300044EDC0 /* math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = math.cpp; sourceTree = "<group>"; };
F4C07F502AB059580044EDC0 /* pch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pch.h; sourceTree = "<group>"; };
F4C07F512AB059580044EDC0 /* pch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pch.cpp; sourceTree = "<group>"; };
F4C07F532AB05A240044EDC0 /* compat.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = compat.hpp; sourceTree = "<group>"; };
F4C07F542AB05B5B0044EDC0 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
F4C07F562AB08E690044EDC0 /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = "<group>"; };
F4C07F572AB08E690044EDC0 /* unicode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unicode.cpp; sourceTree = "<group>"; };
F4C07F582AB08E690044EDC0 /* sgml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sgml.cpp; sourceTree = "<group>"; };
F4C07F592AB08E690044EDC0 /* ring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ring.cpp; sourceTree = "<group>"; };
F4C07F5A2AB08E690044EDC0 /* stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stream.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -44,7 +51,16 @@
F4B7FBD32AAF49BC00C6BE9F = {
isa = PBXGroup;
children = (
F4B7FBDE2AAF49BC00C6BE9F /* UnitTests */,
F4C07F542AB05B5B0044EDC0 /* main.cpp */,
F4C07F4E2AB059300044EDC0 /* math.cpp */,
F4C07F562AB08E690044EDC0 /* parser.cpp */,
F4C07F512AB059580044EDC0 /* pch.cpp */,
F4C07F592AB08E690044EDC0 /* ring.cpp */,
F4C07F582AB08E690044EDC0 /* sgml.cpp */,
F4C07F5A2AB08E690044EDC0 /* stream.cpp */,
F4C07F572AB08E690044EDC0 /* unicode.cpp */,
F4C07F502AB059580044EDC0 /* pch.h */,
F4C07F532AB05A240044EDC0 /* compat.hpp */,
F4B7FBDD2AAF49BC00C6BE9F /* Products */,
);
sourceTree = "<group>";
@ -58,16 +74,6 @@
name = Products;
sourceTree = "<group>";
};
F4B7FBDE2AAF49BC00C6BE9F /* UnitTests */ = {
isa = PBXGroup;
children = (
F48105AE2AAF64C7004DE682 /* common.hpp */,
F48105AC2AAF5FD4004DE682 /* math.hpp */,
F4B7FBDF2AAF49BC00C6BE9F /* main.cpp */,
);
path = UnitTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -125,8 +131,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F4B7FBE02AAF49BC00C6BE9F /* main.cpp in Sources */,
F48105AD2AAF5FD4004DE682 /* math.hpp in Sources */,
F4C07F552AB05B5B0044EDC0 /* main.cpp in Sources */,
F4C07F522AB059580044EDC0 /* pch.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -184,10 +190,11 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ../include;
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-liconv";
SDKROOT = macosx;
};
name = Debug;
@ -237,9 +244,10 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ../include;
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
OTHER_LDFLAGS = "-liconv";
SDKROOT = macosx;
};
name = Release;

77
UnitTests/compat.hpp Normal file
View File

@ -0,0 +1,77 @@
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#pragma once
#if defined(_WIN32)
#include <CppUnitTest.h>
#elif defined(__APPLE__)
#include <stdexcept>
#define TEST_CLASS(name) class name
#define TEST_METHOD(name) static void name()
namespace Assert
{
inline void IsTrue(bool c)
{
if (!c)
throw std::runtime_error("not true");
}
inline void IsFalse(bool c)
{
if (c)
throw std::runtime_error("not false");
}
template <class T>
inline void AreEqual(const T& a, const T& b)
{
if (!(a == b))
throw std::runtime_error("not equal");
}
inline void AreEqual(const char* a, const char* b)
{
if (strcmp(a, b) != 0)
throw std::runtime_error("not equal");
}
inline void AreEqual(const wchar_t* a, const wchar_t* b)
{
if (wcscmp(a, b) != 0)
throw std::runtime_error("not equal");
}
template <class T>
inline void AreNotEqual(const T& a, const T& b)
{
if (a == b)
throw std::runtime_error("equal");
}
inline void AreNotEqual(const char* a, const char* b)
{
if (strcmp(a, b) == 0)
throw std::runtime_error("equal");
}
inline void AreNotEqual(const wchar_t* a, const wchar_t* b)
{
if (wcscmp(a, b) == 0)
throw std::runtime_error("equal");
}
template <class E, typename F>
inline void ExpectException(F functor)
{
try { functor(); }
catch (const E&) { return; }
catch (...) { throw std::runtime_error("unexpected exception"); }
throw std::runtime_error("exception not thrown");
}
}
#endif

38
UnitTests/main.cpp Normal file
View File

@ -0,0 +1,38 @@
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#include "pch.h"
#include "math.cpp"
#include "parser.cpp"
#include "ring.cpp"
#include "sgml.cpp"
#include "stream.cpp"
#include "unicode.cpp"
#include <iostream>
int main(int argc, const char * argv[])
{
try {
UnitTests::math::mul();
UnitTests::math::add();
UnitTests::parser::wtest();
UnitTests::parser::sgml_test();
UnitTests::parser::http_test();
UnitTests::ring::test();
UnitTests::sgml::sgml2wstr();
UnitTests::sgml::wstr2sgml();
UnitTests::stream::async();
UnitTests::stream::replicator();
UnitTests::stream::open_close();
UnitTests::unicode::str2wstr();
UnitTests::unicode::wstr2str();
std::cout << "PASS\n";
return 0;
}
catch (const std::exception& ex) {
std::cerr << ex.what() << " FAIL\n";
return 1;
}
}

View File

@ -1,4 +1,4 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
@ -6,7 +6,9 @@
#include "pch.h"
using namespace std;
#ifdef _WIN32
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#endif
namespace UnitTests
{

View File

@ -1,4 +1,4 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
@ -8,7 +8,9 @@
using namespace std;
using namespace stdex;
using namespace stdex::parser;
#ifdef _WIN32
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#endif
namespace UnitTests
{
@ -176,6 +178,7 @@ namespace UnitTests
TEST_METHOD(sgml_test)
{
std::locale locale_slSI("sl_SI");
static const char text[] = "V ko&zcaron;u&scaron;&ccaron;ku zlobnega mizarja stopiclja fant\nin kli&ccaron;e&nbsp;1234567890.";
{
@ -194,7 +197,7 @@ namespace UnitTests
}
{
sgml_cp p("&Zcaron;");
sgml_cp p("&Zcaron;", SIZE_MAX, false, locale_slSI);
Assert::IsFalse(p.match(text, 4));
Assert::IsTrue(p.match(text, 4, _countof(text), match_case_insensitive));
Assert::AreEqual((size_t)4, p.interval.start);
@ -202,7 +205,7 @@ namespace UnitTests
}
{
sgml_space_cp p;
sgml_space_cp p(false, locale_slSI);
Assert::IsFalse(p.match(text));
Assert::IsTrue(p.match(text, 1));
Assert::AreEqual((size_t)1, p.interval.start);
@ -213,7 +216,7 @@ namespace UnitTests
}
{
sgml_string_branch p("apple", "orange", "Ko&Zcaron;u&Scaron;&ccaron;Ku", nullptr);
sgml_string_branch p(locale_slSI, "apple", "orange", "Ko&Zcaron;u&Scaron;&ccaron;Ku", nullptr);
Assert::IsFalse(p.match(text, 2));
Assert::IsTrue(p.match(text, 2, _countof(text), match_case_insensitive));
Assert::AreEqual((size_t)2, p.hit_offset);

View File

@ -6,6 +6,7 @@
#pragma once
#include <stdex/base64.hpp>
#include <stdex/compat.hpp>
#include <stdex/errno.hpp>
#include <stdex/exception.hpp>
#include <stdex/hex.hpp>
@ -16,7 +17,6 @@
#include <stdex/parser.hpp>
#include <stdex/progress.hpp>
#include <stdex/ring.hpp>
#include <stdex/sal.hpp>
#include <stdex/sgml.hpp>
#include <stdex/stream.hpp>
#include <stdex/string.hpp>
@ -24,7 +24,7 @@
#include <stdex/unicode.hpp>
#include <stdex/vector_queue.hpp>
#include <CppUnitTest.h>
#include "compat.hpp"
#include <cstdlib>
#include <filesystem>

View File

@ -1,4 +1,4 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
@ -6,7 +6,9 @@
#include "pch.h"
using namespace std;
#ifdef _WIN32
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#endif
namespace UnitTests
{

View File

@ -1,4 +1,4 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
@ -6,7 +6,9 @@
#include "pch.h"
using namespace std;
#ifdef _WIN32
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#endif
namespace UnitTests
{
@ -38,9 +40,15 @@ namespace UnitTests
{ i + 35, j + 12 },
{ i + 42, j + 14 },
{ i + 53, j + 25 },
#ifdef _WIN32 // wchar_t* is UTF-16
{ i + 62, j + 27 },
{ i + 62, j + 27 },
{ i + 71, j + 29 },
#else // wchar_t* is UTF-32
{ i + 62, j + 26 },
{ i + 62, j + 26 },
{ i + 71, j + 27 },
#endif
} == map);
}

View File

@ -1,4 +1,4 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
@ -8,7 +8,9 @@
using namespace std;
using namespace stdex;
using namespace stdex::stream;
#ifdef _WIN32
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#endif
namespace UnitTests
{
@ -17,11 +19,11 @@ namespace UnitTests
public:
TEST_METHOD(async)
{
constexpr size_t total = 1000;
memory_file source(mul(total, sizeof(size_t)));
constexpr uint32_t total = 1000;
memory_file source(mul(total, sizeof(uint32_t)));
{
async_writer<70> writer(source);
for (size_t i = 0; i < total; ++i) {
for (uint32_t i = 0; i < total; ++i) {
Assert::IsTrue(writer.ok());
writer << i;
}
@ -29,8 +31,8 @@ namespace UnitTests
Assert::AreEqual<stdex::stream::fpos_t>(0, source.seekbeg(0));
{
async_reader<50> reader(source);
size_t x;
for (size_t i = 0; i < total; ++i) {
uint32_t x;
for (uint32_t i = 0; i < total; ++i) {
reader >> x;
Assert::IsTrue(reader.ok());
Assert::AreEqual(i, x);
@ -42,9 +44,9 @@ namespace UnitTests
TEST_METHOD(replicator)
{
constexpr size_t total = 1000;
constexpr uint32_t total = 1000;
memory_file f1(mul(total, sizeof(size_t)));
memory_file f1(mul(total, sizeof(uint32_t)));
sstring filename2, filename3;
filename2 = filename3 = temp_path();
@ -65,7 +67,7 @@ namespace UnitTests
writer.push_back(&f1);
writer.push_back(&f2_buf);
writer.push_back(&f3);
for (size_t i = 0; i < total; ++i) {
for (uint32_t i = 0; i < total; ++i) {
Assert::IsTrue(writer.ok());
writer << i;
}
@ -76,8 +78,8 @@ namespace UnitTests
f3.seekbeg(0);
{
buffer f2_buf(f2, 64, 0);
size_t x;
for (size_t i = 0; i < total; ++i) {
uint32_t x;
for (uint32_t i = 0; i < total; ++i) {
f1 >> x;
Assert::IsTrue(f1.ok());
Assert::AreEqual(i, x);
@ -106,26 +108,26 @@ namespace UnitTests
{
cached_file dat(invalid_handle, state_t::fail, 4096);
const sstring filepath = temp_path();
constexpr size_t count = 3;
constexpr uint32_t count = 3;
sstring filename[count];
stdex::stream::fpos_t start[count];
for (size_t i = 0; i < count; ++i) {
for (uint32_t i = 0; i < count; ++i) {
filename[i] = filepath + sprintf(_T("stdex-stream-open_close%zu.tmp"), NULL, i);
dat.open(filename[i].c_str(), mode_for_reading | mode_for_writing | share_none | mode_preserve_existing | mode_binary);
Assert::IsTrue(dat.ok());
start[i] = dat.tell();
Assert::AreNotEqual(fpos_max, start[i]);
for (size_t j = 0; j < 31 + 11 * i; ++j) {
for (uint32_t j = 0; j < 31 + 11 * i; ++j) {
dat << j * count + i;
Assert::IsTrue(dat.ok());
}
dat.close();
}
for (size_t i = 0; i < count; ++i) {
for (uint32_t i = 0; i < count; ++i) {
dat.open(filename[i].c_str(), mode_for_reading | share_none | mode_binary);
Assert::IsTrue(dat.ok());
for (;;) {
size_t x;
uint32_t x;
dat >> x;
if (!dat.ok())
break;
@ -133,7 +135,7 @@ namespace UnitTests
}
}
dat.close();
for (size_t i = 0; i < count; ++i)
for (uint32_t i = 0; i < count; ++i)
std::filesystem::remove(filename[i]);
}

View File

@ -1,4 +1,4 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
@ -6,7 +6,9 @@
#include "pch.h"
using namespace std;
#ifdef _WIN32
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#endif
namespace UnitTests
{

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include <assert.h>
#include <cstdint>
#include <string>
@ -14,6 +14,35 @@
namespace stdex
{
/// \cond internal
static const char base64_enc_lookup[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
static const uint8_t base64_dec_lookup[256] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* 1 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* 2 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
/* 3 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 64, 255, 255,
/* 4 */ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
/* 6 */ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
/* 7 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
/* 8 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* 9 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* A */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* B */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* C */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* D */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* E */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* F */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
};
/// \endcond
///
/// Base64 encoding session
///
@ -140,17 +169,6 @@ namespace stdex
size_t num; ///< Number of bytes used in `buf`
};
/// \cond internal
static const char base64_enc_lookup[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
/// \endcond
///
/// Base64 decoding session
///
@ -256,27 +274,4 @@ namespace stdex
uint8_t buf[4]; ///< Internal buffer
size_t num; ///< Number of bytes used in `buf`
};
/// \cond internal
static const uint8_t base64_dec_lookup[256] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* 1 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* 2 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
/* 3 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 64, 255, 255,
/* 4 */ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
/* 6 */ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
/* 7 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
/* 8 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* 9 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* A */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* B */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* C */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* D */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* E */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* F */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
};
/// \endcond
}

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include "system.hpp"
#include "string.hpp"
#include <stdint.h>

View File

@ -1,13 +1,15 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2022-2023 Amebis
*/
#pragma once
#include <stddef.h>
#ifdef _WIN32
#include <sal.h>
#endif
#include <type_traits>
#ifndef _In_
#define _In_
@ -30,15 +32,24 @@
#ifndef _In_z_
#define _In_z_
#endif
#ifndef _In_opt_z_
#define _In_opt_z_
#endif
#ifndef _In_z_count_
#define _In_z_count_(p)
#endif
#ifndef _In_reads_
#define _In_reads_(p)
#endif
#ifndef _In_reads_or_z_
#define _In_reads_or_z_(p)
#endif
#ifndef _In_reads_or_z_opt_
#define _In_reads_or_z_opt_(p)
#endif
#ifndef _In_reads_bytes_opt_
#define _In_reads_bytes_opt_(p)
#endif
#ifndef _Printf_format_string_params_
#define _Printf_format_string_params_(n)
#endif
@ -46,6 +57,12 @@
#ifndef _Inout_
#define _Inout_
#endif
#ifndef _Inout_opt_
#define _Inout_opt_
#endif
#ifndef _Inout_cap_
#define _Inout_cap_(p)
#endif
#ifndef _Use_decl_annotations_
#define _Use_decl_annotations_
@ -57,19 +74,47 @@
#ifndef _Out_opt_
#define _Out_opt_
#endif
#ifndef _Out_z_cap_
#define _Out_z_cap_(p)
#endif
#ifndef _Out_writes_
#define _Out_writes_(p)
#endif
#ifndef _Out_writes_bytes_
#define _Out_writes_bytes_(p)
#endif
#ifndef _Out_writes_z_
#define _Out_writes_z_(p)
#endif
#ifndef _Out_writes_bytes_to_opt_
#define _Out_writes_bytes_to_opt_(p, q)
#endif
#ifndef _Success_
#define _Success_(p)
#endif
#ifndef _Ret_maybenull_z_
#define _Ret_maybenull_z_
#endif
#ifndef _Ret_notnull_
#define _Ret_notnull_
#endif
#ifndef _Ret_z_
#define _Ret_z_
#endif
#ifndef _Must_inspect_result_
#define _Must_inspect_result_
#endif
#ifndef _Check_return_
#define _Check_return_
#endif
#ifndef _Post_maybez_
#define _Post_maybez_
#endif
#ifndef _Analysis_assume_
#define _Analysis_assume_(p)
#endif
#ifndef _Likely_
#if _HAS_CXX20
@ -98,3 +143,19 @@
#else
#define _Unreferenced_(x)
#endif
#ifndef _WIN32
template <typename T, size_t N>
size_t _countof(T (&arr)[N])
{
return std::extent<T[N]>::value;
}
#endif
#ifdef __APPLE__
#define off64_t off_t
#define lseek64 lseek
#define lockf64 lockf
#define ftruncate64 ftruncate
#endif

View File

@ -1,67 +1,87 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include "system.hpp"
#include <assert.h>
#include <stdint.h>
#ifdef _WIN32
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
#ifndef BYTE_ORDER
#if defined(_WIN32)
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
#define BYTE_ORDER LITTLE_ENDIAN
#elif REG_DWORD == REG_DWORD_BIG_ENDIAN
#define BIG_ENDIAN
#else
#error Unknown endian
#define BYTE_ORDER BIG_ENDIAN
#endif
#elif defined(__APPLE__)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define BYTE_ORDER LITTLE_ENDIAN
#elif __BYTE_ORDER == __ORDER_BIG_ENDIAN__
#define BYTE_ORDER BIG_ENDIAN
#endif
#else
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define BYTE_ORDER LITTLE_ENDIAN
#elif __BYTE_ORDER == __BIG_ENDIAN
#define BIG_ENDIAN
#else
#define BYTE_ORDER BIG_ENDIAN
#endif
#endif
#ifndef BYTE_ORDER
#error Unknown endian
#endif
#endif
namespace stdex
{
inline uint8_t byteswap(_In_ const uint8_t value)
{
return value;
}
inline uint16_t byteswap(_In_ const uint16_t value)
{
#if _MSC_VER >= 1300
#if _MSC_VER >= 1300
return _byteswap_ushort(value);
#elif defined(_MSC_VER)
#elif defined(_MSC_VER)
uint16_t t = (value & 0x00ff) << 8;
t |= (value) >> 8;
return t;
#else
#else
return __builtin_bswap16(value);
#endif
#endif
}
inline uint32_t byteswap(_In_ const uint32_t value)
{
#if _MSC_VER >= 1300
#if _MSC_VER >= 1300
return _byteswap_ulong(value);
#elif defined(_MSC_VER)
#elif defined(_MSC_VER)
uint32_t t = (value & 0x000000ff) << 24;
t |= (value & 0x0000ff00) << 8;
t |= (value & 0x00ff0000) >> 8;
t |= (value) >> 24;
return t;
#else
#else
return __builtin_bswap32(value);
#endif
#endif
}
inline uint64_t byteswap(_In_ const uint64_t value)
{
#if _MSC_VER >= 1300
#if _MSC_VER >= 1300
return _byteswap_uint64(value);
#elif defined(_MSC_VER)
#elif defined(_MSC_VER)
uint64_t t = (value & 0x00000000000000ff) << 56;
t |= (value & 0x000000000000ff00) << 40;
t |= (value & 0x0000000000ff0000) << 24;
@ -71,25 +91,34 @@ namespace stdex
t |= (value & 0x00ff000000000000) >> 40;
t |= (value) >> 56;
return t;
#else
#else
return __builtin_bswap64(value);
#endif
#endif
}
inline int16_t byteswap(_In_ const int16_t value) { return byteswap((uint16_t)value); }
inline int32_t byteswap(_In_ const int32_t value) { return byteswap((uint32_t)value); }
inline int64_t byteswap(_In_ const int64_t value) { return byteswap((uint64_t)value); }
inline int8_t byteswap(_In_ const char value) { return byteswap(static_cast<uint8_t>(value)); }
inline int8_t byteswap(_In_ const int8_t value) { return byteswap(static_cast<uint8_t>(value)); }
inline int16_t byteswap(_In_ const int16_t value) { return byteswap(static_cast<uint16_t>(value)); }
inline int32_t byteswap(_In_ const int32_t value) { return byteswap(static_cast<uint32_t>(value)); }
inline int64_t byteswap(_In_ const int64_t value) { return byteswap(static_cast<uint64_t>(value)); }
inline float byteswap(_In_ const float value) { return byteswap(*reinterpret_cast<const uint32_t*>(&value)); }
inline double byteswap(_In_ const double value) { return byteswap(*reinterpret_cast<const uint64_t*>(&value)); }
inline void byteswap(_Inout_ uint8_t* value) { assert(value); *value = byteswap(*value); }
inline void byteswap(_Inout_ uint16_t* value) { assert(value); *value = byteswap(*value); }
inline void byteswap(_Inout_ uint32_t* value) { assert(value); *value = byteswap(*value); }
inline void byteswap(_Inout_ uint64_t* value) { assert(value); *value = byteswap(*value); }
inline void byteswap(_Inout_ int16_t* value) { byteswap((uint16_t*)value); }
inline void byteswap(_Inout_ int32_t* value) { byteswap((uint32_t*)value); }
inline void byteswap(_Inout_ int64_t* value) { byteswap((uint64_t*)value); }
inline void byteswap(_Inout_ char* value) { byteswap(reinterpret_cast<uint8_t*>(value)); }
inline void byteswap(_Inout_ int8_t* value) { byteswap(reinterpret_cast<uint8_t*>(value)); }
inline void byteswap(_Inout_ int16_t* value) { byteswap(reinterpret_cast<uint16_t*>(value)); }
inline void byteswap(_Inout_ int32_t* value) { byteswap(reinterpret_cast<uint32_t*>(value)); }
inline void byteswap(_Inout_ int64_t* value) { byteswap(reinterpret_cast<uint64_t*>(value)); }
inline void byteswap(_Inout_ float* value) { byteswap(reinterpret_cast<uint32_t*>(value)); }
inline void byteswap(_Inout_ double* value) { byteswap(reinterpret_cast<uint64_t*>(value)); }
}
#ifdef BIG_ENDIAN
#if BYTE_ORDER == BIG_ENDIAN
#define LE2HE(x) stdex::byteswap(x)
#define BE2HE(x) (x)
#define HE2LE(x) stdex::byteswap(x)

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include <stdexcept>
#include <cstring>

View File

@ -1,11 +1,11 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include <exception>
namespace stdex
@ -13,7 +13,7 @@ namespace stdex
///
/// User cancelled exception
///
class user_cancelled : public std::exception
class user_cancelled : public std::runtime_error
{
public:
///
@ -21,8 +21,8 @@ namespace stdex
///
/// \param[in] msg Error message
///
user_cancelled(_In_opt_z_ const char *msg = nullptr) : exception(msg)
user_cancelled(_In_opt_z_ const char *msg = nullptr) : runtime_error(msg)
{
}
};
}
}

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include <assert.h>
#include <cstdint>
#include <string>

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include "stream.hpp"
#include <ios>
#include <istream>

View File

@ -1,11 +1,11 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include <vector>
namespace stdex
@ -78,7 +78,7 @@ namespace stdex
/// Adds two intervals by components
///
/// \param[in] a First interval
/// \param[in] a Second interval
/// \param[in] b Second interval
///
/// \returns Resulting interval
///
@ -137,7 +137,7 @@ inline stdex::interval<T> operator++(_Inout_ stdex::interval<T>& i, int) // Post
/// Subtracts two intervals by components
///
/// \param[in] a First interval
/// \param[in] a Second interval
/// \param[in] b Second interval
///
/// \returns Resulting interval
///

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include <vector>
namespace stdex

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include "system.hpp"
#include <stdexcept>

View File

@ -1,4 +1,4 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
@ -19,7 +19,7 @@ namespace stdex
template <class T2, std::enable_if_t<std::is_convertible_v<T2*, T*>, int> = 0>
inline no_delete(const no_delete<T2>&) noexcept {}
inline void operator()(T* p) const noexcept { p; }
inline void operator()(T* p) const noexcept { _Unreferenced_(p); }
};
///

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include "interval.hpp"
#include <chrono>
@ -25,7 +25,7 @@ namespace stdex
///
virtual void set_text(_In_z_ const char* msg)
{
msg;
_Unreferenced_(msg);
}
///
@ -56,7 +56,7 @@ namespace stdex
///
virtual void show(_In_ bool show = true)
{
show;
_Unreferenced_(show);
}
///
@ -168,7 +168,7 @@ namespace stdex
///
inline progress<T>* detach()
{
progress* k = m_host;
progress<T>* k = m_host;
m_host = NULL;
return k;
}
@ -258,7 +258,7 @@ namespace stdex
}
protected:
progress* m_host;
progress<T>* m_host;
interval<T> m_local, m_global, m_section;
};
@ -281,10 +281,10 @@ namespace stdex
~progress_switcher()
{
m_host_ref = detach();
m_host_ref = this->detach();
}
protected:
progress<T>*& m_host_ref;
};
}
}

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include <assert.h>
#include <condition_variable>
#include <mutex>

View File

@ -1,12 +1,12 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#pragma once
#include "compat.hpp"
#include "mapping.hpp"
#include "sal.hpp"
#include "sgml_unicode.hpp"
#include "string.hpp"
#include <assert.h>
@ -173,7 +173,8 @@ namespace stdex
}
template <class T>
inline _Deprecated_("Use stdex::sgml2wstrcat") void sgml2wstr(
_Deprecated_("Use stdex::sgml2wstrcat")
inline void sgml2wstr(
_Inout_ std::wstring& dst,
_In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
_In_ int skip = 0,
@ -192,8 +193,6 @@ namespace stdex
/// \param[in] offset Logical starting offset of source and destination strings. Unused when map parameter is nullptr.
/// \param[in,out] map The vector to append index mapping between source and destination string to.
///
/// \return Unicode string
///
template <class T>
inline void sgml2wstrcat(
_Inout_ std::wstring& dst,
@ -206,7 +205,8 @@ namespace stdex
}
template <class T>
inline _Deprecated_("Use stdex::sgml2wstrcat") void sgml2wstr(
_Deprecated_("Use stdex::sgml2wstrcat")
inline void sgml2wstr(
_Inout_ std::wstring& dst,
_In_ const std::basic_string<T>& src,
_In_ int skip = 0,
@ -324,7 +324,8 @@ namespace stdex
}
template <class T>
inline _Deprecated_("Use stdex::sgml2wstrcat") size_t sgml2wstr(
_Deprecated_("Use stdex::sgml2wstrcat")
inline size_t sgml2wstr(
_Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
_In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
_In_ int skip = 0,
@ -582,7 +583,8 @@ namespace stdex
}
}
inline _Deprecated_("Use stdex::wstr2sgmlcat") void wstr2sgml(
_Deprecated_("Use stdex::wstr2sgmlcat")
inline void wstr2sgml(
_Inout_ std::string& dst,
_In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
_In_ size_t what = 0)
@ -605,7 +607,8 @@ namespace stdex
wstr2sgmlcat(dst, src.c_str(), src.size(), what);
}
inline _Deprecated_("Use stdex::wstr2sgmlcat") void wstr2sgml(
_Deprecated_("Use stdex::wstr2sgmlcat")
inline void wstr2sgml(
_Inout_ std::string& dst,
_In_ const std::wstring& src,
_In_ size_t what = 0)
@ -745,7 +748,8 @@ namespace stdex
return j;
}
inline _Deprecated_("Use stdex::wstr2sgmlcat") size_t wstr2sgml(
_Deprecated_("Use stdex::wstr2sgmlcat")
inline size_t wstr2sgml(
_Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
_In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
_In_ size_t what = 0)

View File

@ -1,15 +1,15 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#pragma once
#include "compat.hpp"
#include "endian.hpp"
#include "interval.hpp"
#include "math.hpp"
#include "ring.hpp"
#include "sal.hpp"
#include "string.hpp"
#include "system.hpp"
#include "unicode.hpp"
@ -19,6 +19,10 @@
#if defined(_WIN32)
#include <asptlb.h>
#include <objidl.h>
#else
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#endif
#include <chrono>
#include <condition_variable>
@ -254,7 +258,7 @@ namespace stdex
return *this;
}
if (read_array(&data, sizeof(T), 1) == 1)
LE2HE(&data);
(void)LE2HE(&data);
else {
data = 0;
if (ok())
@ -279,7 +283,7 @@ namespace stdex
{
if (!ok()) _Unlikely_
return *this;
#ifdef BIG_ENDIAN
#if BYTE_ORDER == BIG_ENDIAN
T data_le = HE2LE(data);
write(&data_le, sizeof(T));
#else
@ -630,10 +634,6 @@ namespace stdex
inline basic& operator <<(_In_ const uint32_t data) { return write_data(data); }
inline basic& operator >>(_Out_ uint64_t& data) { return read_data(data); }
inline basic& operator <<(_In_ const uint64_t data) { return write_data(data); }
#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
inline basic& operator >>(_Out_ size_t& data) { return read_data(data); }
inline basic& operator <<(_In_ const size_t data) { return write_data(data); }
#endif
inline basic& operator >>(_Out_ float& data) { return read_data(data); }
inline basic& operator <<(_In_ const float data) { return write_data(data); }
inline basic& operator >>(_Out_ double& data) { return read_data(data); }
@ -683,10 +683,11 @@ namespace stdex
};
#if _HAS_CXX20
using time_point = std::chrono::time_point<std::chrono::file_clock>;
using clock = std::chrono::file_clock;
#else
using time_point = std::chrono::time_point<std::chrono::system_clock>;
using clock = std::chrono::system_clock;
#endif
using time_point = std::chrono::time_point<clock>;
///
/// Basic seekable stream operations
@ -755,7 +756,7 @@ namespace stdex
{
_Unreferenced_(offset);
_Unreferenced_(length);
throw std::exception("not implemented");
throw std::domain_error("not implemented");
}
///
@ -765,7 +766,7 @@ namespace stdex
{
_Unreferenced_(offset);
_Unreferenced_(length);
throw std::exception("not implemented");
throw std::domain_error("not implemented");
}
///
@ -809,7 +810,7 @@ namespace stdex
virtual void set_ctime(time_point date)
{
_Unreferenced_(date);
throw std::exception("not implemented");
throw std::domain_error("not implemented");
}
///
@ -818,7 +819,7 @@ namespace stdex
virtual void set_atime(time_point date)
{
_Unreferenced_(date);
throw std::exception("not implemented");
throw std::domain_error("not implemented");
}
///
@ -827,7 +828,7 @@ namespace stdex
virtual void set_mtime(time_point date)
{
_Unreferenced_(date);
throw std::exception("not implemented");
throw std::domain_error("not implemented");
}
#ifdef _WIN32
@ -855,7 +856,7 @@ namespace stdex
///
/// \param[in] default_charset Fallback charset to return when no BOM detected.
///
charset_id read_charset(_In_ charset_id default_charset = charset_id::default)
charset_id read_charset(_In_ charset_id default_charset = charset_id::system)
{
if (seek(0) != 0)
throw std::runtime_error("failed to seek");
@ -1057,6 +1058,7 @@ namespace stdex
case op_t::flush:
w.source->flush();
break;
case op_t::noop:;
}
w.op = op_t::noop;
lk.unlock();
@ -2096,8 +2098,7 @@ namespace stdex
}
if (!succeeded) _Unlikely_
#else
ssize_t num_read = static_cast<ssize_t>(std::min<size_t>(to_read, block_size));
num_read = read(m_h, data, num_read);
ssize_t num_read = ::read(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_read, block_size)));
if (num_read < 0) _Unlikely_
#endif
{
@ -2149,7 +2150,7 @@ namespace stdex
return length - to_write;
}
#else
ssize_t num_written = write(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_write, block_size)));
ssize_t num_written = ::write(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_write, block_size)));
if (num_written < 0) _Unlikely_ {
m_state = state_t::fail;
return length - to_write;
@ -2487,13 +2488,18 @@ namespace stdex
m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, nullptr);
#else
int flags = 0;
if (mode & mode_for_reading) flags |= O_RDONLY;
if (mode & mode_for_writing) flags |= O_WRONLY;
switch (mode & (mode_for_reading | mode_for_writing)) {
case mode_for_reading: flags |= O_RDONLY; break;
case mode_for_writing: flags |= O_WRONLY; break;
case mode_for_reading | mode_for_writing: flags |= O_RDWR; break;
}
if (mode & mode_create) flags |= mode & mode_preserve_existing ? O_CREAT : (O_CREAT | O_EXCL);
if (mode & hint_write_thru) flags |= O_DSYNC;
#ifndef __APPLE__
if (mode & hint_no_buffering) flags |= O_RSYNC;
#endif
m_h = open(filename, flags, DEFFILEMODE);
m_h = ::open(filename, flags, DEFFILEMODE);
#endif
if (m_h != invalid_handle) {
m_state = state_t::ok;
@ -2515,7 +2521,7 @@ namespace stdex
return li.QuadPart;
}
#else
off64_t result = lseek64(m_h, offset, how);
off64_t result = lseek64(m_h, offset, static_cast<int>(how));
if (result >= 0) {
m_state = state_t::ok;
return result;
@ -2667,8 +2673,8 @@ namespace stdex
return ft2tp(ft);
#else
struct stat buf;
if (fstat(m_h, &buf) >= 0);
return time_point::from_time_t(buf.st_atim);
if (fstat(m_h, &buf) >= 0)
return clock::from_time_t(buf.st_atime);
#endif
return time_point::min();
}
@ -2682,7 +2688,7 @@ namespace stdex
#else
struct stat buf;
if (fstat(m_h, &buf) >= 0)
return time_point::from_time_t(buf.st_mtim);
return clock::from_time_t(buf.st_mtime);
#endif
return time_point::min();
}
@ -2708,9 +2714,10 @@ namespace stdex
if (SetFileTime(m_h, nullptr, &ft, nullptr))
return;
#else
struct timespec ts[2];
ts[0].tv_sec = date;
ts[1].tv_nsec = UTIME_OMIT;
struct timespec ts[2] = {
{ date.time_since_epoch().count(), 0 },
{ 0, UTIME_OMIT },
};
if (futimens(m_h, ts) >= 0)
return;
#endif
@ -2725,9 +2732,10 @@ namespace stdex
if (SetFileTime(m_h, nullptr, nullptr, &ft))
return;
#else
struct timespec ts[2];
ts[0].tv_nsec = UTIME_OMIT;
ts[1].tv_sec = date;
struct timespec ts[2] = {
{ 0, UTIME_OMIT },
{ date.time_since_epoch().count(), 0 },
};
if (futimens(m_h, ts) >= 0)
return;
#endif
@ -2773,7 +2781,6 @@ namespace stdex
///
/// \param[in] filename Filename
/// \param[in] mode Bitwise combination of mode_t flags
/// \param[in] cache_size Size of the cache block
///
void open(_In_z_ const schar_t* filename, _In_ int mode)
{
@ -3077,7 +3084,7 @@ namespace stdex
if (end_offset <= m_size) {
uint32_t num_chars = LE2HE(*reinterpret_cast<uint32_t*>(m_data + m_offset));
m_offset = end_offset;
end_offset = stdex::add(m_offset + stdex::mul(num_chars, sizeof(_Elem)));
end_offset = stdex::add(m_offset, stdex::mul(num_chars, sizeof(_Elem)));
_Elem* start = reinterpret_cast<_Elem*>(m_data + m_offset);
if (end_offset <= m_size) {
data.assign(start, start + num_chars);
@ -3208,7 +3215,7 @@ namespace stdex
if (!ok()) _Unlikely_
return *this;
}
auto p = tok.m_podatki + m_offset;
auto p = m_data + m_offset;
*reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
memcpy(p + sizeof(uint32_t), data, size_chars);
m_offset = end_offset;
@ -3384,9 +3391,6 @@ namespace stdex
inline void set(_In_ fpos_t offset, _In_ const uint16_t data) { set<uint16_t>(offset, data); }
inline void set(_In_ fpos_t offset, _In_ const uint32_t data) { set<uint32_t>(offset, data); }
inline void set(_In_ fpos_t offset, _In_ const uint64_t data) { set<uint64_t>(offset, data); }
#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
inline void set(_In_ fpos_t offset, _In_ const size_t data) { set<size_t>(offset, data); }
#endif
inline void set(_In_ fpos_t offset, _In_ const float data) { set<float>(offset, data); }
inline void set(_In_ fpos_t offset, _In_ const double data) { set<double>(offset, data); }
inline void set(_In_ fpos_t offset, _In_ const char data) { set<char>(offset, data); }
@ -3421,9 +3425,6 @@ namespace stdex
inline void get(_In_ fpos_t offset, _Out_ uint16_t & data) { get<uint16_t>(offset, data); }
inline void get(_In_ fpos_t offset, _Out_ uint32_t & data) { get<uint32_t>(offset, data); }
inline void get(_In_ fpos_t offset, _Out_ uint64_t & data) { get<uint64_t>(offset, data); }
#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
inline void get(_In_ fpos_t offset, _Out_ size_t & data) { get<size_t>(offset, data); }
#endif
inline void get(_In_ fpos_t offset, _Out_ float& data) { get<float>(offset, data); }
inline void get(_In_ fpos_t offset, _Out_ double& data) { get<double>(offset, data); }
inline void get(_In_ fpos_t offset, _Out_ char& data) { get<char>(offset, data); }
@ -3447,10 +3448,6 @@ namespace stdex
inline memory_file& operator >>(_Out_ uint32_t & data) { return read_data(data); }
inline memory_file& operator <<(_In_ const uint64_t data) { return write_data(data); }
inline memory_file& operator >>(_Out_ uint64_t & data) { return read_data(data); }
#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
inline memory_file& operator <<(_In_ const size_t data) { return write_data(data); }
inline memory_file& operator >>(_Out_ size_t & data) { return read_data(data); }
#endif
inline memory_file& operator <<(_In_ const float data) { return write_data(data); }
inline memory_file& operator >>(_Out_ float& data) { return read_data(data); }
inline memory_file& operator <<(_In_ const double data) { return write_data(data); }

View File

@ -1,16 +1,22 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2016-2023 Amebis
*/
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include <assert.h>
#include <ctype.h>
#include <locale.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef __APPLE__
#include <xlocale.h>
#endif
#include <locale>
#include <memory>
#include <stdexcept>
@ -36,19 +42,35 @@ namespace stdex
///
void operator()(_In_ locale_t locale) const
{
#ifdef _WIN32
free_locale(locale);
#else
freelocale(locale);
#endif
}
};
///
/// locale_t helper class to free_locale when going out of scope
///
#if defined(_WIN32)
using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
#elif defined(__APPLE__)
using locale = std::unique_ptr<struct _xlocale, free_locale_delete>;
#else
using locale = std::unique_ptr<struct __locale_struct, free_locale_delete>;
#endif
///
/// Reusable C locale
///
#if defined(_WIN32)
static locale locale_C(_create_locale(LC_ALL, "C"));
#elif defined(__APPLE__)
static locale locale_C(newlocale(LC_ALL_MASK, "C", LC_GLOBAL_LOCALE));
#else
#error TODO
#endif
///
/// UTF-16 code unit
@ -124,10 +146,10 @@ namespace stdex
inline bool iscombining(_In_ char32_t chr)
{
return
0x0300 <= chr && chr < 0x0370 ||
0x1dc0 <= chr && chr < 0x1e00 ||
0x20d0 <= chr && chr < 0x2100 ||
0xfe20 <= chr && chr < 0xfe30;
(0x0300 <= chr && chr < 0x0370) ||
(0x1dc0 <= chr && chr < 0x1e00) ||
(0x20d0 <= chr && chr < 0x2100) ||
(0xfe20 <= chr && chr < 0xfe30);
}
///
@ -151,7 +173,7 @@ namespace stdex
inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
{
_Analysis_assume_(chr || !count);
if (count >= 2 && (chr[0] == '\r' && chr[1] == '\n' || chr[0] == '\n' && chr[1] == '\r'))
if (count >= 2 && ((chr[0] == '\r' && chr[1] == '\n') || (chr[0] == '\n' && chr[1] == '\r')))
return 2;
if (count > 1 && (chr[0] == '\n' || chr[0] == '\r'))
return 1;
@ -811,7 +833,7 @@ namespace stdex
goto error;
if (value < max_ui_pre1 || // Multiplication nor addition will not overflow.
value == max_ui_pre1 && digit <= max_ui_pre2) // Small digits will not overflow.
(value == max_ui_pre1 && digit <= max_ui_pre2)) // Small digits will not overflow.
value = value * (T_bin)radix + digit;
else {
// Overflow!
@ -1060,7 +1082,7 @@ namespace stdex
#pragma warning(suppress: 4996)
r = _vsnprintf_l(str, capacity, format, locale, arg);
#else
r = vsnprintf(str, capacity, format, arg);
r = ::vsnprintf(str, capacity, format, arg);
#endif
if (r == -1 && strnlen(str, capacity) == capacity) {
// Buffer overrun. Estimate buffer size for the next iteration.
@ -1206,4 +1228,4 @@ namespace stdex
va_end(arg);
return str;
}
}
}

View File

@ -12,9 +12,11 @@
#include <oaidl.h>
#include <tchar.h>
#else
#define _LARGEFILE64_SOURCE
#include <sys/types.h>
#include <unistd.h>
#endif
#include "sal.hpp"
#include "compat.hpp"
#include <assert.h>
#include <stdexcept>
#include <string>

View File

@ -1,14 +1,19 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2023 Amebis
*/
#pragma once
#include "sal.hpp"
#include "compat.hpp"
#include "endian.hpp"
#include "math.hpp"
#include "system.hpp"
#include <assert.h>
#include <stdint.h>
#ifndef _WIN32
#include <iconv.h>
#endif
#include <memory>
#include <string>
@ -16,28 +21,87 @@ namespace stdex
{
enum class charset_id : uint16_t {
#ifdef _WIN32
default = CP_ACP,
system = CP_ACP,
utf8 = CP_UTF8,
utf16 = 1200 /*CP_WINUNICODE*/,
#else
default = 0,
system = 0,
utf8,
utf16,
utf32,
#endif
};
#ifndef _WIN32
///
/// Convert string to Unicode (UTF-16 on Windows) and append to string
/// Unicode converter context
///
template <typename T_from, typename T_to>
class iconverter
{
public:
iconverter(_In_ charset_id from, _In_ charset_id to)
{
m_handle = iconv_open(to_encoding(to), to_encoding(from));
if (m_handle == (iconv_t)-1)
throw std::runtime_error("iconv_open failed");
}
~iconverter()
{
iconv_close(m_handle);
}
void convert(_Inout_ std::basic_string<T_to> &dst, _In_reads_or_z_opt_(count) const T_from* src, _In_ size_t count_src) const
{
T_to buf[0x100];
count_src = stdex::strnlen(src, count_src);
size_t src_size = stdex::mul(sizeof(T_from), count_src);
do {
T_to* output = &buf[0];
size_t output_size = sizeof(buf);
errno = 0;
iconv(m_handle, (char**)&src, &src_size, (char**)&output, &output_size);
if (errno)
throw std::runtime_error("iconv failed");
dst.insert(dst.end(), buf, (T_to*)((char*)buf + sizeof(buf) - output_size));
} while (src_size);
}
protected:
static const char* to_encoding(_In_ charset_id charset)
{
switch (charset) {
case charset_id::system:
case charset_id::utf8: return "UTF-8";
#if BYTE_ORDER == BIG_ENDIAN
case charset_id::utf16: return "UTF-16BE";
case charset_id::utf32: return "UTF-32BE";
#else
case charset_id::utf16: return "UTF-16LE";
case charset_id::utf32: return "UTF-32LE";
#endif
default: throw std::invalid_argument("unsupported charset");
}
}
protected:
iconv_t m_handle;
};
#endif
///
/// Convert string to Unicode (UTF-16 on Windows, UTF-32 elsewhere)) and append to string
///
/// \param[in,out] dst String to append Unicode to
/// \param[in] src String
/// \param[in] count_src String character count limit
/// \param[in] charset Charset (stdex::charset_id::default - system default)
///
/// \return Unicode string
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
inline void strcat(
_Inout_ std::wstring& dst,
_In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
assert(src || !count_src);
#ifdef _WIN32
@ -59,14 +123,15 @@ namespace stdex
dst.append(szBuffer.get(), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) : (size_t)cch - 1);
}
#else
throw std::exception("not implemented");
iconverter<char, wchar_t>(charset, charset_id::utf32).convert(dst, src, count_src);
#endif
}
inline _Deprecated_("Use stdex::strcat") void str2wstr(
_Deprecated_("Use stdex::strcat")
inline void str2wstr(
_Inout_ std::wstring& dst,
_In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
strcat(dst, src, count_src, charset);
}
@ -76,22 +141,21 @@ namespace stdex
///
/// \param[in,out] dst String to append Unicode to
/// \param[in] src String
/// \param[in] charset Charset (stdex::charset_id::default - system default)
///
/// \return Unicode string
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
inline void strcat(
_Inout_ std::wstring& dst,
_In_ const std::string& src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
strcat(dst, src.data(), src.size(), charset);
}
inline _Deprecated_("Use stdex::strcat") void str2wstr(
_Deprecated_("Use stdex::strcat")
inline void str2wstr(
_Inout_ std::wstring& dst,
_In_ const std::string& src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
strcat(dst, src, charset);
}
@ -102,14 +166,12 @@ namespace stdex
/// \param[in,out] dst String to write Unicode to
/// \param[in] src String
/// \param[in] count_src String character count limit
/// \param[in] charset Charset (stdex::charset_id::default - system default)
///
/// \return Unicode string
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
inline void strcpy(
_Inout_ std::wstring& dst,
_In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
dst.clear();
strcat(dst, src, count_src, charset);
@ -120,14 +182,12 @@ namespace stdex
///
/// \param[in,out] dst String to write Unicode to
/// \param[in] src String
/// \param[in] charset Charset (stdex::charset_id::default - system default)
///
/// \return Unicode string
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
inline void strcpy(
_Inout_ std::wstring& dst,
_In_ const std::string& src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
strcpy(dst, src.data(), src.size(), charset);
}
@ -136,13 +196,13 @@ namespace stdex
/// Convert string to Unicode string (UTF-16 on Windows)
///
/// \param[in] src String. Must be zero-terminated.
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
/// \return Unicode string
///
inline std::wstring str2wstr(
_In_z_ const char* src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
std::wstring dst;
strcat(dst, src, SIZE_MAX, charset);
@ -154,13 +214,13 @@ namespace stdex
///
/// \param[in] src String
/// \param[in] count_src String character count limit
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
/// \return Unicode string
///
inline std::wstring str2wstr(
_In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
std::wstring dst;
strcat(dst, src, count_src, charset);
@ -171,29 +231,29 @@ namespace stdex
/// Convert string to Unicode string (UTF-16 on Windows)
///
/// \param[in] src String
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
/// \return Unicode string
///
inline std::wstring str2wstr(
_In_ const std::string& src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
return str2wstr(src.c_str(), src.size(), charset);
}
///
/// Convert Unicode string (UTF-16 on Windows) to SGML and append to string
/// Convert Unicode string (UTF-16 on Windows, UTF-32 elsewhere) to SGML and append to string
///
/// \param[in,out] dst String to append SGML to
/// \param[in] src Unicode string
/// \param[in] count_src Unicode string character count limit
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
inline void strcat(
_Inout_ std::string& dst,
_In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
assert(src || !count_src);
#ifdef _WIN32
@ -216,14 +276,15 @@ namespace stdex
dst.append(szBuffer.get(), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) : (size_t)cch - 1);
}
#else
throw std::exception("not implemented");
iconverter<wchar_t, char>(charset_id::utf32, charset).convert(dst, src, count_src);
#endif
}
inline _Deprecated_("Use stdex::strcat") void wstr2str(
_Deprecated_("Use stdex::strcat")
inline void wstr2str(
_Inout_ std::string& dst,
_In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
strcat(dst, src, count_src, charset);
}
@ -233,20 +294,21 @@ namespace stdex
///
/// \param[in,out] dst String to append SGML to
/// \param[in] src Unicode string
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
inline void strcat(
_Inout_ std::string& dst,
_In_ const std::wstring& src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
strcat(dst, src.c_str(), src.size(), charset);
}
inline _Deprecated_("Use stdex::strcat") void wstr2str(
_Deprecated_("Use stdex::strcat")
inline void wstr2str(
_Inout_ std::string& dst,
_In_ const std::wstring& src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
strcat(dst, src, charset);
}
@ -257,12 +319,12 @@ namespace stdex
/// \param[in,out] dst String to write SGML to
/// \param[in] src Unicode string
/// \param[in] count_src Unicode string character count limit
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
inline void strcpy(
_Inout_ std::string& dst,
_In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
dst.clear();
strcat(dst, src, count_src, charset);
@ -273,12 +335,12 @@ namespace stdex
///
/// \param[in,out] dst String to write SGML to
/// \param[in] src Unicode string
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
inline void strcpy(
_Inout_ std::string& dst,
_In_ const std::wstring& src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
strcpy(dst, src.data(), src.size(), charset);
}
@ -287,13 +349,13 @@ namespace stdex
/// Convert Unicode string (UTF-16 on Windows) to string
///
/// \param[in] src Unicode string. Must be zero-terminated.
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
/// \return String
///
inline std::string wstr2str(
_In_z_ const wchar_t* src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
std::string dst;
strcat(dst, src, SIZE_MAX, charset);
@ -305,13 +367,13 @@ namespace stdex
///
/// \param[in] src Unicode string
/// \param[in] count_src Unicode string character count limit
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
/// \return String
///
inline std::string wstr2str(
_In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
std::string dst;
strcat(dst, src, count_src, charset);
@ -322,14 +384,14 @@ namespace stdex
/// Convert Unicode string (UTF-16 on Windows) to string
///
/// \param[in] src Unicode string
/// \param[in] charset Charset (stdex::charset_id::default - system default)
/// \param[in] charset Charset (stdex::charset_id::system - system default)
///
/// \return String
///
inline std::string wstr2str(
_In_ const std::wstring& src,
_In_ charset_id charset = charset_id::default)
_In_ charset_id charset = charset_id::system)
{
return wstr2str(src.c_str(), src.size(), charset);
}
}
}

View File

@ -5,7 +5,7 @@
#pragma once
#include "sal.hpp"
#include "compat.hpp"
namespace stdex
{

View File

@ -1,18 +0,0 @@
#pragma once
#include <stdexcept>
template <class T>
void are_equal(const T& a, const T& b)
{
if (!(a == b))
throw std::runtime_error("values are not equal");
}
template <class E, typename F>
void expect_exception(F functor)
{
try { functor(); }
catch (const E&) { return; }
throw std::runtime_error("exception expected");
}

View File

@ -1,16 +0,0 @@
#include "math.hpp"
#include <iostream>
int main(int argc, const char * argv[])
{
try {
UnitTests::math::mul();
UnitTests::math::add();
std::cout << "PASS\n";
return 0;
}
catch (const std::exception& ex) {
std::cerr << ex.what() << " FAIL\n";
return 1;
}
}

View File

@ -1,39 +0,0 @@
#pragma once
#include "common.hpp"
#include <stdex/math.hpp>
using namespace std;
namespace UnitTests
{
class math
{
public:
static void mul()
{
are_equal<size_t>(10, stdex::mul(2, 5));
are_equal<size_t>(10, stdex::mul(5, 2));
are_equal<size_t>(0, stdex::mul(0, 10));
are_equal<size_t>(0, stdex::mul(10, 0));
are_equal<size_t>(0, stdex::mul(SIZE_MAX, 0));
are_equal<size_t>(0, stdex::mul(0, SIZE_MAX));
are_equal<size_t>(SIZE_MAX, stdex::mul(SIZE_MAX, 1));
are_equal<size_t>(SIZE_MAX, stdex::mul(1, SIZE_MAX));
expect_exception<std::invalid_argument>([] { stdex::mul(SIZE_MAX, 2); });
expect_exception<std::invalid_argument>([] { stdex::mul(2, SIZE_MAX); });
}
static void add()
{
are_equal<size_t>(7, stdex::add(2, 5));
are_equal<size_t>(7, stdex::add(5, 2));
are_equal<size_t>(10, stdex::add(0, 10));
are_equal<size_t>(10, stdex::add(10, 0));
are_equal<size_t>(SIZE_MAX, stdex::add(SIZE_MAX, 0));
are_equal<size_t>(SIZE_MAX, stdex::add(0, SIZE_MAX));
expect_exception<std::invalid_argument>([] { stdex::add(SIZE_MAX, 1); });
expect_exception<std::invalid_argument>([] { stdex::add(1, SIZE_MAX); });
}
};
}