feat: add helper macro and new Win32 function.
- add IsValidCodePage in WinFctHelper to check whether code page number is valid. - add 6 macros to batchly (add / set default) (move / copy) (constructor / assign operator). - add default or delete (copy / move) (constructor / assign operator) for some classes.
This commit is contained in:
parent
6da990876e
commit
e6c24b8b61
|
@ -29,7 +29,7 @@
|
|||
|
||||
\li \subpage intro
|
||||
|
||||
\li \subpage platform_checker
|
||||
\li \subpage library_macros
|
||||
|
||||
\li \subpage library_encoding
|
||||
|
||||
|
|
80
doc/src/library_macros.dox
Normal file
80
doc/src/library_macros.dox
Normal file
|
@ -0,0 +1,80 @@
|
|||
namespace YYCC {
|
||||
/**
|
||||
|
||||
\page library_macros Library Macros
|
||||
|
||||
In this page we will introduce the macros defined by this library
|
||||
which can not be grouped in other topic.
|
||||
|
||||
\section library_macros__platform_checker Platform Checker
|
||||
|
||||
In many cross platform applications,
|
||||
programmer usually write code adapted to different platforms in one source file
|
||||
and enable them respectively by macros representing the target platform.
|
||||
As a cross platform library,
|
||||
YYCC also has this feature and you can utilize it if you don't have other ways to so the same things.
|
||||
|
||||
\subsection library_macros__platform_checker__values Values
|
||||
|
||||
YYCC always define a macro called \c YYCC_OS to indicate the system of target platform.
|
||||
In implementation, it will check following list from top to bottom to set matched value for it.
|
||||
|
||||
\li \c YYCC_OS_WINDOWS: Windows environment. It is done by checking whether environment define \c _WIN32 macro.
|
||||
\li \c YYCC_OS_LINUX: In current implementation, this means target platform is \b NOT Windows.
|
||||
|
||||
\subsection library_macros__platform_checker__usage Usage
|
||||
|
||||
Now you know any possible value of \c YYCC_OS.
|
||||
The next step is how to use it to enable specified code in specific target platform.
|
||||
We take Windows platform for example.
|
||||
Assume \c blabla() function is Windows specific.
|
||||
We have following example code:
|
||||
|
||||
\code
|
||||
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||
blabla();
|
||||
#endif
|
||||
\endcode
|
||||
|
||||
It's enough and simple that use \c \#if to bracket the Windows specified code.
|
||||
|
||||
\section library_macros__batch_class_copy_move Batch Class Copy / Move Functions
|
||||
|
||||
YYCC provides 6 macros to batchly remove class copy constructor and move constructor,
|
||||
or set default class copy constructor and move constructor.
|
||||
|
||||
<UL>
|
||||
<LI>
|
||||
\c YYCC_DEL_CLS_COPY: Declare following 2 statements which delete copy constrcutor and copy assign operator.
|
||||
<UL>
|
||||
<LI><TT>CLSNAME(const CLSNAME&) = delete;</TT></LI>
|
||||
<LI><TT>CLSNAME& operator=(const CLSNAME&) = delete;</TT></LI>
|
||||
</UL>
|
||||
</LI>
|
||||
<LI>
|
||||
\c YYCC_DEL_CLS_MOVE: Declare following 2 statements which delete move constrcutor and move assign operator.
|
||||
<UL>
|
||||
<LI><TT>CLSNAME(CLSNAME&&) = delete;</TT></LI>
|
||||
<LI><TT>CLSNAME& operator=(CLSNAME&&) = delete;</TT></LI>
|
||||
</UL>
|
||||
</LI>
|
||||
<LI>\c YYCC_DEL_CLS_COPY_MOVE: The combination of \c YYCC_DEL_CLS_COPY and \c YYCC_DEL_CLS_MOVE.</LI>
|
||||
<LI>
|
||||
\c YYCC_DEF_CLS_COPY: Declare following 2 statements which set default copy constrcutor and copy assign operator.
|
||||
<UL>
|
||||
<LI><TT>CLSNAME(const CLSNAME&) = default;</TT></LI>
|
||||
<LI><TT>CLSNAME& operator=(const CLSNAME&) = default;</TT></LI>
|
||||
</UL>
|
||||
</LI>
|
||||
<LI>
|
||||
\c YYCC_DEF_CLS_MOVE: Declare following 2 statements which set default move constrcutor and move assign operator.
|
||||
<UL>
|
||||
<LI><TT>CLSNAME(CLSNAME&&) = default;</TT></LI>
|
||||
<LI><TT>CLSNAME& operator=(CLSNAME&&) = default;</TT></LI>
|
||||
</UL>
|
||||
</LI>
|
||||
<LI>\c YYCC_DEF_CLS_COPY_MOVE: The combination of \c YYCC_DEF_CLS_COPY and \c YYCC_DEF_CLS_MOVE.</LI>
|
||||
</UL>
|
||||
|
||||
*/
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
namespace YYCC {
|
||||
/**
|
||||
|
||||
\page platform_checker Platform Checker
|
||||
|
||||
In many cross platform applications,
|
||||
programmer usually write code adapted to different platforms in one source file
|
||||
and enable them respectively by macros representing the target platform.
|
||||
As a cross platform library,
|
||||
YYCC also has this feature and you can utilize it if you don't have other ways to so the same things.
|
||||
|
||||
\section platform_checker__values Values
|
||||
|
||||
YYCC always define a macro called \c YYCC_OS to indicate the system of target platform.
|
||||
In implementation, it will check following list from top to bottom to set matched value for it.
|
||||
|
||||
\li \c YYCC_OS_WINDOWS: Windows environment. It is done by checking whether environment define \c _WIN32 macro.
|
||||
\li \c YYCC_OS_LINUX: In current implementation, this means target platform is \b NOT Windows.
|
||||
|
||||
\section platform_checker__usage Usage
|
||||
|
||||
Now you know any possible value of \c YYCC_OS.
|
||||
The next step is how to use it to enable specified code in specific target platform.
|
||||
We take Windows platform for example.
|
||||
Assume \c blabla() function is Windows specific.
|
||||
We have following example code:
|
||||
|
||||
\code
|
||||
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||
blabla();
|
||||
#endif
|
||||
\endcode
|
||||
|
||||
It's enough and simple that use \c \#if to bracket the Windows specified code.
|
||||
|
||||
*/
|
||||
}
|
|
@ -14,6 +14,7 @@ Currently this namespace has following functions:
|
|||
\li #GetTempDirectory: Get temporary directory in Windows.
|
||||
\li #GetModuleFileName: Get the path to module in file system by given handle.
|
||||
\li #GetLocalAppData: Get the path inside \%LOCALAPPDATA\%
|
||||
\li #IsValidCodePage: Check whether given code page number is valid.
|
||||
|
||||
*/
|
||||
}
|
|
@ -51,22 +51,22 @@ namespace YYCC::ArgParser {
|
|||
#endif
|
||||
|
||||
ArgumentList::ArgumentList(std::vector<yycc_u8string>&& arguments) :
|
||||
m_Arguments(arguments), m_ArgumentsIterator(m_Arguments.begin()) {}
|
||||
m_Arguments(arguments), m_ArgumentsCursor(0u) {}
|
||||
|
||||
void ArgumentList::Prev() {
|
||||
if (m_ArgumentsIterator == m_Arguments.begin())
|
||||
if (m_ArgumentsCursor == 0u)
|
||||
throw std::runtime_error("attempt to move on the head of iterator.");
|
||||
--m_ArgumentsIterator;
|
||||
--m_ArgumentsCursor;
|
||||
}
|
||||
|
||||
void ArgumentList::Next() {
|
||||
if (IsEOF()) throw std::runtime_error("attempt to move on the tail of iterator.");
|
||||
++m_ArgumentsIterator;
|
||||
++m_ArgumentsCursor;
|
||||
}
|
||||
|
||||
const yycc_u8string& ArgumentList::Argument() const {
|
||||
if (IsEOF()) throw std::runtime_error("attempt to get data on the tail of iterator.");
|
||||
return *m_ArgumentsIterator;
|
||||
return m_Arguments[m_ArgumentsCursor];
|
||||
}
|
||||
|
||||
bool ArgumentList::IsSwitch(bool* is_long_name, yycc_u8string* long_name, yycc_char8_t* short_name) const {
|
||||
|
@ -87,7 +87,7 @@ namespace YYCC::ArgParser {
|
|||
bool ArgumentList::IsLongNameSwitch(yycc_u8string* name_part) const {
|
||||
// fetch current parameter
|
||||
if (IsEOF()) throw std::runtime_error("attempt to fetch data on the tail of iterator.");
|
||||
const yycc_u8string& param = *m_ArgumentsIterator;
|
||||
const yycc_u8string& param = m_Arguments[m_ArgumentsCursor];
|
||||
// find double slash
|
||||
if (param.find(AbstractArgument::DOUBLE_DASH) != 0u) return false;
|
||||
// check gotten long name
|
||||
|
@ -101,7 +101,7 @@ namespace YYCC::ArgParser {
|
|||
bool ArgumentList::IsShortNameSwitch(yycc_char8_t* name_part) const {
|
||||
// fetch current parameter
|
||||
if (IsEOF()) throw std::runtime_error("attempt to fetch data on the tail of iterator.");
|
||||
const yycc_u8string& param = *m_ArgumentsIterator;
|
||||
const yycc_u8string& param = m_Arguments[m_ArgumentsCursor];
|
||||
// if the length is not exactly equal to 2,
|
||||
// or it not starts with dash,
|
||||
// it is impossible a short name
|
||||
|
@ -118,13 +118,13 @@ namespace YYCC::ArgParser {
|
|||
bool ArgumentList::IsValue(yycc_u8string* val) const {
|
||||
bool is_value = !IsSwitch();
|
||||
if (is_value && val != nullptr)
|
||||
*val = *m_ArgumentsIterator;
|
||||
*val = m_Arguments[m_ArgumentsCursor];
|
||||
return is_value;
|
||||
}
|
||||
|
||||
bool ArgumentList::IsEOF() const { return m_ArgumentsIterator == m_Arguments.end(); }
|
||||
bool ArgumentList::IsEOF() const { return m_ArgumentsCursor >= m_Arguments.size(); }
|
||||
|
||||
void ArgumentList::Reset() { m_ArgumentsIterator = m_Arguments.begin(); }
|
||||
void ArgumentList::Reset() { m_ArgumentsCursor = 0u; }
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
|
|
@ -61,14 +61,7 @@ namespace YYCC::ArgParser {
|
|||
*/
|
||||
ArgumentList(std::vector<yycc_u8string>&& arguments);
|
||||
public:
|
||||
/// @brief Default copy constructor
|
||||
ArgumentList(const ArgumentList&) = default;
|
||||
/// @brief Default copy assigner
|
||||
ArgumentList& operator=(const ArgumentList&) = default;
|
||||
/// @brief Default move constructor
|
||||
ArgumentList(ArgumentList&&) = default;
|
||||
/// @brief Default move assigner
|
||||
ArgumentList& operator=(ArgumentList&&) = default;
|
||||
YYCC_DEF_CLS_COPY_MOVE(ArgumentList);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -151,7 +144,7 @@ namespace YYCC::ArgParser {
|
|||
|
||||
private:
|
||||
std::vector<yycc_u8string> m_Arguments;
|
||||
std::vector<yycc_u8string>::const_iterator m_ArgumentsIterator;
|
||||
size_t m_ArgumentsCursor;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -209,6 +202,7 @@ namespace YYCC::ArgParser {
|
|||
const yycc_char8_t* description = nullptr, const yycc_char8_t* argument_example = nullptr,
|
||||
bool is_optional = false);
|
||||
virtual ~AbstractArgument();
|
||||
YYCC_DEL_CLS_COPY_MOVE(AbstractArgument);
|
||||
|
||||
// ===== User Implementation =====
|
||||
protected:
|
||||
|
@ -296,6 +290,7 @@ namespace YYCC::ArgParser {
|
|||
const yycc_char8_t* summary, const yycc_char8_t* description,
|
||||
std::initializer_list<AbstractArgument*> arguments);
|
||||
~OptionContext();
|
||||
YYCC_DEL_CLS_COPY_MOVE(OptionContext);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -350,6 +345,7 @@ namespace YYCC::ArgParser {
|
|||
Constraints::Constraint<_Ty> constraint = Constraints::Constraint<_Ty> {}) :
|
||||
AbstractArgument(long_name, short_name, description, argument_example, is_optional), m_Data(), m_Constraint(constraint) {}
|
||||
virtual ~NumberArgument() {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(NumberArgument);
|
||||
|
||||
public:
|
||||
/// @brief Get stored data in argument.
|
||||
|
@ -403,6 +399,7 @@ namespace YYCC::ArgParser {
|
|||
// bool switch doesn't have argument, so it doesn't have example property.
|
||||
AbstractArgument(long_name, short_name, description, nullptr, true) {}
|
||||
virtual ~SwitchArgument() {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(SwitchArgument);
|
||||
|
||||
protected:
|
||||
virtual bool Parse(ArgumentList& al) override { return true; } // simply return true because no value to store.
|
||||
|
@ -429,6 +426,7 @@ namespace YYCC::ArgParser {
|
|||
Constraints::Constraint<yycc_u8string> constraint = Constraints::Constraint<yycc_u8string> {}) :
|
||||
AbstractArgument(long_name, short_name, description, argument_example, is_optional), m_Data(), m_Constraint(constraint) {}
|
||||
virtual ~StringArgument() {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(StringArgument);
|
||||
|
||||
public:
|
||||
/// @brief Get stored data in argument.
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace YYCC::ConfigManager {
|
|||
*/
|
||||
AbstractSetting(const yycc_u8string_view& name);
|
||||
virtual ~AbstractSetting();
|
||||
YYCC_DEL_CLS_COPY_MOVE(AbstractSetting);
|
||||
|
||||
// Name interface
|
||||
public:
|
||||
|
@ -89,6 +90,7 @@ namespace YYCC::ConfigManager {
|
|||
uint64_t version_identifier,
|
||||
std::initializer_list<AbstractSetting*> settings);
|
||||
~CoreManager() {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(CoreManager);
|
||||
|
||||
// Core functions
|
||||
public:
|
||||
|
@ -129,6 +131,7 @@ namespace YYCC::ConfigManager {
|
|||
Constraints::Constraint<_Ty> constraint = Constraints::Constraint<_Ty> {}) :
|
||||
AbstractSetting(name), m_Data(default_value), m_DefaultData(default_value), m_Constraint(constraint) {}
|
||||
virtual ~NumberSetting() {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(NumberSetting);
|
||||
|
||||
/// @brief Get stored data in setting.
|
||||
_Ty Get() const { return m_Data; }
|
||||
|
@ -189,6 +192,7 @@ namespace YYCC::ConfigManager {
|
|||
m_DefaultData = default_value;
|
||||
}
|
||||
virtual ~StringSetting() {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(StringSetting);
|
||||
|
||||
/// @brief Get reference to stored string.
|
||||
const yycc_u8string& Get() const { return m_Data; }
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace YYCC::DialogHelper {
|
|||
friend class WinFileDialog;
|
||||
public:
|
||||
WinFileFilters() : m_WinFilters(), m_WinDataStruct(nullptr) {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(WinFileFilters);
|
||||
|
||||
/// @brief Get the count of available file filters
|
||||
UINT GetFilterCount() const {
|
||||
|
@ -67,6 +68,7 @@ namespace YYCC::DialogHelper {
|
|||
class FileFilters {
|
||||
public:
|
||||
FileFilters() : m_Filters() {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(FileFilters);
|
||||
|
||||
/**
|
||||
* @brief Add a filter pair in file types list.
|
||||
|
@ -123,6 +125,7 @@ namespace YYCC::DialogHelper {
|
|||
m_WinFileTypes(), m_WinDefaultFileTypeIndex(0u),
|
||||
m_HasTitle(false), m_HasInitFileName(false), m_WinTitle(), m_WinInitFileName(),
|
||||
m_WinInitDirectory(nullptr) {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(WinFileDialog);
|
||||
|
||||
/// @brief Get whether this dialog has owner.
|
||||
bool HasOwner() const { return m_WinOwner != NULL; }
|
||||
|
@ -189,6 +192,7 @@ namespace YYCC::DialogHelper {
|
|||
m_DefaultFileTypeIndex(0u),
|
||||
m_Title(), m_InitFileName(), m_InitDirectory(),
|
||||
m_HasTitle(false), m_HasInitFileName(false), m_HasInitDirectory(false) {}
|
||||
YYCC_DEL_CLS_COPY_MOVE(FileDialog);
|
||||
|
||||
/**
|
||||
* @brief Set the owner of dialog.
|
||||
|
|
|
@ -85,6 +85,11 @@ namespace YYCC::WinFctHelper {
|
|||
return YYCC::EncodingHelper::WcharToUTF8(known_path.get(), ret);
|
||||
}
|
||||
|
||||
bool IsValidCodePage(UINT code_page) {
|
||||
CPINFOEXW cpinfo;
|
||||
return GetCPInfoExW(code_page, 0, &cpinfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,13 @@ namespace YYCC::WinFctHelper {
|
|||
*/
|
||||
bool GetLocalAppData(yycc_u8string& ret);
|
||||
|
||||
/**
|
||||
* @brief Check whether given code page number is a valid one.
|
||||
* @param[in] code_page The code page number.
|
||||
* @return True if it is valid, otherwise false.
|
||||
*/
|
||||
bool IsValidCodePage(UINT code_page);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#pragma region Operating System Identifier Macros
|
||||
|
||||
// Define operating system macros
|
||||
#define YYCC_OS_WINDOWS 2
|
||||
#define YYCC_OS_LINUX 3
|
||||
|
@ -10,6 +12,10 @@
|
|||
#define YYCC_OS YYCC_OS_LINUX
|
||||
#endif
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Windows Shitty Behavior Disable Macros
|
||||
|
||||
// If we are in Windows,
|
||||
// we need add 2 macros to disable Windows shitty warnings and errors of
|
||||
// depracted functions and not secure functions.
|
||||
|
@ -24,6 +30,10 @@
|
|||
|
||||
#endif
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region YYCC UTF8 Types
|
||||
|
||||
// Define the UTF8 char type we used.
|
||||
// And do a polyfill if no embedded char8_t type.
|
||||
|
||||
|
@ -67,4 +77,40 @@ namespace YYCC {
|
|||
It is equal to \c std::u8string_view if your current C++ standard support it.
|
||||
*/
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Batch Class Move / Copy Function Macros
|
||||
|
||||
/// @brief Explicitly remove copy (\c constructor and \c operator\=) for given class.
|
||||
#define YYCC_DEL_CLS_COPY(CLSNAME) \
|
||||
CLSNAME(const CLSNAME&) = delete; \
|
||||
CLSNAME& operator=(const CLSNAME&) = delete;
|
||||
|
||||
/// @brief Explicitly remove move (\c constructor and \c operator\=) for given class.
|
||||
#define YYCC_DEL_CLS_MOVE(CLSNAME) \
|
||||
CLSNAME(CLSNAME&&) = delete; \
|
||||
CLSNAME& operator=(CLSNAME&&) = delete;
|
||||
|
||||
/// @brief Explicitly remove (copy and move) (\c constructor and \c operator\=) for given class.
|
||||
#define YYCC_DEL_CLS_COPY_MOVE(CLSNAME) \
|
||||
YYCC_DEL_CLS_COPY(CLSNAME) \
|
||||
YYCC_DEL_CLS_MOVE(CLSNAME)
|
||||
|
||||
/// @brief Explicitly set default copy (\c constructor and \c operator\=) for given class.
|
||||
#define YYCC_DEF_CLS_COPY(CLSNAME) \
|
||||
CLSNAME(const CLSNAME&) = default; \
|
||||
CLSNAME& operator=(const CLSNAME&) = default;
|
||||
|
||||
/// @brief Explicitly set default move (\c constructor and \c operator\=) for given class.
|
||||
#define YYCC_DEF_CLS_MOVE(CLSNAME) \
|
||||
CLSNAME(CLSNAME&&) = default; \
|
||||
CLSNAME& operator=(CLSNAME&&) = default;
|
||||
|
||||
/// @brief Explicitly set default (copy and move) (\c constructor and \c operator\=) for given class.
|
||||
#define YYCC_DEF_CLS_COPY_MOVE(CLSNAME) \
|
||||
YYCC_DEF_CLS_COPY(CLSNAME) \
|
||||
YYCC_DEF_CLS_MOVE(CLSNAME)
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
|
|
|
@ -388,6 +388,9 @@ namespace YYCCTestbench {
|
|||
Assert(YYCC::WinFctHelper::GetLocalAppData(test_localappdata_path), YYCC_U8("YYCC::WinFctHelper::GetLocalAppData"));
|
||||
Console::FormatLine(YYCC_U8("Local AppData: %s"), test_localappdata_path.c_str());
|
||||
|
||||
Assert(YYCC::WinFctHelper::IsValidCodePage(static_cast<UINT>(1252)) == true, YYCC_U8("YYCC::WinFctHelper::IsValidCodePage"));
|
||||
Assert(YYCC::WinFctHelper::IsValidCodePage(static_cast<UINT>(114514)) == false, YYCC_U8("YYCC::WinFctHelper::IsValidCodePage"));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user