clang-format core

This commit is contained in:
clang-format 2018-06-22 22:58:39 +02:00 committed by Hielke Morsink
parent 6f2e84e593
commit 3a4a11f738
40 changed files with 929 additions and 917 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,12 +48,11 @@ 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);
else else
DataSerializerTraits<T>::decode(_activeStream, data); DataSerializerTraits<T>::decode(_activeStream, data);
return *this; return *this;
} }

View File

@ -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);

View File

@ -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"

View File

@ -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);
} }

View File

@ -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,26 +137,27 @@ 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;
} }
#endif #endif
return lastModified; return lastModified;
} }
} // 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;
} }
} }

View File

@ -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

View 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);

View File

@ -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++;

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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);

View File

@ -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());
} }

View File

@ -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)
{ {
} }
}; };

View File

@ -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

View File

@ -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

View File

@ -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);
} }
}; };

View File

@ -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)

View File

@ -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;
} }

View File

@ -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

View File

@ -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++)
{ {

View File

@ -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 &copy) #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);
} }
} }

View File

@ -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);

View File

@ -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;
}; };

View File

@ -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)
{ {

View File

@ -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

View File

@ -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

View File

@ -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))
{ {

View File

@ -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

View File

@ -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)

View File

@ -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;
}; };

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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__