diff --git a/doc/src/index.dox b/doc/src/index.dox
index 91fabc7..ce11db4 100644
--- a/doc/src/index.dox
+++ b/doc/src/index.dox
@@ -29,7 +29,7 @@
\li \subpage intro
- \li \subpage platform_checker
+ \li \subpage library_macros
\li \subpage library_encoding
diff --git a/doc/src/library_macros.dox b/doc/src/library_macros.dox
new file mode 100644
index 0000000..e4bdee8
--- /dev/null
+++ b/doc/src/library_macros.dox
@@ -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.
+
+
+ -
+ \c YYCC_DEL_CLS_COPY: Declare following 2 statements which delete copy constrcutor and copy assign operator.
+
+ - CLSNAME(const CLSNAME&) = delete;
+ - CLSNAME& operator=(const CLSNAME&) = delete;
+
+
+ -
+ \c YYCC_DEL_CLS_MOVE: Declare following 2 statements which delete move constrcutor and move assign operator.
+
+ - CLSNAME(CLSNAME&&) = delete;
+ - CLSNAME& operator=(CLSNAME&&) = delete;
+
+
+ - \c YYCC_DEL_CLS_COPY_MOVE: The combination of \c YYCC_DEL_CLS_COPY and \c YYCC_DEL_CLS_MOVE.
+ -
+ \c YYCC_DEF_CLS_COPY: Declare following 2 statements which set default copy constrcutor and copy assign operator.
+
+ - CLSNAME(const CLSNAME&) = default;
+ - CLSNAME& operator=(const CLSNAME&) = default;
+
+
+ -
+ \c YYCC_DEF_CLS_MOVE: Declare following 2 statements which set default move constrcutor and move assign operator.
+
+ - CLSNAME(CLSNAME&&) = default;
+ - CLSNAME& operator=(CLSNAME&&) = default;
+
+
+ - \c YYCC_DEF_CLS_COPY_MOVE: The combination of \c YYCC_DEF_CLS_COPY and \c YYCC_DEF_CLS_MOVE.
+
+
+*/
+}
\ No newline at end of file
diff --git a/doc/src/platform_checker.dox b/doc/src/platform_checker.dox
deleted file mode 100644
index 185d29b..0000000
--- a/doc/src/platform_checker.dox
+++ /dev/null
@@ -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.
-
-*/
-}
\ No newline at end of file
diff --git a/doc/src/win_fct_helper.dox b/doc/src/win_fct_helper.dox
index 4a56efb..6b17eb0 100644
--- a/doc/src/win_fct_helper.dox
+++ b/doc/src/win_fct_helper.dox
@@ -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.
*/
}
\ No newline at end of file
diff --git a/src/ArgParser.cpp b/src/ArgParser.cpp
index 998a6da..04eacf1 100644
--- a/src/ArgParser.cpp
+++ b/src/ArgParser.cpp
@@ -51,22 +51,22 @@ namespace YYCC::ArgParser {
#endif
ArgumentList::ArgumentList(std::vector&& 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
diff --git a/src/ArgParser.hpp b/src/ArgParser.hpp
index d2b300c..46228f7 100644
--- a/src/ArgParser.hpp
+++ b/src/ArgParser.hpp
@@ -55,20 +55,13 @@ namespace YYCC::ArgParser {
private:
/**
* @brief Constructor of ArgumentList used internally.
- * @param[in] arguments
+ * @param[in] arguments
* Underlying argument list.
* This argument list should remove first executable name before passing it to there.
*/
ArgumentList(std::vector&& 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:
/**
@@ -89,17 +82,17 @@ namespace YYCC::ArgParser {
const yycc_u8string& Argument() const;
/**
* @brief Check whether current argument is a option / switch.
- * @param[out] is_long_name
+ * @param[out] is_long_name
* It will be set true if this argument is long name, otherwise short name.
* nullptr if you don't want to receive this infomation.
- * @param[out] long_name
+ * @param[out] long_name
* The container holding matched long name if it is (double dash stripped).
* nullptr if you don't want to receive this infomation.
- * @param[out] short_name
+ * @param[out] short_name
* The variable holding matched short name if it is (dash stripped).
* nullptr if you don't want to receive this infomation.
* @exception std::runtime_error Try fetching data at the tail of argument list.
- * @return
+ * @return
* True if it is, otherwise false.
* If this function return false, all given parameters are in undefined status.
*/
@@ -109,7 +102,7 @@ namespace YYCC::ArgParser {
yycc_char8_t* short_name = nullptr) const;
/**
* @brief Check whether current argument is a value.
- * @param[out] val
+ * @param[out] val
* The variable holding value if it is.
* nullptr if you don't want to receive this infomation.
* @exception std::runtime_error Try fetching data at the tail of argument list.
@@ -133,7 +126,7 @@ namespace YYCC::ArgParser {
/**
* @brief Check whether current argument is long name option / switch.
* @details This function is used by IsSwitch() internally.
- * @param[out] name_part
+ * @param[out] name_part
* The container holding matched long name if it is (double dash stripped).
* nullptr if you don't want to receive this infomation.
* @return True if it is, otherwise false.
@@ -142,7 +135,7 @@ namespace YYCC::ArgParser {
/**
* @brief Check whether current argument is short name option / switch.
* @details This function is used by IsSwitch() internally.
- * @param[out] name_part
+ * @param[out] name_part
* The variable holding matched short name if it is (dash stripped).
* nullptr if you don't want to receive this infomation.
* @return True if it is, otherwise false.
@@ -151,7 +144,7 @@ namespace YYCC::ArgParser {
private:
std::vector m_Arguments;
- std::vector::const_iterator m_ArgumentsIterator;
+ size_t m_ArgumentsCursor;
};
/**
@@ -171,7 +164,7 @@ namespace YYCC::ArgParser {
/**
* @brief Check whether given short name is valid.
* @details
- * An ASCII code of valid short name
+ * An ASCII code of valid short name
* should not lower than #MIN_SHORT_NAME or higher than #MAX_SHORT_NAME.
* It also can not be #DASH.
* @param[in] short_name Short name for checking.
@@ -181,7 +174,7 @@ namespace YYCC::ArgParser {
/**
* @brief Check whether given long name is valid.
* @details
- * An ASCII code of every item in valid long name
+ * An ASCII code of every item in valid long name
* should not lower than #MIN_SHORT_NAME or higher than #MAX_SHORT_NAME.
* However it can be #DASH. This is different with short name.
* @param[in] long_name Long name for checking.
@@ -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:
@@ -226,12 +220,12 @@ namespace YYCC::ArgParser {
virtual bool Parse(ArgumentList& al) = 0;
/**
* @brief User implemented custom reset function
- * @remarks
+ * @remarks
* In this function, user should claer its stored value if is has.
* You don't need clar capture state. That is done by library self.
*/
virtual void Reset() = 0;
-
+
// ===== Basic Infos =====
public:
/// @brief Check whether this argument specify long name.
@@ -267,7 +261,7 @@ namespace YYCC::ArgParser {
yycc_u8string m_Description;
yycc_u8string m_ArgumentExample;
bool m_IsOptional;
-
+
// ===== Capture State =====
public:
/// @brief Check whether this argument has been captured.
@@ -296,12 +290,13 @@ namespace YYCC::ArgParser {
const yycc_char8_t* summary, const yycc_char8_t* description,
std::initializer_list arguments);
~OptionContext();
+ YYCC_DEL_CLS_COPY_MOVE(OptionContext);
public:
/**
* @brief Start a parse.
* @param[in] al The reference to ArgumentList for parsing.
- * @return
+ * @return
* True if success, otherwise false.
* If this function return false, you should not visit any arguments it managed.
*/
@@ -325,7 +320,7 @@ namespace YYCC::ArgParser {
};
#pragma region Argument Presets
-
+
/**
* @brief Arithmetic (integral, floating point. except bool) type argument
* @tparam _Ty The internal stored type belongs to arithmetic type.
@@ -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.
@@ -401,14 +397,15 @@ namespace YYCC::ArgParser {
const yycc_char8_t* description = nullptr) :
// bool switch must be optional, because it is false if no given switch.
// bool switch doesn't have argument, so it doesn't have example property.
- AbstractArgument(long_name, short_name, description, nullptr, true) {}
+ 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.
virtual void Reset() override {} // nothing need to be reset.
};
-
+
/// @brief String type argument
class StringArgument : public AbstractArgument {
public:
@@ -429,6 +426,7 @@ namespace YYCC::ArgParser {
Constraints::Constraint constraint = Constraints::Constraint {}) :
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.
diff --git a/src/ConfigManager.hpp b/src/ConfigManager.hpp
index b5664a9..0f453d2 100644
--- a/src/ConfigManager.hpp
+++ b/src/ConfigManager.hpp
@@ -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 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; }
diff --git a/src/DialogHelper.hpp b/src/DialogHelper.hpp
index c5986a3..66c0749 100644
--- a/src/DialogHelper.hpp
+++ b/src/DialogHelper.hpp
@@ -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.
diff --git a/src/WinFctHelper.cpp b/src/WinFctHelper.cpp
index 130662d..bb6ee55 100644
--- a/src/WinFctHelper.cpp
+++ b/src/WinFctHelper.cpp
@@ -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
diff --git a/src/WinFctHelper.hpp b/src/WinFctHelper.hpp
index 50a5ffd..03ac29a 100644
--- a/src/WinFctHelper.hpp
+++ b/src/WinFctHelper.hpp
@@ -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
diff --git a/src/YYCCInternal.hpp b/src/YYCCInternal.hpp
index 7614b49..0b901d3 100644
--- a/src/YYCCInternal.hpp
+++ b/src/YYCCInternal.hpp
@@ -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
+
diff --git a/testbench/main.cpp b/testbench/main.cpp
index c5439c9..96cbab0 100644
--- a/testbench/main.cpp
+++ b/testbench/main.cpp
@@ -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(1252)) == true, YYCC_U8("YYCC::WinFctHelper::IsValidCodePage"));
+ Assert(YYCC::WinFctHelper::IsValidCodePage(static_cast(114514)) == false, YYCC_U8("YYCC::WinFctHelper::IsValidCodePage"));
+
#endif
}