mirror of https://github.com/OpenRCT2/OpenRCT2.git
clang-format core
This commit is contained in:
parent
6f2e84e593
commit
3a4a11f738
|
@ -9,21 +9,22 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <initializer_list>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "Memory.hpp"
|
#include "Memory.hpp"
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
namespace Collections
|
namespace Collections
|
||||||
{
|
{
|
||||||
template<typename TCollection, typename TItem>
|
template<typename TCollection, typename TItem>
|
||||||
static void AddRange(TCollection &collection, std::initializer_list<TItem> initializerList)
|
static void AddRange(TCollection& collection, std::initializer_list<TItem> initializerList)
|
||||||
{
|
{
|
||||||
collection.insert(collection.end(), initializerList.begin(), initializerList.end());
|
collection.insert(collection.end(), initializerList.begin(), initializerList.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TCollection, typename TItem, typename TComparer>
|
template<typename TCollection, typename TItem, typename TComparer>
|
||||||
static bool Contains(TCollection &collection, TItem needle, TComparer comparer)
|
static bool Contains(TCollection& collection, TItem needle, TComparer comparer)
|
||||||
{
|
{
|
||||||
for (TItem item : collection)
|
for (TItem item : collection)
|
||||||
{
|
{
|
||||||
|
@ -36,7 +37,7 @@ namespace Collections
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TCollection, typename TItem, typename TComparer>
|
template<typename TCollection, typename TItem, typename TComparer>
|
||||||
static size_t IndexOf(TCollection &collection, TItem needle, TComparer comparer)
|
static size_t IndexOf(TCollection& collection, TItem needle, TComparer comparer)
|
||||||
{
|
{
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (TItem item : collection)
|
for (TItem item : collection)
|
||||||
|
@ -50,8 +51,7 @@ namespace Collections
|
||||||
return SIZE_MAX;
|
return SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TCollection, typename TPred>
|
template<typename TCollection, typename TPred> static size_t IndexOf(TCollection& collection, TPred predicate)
|
||||||
static size_t IndexOf(TCollection &collection, TPred predicate)
|
|
||||||
{
|
{
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (auto item : collection)
|
for (auto item : collection)
|
||||||
|
@ -65,30 +65,21 @@ namespace Collections
|
||||||
return SIZE_MAX;
|
return SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma region String helpers
|
#pragma region String helpers
|
||||||
|
|
||||||
template<typename TCollection>
|
template<typename TCollection> static bool Contains(TCollection& collection, const char* item, bool ignoreCase = false)
|
||||||
static bool Contains(TCollection &collection, const char * item, bool ignoreCase = false)
|
|
||||||
{
|
{
|
||||||
return Contains(collection, item,
|
return Contains(
|
||||||
[ignoreCase](const char * a, const char * b)
|
collection, item, [ignoreCase](const char* a, const char* b) { return String::Equals(a, b, ignoreCase); });
|
||||||
{
|
|
||||||
return String::Equals(a, b, ignoreCase);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TCollection>
|
template<typename TCollection> static size_t IndexOf(TCollection& collection, const char* item, bool ignoreCase = false)
|
||||||
static size_t IndexOf(TCollection &collection, const char * item, bool ignoreCase = false)
|
|
||||||
{
|
{
|
||||||
return IndexOf(collection, item,
|
return IndexOf(
|
||||||
[ignoreCase](const char * a, const char * b)
|
collection, item, [ignoreCase](const char* a, const char* b) { return String::Equals(a, b, ignoreCase); });
|
||||||
{
|
|
||||||
return String::Equals(a, b, ignoreCase);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TCollection>
|
template<typename TCollection> static typename TCollection::value_type* ToArray(const TCollection& collection)
|
||||||
static typename TCollection::value_type * ToArray(const TCollection &collection)
|
|
||||||
{
|
{
|
||||||
size_t count = collection.size();
|
size_t count = collection.size();
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
|
@ -96,9 +87,9 @@ namespace Collections
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto * items = Memory::AllocateArray<typename TCollection::value_type>(count);
|
auto* items = Memory::AllocateArray<typename TCollection::value_type>(count);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (const auto &item : collection)
|
for (const auto& item : collection)
|
||||||
{
|
{
|
||||||
items[i] = item;
|
items[i] = item;
|
||||||
i++;
|
i++;
|
||||||
|
@ -106,5 +97,5 @@ namespace Collections
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
} // namespace Collections
|
} // namespace Collections
|
||||||
|
|
|
@ -7,12 +7,13 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "Console.hpp"
|
||||||
|
|
||||||
|
#include "../platform/platform.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Console.hpp"
|
|
||||||
#include "../platform/platform.h"
|
|
||||||
|
|
||||||
namespace Console
|
namespace Console
|
||||||
{
|
{
|
||||||
void Write(char c)
|
void Write(char c)
|
||||||
|
@ -20,7 +21,7 @@ namespace Console
|
||||||
fputc(c, stdout);
|
fputc(c, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(const utf8 * str)
|
void Write(const utf8* str)
|
||||||
{
|
{
|
||||||
fputs(str, stdout);
|
fputs(str, stdout);
|
||||||
}
|
}
|
||||||
|
@ -31,7 +32,7 @@ namespace Console
|
||||||
Write(sz.c_str());
|
Write(sz.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteFormat(const utf8 * format, ...)
|
void WriteFormat(const utf8* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ namespace Console
|
||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteLine(const utf8 * format, ...)
|
void WriteLine(const utf8* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
|
@ -62,12 +63,12 @@ namespace Console
|
||||||
fputc(c, stderr);
|
fputc(c, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(const utf8 * str)
|
void Write(const utf8* str)
|
||||||
{
|
{
|
||||||
fputs(str, stderr);
|
fputs(str, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteFormat(const utf8 * format, ...)
|
void WriteFormat(const utf8* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ namespace Console
|
||||||
fputs(PLATFORM_NEWLINE, stderr);
|
fputs(PLATFORM_NEWLINE, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteLine(const utf8 * format, ...)
|
void WriteLine(const utf8* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
@ -89,7 +90,7 @@ namespace Console
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteLine_VA(const utf8 * format, va_list args)
|
void WriteLine_VA(const utf8* format, va_list args)
|
||||||
{
|
{
|
||||||
auto formatLn = std::string(format) + "\n";
|
auto formatLn = std::string(format) + "\n";
|
||||||
vfprintf(stdout, formatLn.c_str(), args);
|
vfprintf(stdout, formatLn.c_str(), args);
|
||||||
|
|
|
@ -16,19 +16,19 @@
|
||||||
namespace Console
|
namespace Console
|
||||||
{
|
{
|
||||||
void Write(char c);
|
void Write(char c);
|
||||||
void Write(const utf8 * str);
|
void Write(const utf8* str);
|
||||||
void WriteSpace(size_t count);
|
void WriteSpace(size_t count);
|
||||||
void WriteFormat(const utf8 * format, ...);
|
void WriteFormat(const utf8* format, ...);
|
||||||
void WriteLine();
|
void WriteLine();
|
||||||
void WriteLine(const utf8 * format, ...);
|
void WriteLine(const utf8* format, ...);
|
||||||
|
|
||||||
namespace Error
|
namespace Error
|
||||||
{
|
{
|
||||||
void Write(char c);
|
void Write(char c);
|
||||||
void Write(const utf8 * str);
|
void Write(const utf8* str);
|
||||||
void WriteFormat(const utf8 * format, ...);
|
void WriteFormat(const utf8* format, ...);
|
||||||
void WriteLine();
|
void WriteLine();
|
||||||
void WriteLine(const utf8 * format, ...);
|
void WriteLine(const utf8* format, ...);
|
||||||
void WriteLine_VA(const utf8 * format, va_list args);
|
void WriteLine_VA(const utf8* format, va_list args);
|
||||||
} // namespace Error
|
} // namespace Error
|
||||||
} // namespace Console
|
} // namespace Console
|
||||||
|
|
|
@ -10,11 +10,12 @@
|
||||||
#ifndef DISABLE_NETWORK
|
#ifndef DISABLE_NETWORK
|
||||||
|
|
||||||
#include "Crypt.h"
|
#include "Crypt.h"
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
|
|
||||||
using namespace Crypt;
|
using namespace Crypt;
|
||||||
|
|
||||||
|
@ -36,16 +37,15 @@ static void OpenSSLInitialise()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TBase>
|
template<typename TBase> class OpenSSLHashAlgorithm final : public TBase
|
||||||
class OpenSSLHashAlgorithm final : public TBase
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
const EVP_MD * _type;
|
const EVP_MD* _type;
|
||||||
EVP_MD_CTX * _ctx{};
|
EVP_MD_CTX* _ctx{};
|
||||||
bool _initialised{};
|
bool _initialised{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenSSLHashAlgorithm(const EVP_MD * type)
|
OpenSSLHashAlgorithm(const EVP_MD* type)
|
||||||
{
|
{
|
||||||
_type = type;
|
_type = type;
|
||||||
_ctx = EVP_MD_CTX_create();
|
_ctx = EVP_MD_CTX_create();
|
||||||
|
@ -60,7 +60,7 @@ public:
|
||||||
EVP_MD_CTX_destroy(_ctx);
|
EVP_MD_CTX_destroy(_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TBase * Clear() override
|
TBase* Clear() override
|
||||||
{
|
{
|
||||||
if (EVP_DigestInit_ex(_ctx, _type, nullptr) <= 0)
|
if (EVP_DigestInit_ex(_ctx, _type, nullptr) <= 0)
|
||||||
{
|
{
|
||||||
|
@ -70,7 +70,7 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TBase * Update(const void * data, size_t dataLen) override
|
TBase* Update(const void* data, size_t dataLen) override
|
||||||
{
|
{
|
||||||
// Auto initialise
|
// Auto initialise
|
||||||
if (!_initialised)
|
if (!_initialised)
|
||||||
|
@ -111,7 +111,10 @@ public:
|
||||||
class OpenSSLRsaKey final : public RsaKey
|
class OpenSSLRsaKey final : public RsaKey
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EVP_PKEY * GetEvpKey() const { return _evpKey; }
|
EVP_PKEY* GetEvpKey() const
|
||||||
|
{
|
||||||
|
return _evpKey;
|
||||||
|
}
|
||||||
|
|
||||||
~OpenSSLRsaKey()
|
~OpenSSLRsaKey()
|
||||||
{
|
{
|
||||||
|
@ -137,7 +140,7 @@ public:
|
||||||
status = EVP_PKEY_keygen_init(ctx);
|
status = EVP_PKEY_keygen_init(ctx);
|
||||||
OpenSSLThrowOnBadStatus("EVP_PKEY_keygen_init", status);
|
OpenSSLThrowOnBadStatus("EVP_PKEY_keygen_init", status);
|
||||||
|
|
||||||
EVP_PKEY * key{};
|
EVP_PKEY* key{};
|
||||||
status = EVP_PKEY_keygen(ctx, &key);
|
status = EVP_PKEY_keygen(ctx, &key);
|
||||||
OpenSSLThrowOnBadStatus("EVP_PKEY_keygen", status);
|
OpenSSLThrowOnBadStatus("EVP_PKEY_keygen", status);
|
||||||
|
|
||||||
|
@ -163,31 +166,34 @@ public:
|
||||||
SetKey(pem, false);
|
SetKey(pem, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetPrivate() override { return GetKey(true); }
|
std::string GetPrivate() override
|
||||||
|
{
|
||||||
|
return GetKey(true);
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetPublic() override { return GetKey(false); }
|
std::string GetPublic() override
|
||||||
|
{
|
||||||
|
return GetKey(false);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EVP_PKEY * _evpKey{};
|
EVP_PKEY* _evpKey{};
|
||||||
|
|
||||||
void SetKey(const std::string_view& pem, bool isPrivate)
|
void SetKey(const std::string_view& pem, bool isPrivate)
|
||||||
{
|
{
|
||||||
// Read PEM data via BIO buffer
|
// Read PEM data via BIO buffer
|
||||||
// HACK first parameter is not const on MINGW for some reason
|
// HACK first parameter is not const on MINGW for some reason
|
||||||
auto bio = BIO_new_mem_buf((void *)pem.data(), (int)pem.size());
|
auto bio = BIO_new_mem_buf((void*)pem.data(), (int)pem.size());
|
||||||
if (bio == nullptr)
|
if (bio == nullptr)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("BIO_new_mem_buf failed");
|
throw std::runtime_error("BIO_new_mem_buf failed");
|
||||||
}
|
}
|
||||||
auto rsa = isPrivate ?
|
auto rsa = isPrivate ? PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr)
|
||||||
PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr) :
|
: PEM_read_bio_RSAPublicKey(bio, nullptr, nullptr, nullptr);
|
||||||
PEM_read_bio_RSAPublicKey(bio, nullptr, nullptr, nullptr);
|
|
||||||
if (rsa == nullptr)
|
if (rsa == nullptr)
|
||||||
{
|
{
|
||||||
BIO_free_all(bio);
|
BIO_free_all(bio);
|
||||||
auto msg = isPrivate ?
|
auto msg = isPrivate ? "PEM_read_bio_RSAPrivateKey failed" : "PEM_read_bio_RSAPublicKey failed";
|
||||||
"PEM_read_bio_RSAPrivateKey failed" :
|
|
||||||
"PEM_read_bio_RSAPublicKey failed";
|
|
||||||
throw std::runtime_error(msg);
|
throw std::runtime_error(msg);
|
||||||
}
|
}
|
||||||
BIO_free_all(bio);
|
BIO_free_all(bio);
|
||||||
|
@ -224,9 +230,8 @@ private:
|
||||||
throw std::runtime_error("BIO_new failed");
|
throw std::runtime_error("BIO_new failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto status = isPrivate ?
|
auto status = isPrivate ? PEM_write_bio_RSAPrivateKey(bio, rsa, nullptr, nullptr, 0, nullptr, nullptr)
|
||||||
PEM_write_bio_RSAPrivateKey(bio, rsa, nullptr, nullptr, 0, nullptr, nullptr) :
|
: PEM_write_bio_RSAPublicKey(bio, rsa);
|
||||||
PEM_write_bio_RSAPublicKey(bio, rsa);
|
|
||||||
if (status != 1)
|
if (status != 1)
|
||||||
{
|
{
|
||||||
BIO_free_all(bio);
|
BIO_free_all(bio);
|
||||||
|
@ -246,10 +251,10 @@ private:
|
||||||
class OpenSSLRsaAlgorithm final : public RsaAlgorithm
|
class OpenSSLRsaAlgorithm final : public RsaAlgorithm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::vector<uint8_t> SignData(const RsaKey& key, const void * data, size_t dataLen) override
|
std::vector<uint8_t> SignData(const RsaKey& key, const void* data, size_t dataLen) override
|
||||||
{
|
{
|
||||||
auto evpKey = static_cast<const OpenSSLRsaKey&>(key).GetEvpKey();
|
auto evpKey = static_cast<const OpenSSLRsaKey&>(key).GetEvpKey();
|
||||||
EVP_MD_CTX * mdctx{};
|
EVP_MD_CTX* mdctx{};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mdctx = EVP_MD_CTX_create();
|
mdctx = EVP_MD_CTX_create();
|
||||||
|
@ -284,10 +289,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VerifyData(const RsaKey& key, const void * data, size_t dataLen, const void * sig, size_t sigLen) override
|
bool VerifyData(const RsaKey& key, const void* data, size_t dataLen, const void* sig, size_t sigLen) override
|
||||||
{
|
{
|
||||||
auto evpKey = static_cast<const OpenSSLRsaKey&>(key).GetEvpKey();
|
auto evpKey = static_cast<const OpenSSLRsaKey&>(key).GetEvpKey();
|
||||||
EVP_MD_CTX * mdctx{};
|
EVP_MD_CTX* mdctx{};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mdctx = EVP_MD_CTX_create();
|
mdctx = EVP_MD_CTX_create();
|
||||||
|
@ -343,6 +348,6 @@ namespace Crypt
|
||||||
OpenSSLInitialise();
|
OpenSSLInitialise();
|
||||||
return std::make_unique<OpenSSLRsaKey>();
|
return std::make_unique<OpenSSLRsaKey>();
|
||||||
}
|
}
|
||||||
}
|
} // namespace Crypt
|
||||||
|
|
||||||
#endif // DISABLE_NETWORK
|
#endif // DISABLE_NETWORK
|
||||||
|
|
|
@ -16,15 +16,14 @@
|
||||||
|
|
||||||
namespace Crypt
|
namespace Crypt
|
||||||
{
|
{
|
||||||
template<size_t TLength>
|
template<size_t TLength> class HashAlgorithm
|
||||||
class HashAlgorithm
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::array<uint8_t, TLength> Result;
|
typedef std::array<uint8_t, TLength> Result;
|
||||||
|
|
||||||
virtual ~HashAlgorithm() = default;
|
virtual ~HashAlgorithm() = default;
|
||||||
virtual HashAlgorithm * Clear() = 0;
|
virtual HashAlgorithm* Clear() = 0;
|
||||||
virtual HashAlgorithm * Update(const void * data, size_t dataLen) = 0;
|
virtual HashAlgorithm* Update(const void* data, size_t dataLen) = 0;
|
||||||
virtual Result Finish() = 0;
|
virtual Result Finish() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,8 +42,8 @@ namespace Crypt
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~RsaAlgorithm() = default;
|
virtual ~RsaAlgorithm() = default;
|
||||||
virtual std::vector<uint8_t> SignData(const RsaKey& key, const void * data, size_t dataLen) = 0;
|
virtual std::vector<uint8_t> SignData(const RsaKey& key, const void* data, size_t dataLen) = 0;
|
||||||
virtual bool VerifyData(const RsaKey& key, const void * data, size_t dataLen, const void * sig, size_t sigLen) = 0;
|
virtual bool VerifyData(const RsaKey& key, const void* data, size_t dataLen, const void* sig, size_t sigLen) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Sha1Algorithm = HashAlgorithm<20>;
|
using Sha1Algorithm = HashAlgorithm<20>;
|
||||||
|
@ -56,17 +55,13 @@ namespace Crypt
|
||||||
std::unique_ptr<RsaAlgorithm> CreateRSA();
|
std::unique_ptr<RsaAlgorithm> CreateRSA();
|
||||||
std::unique_ptr<RsaKey> CreateRSAKey();
|
std::unique_ptr<RsaKey> CreateRSAKey();
|
||||||
|
|
||||||
inline Sha1Algorithm::Result SHA1(const void * data, size_t dataLen)
|
inline Sha1Algorithm::Result SHA1(const void* data, size_t dataLen)
|
||||||
{
|
{
|
||||||
return CreateSHA1()
|
return CreateSHA1()->Update(data, dataLen)->Finish();
|
||||||
->Update(data, dataLen)
|
|
||||||
->Finish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Sha256Algorithm::Result SHA256(const void * data, size_t dataLen)
|
inline Sha256Algorithm::Result SHA256(const void* data, size_t dataLen)
|
||||||
{
|
{
|
||||||
return CreateSHA256()
|
return CreateSHA256()->Update(data, dataLen)->Finish();
|
||||||
->Update(data, dataLen)
|
|
||||||
->Finish();
|
|
||||||
}
|
}
|
||||||
}
|
} // namespace Crypt
|
||||||
|
|
|
@ -9,23 +9,26 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include "DataSerialiserTraits.h"
|
#include "DataSerialiserTraits.h"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
class DataSerialiser
|
class DataSerialiser
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
MemoryStream _stream;
|
MemoryStream _stream;
|
||||||
MemoryStream *_activeStream;
|
MemoryStream* _activeStream;
|
||||||
bool _isSaving;
|
bool _isSaving;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DataSerialiser(bool isSaving) : _isSaving(isSaving)
|
DataSerialiser(bool isSaving)
|
||||||
|
: _isSaving(isSaving)
|
||||||
{
|
{
|
||||||
_activeStream = &_stream;
|
_activeStream = &_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSerialiser(bool isSaving, MemoryStream& stream) : _isSaving(isSaving)
|
DataSerialiser(bool isSaving, MemoryStream& stream)
|
||||||
|
: _isSaving(isSaving)
|
||||||
{
|
{
|
||||||
_activeStream = &stream;
|
_activeStream = &stream;
|
||||||
}
|
}
|
||||||
|
@ -45,8 +48,7 @@ public:
|
||||||
return _stream;
|
return _stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> DataSerialiser& operator<<(T& data)
|
||||||
DataSerialiser& operator<<(T& data)
|
|
||||||
{
|
{
|
||||||
if (_isSaving)
|
if (_isSaving)
|
||||||
DataSerializerTraits<T>::encode(_activeStream, data);
|
DataSerializerTraits<T>::encode(_activeStream, data);
|
||||||
|
|
|
@ -12,21 +12,20 @@
|
||||||
#include "Endianness.h"
|
#include "Endianness.h"
|
||||||
#include "MemoryStream.h"
|
#include "MemoryStream.h"
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> struct DataSerializerTraits
|
||||||
struct DataSerializerTraits {
|
{
|
||||||
static void encode(IStream *stream, const T& v) = delete;
|
static void encode(IStream* stream, const T& v) = delete;
|
||||||
static void decode(IStream *stream, T& val) = delete;
|
static void decode(IStream* stream, T& val) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> struct DataSerializerTraitsIntegral
|
||||||
struct DataSerializerTraitsIntegral
|
|
||||||
{
|
{
|
||||||
static void encode(IStream *stream, const T& val)
|
static void encode(IStream* stream, const T& val)
|
||||||
{
|
{
|
||||||
T temp = ByteSwapBE(val);
|
T temp = ByteSwapBE(val);
|
||||||
stream->Write(&temp);
|
stream->Write(&temp);
|
||||||
}
|
}
|
||||||
static void decode(IStream *stream, T& val)
|
static void decode(IStream* stream, T& val)
|
||||||
{
|
{
|
||||||
T temp;
|
T temp;
|
||||||
stream->Read(&temp);
|
stream->Read(&temp);
|
||||||
|
@ -34,38 +33,44 @@ struct DataSerializerTraitsIntegral
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<> struct DataSerializerTraits<bool> : public DataSerializerTraitsIntegral<bool>
|
||||||
struct DataSerializerTraits<bool> : public DataSerializerTraitsIntegral<bool> {};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct DataSerializerTraits<uint8_t> : public DataSerializerTraitsIntegral<uint8_t> {};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct DataSerializerTraits<int8_t> : public DataSerializerTraitsIntegral<int8_t> {};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct DataSerializerTraits<uint16_t> : public DataSerializerTraitsIntegral<uint16_t> {};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct DataSerializerTraits<int16_t> : public DataSerializerTraitsIntegral<int16_t> {};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct DataSerializerTraits<uint32_t> : public DataSerializerTraitsIntegral<uint32_t> {};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct DataSerializerTraits<int32_t> : public DataSerializerTraitsIntegral<int32_t> {};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct DataSerializerTraits<std::string>
|
|
||||||
{
|
{
|
||||||
static void encode(IStream *stream, const std::string& str)
|
};
|
||||||
|
|
||||||
|
template<> struct DataSerializerTraits<uint8_t> : public DataSerializerTraitsIntegral<uint8_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct DataSerializerTraits<int8_t> : public DataSerializerTraitsIntegral<int8_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct DataSerializerTraits<uint16_t> : public DataSerializerTraitsIntegral<uint16_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct DataSerializerTraits<int16_t> : public DataSerializerTraitsIntegral<int16_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct DataSerializerTraits<uint32_t> : public DataSerializerTraitsIntegral<uint32_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct DataSerializerTraits<int32_t> : public DataSerializerTraitsIntegral<int32_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct DataSerializerTraits<std::string>
|
||||||
|
{
|
||||||
|
static void encode(IStream* stream, const std::string& str)
|
||||||
{
|
{
|
||||||
uint16_t len = (uint16_t)str.size();
|
uint16_t len = (uint16_t)str.size();
|
||||||
uint16_t swapped = ByteSwapBE(len);
|
uint16_t swapped = ByteSwapBE(len);
|
||||||
stream->Write(&swapped);
|
stream->Write(&swapped);
|
||||||
stream->WriteArray(str.c_str(), len);
|
stream->WriteArray(str.c_str(), len);
|
||||||
}
|
}
|
||||||
static void decode(IStream *stream, std::string& res)
|
static void decode(IStream* stream, std::string& res)
|
||||||
{
|
{
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
stream->Read(&len);
|
stream->Read(&len);
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#if defined(DEBUG) && defined(_WIN32)
|
#if defined(DEBUG) && defined(_WIN32)
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Diagnostics.hpp"
|
#include "Diagnostics.hpp"
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
template <size_t size>
|
template<size_t size> struct ByteSwapT
|
||||||
struct ByteSwapT { };
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template<> struct ByteSwapT<1>
|
||||||
struct ByteSwapT<1>
|
|
||||||
{
|
{
|
||||||
static uint8_t SwapBE(uint8_t value)
|
static uint8_t SwapBE(uint8_t value)
|
||||||
{
|
{
|
||||||
|
@ -23,8 +23,7 @@ struct ByteSwapT<1>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template<> struct ByteSwapT<2>
|
||||||
struct ByteSwapT<2>
|
|
||||||
{
|
{
|
||||||
static uint16_t SwapBE(uint16_t value)
|
static uint16_t SwapBE(uint16_t value)
|
||||||
{
|
{
|
||||||
|
@ -32,20 +31,15 @@ struct ByteSwapT<2>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template<> struct ByteSwapT<4>
|
||||||
struct ByteSwapT<4>
|
|
||||||
{
|
{
|
||||||
static uint32_t SwapBE(uint32_t value)
|
static uint32_t SwapBE(uint32_t value)
|
||||||
{
|
{
|
||||||
return (uint32_t)(((value << 24) |
|
return (uint32_t)(((value << 24) | ((value << 8) & 0x00FF0000) | ((value >> 8) & 0x0000FF00) | (value >> 24)));
|
||||||
((value << 8) & 0x00FF0000) |
|
|
||||||
((value >> 8) & 0x0000FF00) |
|
|
||||||
(value >> 24)));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template<typename T> static T ByteSwapBE(const T& value)
|
||||||
static T ByteSwapBE(const T& value)
|
|
||||||
{
|
{
|
||||||
return ByteSwapT<sizeof(T)>::SwapBE(value);
|
return ByteSwapT<sizeof(T)>::SwapBE(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,38 +8,38 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <fstream>
|
#include "../platform/platform.h"
|
||||||
|
#include "../util/Util.h"
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
#include "FileStream.hpp"
|
#include "FileStream.hpp"
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
#include "../util/Util.h"
|
|
||||||
|
|
||||||
#include "../platform/platform.h"
|
#include <fstream>
|
||||||
|
|
||||||
namespace File
|
namespace File
|
||||||
{
|
{
|
||||||
bool Exists(const std::string &path)
|
bool Exists(const std::string& path)
|
||||||
{
|
{
|
||||||
return platform_file_exists(path.c_str());
|
return platform_file_exists(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Copy(const std::string &srcPath, const std::string &dstPath, bool overwrite)
|
bool Copy(const std::string& srcPath, const std::string& dstPath, bool overwrite)
|
||||||
{
|
{
|
||||||
return platform_file_copy(srcPath.c_str(), dstPath.c_str(), overwrite);
|
return platform_file_copy(srcPath.c_str(), dstPath.c_str(), overwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Delete(const std::string &path)
|
bool Delete(const std::string& path)
|
||||||
{
|
{
|
||||||
return platform_file_delete(path.c_str());
|
return platform_file_delete(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Move(const std::string &srcPath, const std::string &dstPath)
|
bool Move(const std::string& srcPath, const std::string& dstPath)
|
||||||
{
|
{
|
||||||
return platform_file_move(srcPath.c_str(), dstPath.c_str());
|
return platform_file_move(srcPath.c_str(), dstPath.c_str());
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ namespace File
|
||||||
{
|
{
|
||||||
result.resize(fsize);
|
result.resize(fsize);
|
||||||
fs.seekg(0);
|
fs.seekg(0);
|
||||||
fs.read((char *)result.data(), result.size());
|
fs.read((char*)result.data(), result.size());
|
||||||
fs.exceptions(fs.failbit);
|
fs.exceptions(fs.failbit);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -85,17 +85,17 @@ namespace File
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteAllBytes(const std::string &path, const void * buffer, size_t length)
|
void WriteAllBytes(const std::string& path, const void* buffer, size_t length)
|
||||||
{
|
{
|
||||||
auto fs = FileStream(path, FILE_MODE_WRITE);
|
auto fs = FileStream(path, FILE_MODE_WRITE);
|
||||||
fs.Write(buffer, length);
|
fs.Write(buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> ReadAllLines(const std::string &path)
|
std::vector<std::string> ReadAllLines(const std::string& path)
|
||||||
{
|
{
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
auto data = ReadAllBytes(path);
|
auto data = ReadAllBytes(path);
|
||||||
auto lineStart = (const char *)data.data();
|
auto lineStart = (const char*)data.data();
|
||||||
auto ch = lineStart;
|
auto ch = lineStart;
|
||||||
char lastC = 0;
|
char lastC = 0;
|
||||||
for (size_t i = 0; i < data.size(); i++)
|
for (size_t i = 0; i < data.size(); i++)
|
||||||
|
@ -120,7 +120,7 @@ namespace File
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GetLastModified(const std::string &path)
|
uint64_t GetLastModified(const std::string& path)
|
||||||
{
|
{
|
||||||
uint64_t lastModified = 0;
|
uint64_t lastModified = 0;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -137,7 +137,9 @@ namespace File
|
||||||
}
|
}
|
||||||
free(pathW);
|
free(pathW);
|
||||||
#else
|
#else
|
||||||
struct stat statInfo{};
|
struct stat statInfo
|
||||||
|
{
|
||||||
|
};
|
||||||
if (stat(path.c_str(), &statInfo) == 0)
|
if (stat(path.c_str(), &statInfo) == 0)
|
||||||
{
|
{
|
||||||
lastModified = statInfo.st_mtime;
|
lastModified = statInfo.st_mtime;
|
||||||
|
@ -147,16 +149,15 @@ namespace File
|
||||||
}
|
}
|
||||||
} // namespace File
|
} // namespace File
|
||||||
|
|
||||||
bool writeentirefile(const utf8 * path, const void * buffer, size_t length)
|
bool writeentirefile(const utf8* path, const void* buffer, size_t length)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File::WriteAllBytes(String::ToStd(path), buffer, length);
|
File::WriteAllBytes(String::ToStd(path), buffer, length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,20 +9,21 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../common.h"
|
|
||||||
|
|
||||||
namespace File
|
namespace File
|
||||||
{
|
{
|
||||||
bool Exists(const std::string &path);
|
bool Exists(const std::string& path);
|
||||||
bool Copy(const std::string &srcPath, const std::string &dstPath, bool overwrite);
|
bool Copy(const std::string& srcPath, const std::string& dstPath, bool overwrite);
|
||||||
bool Delete(const std::string &path);
|
bool Delete(const std::string& path);
|
||||||
bool Move(const std::string &srcPath, const std::string &dstPath);
|
bool Move(const std::string& srcPath, const std::string& dstPath);
|
||||||
std::vector<uint8_t> ReadAllBytes(const std::string_view& path);
|
std::vector<uint8_t> ReadAllBytes(const std::string_view& path);
|
||||||
std::string ReadAllText(const std::string_view& path);
|
std::string ReadAllText(const std::string_view& path);
|
||||||
void WriteAllBytes(const std::string &path, const void * buffer, size_t length);
|
void WriteAllBytes(const std::string& path, const void* buffer, size_t length);
|
||||||
std::vector<std::string> ReadAllLines(const std::string &path);
|
std::vector<std::string> ReadAllLines(const std::string& path);
|
||||||
uint64_t GetLastModified(const std::string &path);
|
uint64_t GetLastModified(const std::string& path);
|
||||||
} // namespace File
|
} // namespace File
|
||||||
|
|
|
@ -9,11 +9,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <string>
|
|
||||||
#include <tuple>
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "Console.hpp"
|
#include "Console.hpp"
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
@ -22,8 +17,13 @@
|
||||||
#include "JobPool.hpp"
|
#include "JobPool.hpp"
|
||||||
#include "Path.hpp"
|
#include "Path.hpp"
|
||||||
|
|
||||||
template<typename TItem>
|
#include <chrono>
|
||||||
class FileIndex
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template<typename TItem> class FileIndex
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct DirectoryStats
|
struct DirectoryStats
|
||||||
|
@ -40,21 +40,21 @@ private:
|
||||||
std::vector<std::string> const Files;
|
std::vector<std::string> const Files;
|
||||||
|
|
||||||
ScanResult(DirectoryStats stats, std::vector<std::string> files)
|
ScanResult(DirectoryStats stats, std::vector<std::string> files)
|
||||||
: Stats(stats),
|
: Stats(stats)
|
||||||
Files(files)
|
, Files(files)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FileIndexHeader
|
struct FileIndexHeader
|
||||||
{
|
{
|
||||||
uint32_t HeaderSize = sizeof(FileIndexHeader);
|
uint32_t HeaderSize = sizeof(FileIndexHeader);
|
||||||
uint32_t MagicNumber = 0;
|
uint32_t MagicNumber = 0;
|
||||||
uint8_t VersionA = 0;
|
uint8_t VersionA = 0;
|
||||||
uint8_t VersionB = 0;
|
uint8_t VersionB = 0;
|
||||||
uint16_t LanguageId = 0;
|
uint16_t LanguageId = 0;
|
||||||
DirectoryStats Stats;
|
DirectoryStats Stats;
|
||||||
uint32_t NumItems = 0;
|
uint32_t NumItems = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Index file format version which when incremented forces a rebuild
|
// Index file format version which when incremented forces a rebuild
|
||||||
|
@ -79,18 +79,19 @@ public:
|
||||||
* @param pattern The search pattern for indexing files.
|
* @param pattern The search pattern for indexing files.
|
||||||
* @param paths A list of search directories.
|
* @param paths A list of search directories.
|
||||||
*/
|
*/
|
||||||
FileIndex(std::string name,
|
FileIndex(
|
||||||
uint32_t magicNumber,
|
std::string name,
|
||||||
uint8_t version,
|
uint32_t magicNumber,
|
||||||
std::string indexPath,
|
uint8_t version,
|
||||||
std::string pattern,
|
std::string indexPath,
|
||||||
std::vector<std::string> paths) :
|
std::string pattern,
|
||||||
_name(name),
|
std::vector<std::string> paths)
|
||||||
_magicNumber(magicNumber),
|
: _name(name)
|
||||||
_version(version),
|
, _magicNumber(magicNumber)
|
||||||
_indexPath(indexPath),
|
, _version(version)
|
||||||
_pattern(pattern),
|
, _indexPath(indexPath)
|
||||||
SearchPaths(paths)
|
, _pattern(pattern)
|
||||||
|
, SearchPaths(paths)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,22 +131,22 @@ protected:
|
||||||
* Loads the given file and creates the item representing the data to store in the index.
|
* Loads the given file and creates the item representing the data to store in the index.
|
||||||
* TODO Use std::optional when C++17 is available.
|
* TODO Use std::optional when C++17 is available.
|
||||||
*/
|
*/
|
||||||
virtual std::tuple<bool, TItem> Create(int32_t language, const std::string &path) const abstract;
|
virtual std::tuple<bool, TItem> Create(int32_t language, const std::string& path) const abstract;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialises an index item to the given stream.
|
* Serialises an index item to the given stream.
|
||||||
*/
|
*/
|
||||||
virtual void Serialise(IStream * stream, const TItem &item) const abstract;
|
virtual void Serialise(IStream* stream, const TItem& item) const abstract;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialises an index item from the given stream.
|
* Deserialises an index item from the given stream.
|
||||||
*/
|
*/
|
||||||
virtual TItem Deserialise(IStream * stream) const abstract;
|
virtual TItem Deserialise(IStream* stream) const abstract;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ScanResult Scan() const
|
ScanResult Scan() const
|
||||||
{
|
{
|
||||||
DirectoryStats stats {};
|
DirectoryStats stats{};
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
for (const auto& directory : SearchPaths)
|
for (const auto& directory : SearchPaths)
|
||||||
{
|
{
|
||||||
|
@ -162,9 +163,8 @@ private:
|
||||||
|
|
||||||
stats.TotalFiles++;
|
stats.TotalFiles++;
|
||||||
stats.TotalFileSize += fileInfo->Size;
|
stats.TotalFileSize += fileInfo->Size;
|
||||||
stats.FileDateModifiedChecksum ^=
|
stats.FileDateModifiedChecksum
|
||||||
(uint32_t)(fileInfo->LastModified >> 32) ^
|
^= (uint32_t)(fileInfo->LastModified >> 32) ^ (uint32_t)(fileInfo->LastModified & 0xFFFFFFFF);
|
||||||
(uint32_t)(fileInfo->LastModified & 0xFFFFFFFF);
|
|
||||||
stats.FileDateModifiedChecksum = ror32(stats.FileDateModifiedChecksum, 5);
|
stats.FileDateModifiedChecksum = ror32(stats.FileDateModifiedChecksum, 5);
|
||||||
stats.PathChecksum += GetPathChecksum(path);
|
stats.PathChecksum += GetPathChecksum(path);
|
||||||
}
|
}
|
||||||
|
@ -173,13 +173,14 @@ private:
|
||||||
return ScanResult(stats, files);
|
return ScanResult(stats, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildRange(int32_t language,
|
void BuildRange(
|
||||||
const ScanResult &scanResult,
|
int32_t language,
|
||||||
size_t rangeStart,
|
const ScanResult& scanResult,
|
||||||
size_t rangeEnd,
|
size_t rangeStart,
|
||||||
std::vector<TItem>& items,
|
size_t rangeEnd,
|
||||||
std::atomic<size_t>& processed,
|
std::vector<TItem>& items,
|
||||||
std::mutex& printLock) const
|
std::atomic<size_t>& processed,
|
||||||
|
std::mutex& printLock) const
|
||||||
{
|
{
|
||||||
items.reserve(rangeEnd - rangeStart);
|
items.reserve(rangeEnd - rangeStart);
|
||||||
for (size_t i = rangeStart; i < rangeEnd; i++)
|
for (size_t i = rangeStart; i < rangeEnd; i++)
|
||||||
|
@ -202,7 +203,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TItem> Build(int32_t language, const ScanResult &scanResult) const
|
std::vector<TItem> Build(int32_t language, const ScanResult& scanResult) const
|
||||||
{
|
{
|
||||||
std::vector<TItem> allItems;
|
std::vector<TItem> allItems;
|
||||||
Console::WriteLine("Building %s (%zu items)", _name.c_str(), scanResult.Files.size());
|
Console::WriteLine("Building %s (%zu items)", _name.c_str(), scanResult.Files.size());
|
||||||
|
@ -221,12 +222,10 @@ private:
|
||||||
|
|
||||||
std::atomic<size_t> processed = ATOMIC_VAR_INIT(0);
|
std::atomic<size_t> processed = ATOMIC_VAR_INIT(0);
|
||||||
|
|
||||||
auto reportProgress =
|
auto reportProgress = [&]() {
|
||||||
[&]()
|
const size_t completed = processed;
|
||||||
{
|
Console::WriteFormat("File %5d of %d, done %3d%%\r", completed, totalCount, completed * 100 / totalCount);
|
||||||
const size_t completed = processed;
|
};
|
||||||
Console::WriteFormat("File %5d of %d, done %3d%%\r", completed, totalCount, completed * 100 / totalCount);
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t rangeStart = 0; rangeStart < totalCount; rangeStart += stepSize)
|
for (size_t rangeStart = 0; rangeStart < totalCount; rangeStart += stepSize)
|
||||||
{
|
{
|
||||||
|
@ -237,7 +236,8 @@ private:
|
||||||
|
|
||||||
auto& items = containers.emplace_back();
|
auto& items = containers.emplace_back();
|
||||||
|
|
||||||
jobPool.AddTask(std::bind(&FileIndex<TItem>::BuildRange,
|
jobPool.AddTask(std::bind(
|
||||||
|
&FileIndex<TItem>::BuildRange,
|
||||||
this,
|
this,
|
||||||
language,
|
language,
|
||||||
std::cref(scanResult),
|
std::cref(scanResult),
|
||||||
|
@ -267,7 +267,7 @@ private:
|
||||||
return allItems;
|
return allItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<bool, std::vector<TItem>> ReadIndexFile(int32_t language, const DirectoryStats &stats) const
|
std::tuple<bool, std::vector<TItem>> ReadIndexFile(int32_t language, const DirectoryStats& stats) const
|
||||||
{
|
{
|
||||||
bool loadedItems = false;
|
bool loadedItems = false;
|
||||||
std::vector<TItem> items;
|
std::vector<TItem> items;
|
||||||
|
@ -280,15 +280,11 @@ private:
|
||||||
|
|
||||||
// Read header, check if we need to re-scan
|
// Read header, check if we need to re-scan
|
||||||
auto header = fs.ReadValue<FileIndexHeader>();
|
auto header = fs.ReadValue<FileIndexHeader>();
|
||||||
if (header.HeaderSize == sizeof(FileIndexHeader) &&
|
if (header.HeaderSize == sizeof(FileIndexHeader) && header.MagicNumber == _magicNumber
|
||||||
header.MagicNumber == _magicNumber &&
|
&& header.VersionA == FILE_INDEX_VERSION && header.VersionB == _version && header.LanguageId == language
|
||||||
header.VersionA == FILE_INDEX_VERSION &&
|
&& header.Stats.TotalFiles == stats.TotalFiles && header.Stats.TotalFileSize == stats.TotalFileSize
|
||||||
header.VersionB == _version &&
|
&& header.Stats.FileDateModifiedChecksum == stats.FileDateModifiedChecksum
|
||||||
header.LanguageId == language &&
|
&& header.Stats.PathChecksum == stats.PathChecksum)
|
||||||
header.Stats.TotalFiles == stats.TotalFiles &&
|
|
||||||
header.Stats.TotalFileSize == stats.TotalFileSize &&
|
|
||||||
header.Stats.FileDateModifiedChecksum == stats.FileDateModifiedChecksum &&
|
|
||||||
header.Stats.PathChecksum == stats.PathChecksum)
|
|
||||||
{
|
{
|
||||||
items.reserve(header.NumItems);
|
items.reserve(header.NumItems);
|
||||||
// Directory is the same, just read the saved items
|
// Directory is the same, just read the saved items
|
||||||
|
@ -304,7 +300,7 @@ private:
|
||||||
Console::WriteLine("%s out of date", _name.c_str());
|
Console::WriteLine("%s out of date", _name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
Console::Error::WriteLine("Unable to load index: '%s'.", _indexPath.c_str());
|
Console::Error::WriteLine("Unable to load index: '%s'.", _indexPath.c_str());
|
||||||
Console::Error::WriteLine("%s", e.what());
|
Console::Error::WriteLine("%s", e.what());
|
||||||
|
@ -313,7 +309,7 @@ private:
|
||||||
return std::make_tuple(loadedItems, items);
|
return std::make_tuple(loadedItems, items);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteIndexFile(int32_t language, const DirectoryStats &stats, const std::vector<TItem> &items) const
|
void WriteIndexFile(int32_t language, const DirectoryStats& stats, const std::vector<TItem>& items) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -337,17 +333,17 @@ private:
|
||||||
Serialise(&fs, item);
|
Serialise(&fs, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
Console::Error::WriteLine("Unable to save index: '%s'.", _indexPath.c_str());
|
Console::Error::WriteLine("Unable to save index: '%s'.", _indexPath.c_str());
|
||||||
Console::Error::WriteLine("%s", e.what());
|
Console::Error::WriteLine("%s", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t GetPathChecksum(const std::string &path)
|
static uint32_t GetPathChecksum(const std::string& path)
|
||||||
{
|
{
|
||||||
uint32_t hash = 0xD8430DED;
|
uint32_t hash = 0xD8430DED;
|
||||||
for (const utf8 * ch = path.c_str(); *ch != '\0'; ch++)
|
for (const utf8* ch = path.c_str(); *ch != '\0'; ch++)
|
||||||
{
|
{
|
||||||
hash += (*ch);
|
hash += (*ch);
|
||||||
hash += (hash << 10);
|
hash += (hash << 10);
|
||||||
|
|
|
@ -10,28 +10,29 @@
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/types.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
// Windows needs this for widechar <-> utf8 conversion utils
|
// Windows needs this for widechar <-> utf8 conversion utils
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "FileScanner.h"
|
||||||
|
#include "Memory.hpp"
|
||||||
|
#include "Path.hpp"
|
||||||
|
#include "String.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "FileScanner.h"
|
|
||||||
#include "Memory.hpp"
|
|
||||||
#include "Path.hpp"
|
|
||||||
#include "String.hpp"
|
|
||||||
|
|
||||||
enum class DIRECTORY_CHILD_TYPE
|
enum class DIRECTORY_CHILD_TYPE
|
||||||
{
|
{
|
||||||
|
@ -45,38 +46,38 @@ struct DirectoryChild
|
||||||
std::string Name;
|
std::string Name;
|
||||||
|
|
||||||
// Files only
|
// Files only
|
||||||
uint64_t Size = 0;
|
uint64_t Size = 0;
|
||||||
uint64_t LastModified = 0;
|
uint64_t LastModified = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t GetPathChecksum(const utf8 * path);
|
static uint32_t GetPathChecksum(const utf8* path);
|
||||||
static bool MatchWildcard(const utf8 * fileName, const utf8 * pattern);
|
static bool MatchWildcard(const utf8* fileName, const utf8* pattern);
|
||||||
|
|
||||||
class FileScannerBase : public IFileScanner
|
class FileScannerBase : public IFileScanner
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct DirectoryState
|
struct DirectoryState
|
||||||
{
|
{
|
||||||
std::string Path;
|
std::string Path;
|
||||||
std::vector<DirectoryChild> Listing;
|
std::vector<DirectoryChild> Listing;
|
||||||
int32_t Index = 0;
|
int32_t Index = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Options
|
// Options
|
||||||
std::string _rootPath;
|
std::string _rootPath;
|
||||||
std::vector<std::string> _patterns;
|
std::vector<std::string> _patterns;
|
||||||
bool _recurse;
|
bool _recurse;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
bool _started = false;
|
bool _started = false;
|
||||||
std::stack<DirectoryState> _directoryStack;
|
std::stack<DirectoryState> _directoryStack;
|
||||||
|
|
||||||
// Current
|
// Current
|
||||||
FileInfo * _currentFileInfo;
|
FileInfo* _currentFileInfo;
|
||||||
utf8 * _currentPath;
|
utf8* _currentPath;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileScannerBase(const std::string &pattern, bool recurse)
|
FileScannerBase(const std::string& pattern, bool recurse)
|
||||||
{
|
{
|
||||||
_rootPath = Path::GetDirectory(pattern);
|
_rootPath = Path::GetDirectory(pattern);
|
||||||
_recurse = recurse;
|
_recurse = recurse;
|
||||||
|
@ -94,17 +95,17 @@ public:
|
||||||
Memory::Free(_currentFileInfo);
|
Memory::Free(_currentFileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileInfo * GetFileInfo() const override
|
const FileInfo* GetFileInfo() const override
|
||||||
{
|
{
|
||||||
return _currentFileInfo;
|
return _currentFileInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
const utf8 * GetPath() const override
|
const utf8* GetPath() const override
|
||||||
{
|
{
|
||||||
return _currentPath;
|
return _currentPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const utf8 * GetPathRelative() const override
|
const utf8* GetPathRelative() const override
|
||||||
{
|
{
|
||||||
// +1 to remove the path separator
|
// +1 to remove the path separator
|
||||||
return _currentPath + _rootPath.size() + 1;
|
return _currentPath + _rootPath.size() + 1;
|
||||||
|
@ -127,7 +128,7 @@ public:
|
||||||
|
|
||||||
while (!_directoryStack.empty())
|
while (!_directoryStack.empty())
|
||||||
{
|
{
|
||||||
DirectoryState * state = &_directoryStack.top();
|
DirectoryState* state = &_directoryStack.top();
|
||||||
state->Index++;
|
state->Index++;
|
||||||
if (state->Index >= (int32_t)state->Listing.size())
|
if (state->Index >= (int32_t)state->Listing.size())
|
||||||
{
|
{
|
||||||
|
@ -135,7 +136,7 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const DirectoryChild * child = &state->Listing[state->Index];
|
const DirectoryChild* child = &state->Listing[state->Index];
|
||||||
if (child->Type == DIRECTORY_CHILD_TYPE::DC_DIRECTORY)
|
if (child->Type == DIRECTORY_CHILD_TYPE::DC_DIRECTORY)
|
||||||
{
|
{
|
||||||
if (_recurse)
|
if (_recurse)
|
||||||
|
@ -162,10 +163,10 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void GetDirectoryChildren(std::vector<DirectoryChild> &children, const std::string &path) abstract;
|
virtual void GetDirectoryChildren(std::vector<DirectoryChild>& children, const std::string& path) abstract;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PushState(const std::string &directory)
|
void PushState(const std::string& directory)
|
||||||
{
|
{
|
||||||
DirectoryState newState;
|
DirectoryState newState;
|
||||||
newState.Path = directory;
|
newState.Path = directory;
|
||||||
|
@ -174,9 +175,9 @@ private:
|
||||||
_directoryStack.push(newState);
|
_directoryStack.push(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PatternMatch(const std::string &fileName)
|
bool PatternMatch(const std::string& fileName)
|
||||||
{
|
{
|
||||||
for (const auto &pattern : _patterns)
|
for (const auto& pattern : _patterns)
|
||||||
{
|
{
|
||||||
if (MatchWildcard(fileName.c_str(), pattern.c_str()))
|
if (MatchWildcard(fileName.c_str(), pattern.c_str()))
|
||||||
{
|
{
|
||||||
|
@ -186,12 +187,12 @@ private:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> GetPatterns(const std::string &delimitedPatterns)
|
static std::vector<std::string> GetPatterns(const std::string& delimitedPatterns)
|
||||||
{
|
{
|
||||||
std::vector<std::string> patterns;
|
std::vector<std::string> patterns;
|
||||||
|
|
||||||
const utf8 * start = delimitedPatterns.c_str();
|
const utf8* start = delimitedPatterns.c_str();
|
||||||
const utf8 * ch = start;
|
const utf8* ch = start;
|
||||||
utf8 c;
|
utf8 c;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -207,8 +208,7 @@ private:
|
||||||
start = ch + 1;
|
start = ch + 1;
|
||||||
}
|
}
|
||||||
ch++;
|
ch++;
|
||||||
}
|
} while (c != '\0');
|
||||||
while (c != '\0');
|
|
||||||
|
|
||||||
patterns.shrink_to_fit();
|
patterns.shrink_to_fit();
|
||||||
return patterns;
|
return patterns;
|
||||||
|
@ -220,15 +220,15 @@ private:
|
||||||
class FileScannerWindows final : public FileScannerBase
|
class FileScannerWindows final : public FileScannerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileScannerWindows(const std::string &pattern, bool recurse)
|
FileScannerWindows(const std::string& pattern, bool recurse)
|
||||||
: FileScannerBase(pattern, recurse)
|
: FileScannerBase(pattern, recurse)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetDirectoryChildren(std::vector<DirectoryChild> &children, const std::string &path) override
|
void GetDirectoryChildren(std::vector<DirectoryChild>& children, const std::string& path) override
|
||||||
{
|
{
|
||||||
std::string pattern = path + "\\*";
|
std::string pattern = path + "\\*";
|
||||||
wchar_t * wPattern = utf8_to_widechar(pattern.c_str());
|
wchar_t* wPattern = utf8_to_widechar(pattern.c_str());
|
||||||
|
|
||||||
WIN32_FIND_DATAW findData;
|
WIN32_FIND_DATAW findData;
|
||||||
HANDLE hFile = FindFirstFileW(wPattern, &findData);
|
HANDLE hFile = FindFirstFileW(wPattern, &findData);
|
||||||
|
@ -236,14 +236,12 @@ public:
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (lstrcmpW(findData.cFileName, L".") != 0 &&
|
if (lstrcmpW(findData.cFileName, L".") != 0 && lstrcmpW(findData.cFileName, L"..") != 0)
|
||||||
lstrcmpW(findData.cFileName, L"..") != 0)
|
|
||||||
{
|
{
|
||||||
DirectoryChild child = CreateChild(&findData);
|
DirectoryChild child = CreateChild(&findData);
|
||||||
children.push_back(child);
|
children.push_back(child);
|
||||||
}
|
}
|
||||||
}
|
} while (FindNextFileW(hFile, &findData));
|
||||||
while (FindNextFileW(hFile, &findData));
|
|
||||||
FindClose(hFile);
|
FindClose(hFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,11 +249,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static DirectoryChild CreateChild(const WIN32_FIND_DATAW * child)
|
static DirectoryChild CreateChild(const WIN32_FIND_DATAW* child)
|
||||||
{
|
{
|
||||||
DirectoryChild result;
|
DirectoryChild result;
|
||||||
|
|
||||||
utf8 * name = widechar_to_utf8(child->cFileName);
|
utf8* name = widechar_to_utf8(child->cFileName);
|
||||||
result.Name = std::string(name);
|
result.Name = std::string(name);
|
||||||
Memory::Free(name);
|
Memory::Free(name);
|
||||||
|
|
||||||
|
@ -267,7 +265,8 @@ private:
|
||||||
{
|
{
|
||||||
result.Type = DIRECTORY_CHILD_TYPE::DC_FILE;
|
result.Type = DIRECTORY_CHILD_TYPE::DC_FILE;
|
||||||
result.Size = ((uint64_t)child->nFileSizeHigh << 32ULL) | (uint64_t)child->nFileSizeLow;
|
result.Size = ((uint64_t)child->nFileSizeHigh << 32ULL) | (uint64_t)child->nFileSizeLow;
|
||||||
result.LastModified = ((uint64_t)child->ftLastWriteTime.dwHighDateTime << 32ULL) | (uint64_t)child->ftLastWriteTime.dwLowDateTime;
|
result.LastModified
|
||||||
|
= ((uint64_t)child->ftLastWriteTime.dwHighDateTime << 32ULL) | (uint64_t)child->ftLastWriteTime.dwLowDateTime;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -280,22 +279,21 @@ private:
|
||||||
class FileScannerUnix final : public FileScannerBase
|
class FileScannerUnix final : public FileScannerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileScannerUnix(const std::string &pattern, bool recurse)
|
FileScannerUnix(const std::string& pattern, bool recurse)
|
||||||
: FileScannerBase(pattern, recurse)
|
: FileScannerBase(pattern, recurse)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetDirectoryChildren(std::vector<DirectoryChild> &children, const std::string &path) override
|
void GetDirectoryChildren(std::vector<DirectoryChild>& children, const std::string& path) override
|
||||||
{
|
{
|
||||||
struct dirent * * namelist;
|
struct dirent** namelist;
|
||||||
int32_t count = scandir(path.c_str(), &namelist, FilterFunc, alphasort);
|
int32_t count = scandir(path.c_str(), &namelist, FilterFunc, alphasort);
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
for (int32_t i = 0; i < count; i++)
|
for (int32_t i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
const struct dirent * node = namelist[i];
|
const struct dirent* node = namelist[i];
|
||||||
if (!String::Equals(node->d_name, ".") &&
|
if (!String::Equals(node->d_name, ".") && !String::Equals(node->d_name, ".."))
|
||||||
!String::Equals(node->d_name, ".."))
|
|
||||||
{
|
{
|
||||||
DirectoryChild child = CreateChild(path.c_str(), node);
|
DirectoryChild child = CreateChild(path.c_str(), node);
|
||||||
children.push_back(child);
|
children.push_back(child);
|
||||||
|
@ -307,12 +305,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int32_t FilterFunc(const struct dirent * d)
|
static int32_t FilterFunc(const struct dirent* d)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DirectoryChild CreateChild(const utf8 * directory, const struct dirent * node)
|
static DirectoryChild CreateChild(const utf8* directory, const struct dirent* node)
|
||||||
{
|
{
|
||||||
DirectoryChild result;
|
DirectoryChild result;
|
||||||
result.Name = std::string(node->d_name);
|
result.Name = std::string(node->d_name);
|
||||||
|
@ -326,11 +324,13 @@ private:
|
||||||
|
|
||||||
// Get the full path of the file
|
// Get the full path of the file
|
||||||
size_t pathSize = String::SizeOf(directory) + 1 + String::SizeOf(node->d_name) + 1;
|
size_t pathSize = String::SizeOf(directory) + 1 + String::SizeOf(node->d_name) + 1;
|
||||||
utf8 * path = Memory::Allocate<utf8>(pathSize);
|
utf8* path = Memory::Allocate<utf8>(pathSize);
|
||||||
String::Set(path, pathSize, directory);
|
String::Set(path, pathSize, directory);
|
||||||
Path::Append(path, pathSize, node->d_name);
|
Path::Append(path, pathSize, node->d_name);
|
||||||
|
|
||||||
struct stat statInfo{};
|
struct stat statInfo
|
||||||
|
{
|
||||||
|
};
|
||||||
int32_t statRes = stat(path, &statInfo);
|
int32_t statRes = stat(path, &statInfo);
|
||||||
if (statRes != -1)
|
if (statRes != -1)
|
||||||
{
|
{
|
||||||
|
@ -351,7 +351,7 @@ private:
|
||||||
|
|
||||||
#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
|
|
||||||
IFileScanner * Path::ScanDirectory(const std::string &pattern, bool recurse)
|
IFileScanner* Path::ScanDirectory(const std::string& pattern, bool recurse)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return new FileScannerWindows(pattern, recurse);
|
return new FileScannerWindows(pattern, recurse);
|
||||||
|
@ -360,35 +360,34 @@ IFileScanner * Path::ScanDirectory(const std::string &pattern, bool recurse)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Path::QueryDirectory(QueryDirectoryResult * result, const std::string &pattern)
|
void Path::QueryDirectory(QueryDirectoryResult* result, const std::string& pattern)
|
||||||
{
|
{
|
||||||
IFileScanner * scanner = Path::ScanDirectory(pattern, true);
|
IFileScanner* scanner = Path::ScanDirectory(pattern, true);
|
||||||
while (scanner->Next())
|
while (scanner->Next())
|
||||||
{
|
{
|
||||||
const FileInfo * fileInfo = scanner->GetFileInfo();
|
const FileInfo* fileInfo = scanner->GetFileInfo();
|
||||||
const utf8 * path = scanner->GetPath();
|
const utf8* path = scanner->GetPath();
|
||||||
|
|
||||||
result->TotalFiles++;
|
result->TotalFiles++;
|
||||||
result->TotalFileSize += fileInfo->Size;
|
result->TotalFileSize += fileInfo->Size;
|
||||||
result->FileDateModifiedChecksum ^=
|
result->FileDateModifiedChecksum
|
||||||
(uint32_t)(fileInfo->LastModified >> 32) ^
|
^= (uint32_t)(fileInfo->LastModified >> 32) ^ (uint32_t)(fileInfo->LastModified & 0xFFFFFFFF);
|
||||||
(uint32_t)(fileInfo->LastModified & 0xFFFFFFFF);
|
|
||||||
result->FileDateModifiedChecksum = ror32(result->FileDateModifiedChecksum, 5);
|
result->FileDateModifiedChecksum = ror32(result->FileDateModifiedChecksum, 5);
|
||||||
result->PathChecksum += GetPathChecksum(path);
|
result->PathChecksum += GetPathChecksum(path);
|
||||||
}
|
}
|
||||||
delete scanner;
|
delete scanner;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Path::GetDirectories(const std::string &path)
|
std::vector<std::string> Path::GetDirectories(const std::string& path)
|
||||||
{
|
{
|
||||||
auto scanner = std::unique_ptr<IFileScanner>(ScanDirectory(path, false));
|
auto scanner = std::unique_ptr<IFileScanner>(ScanDirectory(path, false));
|
||||||
auto baseScanner = static_cast<FileScannerBase *>(scanner.get());
|
auto baseScanner = static_cast<FileScannerBase*>(scanner.get());
|
||||||
|
|
||||||
std::vector<DirectoryChild> children;
|
std::vector<DirectoryChild> children;
|
||||||
baseScanner->GetDirectoryChildren(children, path);
|
baseScanner->GetDirectoryChildren(children, path);
|
||||||
|
|
||||||
std::vector<std::string> subDirectories;
|
std::vector<std::string> subDirectories;
|
||||||
for (const auto &c : children)
|
for (const auto& c : children)
|
||||||
{
|
{
|
||||||
if (c.Type == DIRECTORY_CHILD_TYPE::DC_DIRECTORY)
|
if (c.Type == DIRECTORY_CHILD_TYPE::DC_DIRECTORY)
|
||||||
{
|
{
|
||||||
|
@ -398,10 +397,10 @@ std::vector<std::string> Path::GetDirectories(const std::string &path)
|
||||||
return subDirectories;
|
return subDirectories;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t GetPathChecksum(const utf8 * path)
|
static uint32_t GetPathChecksum(const utf8* path)
|
||||||
{
|
{
|
||||||
uint32_t hash = 0xD8430DED;
|
uint32_t hash = 0xD8430DED;
|
||||||
for (const utf8 * ch = path; *ch != '\0'; ch++)
|
for (const utf8* ch = path; *ch != '\0'; ch++)
|
||||||
{
|
{
|
||||||
hash += (*ch);
|
hash += (*ch);
|
||||||
hash += (hash << 10);
|
hash += (hash << 10);
|
||||||
|
@ -418,41 +417,41 @@ static uint32_t GetPathChecksum(const utf8 * path)
|
||||||
* specified. This will verify if a filename does indeed match the pattern we asked for.
|
* specified. This will verify if a filename does indeed match the pattern we asked for.
|
||||||
* @remarks Based on algorithm (http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html)
|
* @remarks Based on algorithm (http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html)
|
||||||
*/
|
*/
|
||||||
static bool MatchWildcard(const utf8 * fileName, const utf8 * pattern)
|
static bool MatchWildcard(const utf8* fileName, const utf8* pattern)
|
||||||
{
|
{
|
||||||
while (*fileName != '\0')
|
while (*fileName != '\0')
|
||||||
{
|
{
|
||||||
switch (*pattern) {
|
switch (*pattern)
|
||||||
case '?':
|
{
|
||||||
if (*fileName == '.')
|
case '?':
|
||||||
{
|
if (*fileName == '.')
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '*':
|
|
||||||
do
|
|
||||||
{
|
|
||||||
pattern++;
|
|
||||||
}
|
|
||||||
while (*pattern == '*');
|
|
||||||
if (*pattern == '\0')
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
while (*fileName != '\0')
|
|
||||||
{
|
|
||||||
if (MatchWildcard(fileName++, pattern))
|
|
||||||
{
|
{
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pattern++;
|
||||||
|
} while (*pattern == '*');
|
||||||
|
if (*pattern == '\0')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (*fileName != '\0')
|
||||||
|
{
|
||||||
|
if (MatchWildcard(fileName++, pattern))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
if (toupper(*fileName) != toupper(*pattern))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
default:
|
||||||
break;
|
if (toupper(*fileName) != toupper(*pattern))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
pattern++;
|
pattern++;
|
||||||
fileName++;
|
fileName++;
|
||||||
|
|
|
@ -9,24 +9,25 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../common.h"
|
|
||||||
|
|
||||||
struct FileInfo
|
struct FileInfo
|
||||||
{
|
{
|
||||||
const utf8 * Name;
|
const utf8* Name;
|
||||||
uint64_t Size;
|
uint64_t Size;
|
||||||
uint64_t LastModified;
|
uint64_t LastModified;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IFileScanner
|
interface IFileScanner
|
||||||
{
|
{
|
||||||
virtual ~IFileScanner() = default;
|
virtual ~IFileScanner() = default;
|
||||||
|
|
||||||
virtual const FileInfo * GetFileInfo() const abstract;
|
virtual const FileInfo* GetFileInfo() const abstract;
|
||||||
virtual const utf8 * GetPath() const abstract;
|
virtual const utf8* GetPath() const abstract;
|
||||||
virtual const utf8 * GetPathRelative() const abstract;
|
virtual const utf8* GetPathRelative() const abstract;
|
||||||
|
|
||||||
virtual void Reset() abstract;
|
virtual void Reset() abstract;
|
||||||
virtual bool Next() abstract;
|
virtual bool Next() abstract;
|
||||||
|
@ -49,14 +50,14 @@ namespace Path
|
||||||
* @param recurse Whether to scan sub directories or not.
|
* @param recurse Whether to scan sub directories or not.
|
||||||
* @returns A new FileScanner, this must be deleted when no longer needed.
|
* @returns A new FileScanner, this must be deleted when no longer needed.
|
||||||
*/
|
*/
|
||||||
IFileScanner * ScanDirectory(const std::string &pattern, bool recurse);
|
IFileScanner* ScanDirectory(const std::string& pattern, bool recurse);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans a directory and all sub directories
|
* Scans a directory and all sub directories
|
||||||
* @param result The query result to modify.
|
* @param result The query result to modify.
|
||||||
* @param pattern The path followed by a semi-colon delimited list of wildcard patterns.
|
* @param pattern The path followed by a semi-colon delimited list of wildcard patterns.
|
||||||
*/
|
*/
|
||||||
void QueryDirectory(QueryDirectoryResult * result, const std::string &pattern);
|
void QueryDirectory(QueryDirectoryResult* result, const std::string& pattern);
|
||||||
|
|
||||||
std::vector<std::string> GetDirectories(const std::string &path);
|
std::vector<std::string> GetDirectories(const std::string& path);
|
||||||
} // namespace Path
|
} // namespace Path
|
||||||
|
|
|
@ -10,12 +10,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
#include "../localisation/Language.h"
|
||||||
#include "IStream.hpp"
|
#include "IStream.hpp"
|
||||||
#include "Math.hpp"
|
#include "Math.hpp"
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
|
|
||||||
#include "../localisation/Language.h"
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
FILE_MODE_OPEN,
|
FILE_MODE_OPEN,
|
||||||
|
@ -29,45 +28,46 @@ enum
|
||||||
class FileStream final : public IStream
|
class FileStream final : public IStream
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
FILE * _file = nullptr;
|
FILE* _file = nullptr;
|
||||||
bool _ownsFilePtr = false;
|
bool _ownsFilePtr = false;
|
||||||
bool _canRead = false;
|
bool _canRead = false;
|
||||||
bool _canWrite = false;
|
bool _canWrite = false;
|
||||||
bool _disposed = false;
|
bool _disposed = false;
|
||||||
uint64_t _fileSize = 0;
|
uint64_t _fileSize = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileStream(const std::string &path, int32_t fileMode) :
|
FileStream(const std::string& path, int32_t fileMode)
|
||||||
FileStream(path.c_str(), fileMode)
|
: FileStream(path.c_str(), fileMode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStream(const utf8 * path, int32_t fileMode)
|
FileStream(const utf8* path, int32_t fileMode)
|
||||||
{
|
{
|
||||||
const char * mode;
|
const char* mode;
|
||||||
switch (fileMode) {
|
switch (fileMode)
|
||||||
case FILE_MODE_OPEN:
|
{
|
||||||
mode = "rb";
|
case FILE_MODE_OPEN:
|
||||||
_canRead = true;
|
mode = "rb";
|
||||||
_canWrite = false;
|
_canRead = true;
|
||||||
break;
|
_canWrite = false;
|
||||||
case FILE_MODE_WRITE:
|
break;
|
||||||
mode = "w+b";
|
case FILE_MODE_WRITE:
|
||||||
_canRead = true;
|
mode = "w+b";
|
||||||
_canWrite = true;
|
_canRead = true;
|
||||||
break;
|
_canWrite = true;
|
||||||
case FILE_MODE_APPEND:
|
break;
|
||||||
mode = "a";
|
case FILE_MODE_APPEND:
|
||||||
_canRead = false;
|
mode = "a";
|
||||||
_canWrite = true;
|
_canRead = false;
|
||||||
break;
|
_canWrite = true;
|
||||||
default:
|
break;
|
||||||
throw;
|
default:
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
wchar_t * pathW = utf8_to_widechar(path);
|
wchar_t* pathW = utf8_to_widechar(path);
|
||||||
wchar_t * modeW = utf8_to_widechar(mode);
|
wchar_t* modeW = utf8_to_widechar(mode);
|
||||||
_file = _wfopen(pathW, modeW);
|
_file = _wfopen(pathW, modeW);
|
||||||
free(pathW);
|
free(pathW);
|
||||||
free(modeW);
|
free(modeW);
|
||||||
|
@ -98,10 +98,19 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanRead() const override { return _canRead; }
|
bool CanRead() const override
|
||||||
bool CanWrite() const override { return _canWrite; }
|
{
|
||||||
|
return _canRead;
|
||||||
|
}
|
||||||
|
bool CanWrite() const override
|
||||||
|
{
|
||||||
|
return _canWrite;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t GetLength() const override { return _fileSize; }
|
uint64_t GetLength() const override
|
||||||
|
{
|
||||||
|
return _fileSize;
|
||||||
|
}
|
||||||
uint64_t GetPosition() const override
|
uint64_t GetPosition() const override
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
@ -121,45 +130,48 @@ public:
|
||||||
void Seek(int64_t offset, int32_t origin) override
|
void Seek(int64_t offset, int32_t origin) override
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
switch (origin) {
|
switch (origin)
|
||||||
case STREAM_SEEK_BEGIN:
|
{
|
||||||
_fseeki64(_file, offset, SEEK_SET);
|
case STREAM_SEEK_BEGIN:
|
||||||
break;
|
_fseeki64(_file, offset, SEEK_SET);
|
||||||
case STREAM_SEEK_CURRENT:
|
break;
|
||||||
_fseeki64(_file, offset, SEEK_CUR);
|
case STREAM_SEEK_CURRENT:
|
||||||
break;
|
_fseeki64(_file, offset, SEEK_CUR);
|
||||||
case STREAM_SEEK_END:
|
break;
|
||||||
_fseeki64(_file, offset, SEEK_END);
|
case STREAM_SEEK_END:
|
||||||
break;
|
_fseeki64(_file, offset, SEEK_END);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#elif (defined(__APPLE__) && defined(__MACH__)) || defined(__ANDROID__) || defined(__OpenBSD__) || defined(__FreeBSD__)
|
#elif (defined(__APPLE__) && defined(__MACH__)) || defined(__ANDROID__) || defined(__OpenBSD__) || defined(__FreeBSD__)
|
||||||
switch (origin) {
|
switch (origin)
|
||||||
case STREAM_SEEK_BEGIN:
|
{
|
||||||
fseeko(_file, offset, SEEK_SET);
|
case STREAM_SEEK_BEGIN:
|
||||||
break;
|
fseeko(_file, offset, SEEK_SET);
|
||||||
case STREAM_SEEK_CURRENT:
|
break;
|
||||||
fseeko(_file, offset, SEEK_CUR);
|
case STREAM_SEEK_CURRENT:
|
||||||
break;
|
fseeko(_file, offset, SEEK_CUR);
|
||||||
case STREAM_SEEK_END:
|
break;
|
||||||
fseeko(_file, offset, SEEK_END);
|
case STREAM_SEEK_END:
|
||||||
break;
|
fseeko(_file, offset, SEEK_END);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
switch (origin) {
|
switch (origin)
|
||||||
case STREAM_SEEK_BEGIN:
|
{
|
||||||
fseeko64(_file, offset, SEEK_SET);
|
case STREAM_SEEK_BEGIN:
|
||||||
break;
|
fseeko64(_file, offset, SEEK_SET);
|
||||||
case STREAM_SEEK_CURRENT:
|
break;
|
||||||
fseeko64(_file, offset, SEEK_CUR);
|
case STREAM_SEEK_CURRENT:
|
||||||
break;
|
fseeko64(_file, offset, SEEK_CUR);
|
||||||
case STREAM_SEEK_END:
|
break;
|
||||||
fseeko64(_file, offset, SEEK_END);
|
case STREAM_SEEK_END:
|
||||||
break;
|
fseeko64(_file, offset, SEEK_END);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read(void * buffer, uint64_t length) override
|
void Read(void* buffer, uint64_t length) override
|
||||||
{
|
{
|
||||||
uint64_t remainingBytes = GetLength() - GetPosition();
|
uint64_t remainingBytes = GetLength() - GetPosition();
|
||||||
if (length <= remainingBytes)
|
if (length <= remainingBytes)
|
||||||
|
@ -172,7 +184,7 @@ public:
|
||||||
throw IOException("Attempted to read past end of file.");
|
throw IOException("Attempted to read past end of file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(const void * buffer, uint64_t length) override
|
void Write(const void* buffer, uint64_t length) override
|
||||||
{
|
{
|
||||||
if (fwrite(buffer, (size_t)length, 1, _file) != 1)
|
if (fwrite(buffer, (size_t)length, 1, _file) != 1)
|
||||||
{
|
{
|
||||||
|
@ -183,7 +195,7 @@ public:
|
||||||
_fileSize = std::max(_fileSize, position);
|
_fileSize = std::max(_fileSize, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TryRead(void * buffer, uint64_t length) override
|
uint64_t TryRead(void* buffer, uint64_t length) override
|
||||||
{
|
{
|
||||||
size_t readBytes = fread(buffer, 1, (size_t)length, _file);
|
size_t readBytes = fread(buffer, 1, (size_t)length, _file);
|
||||||
return readBytes;
|
return readBytes;
|
||||||
|
|
|
@ -34,7 +34,7 @@ void openrct2_assert_fwd(bool expression, const char* message, ...)
|
||||||
|
|
||||||
namespace Guard
|
namespace Guard
|
||||||
{
|
{
|
||||||
constexpr const utf8 * ASSERTION_MESSAGE = "An assertion failed, please report this to the OpenRCT2 developers.";
|
constexpr const utf8* ASSERTION_MESSAGE = "An assertion failed, please report this to the OpenRCT2 developers.";
|
||||||
|
|
||||||
// The default behaviour when an assertion is raised.
|
// The default behaviour when an assertion is raised.
|
||||||
static ASSERT_BEHAVIOUR _assertBehaviour =
|
static ASSERT_BEHAVIOUR _assertBehaviour =
|
||||||
|
@ -46,7 +46,7 @@ namespace Guard
|
||||||
;
|
;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static void GetAssertMessage(char * buffer, size_t bufferSize, const char * formattedMessage);
|
static void GetAssertMessage(char* buffer, size_t bufferSize, const char* formattedMessage);
|
||||||
static void ForceCrash();
|
static void ForceCrash();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ namespace Guard
|
||||||
_assertBehaviour = behaviour;
|
_assertBehaviour = behaviour;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assert(bool expression, const char * message, ...)
|
void Assert(bool expression, const char* message, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
|
@ -68,15 +68,16 @@ namespace Guard
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assert_VA(bool expression, const char * message, va_list args)
|
void Assert_VA(bool expression, const char* message, va_list args)
|
||||||
{
|
{
|
||||||
if (expression) return;
|
if (expression)
|
||||||
|
return;
|
||||||
|
|
||||||
Console::Error::WriteLine(ASSERTION_MESSAGE);
|
Console::Error::WriteLine(ASSERTION_MESSAGE);
|
||||||
Console::Error::WriteLine("Version: %s", gVersionInfoFull);
|
Console::Error::WriteLine("Version: %s", gVersionInfoFull);
|
||||||
|
|
||||||
// This is never freed, but acceptable considering we are about to crash out
|
// This is never freed, but acceptable considering we are about to crash out
|
||||||
utf8 * formattedMessage = nullptr;
|
utf8* formattedMessage = nullptr;
|
||||||
if (message != nullptr)
|
if (message != nullptr)
|
||||||
{
|
{
|
||||||
formattedMessage = String::Format_VA(message, args);
|
formattedMessage = String::Format_VA(message, args);
|
||||||
|
@ -87,31 +88,32 @@ namespace Guard
|
||||||
Debug::Break();
|
Debug::Break();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (_assertBehaviour) {
|
switch (_assertBehaviour)
|
||||||
case ASSERT_BEHAVIOUR::ABORT:
|
|
||||||
abort();
|
|
||||||
default:
|
|
||||||
case ASSERT_BEHAVIOUR::CASSERT:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
#ifdef _WIN32
|
|
||||||
case ASSERT_BEHAVIOUR::MESSAGE_BOX:
|
|
||||||
{
|
{
|
||||||
// Show message box if we are not building for testing
|
case ASSERT_BEHAVIOUR::ABORT:
|
||||||
char buffer[512];
|
abort();
|
||||||
GetAssertMessage(buffer, sizeof(buffer), formattedMessage);
|
default:
|
||||||
int32_t result = MessageBoxA(nullptr, buffer, OPENRCT2_NAME, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION);
|
case ASSERT_BEHAVIOUR::CASSERT:
|
||||||
if (result == IDABORT)
|
assert(false);
|
||||||
|
break;
|
||||||
|
#ifdef _WIN32
|
||||||
|
case ASSERT_BEHAVIOUR::MESSAGE_BOX:
|
||||||
{
|
{
|
||||||
ForceCrash();
|
// Show message box if we are not building for testing
|
||||||
|
char buffer[512];
|
||||||
|
GetAssertMessage(buffer, sizeof(buffer), formattedMessage);
|
||||||
|
int32_t result = MessageBoxA(nullptr, buffer, OPENRCT2_NAME, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION);
|
||||||
|
if (result == IDABORT)
|
||||||
|
{
|
||||||
|
ForceCrash();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fail(const char * message, ...)
|
void Fail(const char* message, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
|
@ -119,13 +121,13 @@ namespace Guard
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fail_VA(const char * message, va_list args)
|
void Fail_VA(const char* message, va_list args)
|
||||||
{
|
{
|
||||||
Assert_VA(false, message, args);
|
Assert_VA(false, message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static void GetAssertMessage(char * buffer, size_t bufferSize, const char * formattedMessage)
|
static void GetAssertMessage(char* buffer, size_t bufferSize, const char* formattedMessage)
|
||||||
{
|
{
|
||||||
String::Set(buffer, bufferSize, ASSERTION_MESSAGE);
|
String::Set(buffer, bufferSize, ASSERTION_MESSAGE);
|
||||||
String::Append(buffer, bufferSize, "\r\n\r\n");
|
String::Append(buffer, bufferSize, "\r\n\r\n");
|
||||||
|
|
|
@ -13,9 +13,13 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
void openrct2_assert_fwd(bool expression, const char * message, ...);
|
void openrct2_assert_fwd(bool expression, const char* message, ...);
|
||||||
|
|
||||||
#define openrct2_assert(expr, msg, ...) if(!(expr)) { openrct2_assert_fwd((expr), msg, ##__VA_ARGS__); }
|
#define openrct2_assert(expr, msg, ...) \
|
||||||
|
if (!(expr)) \
|
||||||
|
{ \
|
||||||
|
openrct2_assert_fwd((expr), msg, ##__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
enum class ASSERT_BEHAVIOUR
|
enum class ASSERT_BEHAVIOUR
|
||||||
{
|
{
|
||||||
|
@ -32,13 +36,12 @@ namespace Guard
|
||||||
ASSERT_BEHAVIOUR GetAssertBehaviour();
|
ASSERT_BEHAVIOUR GetAssertBehaviour();
|
||||||
void SetAssertBehaviour(ASSERT_BEHAVIOUR behaviour);
|
void SetAssertBehaviour(ASSERT_BEHAVIOUR behaviour);
|
||||||
|
|
||||||
void Assert(bool expression, const char * message = nullptr, ...);
|
void Assert(bool expression, const char* message = nullptr, ...);
|
||||||
void Assert_VA(bool expression, const char * message, va_list args);
|
void Assert_VA(bool expression, const char* message, va_list args);
|
||||||
void Fail(const char * message = nullptr, ...);
|
void Fail(const char* message = nullptr, ...);
|
||||||
void Fail_VA(const char * message, va_list args);
|
void Fail_VA(const char* message, va_list args);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static void ArgumentNotNull(T* argument, const char* message = nullptr, ...)
|
||||||
static void ArgumentNotNull(T * argument, const char * message = nullptr, ...)
|
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
|
@ -46,8 +49,7 @@ namespace Guard
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static void ArgumentNotNull(const std::shared_ptr<T>& argument, const char* message = nullptr, ...)
|
||||||
static void ArgumentNotNull(const std::shared_ptr<T>& argument, const char * message = nullptr, ...)
|
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
|
@ -55,8 +57,7 @@ namespace Guard
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static void ArgumentInRange(T argument, T min, T max, const char* message = nullptr, ...)
|
||||||
static void ArgumentInRange(T argument, T min, T max, const char * message = nullptr, ...)
|
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
|
|
|
@ -7,12 +7,14 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "IStream.hpp"
|
#include "IStream.hpp"
|
||||||
|
|
||||||
#include "Memory.hpp"
|
#include "Memory.hpp"
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
|
|
||||||
utf8 * IStream::ReadString()
|
#include <vector>
|
||||||
|
|
||||||
|
utf8* IStream::ReadString()
|
||||||
{
|
{
|
||||||
std::vector<utf8> result;
|
std::vector<utf8> result;
|
||||||
|
|
||||||
|
@ -23,7 +25,7 @@ utf8 * IStream::ReadString()
|
||||||
}
|
}
|
||||||
result.push_back(0);
|
result.push_back(0);
|
||||||
|
|
||||||
utf8 * resultString = Memory::AllocateArray<utf8>(result.size());
|
utf8* resultString = Memory::AllocateArray<utf8>(result.size());
|
||||||
std::copy(result.begin(), result.end(), resultString);
|
std::copy(result.begin(), result.end(), resultString);
|
||||||
return resultString;
|
return resultString;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +41,7 @@ std::string IStream::ReadStdString()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IStream::WriteString(const utf8 * str)
|
void IStream::WriteString(const utf8* str)
|
||||||
{
|
{
|
||||||
if (str == nullptr)
|
if (str == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -52,7 +54,7 @@ void IStream::WriteString(const utf8 * str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IStream::WriteString(const std::string &str)
|
void IStream::WriteString(const std::string& str)
|
||||||
{
|
{
|
||||||
WriteString(str.c_str());
|
WriteString(str.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
#include "Memory.hpp"
|
||||||
|
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../common.h"
|
|
||||||
#include "Memory.hpp"
|
|
||||||
|
|
||||||
enum {
|
enum
|
||||||
|
{
|
||||||
STREAM_SEEK_BEGIN,
|
STREAM_SEEK_BEGIN,
|
||||||
STREAM_SEEK_CURRENT,
|
STREAM_SEEK_CURRENT,
|
||||||
STREAM_SEEK_END
|
STREAM_SEEK_END
|
||||||
|
@ -30,20 +32,22 @@ interface IStream
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Interface methods
|
// Interface methods
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
virtual ~IStream() { }
|
virtual ~IStream()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool CanRead() const abstract;
|
virtual bool CanRead() const abstract;
|
||||||
virtual bool CanWrite() const abstract;
|
virtual bool CanWrite() const abstract;
|
||||||
|
|
||||||
virtual uint64_t GetLength() const abstract;
|
virtual uint64_t GetLength() const abstract;
|
||||||
virtual uint64_t GetPosition() const abstract;
|
virtual uint64_t GetPosition() const abstract;
|
||||||
virtual void SetPosition(uint64_t position) abstract;
|
virtual void SetPosition(uint64_t position) abstract;
|
||||||
virtual void Seek(int64_t offset, int32_t origin) abstract;
|
virtual void Seek(int64_t offset, int32_t origin) abstract;
|
||||||
|
|
||||||
virtual void Read(void * buffer, uint64_t length) abstract;
|
virtual void Read(void* buffer, uint64_t length) abstract;
|
||||||
virtual void Write(const void * buffer, uint64_t length) abstract;
|
virtual void Write(const void* buffer, uint64_t length) abstract;
|
||||||
|
|
||||||
virtual uint64_t TryRead(void * buffer, uint64_t length) abstract;
|
virtual uint64_t TryRead(void* buffer, uint64_t length) abstract;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Helper methods
|
// Helper methods
|
||||||
|
@ -52,8 +56,7 @@ interface IStream
|
||||||
/**
|
/**
|
||||||
* Reads the size of the given type from the stream directly into the given address.
|
* Reads the size of the given type from the stream directly into the given address.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T> void Read(T * value)
|
||||||
void Read(T * value)
|
|
||||||
{
|
{
|
||||||
Read(value, sizeof(T));
|
Read(value, sizeof(T));
|
||||||
}
|
}
|
||||||
|
@ -61,8 +64,7 @@ interface IStream
|
||||||
/**
|
/**
|
||||||
* Writes the size of the given type to the stream directly from the given address.
|
* Writes the size of the given type to the stream directly from the given address.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T> void Write(const T* value)
|
||||||
void Write(const T * value)
|
|
||||||
{
|
{
|
||||||
Write(value, sizeof(T));
|
Write(value, sizeof(T));
|
||||||
}
|
}
|
||||||
|
@ -70,8 +72,7 @@ interface IStream
|
||||||
/**
|
/**
|
||||||
* Reads the given type from the stream. Use this only for small types (e.g. int8_t, int64_t, double)
|
* Reads the given type from the stream. Use this only for small types (e.g. int8_t, int64_t, double)
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T> T ReadValue()
|
||||||
T ReadValue()
|
|
||||||
{
|
{
|
||||||
T buffer;
|
T buffer;
|
||||||
Read(&buffer);
|
Read(&buffer);
|
||||||
|
@ -81,40 +82,39 @@ interface IStream
|
||||||
/**
|
/**
|
||||||
* Writes the given type to the stream. Use this only for small types (e.g. int8_t, int64_t, double)
|
* Writes the given type to the stream. Use this only for small types (e.g. int8_t, int64_t, double)
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T> void WriteValue(const T value)
|
||||||
void WriteValue(const T value)
|
|
||||||
{
|
{
|
||||||
Write(&value);
|
Write(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> T* ReadArray(size_t count)
|
||||||
T * ReadArray(size_t count)
|
|
||||||
{
|
{
|
||||||
T * buffer = Memory::AllocateArray<T>(count);
|
T* buffer = Memory::AllocateArray<T>(count);
|
||||||
Read(buffer, sizeof(T) * count);
|
Read(buffer, sizeof(T) * count);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> void WriteArray(T * buffer, size_t count)
|
||||||
void WriteArray(T * buffer, size_t count)
|
|
||||||
{
|
{
|
||||||
Write(buffer, sizeof(T) * count);
|
Write(buffer, sizeof(T) * count);
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * ReadString();
|
utf8* ReadString();
|
||||||
std::string ReadStdString();
|
std::string ReadStdString();
|
||||||
void WriteString(const utf8 * str);
|
void WriteString(const utf8* str);
|
||||||
void WriteString(const std::string &string);
|
void WriteString(const std::string& string);
|
||||||
};
|
};
|
||||||
|
|
||||||
class IOException : public std::runtime_error
|
class IOException : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit IOException(const std::string &message) : std::runtime_error(message) { }
|
explicit IOException(const std::string& message)
|
||||||
|
: std::runtime_error(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> class ivstream : public std::istream
|
||||||
class ivstream : public std::istream
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
class vector_streambuf : public std::basic_streambuf<char, std::char_traits<char>>
|
class vector_streambuf : public std::basic_streambuf<char, std::char_traits<char>>
|
||||||
|
@ -122,7 +122,7 @@ private:
|
||||||
public:
|
public:
|
||||||
explicit vector_streambuf(const std::vector<T>& vec)
|
explicit vector_streambuf(const std::vector<T>& vec)
|
||||||
{
|
{
|
||||||
this->setg((char *)vec.data(), (char *)vec.data(), (char *)(vec.data() + vec.size()));
|
this->setg((char*)vec.data(), (char*)vec.data(), (char*)(vec.data() + vec.size()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,8 +130,8 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ivstream(const std::vector<T>& vec)
|
ivstream(const std::vector<T>& vec)
|
||||||
: std::istream(&_streambuf),
|
: std::istream(&_streambuf)
|
||||||
_streambuf(vec)
|
, _streambuf(vec)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,17 +9,19 @@
|
||||||
|
|
||||||
#pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
|
#pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <fstream>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <png.h>
|
|
||||||
#include "IStream.hpp"
|
|
||||||
#include "Guard.hpp"
|
|
||||||
#include "Imaging.h"
|
#include "Imaging.h"
|
||||||
|
|
||||||
|
#include "../drawing/Drawing.h"
|
||||||
|
#include "Guard.hpp"
|
||||||
|
#include "IStream.hpp"
|
||||||
#include "Memory.hpp"
|
#include "Memory.hpp"
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
#include "../drawing/Drawing.h"
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <png.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Imaging
|
namespace Imaging
|
||||||
{
|
{
|
||||||
|
@ -29,28 +31,28 @@ namespace Imaging
|
||||||
|
|
||||||
static void PngReadData(png_structp png_ptr, png_bytep data, png_size_t length)
|
static void PngReadData(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
{
|
{
|
||||||
auto istream = static_cast<std::istream *>(png_get_io_ptr(png_ptr));
|
auto istream = static_cast<std::istream*>(png_get_io_ptr(png_ptr));
|
||||||
istream->read((char *)data, length);
|
istream->read((char*)data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PngWriteData(png_structp png_ptr, png_bytep data, png_size_t length)
|
static void PngWriteData(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
{
|
{
|
||||||
auto ostream = static_cast<std::ostream *>(png_get_io_ptr(png_ptr));
|
auto ostream = static_cast<std::ostream*>(png_get_io_ptr(png_ptr));
|
||||||
ostream->write((const char *)data, length);
|
ostream->write((const char*)data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PngFlush(png_structp png_ptr)
|
static void PngFlush(png_structp png_ptr)
|
||||||
{
|
{
|
||||||
auto ostream = static_cast<std::ostream *>(png_get_io_ptr(png_ptr));
|
auto ostream = static_cast<std::ostream*>(png_get_io_ptr(png_ptr));
|
||||||
ostream->flush();
|
ostream->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PngWarning(png_structp, const char * b)
|
static void PngWarning(png_structp, const char* b)
|
||||||
{
|
{
|
||||||
log_warning(b);
|
log_warning(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PngError(png_structp, const char * b)
|
static void PngError(png_structp, const char* b)
|
||||||
{
|
{
|
||||||
log_error(b);
|
log_error(b);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +154,7 @@ namespace Imaging
|
||||||
img.Stride = pngWidth * (expandTo32 ? 4 : 1);
|
img.Stride = pngWidth * (expandTo32 ? 4 : 1);
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
catch (const std::exception &)
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||||
throw;
|
throw;
|
||||||
|
@ -232,7 +234,7 @@ namespace Imaging
|
||||||
auto pixels = image.Pixels.data();
|
auto pixels = image.Pixels.data();
|
||||||
for (uint32_t y = 0; y < image.Height; y++)
|
for (uint32_t y = 0; y < image.Height; y++)
|
||||||
{
|
{
|
||||||
png_write_row(png_ptr, (png_byte *)pixels);
|
png_write_row(png_ptr, (png_byte*)pixels);
|
||||||
pixels += image.Stride;
|
pixels += image.Stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,4 +350,4 @@ namespace Imaging
|
||||||
throw std::runtime_error(EXCEPTION_IMAGE_FORMAT_UNKNOWN);
|
throw std::runtime_error(EXCEPTION_IMAGE_FORMAT_UNKNOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace Imaging
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../drawing/Drawing.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../common.h"
|
|
||||||
#include "../drawing/Drawing.h"
|
|
||||||
|
|
||||||
struct rct_drawpixelinfo;
|
struct rct_drawpixelinfo;
|
||||||
struct rct_palette;
|
struct rct_palette;
|
||||||
|
@ -31,10 +32,10 @@ struct PaletteBGRA
|
||||||
enum class IMAGE_FORMAT
|
enum class IMAGE_FORMAT
|
||||||
{
|
{
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
AUTOMATIC, // Automatically detect from file extension
|
AUTOMATIC, // Automatically detect from file extension
|
||||||
BITMAP,
|
BITMAP,
|
||||||
PNG,
|
PNG,
|
||||||
PNG_32, // Force load to 32bpp buffer
|
PNG_32, // Force load to 32bpp buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Image
|
struct Image
|
||||||
|
@ -60,4 +61,4 @@ namespace Imaging
|
||||||
void WriteToFile(const std::string_view& path, const Image& image, IMAGE_FORMAT format = IMAGE_FORMAT::AUTOMATIC);
|
void WriteToFile(const std::string_view& path, const Image& image, IMAGE_FORMAT format = IMAGE_FORMAT::AUTOMATIC);
|
||||||
|
|
||||||
void SetReader(IMAGE_FORMAT format, ImageReaderFunc impl);
|
void SetReader(IMAGE_FORMAT format, ImageReaderFunc impl);
|
||||||
}
|
} // namespace Imaging
|
||||||
|
|
|
@ -27,8 +27,8 @@ private:
|
||||||
const std::function<void()> CompletionFn;
|
const std::function<void()> CompletionFn;
|
||||||
|
|
||||||
TaskData(std::function<void()> workFn, std::function<void()> completionFn)
|
TaskData(std::function<void()> workFn, std::function<void()> completionFn)
|
||||||
: WorkFn(workFn),
|
: WorkFn(workFn)
|
||||||
CompletionFn(completionFn)
|
, CompletionFn(completionFn)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -86,11 +86,7 @@ public:
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Wait for the queue to become empty or having completed tasks.
|
// Wait for the queue to become empty or having completed tasks.
|
||||||
_condComplete.wait(lock, [this]()
|
_condComplete.wait(lock, [this]() { return (_pending.empty() && _processing == 0) || !_completed.empty(); });
|
||||||
{
|
|
||||||
return (_pending.empty() && _processing == 0) ||
|
|
||||||
!_completed.empty();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Dispatch all completion callbacks if there are any.
|
// Dispatch all completion callbacks if there are any.
|
||||||
while (!_completed.empty())
|
while (!_completed.empty())
|
||||||
|
@ -118,9 +114,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// If everything is empty and no more work has to be done we can stop waiting.
|
// If everything is empty and no more work has to be done we can stop waiting.
|
||||||
if (_completed.empty() &&
|
if (_completed.empty() && _pending.empty() && _processing == 0)
|
||||||
_pending.empty() &&
|
|
||||||
_processing == 0)
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -139,11 +133,7 @@ private:
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Wait for work or cancelation.
|
// Wait for work or cancelation.
|
||||||
_condPending.wait(lock,
|
_condPending.wait(lock, [this]() { return _shouldStop || !_pending.empty(); });
|
||||||
[this]()
|
|
||||||
{
|
|
||||||
return _shouldStop || !_pending.empty();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!_pending.empty())
|
if (!_pending.empty())
|
||||||
{
|
{
|
||||||
|
@ -163,7 +153,6 @@ private:
|
||||||
_processing--;
|
_processing--;
|
||||||
_condComplete.notify_one();
|
_condComplete.notify_one();
|
||||||
}
|
}
|
||||||
}
|
} while (!_shouldStop);
|
||||||
while(!_shouldStop);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,16 +7,17 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "FileStream.hpp"
|
|
||||||
#include "Json.hpp"
|
#include "Json.hpp"
|
||||||
|
|
||||||
|
#include "FileStream.hpp"
|
||||||
#include "Memory.hpp"
|
#include "Memory.hpp"
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
|
|
||||||
namespace Json
|
namespace Json
|
||||||
{
|
{
|
||||||
json_t * ReadFromFile(const utf8 * path, size_t maxSize)
|
json_t* ReadFromFile(const utf8* path, size_t maxSize)
|
||||||
{
|
{
|
||||||
json_t * json = nullptr;
|
json_t* json = nullptr;
|
||||||
auto fs = FileStream(path, FILE_MODE_OPEN);
|
auto fs = FileStream(path, FILE_MODE_OPEN);
|
||||||
|
|
||||||
size_t fileLength = (size_t)fs.GetLength();
|
size_t fileLength = (size_t)fs.GetLength();
|
||||||
|
@ -25,7 +26,7 @@ namespace Json
|
||||||
throw IOException("Json file too large.");
|
throw IOException("Json file too large.");
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * fileData = Memory::Allocate<utf8>(fileLength + 1);
|
utf8* fileData = Memory::Allocate<utf8>(fileLength + 1);
|
||||||
fs.Read(fileData, fileLength);
|
fs.Read(fileData, fileLength);
|
||||||
fileData[fileLength] = '\0';
|
fileData[fileLength] = '\0';
|
||||||
|
|
||||||
|
@ -41,10 +42,10 @@ namespace Json
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteToFile(const utf8 * path, const json_t * json, size_t flags)
|
void WriteToFile(const utf8* path, const json_t* json, size_t flags)
|
||||||
{
|
{
|
||||||
// Serialise JSON
|
// Serialise JSON
|
||||||
const char * jsonOutput = json_dumps(json, flags);
|
const char* jsonOutput = json_dumps(json, flags);
|
||||||
|
|
||||||
// Write to file
|
// Write to file
|
||||||
auto fs = FileStream(path, FILE_MODE_WRITE);
|
auto fs = FileStream(path, FILE_MODE_WRITE);
|
||||||
|
@ -52,9 +53,9 @@ namespace Json
|
||||||
fs.Write(jsonOutput, jsonOutputSize);
|
fs.Write(jsonOutput, jsonOutputSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
json_t * FromString(const std::string & raw)
|
json_t* FromString(const std::string& raw)
|
||||||
{
|
{
|
||||||
json_t * root;
|
json_t* root;
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
root = json_loads(raw.c_str(), 0, &error);
|
root = json_loads(raw.c_str(), 0, &error);
|
||||||
if (root == nullptr)
|
if (root == nullptr)
|
||||||
|
|
|
@ -9,22 +9,22 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
#include <jansson.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <jansson.h>
|
|
||||||
|
|
||||||
#include "../common.h"
|
|
||||||
|
|
||||||
namespace Json
|
namespace Json
|
||||||
{
|
{
|
||||||
// Don't try to load JSON files that exceed 64 MiB
|
// Don't try to load JSON files that exceed 64 MiB
|
||||||
constexpr uint64_t MAX_JSON_SIZE = 64 * 1024 * 1024;
|
constexpr uint64_t MAX_JSON_SIZE = 64 * 1024 * 1024;
|
||||||
|
|
||||||
json_t * ReadFromFile(const utf8 * path, size_t maxSize = MAX_JSON_SIZE);
|
json_t* ReadFromFile(const utf8* path, size_t maxSize = MAX_JSON_SIZE);
|
||||||
void WriteToFile(const utf8 * path, const json_t * json, size_t flags = 0);
|
void WriteToFile(const utf8* path, const json_t* json, size_t flags = 0);
|
||||||
|
|
||||||
json_t * FromString(const std::string & raw);
|
json_t* FromString(const std::string& raw);
|
||||||
}
|
} // namespace Json
|
||||||
|
|
||||||
class JsonException final : public std::runtime_error
|
class JsonException final : public std::runtime_error
|
||||||
{
|
{
|
||||||
|
@ -32,9 +32,13 @@ private:
|
||||||
json_error_t _jsonError = {};
|
json_error_t _jsonError = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonException(const std::string &message) : std::runtime_error(message) { }
|
explicit JsonException(const std::string& message)
|
||||||
|
: std::runtime_error(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
explicit JsonException(const json_error_t * jsonError) : JsonException(std::string(jsonError->text))
|
explicit JsonException(const json_error_t* jsonError)
|
||||||
|
: JsonException(std::string(jsonError->text))
|
||||||
{
|
{
|
||||||
_jsonError = *jsonError;
|
_jsonError = *jsonError;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,17 @@
|
||||||
*/
|
*/
|
||||||
namespace Math
|
namespace Math
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T> static T Clamp(T low, T x, T high)
|
||||||
static T Clamp(T low, T x, T high)
|
|
||||||
{
|
{
|
||||||
return (std::min)((std::max)(low, x), high);
|
return (std::min)((std::max)(low, x), high);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static T Sign(T x)
|
||||||
static T Sign(T x)
|
|
||||||
{
|
{
|
||||||
if (x < 0) return -1;
|
if (x < 0)
|
||||||
if (x > 0) return 1;
|
return -1;
|
||||||
|
if (x > 0)
|
||||||
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace Math
|
} // namespace Math
|
||||||
|
|
|
@ -9,43 +9,40 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
#include "Guard.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include "../common.h"
|
|
||||||
#include "Guard.hpp"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for memory management. Typically helpers and wrappers around the C standard library.
|
* Utility methods for memory management. Typically helpers and wrappers around the C standard library.
|
||||||
*/
|
*/
|
||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T> static T* Allocate()
|
||||||
static T * Allocate()
|
|
||||||
{
|
{
|
||||||
T* result = (T*)malloc(sizeof(T));
|
T* result = (T*)malloc(sizeof(T));
|
||||||
Guard::ArgumentNotNull(result, "Failed to allocate %u bytes for %s", sizeof(T), typeid(T).name());
|
Guard::ArgumentNotNull(result, "Failed to allocate %u bytes for %s", sizeof(T), typeid(T).name());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static T* Allocate(size_t size)
|
||||||
static T * Allocate(size_t size)
|
|
||||||
{
|
{
|
||||||
T* result = (T*)malloc(size);
|
T* result = (T*)malloc(size);
|
||||||
Guard::ArgumentNotNull(result, "Failed to allocate %u bytes for %s", size, typeid(T).name());
|
Guard::ArgumentNotNull(result, "Failed to allocate %u bytes for %s", size, typeid(T).name());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static T* AllocateArray(size_t count)
|
||||||
static T * AllocateArray(size_t count)
|
|
||||||
{
|
{
|
||||||
T* result = (T*)malloc(count * sizeof(T));
|
T* result = (T*)malloc(count * sizeof(T));
|
||||||
Guard::ArgumentNotNull(result, "Failed to allocate array of %u * %s (%u bytes)", count, typeid(T).name(), sizeof(T));
|
Guard::ArgumentNotNull(result, "Failed to allocate array of %u * %s (%u bytes)", count, typeid(T).name(), sizeof(T));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static T* Reallocate(T* ptr, size_t size)
|
||||||
static T * Reallocate(T * ptr, size_t size)
|
|
||||||
{
|
{
|
||||||
T* result;
|
T* result;
|
||||||
if (ptr == nullptr)
|
if (ptr == nullptr)
|
||||||
|
@ -60,8 +57,7 @@ namespace Memory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static T* ReallocateArray(T* ptr, size_t count)
|
||||||
static T * ReallocateArray(T * ptr, size_t count)
|
|
||||||
{
|
{
|
||||||
T* result;
|
T* result;
|
||||||
if (ptr == nullptr)
|
if (ptr == nullptr)
|
||||||
|
@ -72,18 +68,17 @@ namespace Memory
|
||||||
{
|
{
|
||||||
result = (T*)realloc((void*)ptr, count * sizeof(T));
|
result = (T*)realloc((void*)ptr, count * sizeof(T));
|
||||||
}
|
}
|
||||||
Guard::ArgumentNotNull(result, "Failed to reallocate array at %x (%s) to have %u entries", ptr, typeid(T).name(), count);
|
Guard::ArgumentNotNull(
|
||||||
|
result, "Failed to reallocate array at %x (%s) to have %u entries", ptr, typeid(T).name(), count);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static void Free(T* ptr)
|
||||||
static void Free(T * ptr)
|
|
||||||
{
|
{
|
||||||
free((void*)ptr);
|
free((void*)ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static void FreeArray(T* ptr, size_t count)
|
||||||
static void FreeArray(T * ptr, size_t count)
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < count; i++)
|
for (size_t i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,13 +7,15 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstring>
|
|
||||||
#include "Math.hpp"
|
|
||||||
#include "Memory.hpp"
|
|
||||||
#include "MemoryStream.h"
|
#include "MemoryStream.h"
|
||||||
|
|
||||||
MemoryStream::MemoryStream(const MemoryStream ©)
|
#include "Math.hpp"
|
||||||
|
#include "Memory.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
MemoryStream::MemoryStream(const MemoryStream& copy)
|
||||||
{
|
{
|
||||||
_access = copy._access;
|
_access = copy._access;
|
||||||
_dataCapacity = copy._dataCapacity;
|
_dataCapacity = copy._dataCapacity;
|
||||||
|
@ -34,7 +36,7 @@ MemoryStream::MemoryStream(size_t capacity)
|
||||||
_position = _data;
|
_position = _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryStream::MemoryStream(void * data, size_t dataSize, uint8_t access)
|
MemoryStream::MemoryStream(void* data, size_t dataSize, uint8_t access)
|
||||||
{
|
{
|
||||||
_access = access;
|
_access = access;
|
||||||
_dataCapacity = dataSize;
|
_dataCapacity = dataSize;
|
||||||
|
@ -43,8 +45,8 @@ MemoryStream::MemoryStream(void * data, size_t dataSize, uint8_t access)
|
||||||
_position = _data;
|
_position = _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryStream::MemoryStream(const void * data, size_t dataSize)
|
MemoryStream::MemoryStream(const void* data, size_t dataSize)
|
||||||
: MemoryStream((void *)data, dataSize, MEMORY_ACCESS::READ)
|
: MemoryStream((void*)data, dataSize, MEMORY_ACCESS::READ)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,19 +61,19 @@ MemoryStream::~MemoryStream()
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const void * MemoryStream::GetData() const
|
const void* MemoryStream::GetData() const
|
||||||
{
|
{
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * MemoryStream::GetDataCopy() const
|
void* MemoryStream::GetDataCopy() const
|
||||||
{
|
{
|
||||||
auto result = Memory::Allocate<void>(_dataSize);
|
auto result = Memory::Allocate<void>(_dataSize);
|
||||||
std::memcpy(result, _data, _dataSize);
|
std::memcpy(result, _data, _dataSize);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * MemoryStream::TakeData()
|
void* MemoryStream::TakeData()
|
||||||
{
|
{
|
||||||
_access &= ~MEMORY_ACCESS::OWNER;
|
_access &= ~MEMORY_ACCESS::OWNER;
|
||||||
return _data;
|
return _data;
|
||||||
|
@ -105,17 +107,18 @@ void MemoryStream::SetPosition(uint64_t position)
|
||||||
void MemoryStream::Seek(int64_t offset, int32_t origin)
|
void MemoryStream::Seek(int64_t offset, int32_t origin)
|
||||||
{
|
{
|
||||||
uint64_t newPosition;
|
uint64_t newPosition;
|
||||||
switch (origin) {
|
switch (origin)
|
||||||
default:
|
{
|
||||||
case STREAM_SEEK_BEGIN:
|
default:
|
||||||
newPosition = offset;
|
case STREAM_SEEK_BEGIN:
|
||||||
break;
|
newPosition = offset;
|
||||||
case STREAM_SEEK_CURRENT:
|
break;
|
||||||
newPosition = GetPosition() + offset;
|
case STREAM_SEEK_CURRENT:
|
||||||
break;
|
newPosition = GetPosition() + offset;
|
||||||
case STREAM_SEEK_END:
|
break;
|
||||||
newPosition = _dataSize + offset;
|
case STREAM_SEEK_END:
|
||||||
break;
|
newPosition = _dataSize + offset;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPosition > _dataSize)
|
if (newPosition > _dataSize)
|
||||||
|
@ -125,7 +128,7 @@ void MemoryStream::Seek(int64_t offset, int32_t origin)
|
||||||
_position = (void*)((uintptr_t)_data + (uintptr_t)newPosition);
|
_position = (void*)((uintptr_t)_data + (uintptr_t)newPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryStream::Read(void * buffer, uint64_t length)
|
void MemoryStream::Read(void* buffer, uint64_t length)
|
||||||
{
|
{
|
||||||
uint64_t position = GetPosition();
|
uint64_t position = GetPosition();
|
||||||
if (position + length > _dataSize)
|
if (position + length > _dataSize)
|
||||||
|
@ -133,11 +136,11 @@ void MemoryStream::Read(void * buffer, uint64_t length)
|
||||||
throw IOException("Attempted to read past end of stream.");
|
throw IOException("Attempted to read past end of stream.");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::copy_n((const uint8_t *)_position, length, (uint8_t *)buffer);
|
std::copy_n((const uint8_t*)_position, length, (uint8_t*)buffer);
|
||||||
_position = (void*)((uintptr_t)_position + length);
|
_position = (void*)((uintptr_t)_position + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t MemoryStream::TryRead(void * buffer, uint64_t length)
|
uint64_t MemoryStream::TryRead(void* buffer, uint64_t length)
|
||||||
{
|
{
|
||||||
uint64_t remainingBytes = GetLength() - GetPosition();
|
uint64_t remainingBytes = GetLength() - GetPosition();
|
||||||
uint64_t bytesToRead = std::min(length, remainingBytes);
|
uint64_t bytesToRead = std::min(length, remainingBytes);
|
||||||
|
@ -145,7 +148,7 @@ uint64_t MemoryStream::TryRead(void * buffer, uint64_t length)
|
||||||
return bytesToRead;
|
return bytesToRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryStream::Write(const void * buffer, uint64_t length)
|
void MemoryStream::Write(const void* buffer, uint64_t length)
|
||||||
{
|
{
|
||||||
uint64_t position = GetPosition();
|
uint64_t position = GetPosition();
|
||||||
uint64_t nextPosition = position + length;
|
uint64_t nextPosition = position + length;
|
||||||
|
@ -161,7 +164,7 @@ void MemoryStream::Write(const void * buffer, uint64_t length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::copy_n((const uint8_t *)buffer, length, (uint8_t *)_position);
|
std::copy_n((const uint8_t*)buffer, length, (uint8_t*)_position);
|
||||||
_position = (void*)((uintptr_t)_position + length);
|
_position = (void*)((uintptr_t)_position + length);
|
||||||
_dataSize = std::max<size_t>(_dataSize, (size_t)nextPosition);
|
_dataSize = std::max<size_t>(_dataSize, (size_t)nextPosition);
|
||||||
}
|
}
|
||||||
|
@ -179,6 +182,6 @@ void MemoryStream::EnsureCapacity(size_t capacity)
|
||||||
uint64_t position = GetPosition();
|
uint64_t position = GetPosition();
|
||||||
_dataCapacity = newCapacity;
|
_dataCapacity = newCapacity;
|
||||||
_data = Memory::Reallocate(_data, _dataCapacity);
|
_data = Memory::Reallocate(_data, _dataCapacity);
|
||||||
_position = (void *)((uintptr_t)_data + (uintptr_t)position);
|
_position = (void*)((uintptr_t)_data + (uintptr_t)position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
|
|
||||||
namespace MEMORY_ACCESS
|
namespace MEMORY_ACCESS
|
||||||
{
|
{
|
||||||
constexpr uint8_t READ = 1 << 0;
|
constexpr uint8_t READ = 1 << 0;
|
||||||
constexpr uint8_t WRITE = 1 << 1;
|
constexpr uint8_t WRITE = 1 << 1;
|
||||||
constexpr uint8_t OWNER = 1 << 2;
|
constexpr uint8_t OWNER = 1 << 2;
|
||||||
};
|
}; // namespace MEMORY_ACCESS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A stream for reading and writing to a buffer in memory. By default this buffer can grow.
|
* A stream for reading and writing to a buffer in memory. By default this buffer can grow.
|
||||||
|
@ -25,39 +25,39 @@ namespace MEMORY_ACCESS
|
||||||
class MemoryStream final : public IStream
|
class MemoryStream final : public IStream
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
uint8_t _access = MEMORY_ACCESS::READ | MEMORY_ACCESS::WRITE | MEMORY_ACCESS::OWNER;
|
uint8_t _access = MEMORY_ACCESS::READ | MEMORY_ACCESS::WRITE | MEMORY_ACCESS::OWNER;
|
||||||
size_t _dataCapacity = 0;
|
size_t _dataCapacity = 0;
|
||||||
size_t _dataSize = 0;
|
size_t _dataSize = 0;
|
||||||
void * _data = nullptr;
|
void* _data = nullptr;
|
||||||
void * _position = nullptr;
|
void* _position = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryStream() = default;
|
MemoryStream() = default;
|
||||||
MemoryStream(const MemoryStream & copy);
|
MemoryStream(const MemoryStream& copy);
|
||||||
explicit MemoryStream(size_t capacity);
|
explicit MemoryStream(size_t capacity);
|
||||||
MemoryStream(void * data, size_t dataSize, uint8_t access = MEMORY_ACCESS::READ);
|
MemoryStream(void* data, size_t dataSize, uint8_t access = MEMORY_ACCESS::READ);
|
||||||
MemoryStream(const void * data, size_t dataSize);
|
MemoryStream(const void* data, size_t dataSize);
|
||||||
virtual ~MemoryStream();
|
virtual ~MemoryStream();
|
||||||
|
|
||||||
const void * GetData() const;
|
const void* GetData() const;
|
||||||
void * GetDataCopy() const;
|
void* GetDataCopy() const;
|
||||||
void * TakeData();
|
void* TakeData();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// ISteam methods
|
// ISteam methods
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
bool CanRead() const override;
|
bool CanRead() const override;
|
||||||
bool CanWrite() const override;
|
bool CanWrite() const override;
|
||||||
|
|
||||||
uint64_t GetLength() const override;
|
uint64_t GetLength() const override;
|
||||||
uint64_t GetPosition() const override;
|
uint64_t GetPosition() const override;
|
||||||
void SetPosition(uint64_t position) override;
|
void SetPosition(uint64_t position) override;
|
||||||
void Seek(int64_t offset, int32_t origin) override;
|
void Seek(int64_t offset, int32_t origin) override;
|
||||||
|
|
||||||
void Read(void * buffer, uint64_t length) override;
|
void Read(void* buffer, uint64_t length) override;
|
||||||
void Write(const void * buffer, uint64_t length) override;
|
void Write(const void* buffer, uint64_t length) override;
|
||||||
|
|
||||||
uint64_t TryRead(void * buffer, uint64_t length) override;
|
uint64_t TryRead(void* buffer, uint64_t length) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EnsureCapacity(size_t capacity);
|
void EnsureCapacity(size_t capacity);
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> struct Nullable
|
||||||
struct Nullable
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nullable()
|
Nullable()
|
||||||
|
@ -28,7 +28,7 @@ public:
|
||||||
_hasValue = false;
|
_hasValue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable(const T &value)
|
Nullable(const T& value)
|
||||||
{
|
{
|
||||||
_value = value;
|
_value = value;
|
||||||
_hasValue = true;
|
_hasValue = true;
|
||||||
|
@ -50,6 +50,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T _value;
|
T _value;
|
||||||
bool _hasValue;
|
bool _hasValue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,28 +9,27 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../localisation/Language.h"
|
||||||
#include "../platform/platform.h"
|
#include "../platform/platform.h"
|
||||||
#include "../util/Util.h"
|
#include "../util/Util.h"
|
||||||
#include "../localisation/Language.h"
|
|
||||||
|
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
#include "Math.hpp"
|
#include "Math.hpp"
|
||||||
#include "Memory.hpp"
|
#include "Memory.hpp"
|
||||||
#include "Path.hpp"
|
#include "Path.hpp"
|
||||||
#include "Util.hpp"
|
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
|
#include "Util.hpp"
|
||||||
|
|
||||||
namespace Path
|
namespace Path
|
||||||
{
|
{
|
||||||
utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src)
|
utf8* Append(utf8* buffer, size_t bufferSize, const utf8* src)
|
||||||
{
|
{
|
||||||
return safe_strcat_path(buffer, src, bufferSize);
|
return safe_strcat_path(buffer, src, bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Combine(const std::string &a, const std::string &b)
|
std::string Combine(const std::string& a, const std::string& b)
|
||||||
{
|
{
|
||||||
utf8 buffer[MAX_PATH];
|
utf8 buffer[MAX_PATH];
|
||||||
String::Set(buffer, sizeof(buffer), a.c_str());
|
String::Set(buffer, sizeof(buffer), a.c_str());
|
||||||
|
@ -38,7 +37,7 @@ namespace Path
|
||||||
return std::string(buffer);
|
return std::string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDirectory(const std::string &path)
|
std::string GetDirectory(const std::string& path)
|
||||||
{
|
{
|
||||||
const utf8* directory = GetDirectory(path.c_str());
|
const utf8* directory = GetDirectory(path.c_str());
|
||||||
std::string result(directory);
|
std::string result(directory);
|
||||||
|
@ -46,22 +45,19 @@ namespace Path
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * GetDirectory(const utf8 * path)
|
utf8* GetDirectory(const utf8* path)
|
||||||
{
|
{
|
||||||
size_t maxSize = String::SizeOf(path) + 1;
|
size_t maxSize = String::SizeOf(path) + 1;
|
||||||
utf8 * result = Memory::Allocate<utf8>(maxSize);
|
utf8* result = Memory::Allocate<utf8>(maxSize);
|
||||||
GetDirectory(result, maxSize, path);
|
GetDirectory(result, maxSize, path);
|
||||||
size_t reducedSize = String::SizeOf(path) + 1;
|
size_t reducedSize = String::SizeOf(path) + 1;
|
||||||
result = Memory::Reallocate(result, reducedSize);
|
result = Memory::Reallocate(result, reducedSize);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path)
|
utf8* GetDirectory(utf8* buffer, size_t bufferSize, const utf8* path)
|
||||||
{
|
{
|
||||||
auto lastPathSepIndex = std::max(
|
auto lastPathSepIndex = std::max(String::LastIndexOf(path, *PATH_SEPARATOR), String::LastIndexOf(path, '/'));
|
||||||
String::LastIndexOf(path, *PATH_SEPARATOR),
|
|
||||||
String::LastIndexOf(path, '/')
|
|
||||||
);
|
|
||||||
if (lastPathSepIndex < 0)
|
if (lastPathSepIndex < 0)
|
||||||
{
|
{
|
||||||
return String::Set(buffer, bufferSize, String::Empty);
|
return String::Set(buffer, bufferSize, String::Empty);
|
||||||
|
@ -73,25 +69,25 @@ namespace Path
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateDirectory(const std::string &path)
|
void CreateDirectory(const std::string& path)
|
||||||
{
|
{
|
||||||
platform_ensure_directory_exists(path.c_str());
|
platform_ensure_directory_exists(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DirectoryExists(const std::string &path)
|
bool DirectoryExists(const std::string& path)
|
||||||
{
|
{
|
||||||
return platform_directory_exists(path.c_str());
|
return platform_directory_exists(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetFileName(const std::string &path)
|
std::string GetFileName(const std::string& path)
|
||||||
{
|
{
|
||||||
return GetFileName(path.c_str());
|
return GetFileName(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
const utf8 * GetFileName(const utf8 * path)
|
const utf8* GetFileName(const utf8* path)
|
||||||
{
|
{
|
||||||
const utf8 * lastPathSeparator = nullptr;
|
const utf8* lastPathSeparator = nullptr;
|
||||||
for (const utf8 * ch = path; *ch != '\0'; ch++)
|
for (const utf8* ch = path; *ch != '\0'; ch++)
|
||||||
{
|
{
|
||||||
if (*ch == *PATH_SEPARATOR || *ch == '/')
|
if (*ch == *PATH_SEPARATOR || *ch == '/')
|
||||||
{
|
{
|
||||||
|
@ -99,35 +95,33 @@ namespace Path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastPathSeparator == nullptr ?
|
return lastPathSeparator == nullptr ? path : lastPathSeparator + 1;
|
||||||
path :
|
|
||||||
lastPathSeparator + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetFileNameWithoutExtension(const std::string &path)
|
std::string GetFileNameWithoutExtension(const std::string& path)
|
||||||
{
|
{
|
||||||
utf8 * cstr = GetFileNameWithoutExtension(path.c_str());
|
utf8* cstr = GetFileNameWithoutExtension(path.c_str());
|
||||||
std::string result = String::ToStd(cstr);
|
std::string result = String::ToStd(cstr);
|
||||||
Memory::Free(cstr);
|
Memory::Free(cstr);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * GetFileNameWithoutExtension(const utf8 * path)
|
utf8* GetFileNameWithoutExtension(const utf8* path)
|
||||||
{
|
{
|
||||||
size_t maxSize = String::SizeOf(path) + 1;
|
size_t maxSize = String::SizeOf(path) + 1;
|
||||||
utf8 * result = Memory::Allocate<utf8>(maxSize);
|
utf8* result = Memory::Allocate<utf8>(maxSize);
|
||||||
GetFileNameWithoutExtension(result, maxSize, path);
|
GetFileNameWithoutExtension(result, maxSize, path);
|
||||||
size_t reducedSize = String::SizeOf(path) + 1;
|
size_t reducedSize = String::SizeOf(path) + 1;
|
||||||
result = Memory::Reallocate(result, reducedSize);
|
result = Memory::Reallocate(result, reducedSize);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path)
|
utf8* GetFileNameWithoutExtension(utf8* buffer, size_t bufferSize, const utf8* path)
|
||||||
{
|
{
|
||||||
path = GetFileName(path);
|
path = GetFileName(path);
|
||||||
|
|
||||||
const utf8 * lastDot = nullptr;
|
const utf8* lastDot = nullptr;
|
||||||
const utf8 * ch = path;
|
const utf8* ch = path;
|
||||||
for (; *ch != '\0'; ch++)
|
for (; *ch != '\0'; ch++)
|
||||||
{
|
{
|
||||||
if (*ch == '.')
|
if (*ch == '.')
|
||||||
|
@ -147,15 +141,15 @@ namespace Path
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string GetExtension(const std::string &path)
|
const std::string GetExtension(const std::string& path)
|
||||||
{
|
{
|
||||||
return GetExtension(path.c_str());
|
return GetExtension(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
const utf8 * GetExtension(const utf8 * path)
|
const utf8* GetExtension(const utf8* path)
|
||||||
{
|
{
|
||||||
const utf8 * lastDot = nullptr;
|
const utf8* lastDot = nullptr;
|
||||||
const utf8 * ch = GetFileName(path);
|
const utf8* ch = GetFileName(path);
|
||||||
for (; *ch != '\0'; ch++)
|
for (; *ch != '\0'; ch++)
|
||||||
{
|
{
|
||||||
if (*ch == '.')
|
if (*ch == '.')
|
||||||
|
@ -174,11 +168,11 @@ namespace Path
|
||||||
return lastDot;
|
return lastDot;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * GetAbsolute(utf8 *buffer, size_t bufferSize, const utf8 * relativePath)
|
utf8* GetAbsolute(utf8* buffer, size_t bufferSize, const utf8* relativePath)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
wchar_t * relativePathW = utf8_to_widechar(relativePath);
|
wchar_t* relativePathW = utf8_to_widechar(relativePath);
|
||||||
wchar_t absolutePathW[MAX_PATH];
|
wchar_t absolutePathW[MAX_PATH];
|
||||||
DWORD length = GetFullPathNameW(relativePathW, (DWORD)Util::CountOf(absolutePathW), absolutePathW, nullptr);
|
DWORD length = GetFullPathNameW(relativePathW, (DWORD)Util::CountOf(absolutePathW), absolutePathW, nullptr);
|
||||||
Memory::Free(relativePathW);
|
Memory::Free(relativePathW);
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
|
@ -187,13 +181,13 @@ namespace Path
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
utf8 * absolutePath = widechar_to_utf8(absolutePathW);
|
utf8* absolutePath = widechar_to_utf8(absolutePathW);
|
||||||
String::Set(buffer, bufferSize, absolutePath);
|
String::Set(buffer, bufferSize, absolutePath);
|
||||||
Memory::Free(absolutePath);
|
Memory::Free(absolutePath);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
utf8 * absolutePath = realpath(relativePath, nullptr);
|
utf8* absolutePath = realpath(relativePath, nullptr);
|
||||||
if (absolutePath == nullptr)
|
if (absolutePath == nullptr)
|
||||||
{
|
{
|
||||||
return String::Set(buffer, bufferSize, relativePath);
|
return String::Set(buffer, bufferSize, relativePath);
|
||||||
|
@ -207,18 +201,18 @@ namespace Path
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetAbsolute(const std::string &relative)
|
std::string GetAbsolute(const std::string& relative)
|
||||||
{
|
{
|
||||||
utf8 absolute[MAX_PATH];
|
utf8 absolute[MAX_PATH];
|
||||||
return GetAbsolute(absolute, sizeof(absolute), relative.c_str());
|
return GetAbsolute(absolute, sizeof(absolute), relative.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Equals(const std::string &a, const std::string &b)
|
bool Equals(const std::string& a, const std::string& b)
|
||||||
{
|
{
|
||||||
return String::Equals(a.c_str(), b.c_str());
|
return String::Equals(a.c_str(), b.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Equals(const utf8 * a, const utf8 * b)
|
bool Equals(const utf8* a, const utf8* b)
|
||||||
{
|
{
|
||||||
bool ignoreCase = false;
|
bool ignoreCase = false;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -227,7 +221,7 @@ namespace Path
|
||||||
return String::Equals(a, b, ignoreCase);
|
return String::Equals(a, b, ignoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ResolveCasing(const std::string &path)
|
std::string ResolveCasing(const std::string& path)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
if (File::Exists(path))
|
if (File::Exists(path))
|
||||||
|
@ -242,7 +236,7 @@ namespace Path
|
||||||
std::string fileName = Path::GetFileName(path);
|
std::string fileName = Path::GetFileName(path);
|
||||||
std::string directory = Path::GetDirectory(path);
|
std::string directory = Path::GetDirectory(path);
|
||||||
|
|
||||||
struct dirent * * files;
|
struct dirent** files;
|
||||||
auto count = scandir(directory.c_str(), &files, nullptr, alphasort);
|
auto count = scandir(directory.c_str(), &files, nullptr, alphasort);
|
||||||
if (count != -1)
|
if (count != -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,36 +9,36 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace Path
|
namespace Path
|
||||||
{
|
{
|
||||||
utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src);
|
utf8* Append(utf8* buffer, size_t bufferSize, const utf8* src);
|
||||||
std::string Combine(const std::string &a, const std::string &b);
|
std::string Combine(const std::string& a, const std::string& b);
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args> static std::string Combine(const std::string& a, const std::string& b, Args... args)
|
||||||
static std::string Combine(const std::string &a, const std::string &b, Args... args)
|
|
||||||
{
|
{
|
||||||
return Combine(a, Combine(b, args...));
|
return Combine(a, Combine(b, args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDirectory(const std::string &path);
|
std::string GetDirectory(const std::string& path);
|
||||||
utf8 * GetDirectory(const utf8 * path);
|
utf8* GetDirectory(const utf8* path);
|
||||||
utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path);
|
utf8* GetDirectory(utf8* buffer, size_t bufferSize, const utf8* path);
|
||||||
void CreateDirectory(const std::string &path);
|
void CreateDirectory(const std::string& path);
|
||||||
bool DirectoryExists(const std::string &path);
|
bool DirectoryExists(const std::string& path);
|
||||||
std::string GetFileName(const std::string &path);
|
std::string GetFileName(const std::string& path);
|
||||||
const utf8 * GetFileName(const utf8 * path);
|
const utf8* GetFileName(const utf8* path);
|
||||||
std::string GetFileNameWithoutExtension(const std::string &path);
|
std::string GetFileNameWithoutExtension(const std::string& path);
|
||||||
utf8 * GetFileNameWithoutExtension(const utf8 * path);
|
utf8* GetFileNameWithoutExtension(const utf8* path);
|
||||||
utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path);
|
utf8* GetFileNameWithoutExtension(utf8* buffer, size_t bufferSize, const utf8* path);
|
||||||
const std::string GetExtension(const std::string &path);
|
const std::string GetExtension(const std::string& path);
|
||||||
const utf8 * GetExtension(const utf8 * path);
|
const utf8* GetExtension(const utf8* path);
|
||||||
utf8 * GetAbsolute(utf8 * buffer, size_t bufferSize, const utf8 * relativePath);
|
utf8* GetAbsolute(utf8* buffer, size_t bufferSize, const utf8* relativePath);
|
||||||
std::string GetAbsolute(const std::string &relative);
|
std::string GetAbsolute(const std::string& relative);
|
||||||
bool Equals(const std::string &a, const std::string &b);
|
bool Equals(const std::string& a, const std::string& b);
|
||||||
bool Equals(const utf8 * a, const utf8 * b);
|
bool Equals(const utf8* a, const utf8* b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given path is a file. If not, checks to see if
|
* Checks if the given path is a file. If not, checks to see if
|
||||||
|
@ -46,5 +46,5 @@ namespace Path
|
||||||
* one found based on a straight forward character sort.
|
* one found based on a straight forward character sort.
|
||||||
* Note: This will not resolve the case for Windows.
|
* Note: This will not resolve the case for Windows.
|
||||||
*/
|
*/
|
||||||
std::string ResolveCasing(const std::string &path);
|
std::string ResolveCasing(const std::string& path);
|
||||||
} // namespace Path
|
} // namespace Path
|
||||||
|
|
|
@ -28,15 +28,14 @@ namespace OpenRCT2
|
||||||
/**
|
/**
|
||||||
* Class which can wrap a function in an IRegistration.
|
* Class which can wrap a function in an IRegistration.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T> struct CallbackRegistration : public IRegistration
|
||||||
struct CallbackRegistration : public IRegistration
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
T _callback;
|
T _callback;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CallbackRegistration(T callback) :
|
CallbackRegistration(T callback)
|
||||||
_callback(callback)
|
: _callback(callback)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,10 +50,9 @@ namespace OpenRCT2
|
||||||
* Creates a new IRegistration which when deleted, calls the given
|
* Creates a new IRegistration which when deleted, calls the given
|
||||||
* function.
|
* function.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T> static IRegistration* Create(T unregisterCallback)
|
||||||
static IRegistration * Create(T unregisterCallback)
|
|
||||||
{
|
{
|
||||||
return new CallbackRegistration<T>(unregisterCallback);
|
return new CallbackRegistration<T>(unregisterCallback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace OpenRCT2
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "../localisation/ConversionTables.h"
|
#include "../localisation/ConversionTables.h"
|
||||||
#include "../localisation/Language.h"
|
#include "../localisation/Language.h"
|
||||||
#include "../util/Util.h"
|
#include "../util/Util.h"
|
||||||
|
|
||||||
#include "Math.hpp"
|
#include "Math.hpp"
|
||||||
#include "Memory.hpp"
|
#include "Memory.hpp"
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
|
@ -42,13 +41,15 @@
|
||||||
|
|
||||||
namespace String
|
namespace String
|
||||||
{
|
{
|
||||||
std::string ToStd(const utf8 * str)
|
std::string ToStd(const utf8* str)
|
||||||
{
|
{
|
||||||
if (str == nullptr) return std::string();
|
if (str == nullptr)
|
||||||
else return std::string(str);
|
return std::string();
|
||||||
|
else
|
||||||
|
return std::string(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StdFormat_VA(const utf8 * format, va_list args)
|
std::string StdFormat_VA(const utf8* format, va_list args)
|
||||||
{
|
{
|
||||||
auto buffer = Format_VA(format, args);
|
auto buffer = Format_VA(format, args);
|
||||||
auto returnValue = ToStd(buffer);
|
auto returnValue = ToStd(buffer);
|
||||||
|
@ -56,11 +57,11 @@ namespace String
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StdFormat(const utf8 * format, ...)
|
std::string StdFormat(const utf8* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
const utf8 * buffer = Format_VA(format, args);
|
const utf8* buffer = Format_VA(format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
std::string returnValue = ToStd(buffer);
|
std::string returnValue = ToStd(buffer);
|
||||||
Memory::Free(buffer);
|
Memory::Free(buffer);
|
||||||
|
@ -79,11 +80,11 @@ namespace String
|
||||||
// Which constructor to use depends on the size of wchar_t...
|
// Which constructor to use depends on the size of wchar_t...
|
||||||
// UTF-32 is the default on most POSIX systems; Windows uses UTF-16.
|
// UTF-32 is the default on most POSIX systems; Windows uses UTF-16.
|
||||||
// Unfortunately, we'll have to help the compiler here.
|
// Unfortunately, we'll have to help the compiler here.
|
||||||
#if U_SIZEOF_WCHAR_T==4
|
#if U_SIZEOF_WCHAR_T == 4
|
||||||
icu::UnicodeString str = icu::UnicodeString::fromUTF32((const UChar32*) src.data(), src.length());
|
icu::UnicodeString str = icu::UnicodeString::fromUTF32((const UChar32*)src.data(), src.length());
|
||||||
#elif U_SIZEOF_WCHAR_T==2
|
#elif U_SIZEOF_WCHAR_T == 2
|
||||||
std::wstring wstr = std::wstring(src);
|
std::wstring wstr = std::wstring(src);
|
||||||
icu::UnicodeString str = icu::UnicodeString((const wchar_t*) wstr.c_str());
|
icu::UnicodeString str = icu::UnicodeString((const wchar_t*)wstr.c_str());
|
||||||
#else
|
#else
|
||||||
#error Unsupported U_SIZEOF_WCHAR_T size
|
#error Unsupported U_SIZEOF_WCHAR_T size
|
||||||
#endif
|
#endif
|
||||||
|
@ -109,16 +110,16 @@ namespace String
|
||||||
// Which constructor to use depends on the size of wchar_t...
|
// Which constructor to use depends on the size of wchar_t...
|
||||||
// UTF-32 is the default on most POSIX systems; Windows uses UTF-16.
|
// UTF-32 is the default on most POSIX systems; Windows uses UTF-16.
|
||||||
// Unfortunately, we'll have to help the compiler here.
|
// Unfortunately, we'll have to help the compiler here.
|
||||||
#if U_SIZEOF_WCHAR_T==4
|
#if U_SIZEOF_WCHAR_T == 4
|
||||||
size_t length = (size_t) str.length();
|
size_t length = (size_t)str.length();
|
||||||
std::wstring result(length, '\0');
|
std::wstring result(length, '\0');
|
||||||
|
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
str.toUTF32((UChar32*) &result[0], str.length(), status);
|
str.toUTF32((UChar32*)&result[0], str.length(), status);
|
||||||
|
|
||||||
#elif U_SIZEOF_WCHAR_T==2
|
#elif U_SIZEOF_WCHAR_T == 2
|
||||||
const char16_t* buffer = str.getBuffer();
|
const char16_t* buffer = str.getBuffer();
|
||||||
std::wstring result = (wchar_t*) buffer;
|
std::wstring result = (wchar_t*)buffer;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error Unsupported U_SIZEOF_WCHAR_T size
|
#error Unsupported U_SIZEOF_WCHAR_T size
|
||||||
|
@ -128,21 +129,24 @@ namespace String
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsNullOrEmpty(const utf8 * str)
|
bool IsNullOrEmpty(const utf8* str)
|
||||||
{
|
{
|
||||||
return str == nullptr || str[0] == '\0';
|
return str == nullptr || str[0] == '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Compare(const std::string &a, const std::string &b, bool ignoreCase)
|
int32_t Compare(const std::string& a, const std::string& b, bool ignoreCase)
|
||||||
{
|
{
|
||||||
return Compare(a.c_str(), b.c_str(), ignoreCase);
|
return Compare(a.c_str(), b.c_str(), ignoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Compare(const utf8 * a, const utf8 * b, bool ignoreCase)
|
int32_t Compare(const utf8* a, const utf8* b, bool ignoreCase)
|
||||||
{
|
{
|
||||||
if (a == b) return 0;
|
if (a == b)
|
||||||
if (a == nullptr) a = "";
|
return 0;
|
||||||
if (b == nullptr) b = "";
|
if (a == nullptr)
|
||||||
|
a = "";
|
||||||
|
if (b == nullptr)
|
||||||
|
b = "";
|
||||||
if (ignoreCase)
|
if (ignoreCase)
|
||||||
{
|
{
|
||||||
return _stricmp(a, b);
|
return _stricmp(a, b);
|
||||||
|
@ -153,15 +157,17 @@ namespace String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Equals(const std::string &a, const std::string &b, bool ignoreCase)
|
bool Equals(const std::string& a, const std::string& b, bool ignoreCase)
|
||||||
{
|
{
|
||||||
return Equals(a.c_str(), b.c_str(), ignoreCase);
|
return Equals(a.c_str(), b.c_str(), ignoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase)
|
bool Equals(const utf8* a, const utf8* b, bool ignoreCase)
|
||||||
{
|
{
|
||||||
if (a == b) return true;
|
if (a == b)
|
||||||
if (a == nullptr || b == nullptr) return false;
|
return true;
|
||||||
|
if (a == nullptr || b == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (ignoreCase)
|
if (ignoreCase)
|
||||||
{
|
{
|
||||||
|
@ -173,7 +179,7 @@ namespace String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartsWith(const utf8 * str, const utf8 * match, bool ignoreCase)
|
bool StartsWith(const utf8* str, const utf8* match, bool ignoreCase)
|
||||||
{
|
{
|
||||||
if (ignoreCase)
|
if (ignoreCase)
|
||||||
{
|
{
|
||||||
|
@ -199,7 +205,7 @@ namespace String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartsWith(const std::string &str, const std::string &match, bool ignoreCase)
|
bool StartsWith(const std::string& str, const std::string& match, bool ignoreCase)
|
||||||
{
|
{
|
||||||
return StartsWith(str.c_str(), match.c_str(), ignoreCase);
|
return StartsWith(str.c_str(), match.c_str(), ignoreCase);
|
||||||
}
|
}
|
||||||
|
@ -214,9 +220,9 @@ namespace String
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t IndexOf(const utf8 * str, utf8 match, size_t startIndex)
|
size_t IndexOf(const utf8* str, utf8 match, size_t startIndex)
|
||||||
{
|
{
|
||||||
const utf8 * ch = str + startIndex;
|
const utf8* ch = str + startIndex;
|
||||||
for (; *ch != '\0'; ch++)
|
for (; *ch != '\0'; ch++)
|
||||||
{
|
{
|
||||||
if (*ch == match)
|
if (*ch == match)
|
||||||
|
@ -227,10 +233,10 @@ namespace String
|
||||||
return SIZE_MAX;
|
return SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrdiff_t LastIndexOf(const utf8 * str, utf8 match)
|
ptrdiff_t LastIndexOf(const utf8* str, utf8 match)
|
||||||
{
|
{
|
||||||
const utf8 * lastOccurance = nullptr;
|
const utf8* lastOccurance = nullptr;
|
||||||
const utf8 * ch = str;
|
const utf8* ch = str;
|
||||||
for (; *ch != '\0'; ch++)
|
for (; *ch != '\0'; ch++)
|
||||||
{
|
{
|
||||||
if (*ch == match)
|
if (*ch == match)
|
||||||
|
@ -249,41 +255,42 @@ namespace String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t LengthOf(const utf8 * str)
|
size_t LengthOf(const utf8* str)
|
||||||
{
|
{
|
||||||
return utf8_length(str);
|
return utf8_length(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SizeOf(const utf8 * str)
|
size_t SizeOf(const utf8* str)
|
||||||
{
|
{
|
||||||
return strlen(str);
|
return strlen(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src)
|
utf8* Set(utf8* buffer, size_t bufferSize, const utf8* src)
|
||||||
{
|
{
|
||||||
return safe_strcpy(buffer, src, bufferSize);
|
return safe_strcpy(buffer, src, bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src, size_t srcSize)
|
utf8* Set(utf8* buffer, size_t bufferSize, const utf8* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
utf8 * dst = buffer;
|
utf8* dst = buffer;
|
||||||
size_t minSize = std::min(bufferSize - 1, srcSize);
|
size_t minSize = std::min(bufferSize - 1, srcSize);
|
||||||
for (size_t i = 0; i < minSize; i++)
|
for (size_t i = 0; i < minSize; i++)
|
||||||
{
|
{
|
||||||
*dst++ = *src;
|
*dst++ = *src;
|
||||||
if (*src == '\0') break;
|
if (*src == '\0')
|
||||||
|
break;
|
||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src)
|
utf8* Append(utf8* buffer, size_t bufferSize, const utf8* src)
|
||||||
{
|
{
|
||||||
return safe_strcat(buffer, src, bufferSize);
|
return safe_strcat(buffer, src, bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Format(utf8 * buffer, size_t bufferSize, const utf8 * format, ...)
|
utf8* Format(utf8* buffer, size_t bufferSize, const utf8* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
|
@ -297,16 +304,16 @@ namespace String
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Format(const utf8 * format, ...)
|
utf8* Format(const utf8* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
utf8 * result = Format_VA(format, args);
|
utf8* result = Format_VA(format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Format_VA(const utf8 * format, va_list args)
|
utf8* Format_VA(const utf8* format, va_list args)
|
||||||
{
|
{
|
||||||
va_list args1, args2;
|
va_list args1, args2;
|
||||||
va_copy(args1, args);
|
va_copy(args1, args);
|
||||||
|
@ -314,7 +321,7 @@ namespace String
|
||||||
|
|
||||||
// Try to format to a initial buffer, enlarge if not big enough
|
// Try to format to a initial buffer, enlarge if not big enough
|
||||||
size_t bufferSize = 4096;
|
size_t bufferSize = 4096;
|
||||||
utf8 * buffer = Memory::Allocate<utf8>(bufferSize);
|
utf8* buffer = Memory::Allocate<utf8>(bufferSize);
|
||||||
|
|
||||||
// Start with initial buffer
|
// Start with initial buffer
|
||||||
int32_t len = vsnprintf(buffer, bufferSize, format, args);
|
int32_t len = vsnprintf(buffer, bufferSize, format, args);
|
||||||
|
@ -359,13 +366,14 @@ namespace String
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * AppendFormat(utf8 * buffer, size_t bufferSize, const utf8 * format, ...)
|
utf8* AppendFormat(utf8* buffer, size_t bufferSize, const utf8* format, ...)
|
||||||
{
|
{
|
||||||
utf8 * dst = buffer;
|
utf8* dst = buffer;
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < bufferSize; i++)
|
for (i = 0; i < bufferSize; i++)
|
||||||
{
|
{
|
||||||
if (*dst == '\0') break;
|
if (*dst == '\0')
|
||||||
|
break;
|
||||||
dst++;
|
dst++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,14 +391,14 @@ namespace String
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Duplicate(const std::string &src)
|
utf8* Duplicate(const std::string& src)
|
||||||
{
|
{
|
||||||
return String::Duplicate(src.c_str());
|
return String::Duplicate(src.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Duplicate(const utf8 * src)
|
utf8* Duplicate(const utf8* src)
|
||||||
{
|
{
|
||||||
utf8 * result = nullptr;
|
utf8* result = nullptr;
|
||||||
if (src != nullptr)
|
if (src != nullptr)
|
||||||
{
|
{
|
||||||
size_t srcSize = SizeOf(src) + 1;
|
size_t srcSize = SizeOf(src) + 1;
|
||||||
|
@ -400,19 +408,19 @@ namespace String
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * DiscardUse(utf8 * * ptr, utf8 * replacement)
|
utf8* DiscardUse(utf8** ptr, utf8* replacement)
|
||||||
{
|
{
|
||||||
Memory::Free(*ptr);
|
Memory::Free(*ptr);
|
||||||
*ptr = replacement;
|
*ptr = replacement;
|
||||||
return replacement;
|
return replacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * DiscardDuplicate(utf8 * * ptr, const utf8 * replacement)
|
utf8* DiscardDuplicate(utf8** ptr, const utf8* replacement)
|
||||||
{
|
{
|
||||||
return DiscardUse(ptr, String::Duplicate(replacement));
|
return DiscardUse(ptr, String::Duplicate(replacement));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Split(const std::string &s, const std::string &delimiter)
|
std::vector<std::string> Split(const std::string& s, const std::string& delimiter)
|
||||||
{
|
{
|
||||||
if (delimiter.empty())
|
if (delimiter.empty())
|
||||||
{
|
{
|
||||||
|
@ -438,18 +446,17 @@ namespace String
|
||||||
}
|
}
|
||||||
results.push_back(value);
|
results.push_back(value);
|
||||||
index = nextIndex + delimiter.size();
|
index = nextIndex + delimiter.size();
|
||||||
}
|
} while (nextIndex != SIZE_MAX);
|
||||||
while (nextIndex != SIZE_MAX);
|
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * SkipBOM(utf8 * buffer)
|
utf8* SkipBOM(utf8* buffer)
|
||||||
{
|
{
|
||||||
return (utf8*)SkipBOM((const utf8 *)buffer);
|
return (utf8*)SkipBOM((const utf8*)buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const utf8 * SkipBOM(const utf8 * buffer)
|
const utf8* SkipBOM(const utf8* buffer)
|
||||||
{
|
{
|
||||||
if ((uint8_t)buffer[0] == 0xEF && (uint8_t)buffer[1] == 0xBB && (uint8_t)buffer[2] == 0xBF)
|
if ((uint8_t)buffer[0] == 0xEF && (uint8_t)buffer[1] == 0xBB && (uint8_t)buffer[2] == 0xBF)
|
||||||
{
|
{
|
||||||
|
@ -463,17 +470,17 @@ namespace String
|
||||||
return utf8_get_codepoint_length(codepoint);
|
return utf8_get_codepoint_length(codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
codepoint_t GetNextCodepoint(utf8 * ptr, utf8 * * nextPtr)
|
codepoint_t GetNextCodepoint(utf8* ptr, utf8** nextPtr)
|
||||||
{
|
{
|
||||||
return GetNextCodepoint((const utf8 *)ptr, (const utf8 * *)nextPtr);
|
return GetNextCodepoint((const utf8*)ptr, (const utf8**)nextPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
codepoint_t GetNextCodepoint(const utf8 * ptr, const utf8 * * nextPtr)
|
codepoint_t GetNextCodepoint(const utf8* ptr, const utf8** nextPtr)
|
||||||
{
|
{
|
||||||
return utf8_get_next(ptr, nextPtr);
|
return utf8_get_next(ptr, nextPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * WriteCodepoint(utf8 * dst, codepoint_t codepoint)
|
utf8* WriteCodepoint(utf8* dst, codepoint_t codepoint)
|
||||||
{
|
{
|
||||||
return utf8_write_codepoint(dst, codepoint);
|
return utf8_write_codepoint(dst, codepoint);
|
||||||
}
|
}
|
||||||
|
@ -484,13 +491,13 @@ namespace String
|
||||||
return iswspace((wchar_t)codepoint) || codepoint == 0x3000;
|
return iswspace((wchar_t)codepoint) || codepoint == 0x3000;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * Trim(utf8 * str)
|
utf8* Trim(utf8* str)
|
||||||
{
|
{
|
||||||
utf8 * firstNonWhitespace = nullptr;
|
utf8* firstNonWhitespace = nullptr;
|
||||||
|
|
||||||
codepoint_t codepoint;
|
codepoint_t codepoint;
|
||||||
utf8 * ch = str;
|
utf8* ch = str;
|
||||||
utf8 * nextCh;
|
utf8* nextCh;
|
||||||
while ((codepoint = GetNextCodepoint(ch, &nextCh)) != '\0')
|
while ((codepoint = GetNextCodepoint(ch, &nextCh)) != '\0')
|
||||||
{
|
{
|
||||||
if (codepoint <= WCHAR_MAX && !IsWhiteSpace(codepoint))
|
if (codepoint <= WCHAR_MAX && !IsWhiteSpace(codepoint))
|
||||||
|
@ -503,8 +510,7 @@ namespace String
|
||||||
ch = nextCh;
|
ch = nextCh;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstNonWhitespace != nullptr &&
|
if (firstNonWhitespace != nullptr && firstNonWhitespace != str)
|
||||||
firstNonWhitespace != str)
|
|
||||||
{
|
{
|
||||||
// Take multibyte characters into account: use the last byte of the
|
// Take multibyte characters into account: use the last byte of the
|
||||||
// current character.
|
// current character.
|
||||||
|
@ -526,11 +532,11 @@ namespace String
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const utf8 * TrimStart(const utf8 * str)
|
const utf8* TrimStart(const utf8* str)
|
||||||
{
|
{
|
||||||
codepoint_t codepoint;
|
codepoint_t codepoint;
|
||||||
const utf8 * ch = str;
|
const utf8* ch = str;
|
||||||
const utf8 * nextCh;
|
const utf8* nextCh;
|
||||||
while ((codepoint = GetNextCodepoint(ch, &nextCh)) != '\0')
|
while ((codepoint = GetNextCodepoint(ch, &nextCh)) != '\0')
|
||||||
{
|
{
|
||||||
if (codepoint <= WCHAR_MAX && !IsWhiteSpace(codepoint))
|
if (codepoint <= WCHAR_MAX && !IsWhiteSpace(codepoint))
|
||||||
|
@ -543,24 +549,24 @@ namespace String
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * TrimStart(utf8 * buffer, size_t bufferSize, const utf8 * src)
|
utf8* TrimStart(utf8* buffer, size_t bufferSize, const utf8* src)
|
||||||
{
|
{
|
||||||
return String::Set(buffer, bufferSize, TrimStart(src));
|
return String::Set(buffer, bufferSize, TrimStart(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TrimStart(const std::string &s)
|
std::string TrimStart(const std::string& s)
|
||||||
{
|
{
|
||||||
const utf8 * trimmed = TrimStart(s.c_str());
|
const utf8* trimmed = TrimStart(s.c_str());
|
||||||
return std::string(trimmed);
|
return std::string(trimmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Trim(const std::string &s)
|
std::string Trim(const std::string& s)
|
||||||
{
|
{
|
||||||
codepoint_t codepoint;
|
codepoint_t codepoint;
|
||||||
const utf8 * ch = s.c_str();
|
const utf8* ch = s.c_str();
|
||||||
const utf8 * nextCh;
|
const utf8* nextCh;
|
||||||
const utf8 * startSubstr = nullptr;
|
const utf8* startSubstr = nullptr;
|
||||||
const utf8 * endSubstr = nullptr;
|
const utf8* endSubstr = nullptr;
|
||||||
while ((codepoint = GetNextCodepoint(ch, &nextCh)) != '\0')
|
while ((codepoint = GetNextCodepoint(ch, &nextCh)) != '\0')
|
||||||
{
|
{
|
||||||
bool isWhiteSpace = codepoint <= WCHAR_MAX && IsWhiteSpace(codepoint);
|
bool isWhiteSpace = codepoint <= WCHAR_MAX && IsWhiteSpace(codepoint);
|
||||||
|
@ -593,26 +599,26 @@ namespace String
|
||||||
{
|
{
|
||||||
switch (codePage)
|
switch (codePage)
|
||||||
{
|
{
|
||||||
case CODE_PAGE::CP_932:
|
case CODE_PAGE::CP_932:
|
||||||
return "windows-932";
|
return "windows-932";
|
||||||
|
|
||||||
case CODE_PAGE::CP_936:
|
case CODE_PAGE::CP_936:
|
||||||
return "GB2312";
|
return "GB2312";
|
||||||
|
|
||||||
case CODE_PAGE::CP_949:
|
case CODE_PAGE::CP_949:
|
||||||
return "windows-949";
|
return "windows-949";
|
||||||
|
|
||||||
case CODE_PAGE::CP_950:
|
case CODE_PAGE::CP_950:
|
||||||
return "big5";
|
return "big5";
|
||||||
|
|
||||||
case CODE_PAGE::CP_1252:
|
case CODE_PAGE::CP_1252:
|
||||||
return "windows-1252";
|
return "windows-1252";
|
||||||
|
|
||||||
case CODE_PAGE::CP_UTF8:
|
case CODE_PAGE::CP_UTF8:
|
||||||
return "utf-8";
|
return "utf-8";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unsupported code page: " + std::to_string(codePage));
|
throw std::runtime_error("Unsupported code page: " + std::to_string(codePage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +648,7 @@ namespace String
|
||||||
|
|
||||||
// Convert the lot.
|
// Convert the lot.
|
||||||
char* buffer_target = &buffer[0];
|
char* buffer_target = &buffer[0];
|
||||||
ucnv_fromUnicode(conv, &buffer_target, buffer_limit, (const UChar**) &source, source_limit, nullptr, true, &status);
|
ucnv_fromUnicode(conv, &buffer_target, buffer_limit, (const UChar**)&source, source_limit, nullptr, true, &status);
|
||||||
|
|
||||||
if (U_FAILURE(status))
|
if (U_FAILURE(status))
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,96 +9,97 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../common.h"
|
|
||||||
|
|
||||||
namespace CODE_PAGE
|
namespace CODE_PAGE
|
||||||
{
|
{
|
||||||
// windows.h defines CP_UTF8
|
// windows.h defines CP_UTF8
|
||||||
#undef CP_UTF8
|
#undef CP_UTF8
|
||||||
|
|
||||||
constexpr int32_t CP_932 = 932; // ANSI/OEM Japanese; Japanese (Shift-JIS)
|
constexpr int32_t CP_932 = 932; // ANSI/OEM Japanese; Japanese (Shift-JIS)
|
||||||
constexpr int32_t CP_936 = 936; // ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)
|
constexpr int32_t CP_936 = 936; // ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)
|
||||||
constexpr int32_t CP_949 = 949; // ANSI/OEM Korean (Unified Hangul Code)
|
constexpr int32_t CP_949 = 949; // ANSI/OEM Korean (Unified Hangul Code)
|
||||||
constexpr int32_t CP_950 = 950; // ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)
|
constexpr int32_t CP_950 = 950; // ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)
|
||||||
constexpr int32_t CP_1252 = 1252; // ANSI Latin 1; Western European (Windows)
|
constexpr int32_t CP_1252 = 1252; // ANSI Latin 1; Western European (Windows)
|
||||||
constexpr int32_t CP_UTF8 = 65001; // Unicode (UTF-8)
|
constexpr int32_t CP_UTF8 = 65001; // Unicode (UTF-8)
|
||||||
} // namespace CODE_PAGE
|
} // namespace CODE_PAGE
|
||||||
|
|
||||||
namespace String
|
namespace String
|
||||||
{
|
{
|
||||||
constexpr const utf8 * Empty = "";
|
constexpr const utf8* Empty = "";
|
||||||
|
|
||||||
std::string ToStd(const utf8 * str);
|
std::string ToStd(const utf8* str);
|
||||||
std::string StdFormat_VA(const utf8 * format, va_list args);
|
std::string StdFormat_VA(const utf8* format, va_list args);
|
||||||
std::string StdFormat(const utf8 * format, ...);
|
std::string StdFormat(const utf8* format, ...);
|
||||||
std::string ToUtf8(const std::wstring_view& src);
|
std::string ToUtf8(const std::wstring_view& src);
|
||||||
std::wstring ToUtf16(const std::string_view& src);
|
std::wstring ToUtf16(const std::string_view& src);
|
||||||
|
|
||||||
bool IsNullOrEmpty(const utf8 * str);
|
bool IsNullOrEmpty(const utf8* str);
|
||||||
int32_t Compare(const std::string &a, const std::string &b, bool ignoreCase = false);
|
int32_t Compare(const std::string& a, const std::string& b, bool ignoreCase = false);
|
||||||
int32_t Compare(const utf8 * a, const utf8 * b, bool ignoreCase = false);
|
int32_t Compare(const utf8* a, const utf8* b, bool ignoreCase = false);
|
||||||
bool Equals(const std::string &a, const std::string &b, bool ignoreCase = false);
|
bool Equals(const std::string& a, const std::string& b, bool ignoreCase = false);
|
||||||
bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase = false);
|
bool Equals(const utf8* a, const utf8* b, bool ignoreCase = false);
|
||||||
bool StartsWith(const utf8 * str, const utf8 * match, bool ignoreCase = false);
|
bool StartsWith(const utf8* str, const utf8* match, bool ignoreCase = false);
|
||||||
bool StartsWith(const std::string &str, const std::string &match, bool ignoreCase = false);
|
bool StartsWith(const std::string& str, const std::string& match, bool ignoreCase = false);
|
||||||
bool EndsWith(const std::string_view& str, const std::string_view& match, bool ignoreCase = false);
|
bool EndsWith(const std::string_view& str, const std::string_view& match, bool ignoreCase = false);
|
||||||
size_t IndexOf(const utf8 * str, utf8 match, size_t startIndex = 0);
|
size_t IndexOf(const utf8* str, utf8 match, size_t startIndex = 0);
|
||||||
ptrdiff_t LastIndexOf(const utf8 * str, utf8 match);
|
ptrdiff_t LastIndexOf(const utf8* str, utf8 match);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the length of the given string in codepoints.
|
* Gets the length of the given string in codepoints.
|
||||||
*/
|
*/
|
||||||
size_t LengthOf(const utf8 * str);
|
size_t LengthOf(const utf8* str);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the size of the given string in bytes excluding the null terminator.
|
* Gets the size of the given string in bytes excluding the null terminator.
|
||||||
*/
|
*/
|
||||||
size_t SizeOf(const utf8 * str);
|
size_t SizeOf(const utf8* str);
|
||||||
|
|
||||||
utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src);
|
utf8* Set(utf8* buffer, size_t bufferSize, const utf8* src);
|
||||||
utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src, size_t srcSize);
|
utf8* Set(utf8* buffer, size_t bufferSize, const utf8* src, size_t srcSize);
|
||||||
utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src);
|
utf8* Append(utf8* buffer, size_t bufferSize, const utf8* src);
|
||||||
utf8 * Format(utf8 * buffer, size_t bufferSize, const utf8 * format, ...);
|
utf8* Format(utf8* buffer, size_t bufferSize, const utf8* format, ...);
|
||||||
utf8 * Format(const utf8 * format, ...);
|
utf8* Format(const utf8* format, ...);
|
||||||
utf8 * Format_VA(const utf8 * format, va_list args);
|
utf8* Format_VA(const utf8* format, va_list args);
|
||||||
utf8 * AppendFormat(utf8 * buffer, size_t bufferSize, const utf8 * format, ...);
|
utf8* AppendFormat(utf8* buffer, size_t bufferSize, const utf8* format, ...);
|
||||||
utf8 * Duplicate(const std::string &src);
|
utf8* Duplicate(const std::string& src);
|
||||||
utf8 * Duplicate(const utf8 * src);
|
utf8* Duplicate(const utf8* src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to free the string a string pointer points to and set it to a replacement string.
|
* Helper method to free the string a string pointer points to and set it to a replacement string.
|
||||||
*/
|
*/
|
||||||
utf8 * DiscardUse(utf8 * * ptr, utf8 * replacement);
|
utf8* DiscardUse(utf8** ptr, utf8* replacement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to free the string a string pointer points to and set it to a copy of a replacement string.
|
* Helper method to free the string a string pointer points to and set it to a copy of a replacement string.
|
||||||
*/
|
*/
|
||||||
utf8 * DiscardDuplicate(utf8 * * ptr, const utf8 * replacement);
|
utf8* DiscardDuplicate(utf8** ptr, const utf8* replacement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits the given string by a delimiter and returns the values as a new string array.
|
* Splits the given string by a delimiter and returns the values as a new string array.
|
||||||
* @returns the number of values.
|
* @returns the number of values.
|
||||||
*/
|
*/
|
||||||
std::vector<std::string> Split(const std::string &s, const std::string &delimiter);
|
std::vector<std::string> Split(const std::string& s, const std::string& delimiter);
|
||||||
|
|
||||||
utf8 * SkipBOM(utf8 * buffer);
|
utf8* SkipBOM(utf8* buffer);
|
||||||
const utf8 * SkipBOM(const utf8 * buffer);
|
const utf8* SkipBOM(const utf8* buffer);
|
||||||
|
|
||||||
size_t GetCodepointLength(codepoint_t codepoint);
|
size_t GetCodepointLength(codepoint_t codepoint);
|
||||||
codepoint_t GetNextCodepoint(utf8 * ptr, utf8 * * nextPtr = nullptr);
|
codepoint_t GetNextCodepoint(utf8* ptr, utf8** nextPtr = nullptr);
|
||||||
codepoint_t GetNextCodepoint(const utf8 * ptr, const utf8 * * nextPtr = nullptr);
|
codepoint_t GetNextCodepoint(const utf8* ptr, const utf8** nextPtr = nullptr);
|
||||||
utf8 * WriteCodepoint(utf8 * dst, codepoint_t codepoint);
|
utf8* WriteCodepoint(utf8* dst, codepoint_t codepoint);
|
||||||
|
|
||||||
bool IsWhiteSpace(codepoint_t codepoint);
|
bool IsWhiteSpace(codepoint_t codepoint);
|
||||||
utf8 * Trim(utf8 * str);
|
utf8* Trim(utf8* str);
|
||||||
const utf8 * TrimStart(const utf8 * str);
|
const utf8* TrimStart(const utf8* str);
|
||||||
utf8 * TrimStart(utf8 * buffer, size_t bufferSize, const utf8 * src);
|
utf8* TrimStart(utf8* buffer, size_t bufferSize, const utf8* src);
|
||||||
std::string TrimStart(const std::string &s);
|
std::string TrimStart(const std::string& s);
|
||||||
std::string Trim(const std::string &s);
|
std::string Trim(const std::string& s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a multi-byte string from one code page to another.
|
* Converts a multi-byte string from one code page to another.
|
||||||
|
@ -109,4 +110,4 @@ namespace String
|
||||||
* Returns an uppercased version of a UTF-8 string.
|
* Returns an uppercased version of a UTF-8 string.
|
||||||
*/
|
*/
|
||||||
std::string ToUpper(const std::string_view& src);
|
std::string ToUpper(const std::string_view& src);
|
||||||
}
|
} // namespace String
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
#include "Math.hpp"
|
#include "Math.hpp"
|
||||||
#include "Memory.hpp"
|
#include "Memory.hpp"
|
||||||
#include "String.hpp"
|
#include "String.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for constructing strings efficiently. A buffer is automatically allocated and reallocated when characters or strings
|
* Class for constructing strings efficiently. A buffer is automatically allocated and reallocated when characters or strings
|
||||||
* are appended. Use GetString to copy the current state of the string builder to a new fire-and-forget string.
|
* are appended. Use GetString to copy the current state of the string builder to a new fire-and-forget string.
|
||||||
|
@ -55,7 +55,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Appends the given string to the current string.
|
* Appends the given string to the current string.
|
||||||
*/
|
*/
|
||||||
void Append(const utf8 * text)
|
void Append(const utf8* text)
|
||||||
{
|
{
|
||||||
size_t textLength = String::SizeOf(text);
|
size_t textLength = String::SizeOf(text);
|
||||||
Append(text, textLength);
|
Append(text, textLength);
|
||||||
|
@ -67,7 +67,7 @@ public:
|
||||||
* @param text Pointer to the UTF-8 text to append.
|
* @param text Pointer to the UTF-8 text to append.
|
||||||
* @param textLength Number of bytes to copy. (Can be used to append single bytes rather than codepoints)
|
* @param textLength Number of bytes to copy. (Can be used to append single bytes rather than codepoints)
|
||||||
*/
|
*/
|
||||||
void Append(const utf8 * text, size_t textLength)
|
void Append(const utf8* text, size_t textLength)
|
||||||
{
|
{
|
||||||
EnsureCapacity(_length + textLength + 1);
|
EnsureCapacity(_length + textLength + 1);
|
||||||
std::copy_n(text, textLength, _buffer + _length);
|
std::copy_n(text, textLength, _buffer + _length);
|
||||||
|
@ -78,7 +78,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Appends the string of a given StringBuilder to the current string.
|
* Appends the string of a given StringBuilder to the current string.
|
||||||
*/
|
*/
|
||||||
void Append(const StringBuilder * sb)
|
void Append(const StringBuilder* sb)
|
||||||
{
|
{
|
||||||
Append(sb->GetBuffer(), sb->GetLength());
|
Append(sb->GetBuffer(), sb->GetLength());
|
||||||
}
|
}
|
||||||
|
@ -108,9 +108,9 @@ public:
|
||||||
/**
|
/**
|
||||||
* Resets the StringBuilder and returns the working buffer (resized to the string size).
|
* Resets the StringBuilder and returns the working buffer (resized to the string size).
|
||||||
*/
|
*/
|
||||||
utf8 * StealString()
|
utf8* StealString()
|
||||||
{
|
{
|
||||||
utf8 * result = _buffer;
|
utf8* result = _buffer;
|
||||||
result = Memory::ReallocateArray<utf8>(result, _length + 1);
|
result = Memory::ReallocateArray<utf8>(result, _length + 1);
|
||||||
result[_length] = 0;
|
result[_length] = 0;
|
||||||
|
|
||||||
|
@ -124,10 +124,10 @@ public:
|
||||||
/**
|
/**
|
||||||
* Returns the current string buffer as a new fire-and-forget string.
|
* Returns the current string buffer as a new fire-and-forget string.
|
||||||
*/
|
*/
|
||||||
utf8 * GetString() const
|
utf8* GetString() const
|
||||||
{
|
{
|
||||||
// If buffer is null, length should be 0 which will create a new one byte memory block containing a null terminator
|
// If buffer is null, length should be 0 which will create a new one byte memory block containing a null terminator
|
||||||
utf8 * result = Memory::AllocateArray<utf8>(_length + 1);
|
utf8* result = Memory::AllocateArray<utf8>(_length + 1);
|
||||||
std::copy_n(_buffer, _length, result);
|
std::copy_n(_buffer, _length, result);
|
||||||
result[_length] = 0;
|
result[_length] = 0;
|
||||||
return result;
|
return result;
|
||||||
|
@ -145,31 +145,39 @@ public:
|
||||||
* Gets the current state of the StringBuilder. Warning: this represents the StringBuilder's current working buffer and will
|
* Gets the current state of the StringBuilder. Warning: this represents the StringBuilder's current working buffer and will
|
||||||
* be deallocated when the StringBuilder is destructed.
|
* be deallocated when the StringBuilder is destructed.
|
||||||
*/
|
*/
|
||||||
const utf8 * GetBuffer() const
|
const utf8* GetBuffer() const
|
||||||
{
|
{
|
||||||
// buffer may be null, so return an immutable empty string
|
// buffer may be null, so return an immutable empty string
|
||||||
if (_buffer == nullptr) return "";
|
if (_buffer == nullptr)
|
||||||
|
return "";
|
||||||
return _buffer;
|
return _buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the amount of allocated memory for the string buffer.
|
* Gets the amount of allocated memory for the string buffer.
|
||||||
*/
|
*/
|
||||||
size_t GetCapacity() const { return _capacity; }
|
size_t GetCapacity() const
|
||||||
|
{
|
||||||
|
return _capacity;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the length of the current string.
|
* Gets the length of the current string.
|
||||||
*/
|
*/
|
||||||
size_t GetLength() const { return _length; }
|
size_t GetLength() const
|
||||||
|
{
|
||||||
|
return _length;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
utf8 * _buffer = nullptr;
|
utf8* _buffer = nullptr;
|
||||||
size_t _capacity = 0;
|
size_t _capacity = 0;
|
||||||
size_t _length = 0;
|
size_t _length = 0;
|
||||||
|
|
||||||
void EnsureCapacity(size_t capacity)
|
void EnsureCapacity(size_t capacity)
|
||||||
{
|
{
|
||||||
if (_capacity > capacity) return;
|
if (_capacity > capacity)
|
||||||
|
return;
|
||||||
|
|
||||||
_capacity = std::max((size_t)8, _capacity);
|
_capacity = std::max((size_t)8, _capacity);
|
||||||
while (_capacity < capacity)
|
while (_capacity < capacity)
|
||||||
|
|
|
@ -18,16 +18,16 @@ interface IStringReader
|
||||||
{
|
{
|
||||||
virtual ~IStringReader() = default;
|
virtual ~IStringReader() = default;
|
||||||
|
|
||||||
virtual bool TryPeek(codepoint_t * outCodepoint) abstract;
|
virtual bool TryPeek(codepoint_t * outCodepoint) abstract;
|
||||||
virtual bool TryRead(codepoint_t * outCodepoint) abstract;
|
virtual bool TryRead(codepoint_t * outCodepoint) abstract;
|
||||||
virtual void Skip() abstract;
|
virtual void Skip() abstract;
|
||||||
virtual bool CanRead() const abstract;
|
virtual bool CanRead() const abstract;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UTF8StringReader final : public IStringReader
|
class UTF8StringReader final : public IStringReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit UTF8StringReader(const utf8 * text)
|
explicit UTF8StringReader(const utf8* text)
|
||||||
{
|
{
|
||||||
text = String::SkipBOM(text);
|
text = String::SkipBOM(text);
|
||||||
|
|
||||||
|
@ -35,18 +35,20 @@ public:
|
||||||
_current = text;
|
_current = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TryPeek(codepoint_t * outCodepoint) override
|
bool TryPeek(codepoint_t* outCodepoint) override
|
||||||
{
|
{
|
||||||
if (_current == nullptr) return false;
|
if (_current == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
codepoint_t codepoint = String::GetNextCodepoint(_current);
|
codepoint_t codepoint = String::GetNextCodepoint(_current);
|
||||||
*outCodepoint = codepoint;
|
*outCodepoint = codepoint;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TryRead(codepoint_t * outCodepoint) override
|
bool TryRead(codepoint_t* outCodepoint) override
|
||||||
{
|
{
|
||||||
if (_current == nullptr) return false;
|
if (_current == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
codepoint_t codepoint = String::GetNextCodepoint(_current, &_current);
|
codepoint_t codepoint = String::GetNextCodepoint(_current, &_current);
|
||||||
*outCodepoint = codepoint;
|
*outCodepoint = codepoint;
|
||||||
|
@ -70,6 +72,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const utf8 *_text;
|
const utf8* _text;
|
||||||
const utf8 *_current;
|
const utf8* _current;
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,14 +15,13 @@
|
||||||
/**
|
/**
|
||||||
* Common utility functions.
|
* Common utility functions.
|
||||||
*/
|
*/
|
||||||
namespace Util {
|
namespace Util
|
||||||
|
|
||||||
// Based on http://www.g-truc.net/post-0708.html
|
|
||||||
template <typename T, size_t N>
|
|
||||||
static constexpr size_t CountOf(T const (&)[N]) noexcept
|
|
||||||
{
|
{
|
||||||
return N;
|
// Based on http://www.g-truc.net/post-0708.html
|
||||||
}
|
template<typename T, size_t N> static constexpr size_t CountOf(T const (&)[N]) noexcept
|
||||||
|
{
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Util
|
} // namespace Util
|
||||||
|
|
||||||
|
|
|
@ -8,14 +8,16 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#ifndef __ANDROID__
|
#ifndef __ANDROID__
|
||||||
#include <zip.h>
|
|
||||||
#include "IStream.hpp"
|
|
||||||
#include "Zip.h"
|
#include "Zip.h"
|
||||||
|
|
||||||
|
#include "IStream.hpp"
|
||||||
|
|
||||||
|
#include <zip.h>
|
||||||
|
|
||||||
class ZipArchive final : public IZipArchive
|
class ZipArchive final : public IZipArchive
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
zip_t * _zip;
|
zip_t* _zip;
|
||||||
ZIP_ACCESS _access;
|
ZIP_ACCESS _access;
|
||||||
std::vector<std::vector<uint8_t>> _writeBuffers;
|
std::vector<std::vector<uint8_t>> _writeBuffers;
|
||||||
|
|
||||||
|
@ -188,4 +190,4 @@ namespace Zip
|
||||||
}
|
}
|
||||||
} // namespace Zip
|
} // namespace Zip
|
||||||
|
|
||||||
# endif
|
#endif
|
||||||
|
|
|
@ -9,17 +9,20 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../common.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a zip file.
|
* Represents a zip file.
|
||||||
*/
|
*/
|
||||||
interface IZipArchive
|
interface IZipArchive
|
||||||
{
|
{
|
||||||
virtual ~IZipArchive() { }
|
virtual ~IZipArchive()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual size_t GetNumFiles() const abstract;
|
virtual size_t GetNumFiles() const abstract;
|
||||||
virtual std::string GetFileName(size_t index) const abstract;
|
virtual std::string GetFileName(size_t index) const abstract;
|
||||||
|
@ -47,4 +50,4 @@ namespace Zip
|
||||||
{
|
{
|
||||||
std::unique_ptr<IZipArchive> Open(const std::string_view& path, ZIP_ACCESS zipAccess);
|
std::unique_ptr<IZipArchive> Open(const std::string_view& path, ZIP_ACCESS zipAccess);
|
||||||
std::unique_ptr<IZipArchive> TryOpen(const std::string_view& path, ZIP_ACCESS zipAccess);
|
std::unique_ptr<IZipArchive> TryOpen(const std::string_view& path, ZIP_ACCESS zipAccess);
|
||||||
}
|
} // namespace Zip
|
||||||
|
|
|
@ -9,11 +9,12 @@
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
#include <jni.h>
|
|
||||||
#include "IStream.hpp"
|
#include "IStream.hpp"
|
||||||
#include "Zip.h"
|
#include "Zip.h"
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
class ZipArchive final : public IZipArchive
|
class ZipArchive final : public IZipArchive
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -23,7 +24,7 @@ public:
|
||||||
ZipArchive(const std::string_view& path, ZIP_ACCESS access)
|
ZipArchive(const std::string_view& path, ZIP_ACCESS access)
|
||||||
{
|
{
|
||||||
// retrieve the JNI environment.
|
// retrieve the JNI environment.
|
||||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||||
|
|
||||||
jclass jniClass = env->FindClass("website/openrct2/ZipArchive");
|
jclass jniClass = env->FindClass("website/openrct2/ZipArchive");
|
||||||
jmethodID constructor = env->GetMethodID(jniClass, "<init>", "(Ljava/lang/String;)V");
|
jmethodID constructor = env->GetMethodID(jniClass, "<init>", "(Ljava/lang/String;)V");
|
||||||
|
@ -39,7 +40,7 @@ public:
|
||||||
~ZipArchive() override
|
~ZipArchive() override
|
||||||
{
|
{
|
||||||
// retrieve the JNI environment.
|
// retrieve the JNI environment.
|
||||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||||
|
|
||||||
jclass zipClass = env->GetObjectClass(_zip);
|
jclass zipClass = env->GetObjectClass(_zip);
|
||||||
jmethodID closeMethod = env->GetMethodID(zipClass, "close", "()V");
|
jmethodID closeMethod = env->GetMethodID(zipClass, "close", "()V");
|
||||||
|
@ -52,29 +53,28 @@ public:
|
||||||
size_t GetNumFiles() const override
|
size_t GetNumFiles() const override
|
||||||
{
|
{
|
||||||
// retrieve the JNI environment.
|
// retrieve the JNI environment.
|
||||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||||
|
|
||||||
jclass zipClass = env->GetObjectClass(_zip);
|
jclass zipClass = env->GetObjectClass(_zip);
|
||||||
jmethodID fileCountMethod = env->GetMethodID(zipClass, "getNumFiles", "()I");
|
jmethodID fileCountMethod = env->GetMethodID(zipClass, "getNumFiles", "()I");
|
||||||
|
|
||||||
return (size_t) env->CallIntMethod(_zip, fileCountMethod);
|
return (size_t)env->CallIntMethod(_zip, fileCountMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetFileName(size_t index) const override
|
std::string GetFileName(size_t index) const override
|
||||||
{
|
{
|
||||||
// retrieve the JNI environment.
|
// retrieve the JNI environment.
|
||||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||||
|
|
||||||
jclass zipClass = env->GetObjectClass(_zip);
|
jclass zipClass = env->GetObjectClass(_zip);
|
||||||
jmethodID fileNameMethod = env->GetMethodID(zipClass, "getFileName",
|
jmethodID fileNameMethod = env->GetMethodID(zipClass, "getFileName", "(I)Ljava/lang/String;");
|
||||||
"(I)Ljava/lang/String;");
|
|
||||||
|
|
||||||
jstring jniString = (jstring) env->CallObjectMethod(_zip, fileNameMethod, (jint) index);
|
jstring jniString = (jstring)env->CallObjectMethod(_zip, fileNameMethod, (jint)index);
|
||||||
|
|
||||||
const char *jniChars = env->GetStringUTFChars(jniString, nullptr);
|
const char* jniChars = env->GetStringUTFChars(jniString, nullptr);
|
||||||
|
|
||||||
utf8 *string = (char *) malloc(strlen(jniChars) + 1);
|
utf8* string = (char*)malloc(strlen(jniChars) + 1);
|
||||||
memcpy((void *) string, jniChars, strlen(jniChars));
|
memcpy((void*)string, jniChars, strlen(jniChars));
|
||||||
string[strlen(jniChars)] = 0x00;
|
string[strlen(jniChars)] = 0x00;
|
||||||
|
|
||||||
env->ReleaseStringUTFChars(jniString, jniChars);
|
env->ReleaseStringUTFChars(jniString, jniChars);
|
||||||
|
@ -85,18 +85,18 @@ public:
|
||||||
uint64_t GetFileSize(size_t index) const override
|
uint64_t GetFileSize(size_t index) const override
|
||||||
{
|
{
|
||||||
// retrieve the JNI environment.
|
// retrieve the JNI environment.
|
||||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||||
|
|
||||||
jclass zipClass = env->GetObjectClass(_zip);
|
jclass zipClass = env->GetObjectClass(_zip);
|
||||||
jmethodID fileSizeMethod = env->GetMethodID(zipClass, "getFileSize", "(I)J");
|
jmethodID fileSizeMethod = env->GetMethodID(zipClass, "getFileSize", "(I)J");
|
||||||
|
|
||||||
return (size_t) env->CallLongMethod(_zip, fileSizeMethod, (jint) index);
|
return (size_t)env->CallLongMethod(_zip, fileSizeMethod, (jint)index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> GetFileData(const std::string_view& path) const override
|
std::vector<uint8_t> GetFileData(const std::string_view& path) const override
|
||||||
{
|
{
|
||||||
// retrieve the JNI environment.
|
// retrieve the JNI environment.
|
||||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||||
|
|
||||||
jclass zipClass = env->GetObjectClass(_zip);
|
jclass zipClass = env->GetObjectClass(_zip);
|
||||||
jstring javaPath = env->NewStringUTF(path.data());
|
jstring javaPath = env->NewStringUTF(path.data());
|
||||||
|
@ -106,7 +106,7 @@ public:
|
||||||
jmethodID fileMethod = env->GetMethodID(zipClass, "getFile", "(I)J");
|
jmethodID fileMethod = env->GetMethodID(zipClass, "getFile", "(I)J");
|
||||||
jlong ptr = env->CallLongMethod(_zip, fileMethod, index);
|
jlong ptr = env->CallLongMethod(_zip, fileMethod, index);
|
||||||
|
|
||||||
auto dataPtr = reinterpret_cast<uint8_t *>(ptr);
|
auto dataPtr = reinterpret_cast<uint8_t*>(ptr);
|
||||||
auto dataSize = this->GetFileSize(index);
|
auto dataSize = this->GetFileSize(index);
|
||||||
|
|
||||||
return std::vector<uint8_t>(dataPtr, dataPtr + dataSize);
|
return std::vector<uint8_t>(dataPtr, dataPtr + dataSize);
|
||||||
|
@ -147,26 +147,22 @@ namespace Zip
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
} // namespace Zip
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
JNIEXPORT jlong JNICALL
|
JNIEXPORT jlong JNICALL Java_website_openrct2_ZipArchive_allocBytes(JNIEnv* env, jclass, jbyteArray input, jint numBytes);
|
||||||
Java_website_openrct2_ZipArchive_allocBytes(JNIEnv *env, jclass, jbyteArray input,
|
|
||||||
jint numBytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL
|
JNIEXPORT jlong JNICALL Java_website_openrct2_ZipArchive_allocBytes(JNIEnv* env, jclass, jbyteArray input, jint numBytes)
|
||||||
Java_website_openrct2_ZipArchive_allocBytes(JNIEnv *env, jclass, jbyteArray input,
|
{
|
||||||
jint numBytes) {
|
jbyte* bufferPtr = env->GetByteArrayElements(input, nullptr);
|
||||||
|
|
||||||
jbyte *bufferPtr = env->GetByteArrayElements(input, nullptr);
|
void* data = Memory::Allocate<void>((size_t)numBytes);
|
||||||
|
|
||||||
void *data = Memory::Allocate<void>((size_t) numBytes);
|
|
||||||
memcpy(data, bufferPtr, numBytes);
|
memcpy(data, bufferPtr, numBytes);
|
||||||
|
|
||||||
env->ReleaseByteArrayElements(input, bufferPtr, 0);
|
env->ReleaseByteArrayElements(input, bufferPtr, 0);
|
||||||
|
|
||||||
return (uintptr_t) data;
|
return (uintptr_t)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __ANDROID__
|
#endif // __ANDROID__
|
||||||
|
|
Loading…
Reference in New Issue