5 Commits

16 changed files with 618 additions and 144 deletions

View File

@ -2356,7 +2356,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED =
PREDEFINED = YYCC_DOXYGEN
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The

View File

@ -30,7 +30,7 @@ We suggest you to call this function at the beginning of program.
Considering most Linux console supports ASCII Escape Code very well,
this function does nothing in non-Windows platform.
So it is not essential that brack this function calling with Windows-only \#if.
So it is not essential that brack this function calling with Windows-only \c \#if.
\subsection console_helper__color__common Common Usage

View File

@ -80,4 +80,83 @@ Before using this library, I suggest you read this manual fully to have a full o
Otherwise you may make mistake during using this library.
I suggest you read this manual from top to bottom in the left tree panel, one by one.
YYCC library self provides some build scripts for convenient use which are located in \c script directory.
Please note all of these script should be executed in the root of YYCC project, not the script directory
(i.e. work directory is the root directory of YYCC).
All scripts will try to do a simple check about this if you accidently execute them in a wrong place.
If you are not willing to use our build script, or our build script went wrong,
you can create your personal build script by viewing our build script.
\subsection intro__usage__linux Linux
Building YYCC on Linux is easy to do by executing <TT>script/linux_build.sh</TT>.
After script done, you will find installation result in directory <TT>bin/install</TT>.
Then other CMake project can utilize it (non-CMake project also can utilize this).
\subsection intro__usage__win Windows
For building on Windows, there are 2 distribution types which YYCC can create.
First is CMake distribution, this distribution is served for other CMake project using.
Another one is MSVC distribution, this distribution is served for other MSVC project using.
These have different directory layout which is specifically designed for corresponding build tools.
See following section for more details.
\subsubsection intro__usage__win__cmake CMake Distribution
For creating CMake distribution, please execute script <TT>script/win_build.bat</TT>.
After script done, you will find CMake distribution in directory <TT>bin/install</TT> with following structure.
\verbatim
YYCC
├─Win32_Debug: Win32 Debug package
│ ├─include: Headers
│ └─lib: Library for linking and CMake package file
├─Win32_Release: Win32 Release package
│ ├─bin: Executable testbench
│ ├─include: Headers
│ └─lib: Library for linking and CMake package file
├─x64_Debug: x64 Debug package
│ ├─include: Headers
│ └─lib: Library for linking and CMake package file
└─x64_Release: x64 Release package
├─bin: Executable testbench
├─include: Headers
├─lib: Library for linking and CMake package file
└─share: Documentation
\endverbatim
Every different architecture and build type have a single and full directory.
CMake project can use one of by adding their build type in \c find_package path.
So that CMake will automatically utilize correct package when switching build type.
\subsubsection intro__usage__win__msvc MSVC Distribution
Before creating MSVC distribution, you should create CMake distribution first,
because MSVC distribution depend on CMake distribution.
After creating CMake distribution, you can simply create MSVC distribution by executing <TT>script/win_msvc_build.bat</TT>.
Then you will find your MSVC distribution in directory <TT>bin/msvc_install</TT> with following structure.
\verbatim
YYCC
├─bin
│ ├─Win32: Win32 Release testbench
│ └─x64: x64 Release testbench
├─include: Headers
├─lib
│ ├─Win32
│ │ ├─Debug: Win32 Debug library for linking
│ │ └─Release: Win32 Release library for linking
│ └─x64
│ ├─Debug: x64 Debug library for linking
│ └─Release: x64 Release library for linking
└─share: Documentation
\endverbatim
The different between MSVC distribution and CMake distribution is
that MSVC distribution places all static library under one director \c lib.
Thus in MSVC project user can simply spcify the install path of YYCC,
and use MSVC macros in path to choose correct static library for linking
*/

View File

@ -9,11 +9,17 @@
#include <shlobj_core.h>
#include "WinImportSuffix.hpp"
/**
* @brief Windows COM related types and checker.
* @details
* This namespace is Windows specific.
* In other platforms, this whole namespace will be unavailable.
*
* See also \ref com_helper.
*/
namespace YYCC::COMHelper {
/**
* @brief C++ standard deleter for every COM interfaces inheriting IUnknown.
*/
/// @brief C++ standard deleter for every COM interfaces inheriting IUnknown.
class ComPtrDeleter {
public:
ComPtrDeleter() {}
@ -24,15 +30,18 @@ namespace YYCC::COMHelper {
}
};
/// @brief Smart unique pointer of \c IFileDialog
using SmartIFileDialog = std::unique_ptr<IFileDialog, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IFileOpenDialog
using SmartIFileOpenDialog = std::unique_ptr<IFileOpenDialog, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellItem
using SmartIShellItem = std::unique_ptr<IShellItem, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellItemArray
using SmartIShellItemArray = std::unique_ptr<IShellItemArray, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellFolder
using SmartIShellFolder = std::unique_ptr<IShellFolder, ComPtrDeleter>;
/**
* @brief C++ standard deleter for almost raw pointer used in COM which need to be free by CoTaskMemFree()
*/
/// @brief C++ standard deleter for almost raw pointer used in COM which need to be free by CoTaskMemFree()
class CoTaskMemDeleter {
public:
CoTaskMemDeleter() {}
@ -42,7 +51,8 @@ namespace YYCC::COMHelper {
}
}
};
/// @brief Smart unique pointer of COM created \c WCHAR sequence.
using SmartLPWSTR = std::unique_ptr<std::remove_pointer_t<LPWSTR>, CoTaskMemDeleter>;
/**

View File

@ -11,8 +11,16 @@
#include <stdexcept>
#include <cstring>
/**
* @brief Universal configuration manager
* @details For how to use this namespace, please see \ref config_manager.
*/
namespace YYCC::ConfigManager {
/**
* @brief The constraint applied to settings to limit its stored value.
* @tparam _Ty The internal data type stroed in corresponding setting.
*/
template<typename _Ty>
struct Constraint {
using CheckFct_t = std::function<bool(const _Ty&)>;
@ -25,8 +33,18 @@ namespace YYCC::ConfigManager {
}
};
/**
* @brief The namespace containing functions generating common used constraint.
*/
namespace ConstraintPresets {
/**
* @brief Get constraint for arithmetic values by minimum and maximum value range.
* @tparam _Ty The underlying arithmetic type.
* @param[in] min_value The minimum value of range (inclusive).
* @param[in] max_value The maximum value of range (inclusive).
* @return The generated constraint instance which can be directly applied.
*/
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> && !std::is_enum_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0>
Constraint<_Ty> GetNumberRangeConstraint(_Ty min_value, _Ty max_value) {
if (min_value > max_value)
@ -39,9 +57,15 @@ namespace YYCC::ConfigManager {
}
/// @brief The base class of every setting.
/// @details Programmer can inherit this class and implement essential to create custom setting.
class AbstractSetting {
friend class CoreManager;
public:
/**
* @brief Construct a setting
* @param[in] name The name of this setting.
*/
AbstractSetting(const yycc_char8_t* name) : m_Name(), m_RawData() {
if (name != nullptr) m_Name = name;
}
@ -49,28 +73,57 @@ namespace YYCC::ConfigManager {
// Name interface
public:
/// @brief Get name of this setting.
/// @details Name was used in storing setting in file.
const yycc_u8string& GetName() const { return m_Name; }
private:
yycc_u8string m_Name;
// User Implementations
protected:
/// @brief User implemented custom load functions
/// @remarks
/// In this function, programmer should read data from internal buffer
/// and store it to its own another internal variables.
/// @return True if success, otherwise false.
virtual bool UserLoad() = 0;
/// @brief User implemented custom save functions
/// @remarks
/// In this function, programmer should write data,
/// which is stored in another variavle by it own, to internal buffer.
/// @return True if success, otherwise false.
virtual bool UserSave() = 0;
/// @brief User implemented custom reset functions
/// @remarks In this function, programmer should reset its internal variable to default value.
virtual void UserReset() = 0;
// Buffer related functions
protected:
/// @brief Resize internal buffer to given size.
/// @remarks It is usually used in UserSave.
/// @param[in] new_size The new size of internal buffer.
void ResizeData(size_t new_size) { m_RawData.resize(new_size); }
/// @brief Get data pointer to internal buffer.
/// @remarks It is usually used in UserLoad.
const void* GetDataPtr() const { return m_RawData.data(); }
/// @brief Get mutable data pointer to internal buffer.
/// @remarks It is usually used in UserSave.
void* GetDataPtr() { return m_RawData.data(); }
/// @brief Get the length of internal buffer.
size_t GetDataSize() const { return m_RawData.size(); }
private:
std::vector<uint8_t> m_RawData;
};
/// @brief Settings manager and config file reader writer.
class CoreManager {
public:
/**
* @brief Build core manager.
* @param[in] cfg_file_path The path to config file.
* @param[in] version_identifier The identifier of version. Higher is newer. Lower config will try doing migration.
* @param[in] settings An initializer list containing pointers to all managed settings.
*/
CoreManager(
const yycc_char8_t* cfg_file_path,
uint64_t version_identifier,
@ -79,8 +132,14 @@ namespace YYCC::ConfigManager {
// Core functions
public:
/// @brief Load settings from file.
/// @details Before loading, all settings will be reset to default value first.
/// @return True if success, otherwise false.
bool Load();
/// @brief Save settings to file.
/// @return True if success, otherwise false.
bool Save();
/// @brief Reset all settings to default value.
void Reset();
private:
@ -94,14 +153,30 @@ namespace YYCC::ConfigManager {
#pragma region Setting Presets
/**
* @brief Arithmetic (integral, floating point, bool) and enum type setting
* @tparam _Ty The internal stored type belongs to arithmetic type.
*/
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> || std::is_enum_v<_Ty>, int> = 0>
class NumberSetting : public AbstractSetting {
public:
/**
* @brief Construct arithmetic type setting.
* @param[in] name The name of this setting.
* @param[in] default_value The default value of this setting.
* @param[in] constraint The constraint applied to this setting.
*/
NumberSetting(const yycc_char8_t* name, _Ty default_value, Constraint<_Ty> constraint = Constraint<_Ty> {}) :
AbstractSetting(name), m_Data(default_value), m_DefaultData(default_value), m_Constraint(constraint) {}
virtual ~NumberSetting() {}
/// @brief Get stored data in setting.
_Ty Get() const { return m_Data; }
/**
* @brief Set data to setting.
* @param[in] new_data The new data.
* @return True if success, otherwise false (given value is invalid)
*/
bool Set(_Ty new_data) {
// validate data
if (m_Constraint.IsValid() && !m_Constraint.m_CheckFct(new_data))
@ -136,16 +211,29 @@ namespace YYCC::ConfigManager {
Constraint<_Ty> m_Constraint;
};
/// @brief String type setting
class StringSetting : public AbstractSetting {
public:
/**
* @brief Construct string setting
* @param[in] name The name of this setting.
* @param[in] default_value The default value of this setting.
* @param[in] constraint The constraint applied to this setting.
*/
StringSetting(const yycc_char8_t* name, const yycc_u8string_view& default_value, Constraint<yycc_u8string_view> constraint = Constraint<yycc_u8string_view> {}) :
AbstractSetting(name), m_Data(), m_DefaultData(), m_Constraint(constraint) {
m_Data = default_value;
m_DefaultData = default_value;
}
virtual ~StringSetting() {}
/// @brief Get reference to stored string.
const yycc_u8string& Get() const { return m_Data; }
/**
* @brief Set string data to setting.
* @param[in] new_data The new string data.
* @return True if success, otherwise false (given value is invalid)
*/
bool Set(const yycc_u8string_view& new_data) {
// check data validation
if (m_Constraint.IsValid() && !m_Constraint.m_CheckFct(new_data))

View File

@ -5,117 +5,158 @@
#include <string>
/**
* @brief The namespace providing universal Console visiting functions like C-Sharp Console class.
* @brief The helper providing universal C\# style console function and other console related stuff
* @details
* \ref console_helper
* For how to utilize this functions provided by this namespace, please view \ref console_helper.
*/
namespace YYCC::ConsoleHelper {
/// @brief The head of ASCII escape code of black color.
#define YYCC_COLORHDR_BLACK "\033[30m"
/// @brief The head of ASCII escape code of red color.
#define YYCC_COLORHDR_RED "\033[31m"
/// @brief The head of ASCII escape code of green color.
#define YYCC_COLORHDR_GREEN "\033[32m"
/// @brief The head of ASCII escape code of yellow color.
#define YYCC_COLORHDR_YELLOW "\033[33m"
/// @brief The head of ASCII escape code of blue color.
#define YYCC_COLORHDR_BLUE "\033[34m"
/// @brief The head of ASCII escape code of magenta color.
#define YYCC_COLORHDR_MAGENTA "\033[35m"
/// @brief The head of ASCII escape code of cyan color.
#define YYCC_COLORHDR_CYAN "\033[36m"
/// @brief The head of ASCII escape code of white color.
#define YYCC_COLORHDR_WHITE "\033[37m"
/// @brief The head of ASCII escape code of light black color.
#define YYCC_COLORHDR_LIGHT_BLACK "\033[90m"
/// @brief The head of ASCII escape code of light red color.
#define YYCC_COLORHDR_LIGHT_RED "\033[91m"
/// @brief The head of ASCII escape code of light green color.
#define YYCC_COLORHDR_LIGHT_GREEN "\033[92m"
/// @brief The head of ASCII escape code of light yellow color.
#define YYCC_COLORHDR_LIGHT_YELLOW "\033[93m"
/// @brief The head of ASCII escape code of light blue color.
#define YYCC_COLORHDR_LIGHT_BLUE "\033[94m"
/// @brief The head of ASCII escape code of light magenta color.
#define YYCC_COLORHDR_LIGHT_MAGENTA "\033[95m"
/// @brief The head of ASCII escape code of light cyan color.
#define YYCC_COLORHDR_LIGHT_CYAN "\033[96m"
/// @brief The head of ASCII escape code of light white color.
#define YYCC_COLORHDR_LIGHT_WHITE "\033[97m"
/// @brief The tail of ASCII escape code of every color.
#define YYCC_COLORTAIL "\033[0m"
/// @brief The ASCII escape code pair of black color.
#define YYCC_COLOR_BLACK(T) "\033[30m" T "\033[0m"
/// @brief The ASCII escape code pair of red color.
#define YYCC_COLOR_RED(T) "\033[31m" T "\033[0m"
/// @brief The ASCII escape code pair of green color.
#define YYCC_COLOR_GREEN(T) "\033[32m" T "\033[0m"
/// @brief The ASCII escape code pair of yellow color.
#define YYCC_COLOR_YELLOW(T) "\033[33m" T "\033[0m"
/// @brief The ASCII escape code pair of blue color.
#define YYCC_COLOR_BLUE(T) "\033[34m" T "\033[0m"
/// @brief The ASCII escape code pair of magenta color.
#define YYCC_COLOR_MAGENTA(T) "\033[35m" T "\033[0m"
/// @brief The ASCII escape code pair of cyan color.
#define YYCC_COLOR_CYAN(T) "\033[36m" T "\033[0m"
/// @brief The ASCII escape code pair of white color.
#define YYCC_COLOR_WHITE(T) "\033[37m" T "\033[0m"
/// @brief The ASCII escape code pair of light black color.
#define YYCC_COLOR_LIGHT_BLACK(T) "\033[90m" T "\033[0m"
/// @brief The ASCII escape code pair of light red color.
#define YYCC_COLOR_LIGHT_RED(T) "\033[91m" T "\033[0m"
/// @brief The ASCII escape code pair of light green color.
#define YYCC_COLOR_LIGHT_GREEN(T) "\033[92m" T "\033[0m"
/// @brief The ASCII escape code pair of light yellow color.
#define YYCC_COLOR_LIGHT_YELLOW(T) "\033[93m" T "\033[0m"
/// @brief The ASCII escape code pair of light blue color.
#define YYCC_COLOR_LIGHT_BLUE(T) "\033[94m" T "\033[0m"
/// @brief The ASCII escape code pair of light magenta color.
#define YYCC_COLOR_LIGHT_MAGENTA(T) "\033[95m" T "\033[0m"
/// @brief The ASCII escape code pair of light cyan color.
#define YYCC_COLOR_LIGHT_CYAN(T) "\033[96m" T "\033[0m"
/// @brief The ASCII escape code pair of light white color.
#define YYCC_COLOR_LIGHT_WHITE(T) "\033[97m" T "\033[0m"
/**
* @brief Enable Windows console color support.
* @details This actually is enable virtual console feature for stdout and stderr.
* @brief Enable console color support for Windows.
* @details This actually is enable virtual console feature for \c stdout and \c stderr.
* @return True if success, otherwise false.
* @remarks This function only works on Windows and do nothing on other platforms such as Linux,
* @remarks
* This function only works on Windows and do nothing on other platforms such as Linux,
* because we assume all terminals existing on other platform support color feature as default.
*/
bool EnableColorfulConsole();
/**
* @brief Universal console read function
* @brief Reads the next line of UTF8 characters from the standard input stream.
* @return
* The UTF8 encoded string this function read. EOL is excluded.
* The next line of UTF8 characters from the input stream.
* Empty string if user just press Enter key or function failed.
* @remarks
* This function is more like C# Console.ReadLine().
* It read user input with UTF8 encoding until reaching EOL.
* \par
* This function also can be used as ordering user press Enter key by
* simply calling this function and ignoring its return value.
*/
yycc_u8string ReadLine();
/**
* @brief Universal console write function with format feature.
* @brief
* Writes the text representation of the specified object
* to the standard output stream using the specified format information.
* @param[in] u8_fmt The format string.
* @param[in] ... The arguments to be formatted.
* @param[in] ... The arguments of format string.
*/
void Format(const yycc_char8_t* u8_fmt, ...);
/**
* @brief Universal console write function with format and auto EOL feature.
* @brief
* Writes the text representation of the specified object,
* followed by the current line terminator,
* to the standard output stream using the specified format information.
* @param[in] u8_fmt The format string.
* @param[in] ... The arguments to be formatted.
* @param[in] ... The arguments of format string.
*/
void FormatLine(const yycc_char8_t* u8_fmt, ...);
/**
* @brief Universal console write function.
* @param[in] u8_strl The string to be written.
* @brief Writes the specified string value to the standard output stream.
* @param[in] u8_strl The value to write.
*/
void Write(const yycc_char8_t* u8_strl);
/**
* @brief Universal console write function with auto EOL feature.
* @param[in] u8_strl The string to be written.
* @brief
* Writes the specified string value, followed by the current line terminator,
* to the standard output stream.
* @param[in] u8_strl The value to write.
*/
void WriteLine(const yycc_char8_t* u8_strl);
/**
* @brief Universal console error write function with format and feature.
* @brief
* Writes the text representation of the specified object
* to the standard error stream using the specified format information.
* @param[in] u8_fmt The format string.
* @param[in] ... The arguments to be formatted.
* @param[in] ... The arguments of format string.
*/
void ErrFormat(const yycc_char8_t* u8_fmt, ...);
/**
* @brief Universal console error write function with format and auto EOL feature.
* @brief
* Writes the text representation of the specified object,
* followed by the current line terminator,
* to the standard error stream using the specified format information.
* @param[in] u8_fmt The format string.
* @param[in] ... The arguments to be formatted.
* @param[in] ... The arguments of format string.
*/
void ErrFormatLine(const yycc_char8_t* u8_fmt, ...);
/**
* @brief Universal console error write function.
* @param[in] u8_strl The string to be written.
* @brief Writes the specified string value to the standard error stream.
* @param[in] u8_strl The value to write.
*/
void ErrWrite(const yycc_char8_t* u8_strl);
/**
* @brief Universal console error write function with auto EOL feature.
* @param[in] u8_strl The string to be written.
* @brief
* Writes the specified string value, followed by the current line terminator,
* to the standard error stream.
* @param[in] u8_strl The value to write.
*/
void ErrWriteLine(const yycc_char8_t* u8_strl);

View File

@ -12,11 +12,19 @@
#include <shlobj_core.h>
#include "WinImportSuffix.hpp"
/**
* @brief The namespace providing Windows universal dialog features.
* @details
* This namespace only available on Windows platform.
* See also \ref dialog_helper.
*/
namespace YYCC::DialogHelper {
/**
* @brief The class represent the file types region in file dialog
* @details THis class is specific for Windows use, not user oriented.
* @brief The class representing the file types region in file dialog.
* @details
* This class is served for Windows used.
* Programmer should \b not create this class manually.
*/
class WinFileFilters {
friend class FileFilters;
@ -24,9 +32,11 @@ namespace YYCC::DialogHelper {
public:
WinFileFilters() : m_WinFilters(), m_WinDataStruct(nullptr) {}
/// @brief Get the count of available file filters
UINT GetFilterCount() const {
return static_cast<UINT>(m_WinFilters.size());
}
/// @brief Get pointer to Windows used file filters declarations
const COMDLG_FILTERSPEC* GetFilterSpecs() const {
return m_WinDataStruct.get();
}
@ -39,6 +49,7 @@ namespace YYCC::DialogHelper {
std::vector<WinFilterPair> m_WinFilters;
std::unique_ptr<COMDLG_FILTERSPEC[]> m_WinDataStruct;
/// @brief Clear all current file filters
void Clear() {
m_WinDataStruct.reset();
m_WinFilters.clear();
@ -46,9 +57,12 @@ namespace YYCC::DialogHelper {
};
/**
* @brief The class represent the file types region in file dialog.
* @details This class is user oriented. User can use function manipulate file types
* and final generation function will produce Windows-understood data struct from this.
* @brief The class representing the file types region in file dialog.
* @details
* This class is served for programmer using.
* But you don't need create it on your own.
* You can simply fetch it by FileDialog::ConfigreFileTypes ,
* because this class is a part of FileDialog.
*/
class FileFilters {
public:
@ -56,31 +70,34 @@ namespace YYCC::DialogHelper {
/**
* @brief Add a filter pair in file types list.
* @param filter_name[in] The friendly name of the filter.
* @param il[in] A C++ initialize list.
* Every entries must be `const yycc_char8_t*` represent a single filter pattern.
* @param[in] filter_name The friendly name of the filter.
* @param[in] il
* A C++ initialize list containing acceptable file filter pattern.
* Every entries must be `const yycc_char8_t*` representing a single filter pattern.
* The list at least should have one valid pattern.
* This function will not validate these filter patterns, so please write them carefully.
* @return True if added success, otherwise false.
* @remarks This function allow you register multiple filter patterns for single friendly name.
* For example: `Add("Microsoft Word (*.doc; *.docx)", {"*.doc", "*.docx"})`
* @remarks
* This function allow you register multiple filter patterns for single friendly name.
* For example: <TT>Add(u8"Microsoft Word (*.doc; *.docx)", {u8"*.doc", u8"*.docx"})</TT>
*/
bool Add(const yycc_char8_t* filter_name, std::initializer_list<const yycc_char8_t*> il);
/**
* @brief Clear filter pairs for following re-use.
*/
void Clear() { m_Filters.clear(); }
/**
* @brief Get the count of added filter pairs.
* @return The count of already added filter pairs.
*/
size_t Count() const { return m_Filters.size(); }
/// @brief Clear filter pairs for following re-use.
void Clear() { m_Filters.clear(); }
/**
* @brief Generate Windows dialog system used data struct.
* @param win_result[out] The class holding the generated filter data struct.
* @return True if generation is success, otherwise false.
* @remarks User should not call this function, this function is used in internal code.
* @param[out] win_result The class receiving the generated filter data struct.
* @return True if generation success, otherwise false.
* @remarks
* Programmer should not call this function,
* this function is used as YYCC internal code.
*/
bool Generate(WinFileFilters& win_result) const;
@ -93,8 +110,10 @@ namespace YYCC::DialogHelper {
};
/**
* @brief The class represent the file dialog
* @details THis class is specific for Windows use, not user oriented.
* @brief The class representing the file dialog.
* @details
* This class is served for Windows used.
* Programmer should \b not create this class manually.
*/
class WinFileDialog {
friend class FileDialog;
@ -105,18 +124,28 @@ namespace YYCC::DialogHelper {
m_HasTitle(false), m_HasInitFileName(false), m_WinTitle(), m_WinInitFileName(),
m_WinInitDirectory(nullptr) {}
/// @brief Get whether this dialog has owner.
bool HasOwner() const { return m_WinOwner != NULL; }
/// @brief Get the \c HWND of dialog owner.
HWND GetOwner() const { return m_WinOwner; }
/// @brief Get the struct holding Windows used file filters data.
const WinFileFilters& GetFileTypes() const { return m_WinFileTypes; }
/// @brief Get the index of default selected file filter.
UINT GetDefaultFileTypeIndex() const { return m_WinDefaultFileTypeIndex; }
/// @brief Get whether dialog has custom title.
bool HasTitle() const { return m_HasTitle; }
/// @brief Get custom title of dialog.
const wchar_t* GetTitle() const { return m_WinTitle.c_str(); }
/// @brief Get whether dialog has custom initial file name.
bool HasInitFileName() const { return m_HasInitFileName; }
/// @brief Get custom initial file name of dialog
const wchar_t* GetInitFileName() const { return m_WinInitFileName.c_str(); }
/// @brief Get whether dialog has custom initial directory.
bool HasInitDirectory() const { return m_WinInitDirectory.get() != nullptr; }
/// @brief Get custom initial directory of dialog.
IShellItem* GetInitDirectory() const { return m_WinInitDirectory.get(); }
protected:
@ -124,15 +153,17 @@ namespace YYCC::DialogHelper {
WinFileFilters m_WinFileTypes;
/**
* @brief The default selected file type in dialog
* @remarks This is 1-based index according to Windows specification.
* In other words, you should plus 1 for this index when generating this struct from
* user oriented file dialog parameters.
* @remarks
* This is 1-based index according to Windows specification.
* In other words, when generating this struct from FileDialog to this struct this field should plus 1.
* Because the same field located in FileDialog is 0-based index.
*/
UINT m_WinDefaultFileTypeIndex;
bool m_HasTitle, m_HasInitFileName;
std::wstring m_WinTitle, m_WinInitFileName;
COMHelper::SmartIShellItem m_WinInitDirectory;
/// @brief Clear all data and reset them to default value.
void Clear() {
m_WinOwner = nullptr;
m_WinFileTypes.Clear();
@ -145,9 +176,10 @@ namespace YYCC::DialogHelper {
};
/**
* @brief The class represent the file dialog.
* @details This class is user oriented. User can use function manipulate file dialog properties
* and final generation function will produce Windows-understood data struct from this.
* @brief The class representing the file dialog.
* @details
* This class is served for programming using to describe every aspectes of the dialog.
* For how to use this struct, see \ref dialog_helper.
*/
class FileDialog {
public:
@ -158,27 +190,55 @@ namespace YYCC::DialogHelper {
m_Title(), m_InitFileName(), m_InitDirectory(),
m_HasTitle(false), m_HasInitFileName(false), m_HasInitDirectory(false) {}
/**
* @brief Set the owner of dialog.
* @param[in] owner The \c HWND pointing to the owner of dialog, or NULL to remove owner.
*/
void SetOwner(HWND owner) { m_Owner = owner; }
/**
* @brief Set custom title of dialog
* @param[in] title The string pointer to custom title, or nullptr to remove it.
*/
void SetTitle(const yycc_char8_t* title) {
if (m_HasTitle = title != nullptr)
m_Title = title;
}
/**
* @brief Fetch the struct describing file filters for future configuration.
* @return The reference to the struct describing file filters.
*/
FileFilters& ConfigreFileTypes() {
return m_FileTypes;
}
/**
* @brief Set the index of default selected file filter.
* @param[in] idx
* The index to default one.
* This must be a valid index in file filters.
*/
void SetDefaultFileTypeIndex(size_t idx) { m_DefaultFileTypeIndex = idx; }
/**
* @brief Set the initial file name of dialog
* @details If set, the file name will always be same one when opening dialog.
* @param[in] init_filename String pointer to initial file name, or nullptr to remove it.
*/
void SetInitFileName(const yycc_char8_t* init_filename) {
if (m_HasInitFileName = init_filename != nullptr)
m_InitFileName = init_filename;
}
/**
* @brief Set the initial directory of dialog
* @details If set, the opended directory will always be the same one when opening dialog
* @param[in] init_dir
* String pointer to initial directory.
* Invalid path or nullptr will remove this feature.
*/
void SetInitDirectory(const yycc_char8_t* init_dir) {
if (m_HasInitDirectory = init_dir != nullptr)
m_InitDirectory = init_dir;
}
/**
* @brief Clear file dialog parameters for following re-use.
*/
/// @brief Clear file dialog parameters for following re-use.
void Clear() {
m_Owner = nullptr;
m_HasTitle = m_HasInitFileName = m_HasInitDirectory = false;
@ -191,9 +251,11 @@ namespace YYCC::DialogHelper {
/**
* @brief Generate Windows dialog system used data struct.
* @param win_result[out] The class holding the generated filter data struct.
* @param[out] win_result The class receiving the generated filter data struct.
* @return True if generation is success, otherwise false.
* @remarks User should not call this function, this function is used in internal code.
* @remarks
* Programmer should not call this function.
* This function is used as YYCC internal code.
*/
bool Generate(WinFileDialog& win_result) const;
@ -204,16 +266,41 @@ namespace YYCC::DialogHelper {
FileFilters m_FileTypes;
/**
* @brief The default selected file type in dialog
* @remarks Although Windows notice that this is a 1-based index,
* but for universal experience, we order this is 0-based index.
* @remarks
* The index Windows used is 1-based index.
* But for universal experience, we order this is 0-based index.
* And do convertion when generating Windows used struct.
*/
size_t m_DefaultFileTypeIndex;
};
/**
* @brief Open the dialog which order user select single file to open.
* @param[in] params The configuration of dialog.
* @param[out] ret Full path to user selected file.
* @return False if user calcel the operation or something went wrong, otherwise true.
*/
bool OpenFileDialog(const FileDialog& params, yycc_u8string& ret);
/**
* @brief Open the dialog which order user select multiple file to open.
* @param[in] params The configuration of dialog.
* @param[out] ret The list of full path of user selected files.
* @return False if user calcel the operation or something went wrong, otherwise true.
*/
bool OpenMultipleFileDialog(const FileDialog& params, std::vector<yycc_u8string>& ret);
/**
* @brief Open the dialog which order user select single file to save.
* @param[in] params The configuration of dialog.
* @param[out] ret Full path to user selected file.
* @return False if user calcel the operation or something went wrong, otherwise true.
*/
bool SaveFileDialog(const FileDialog& params, yycc_u8string& ret);
/**
* @brief Open the dialog which order user select single directory to open.
* @param[in] params The configuration of dialog.
* @param[out] ret Full path to user selected directory.
* @return False if user calcel the operation or something went wrong, otherwise true.
*/
bool OpenFolderDialog(const FileDialog& params, yycc_u8string& ret);
}

View File

@ -10,7 +10,7 @@
#endif
/**
* @brief The helper for all encoding aspects.
* @brief The helper for all encoding stuff.
* @details
* For more infomations about how to use the functions provided by this namespace,
* please see \ref library_encoding and \ref encoding_helper.
@ -19,7 +19,7 @@ namespace YYCC::EncodingHelper {
#define _YYCC_U8(strl) u8 ## strl ///< The assistant macro for YYCC_U8.
#define YYCC_U8(strl) (reinterpret_cast<const ::YYCC::yycc_char8_t*>(_YYCC_U8(strl))) ///< The macro for creating UTF8 string literal. See \ref library_encoding.
#define YYCC_U8_CHAR(chr) (static_cast<YYCC::yycc_char8_t>(chr)) ///< The macro for casting normal char into YYCC UTF8 char type.
#define YYCC_U8_CHAR(chr) (static_cast<YYCC::yycc_char8_t>(chr)) ///< The macro for casting ordinary char type into YYCC UTF8 char type.
const yycc_char8_t* ToUTF8(const char* src);
yycc_char8_t* ToUTF8(char* src);

View File

@ -6,10 +6,7 @@
* @brief Windows specific unhandled exception processor.
* @details
* This namespace is Windows specific. On other platforms, the whole namespace is unavailable.
*
* This namespace allow user register unhandled exception handler on Windows
* to output error log into \c stderr and log file, and generate coredump if possible.
* This is useful for bug tracing on Windows, especially most Windows user are naive and don't know how to report bug.
* For how to utilize this namespace, please see \ref exception_helper.
*
*/
namespace YYCC::ExceptionHelper {
@ -20,9 +17,9 @@ namespace YYCC::ExceptionHelper {
* This function will set an internal function as unhandled exception handler on Windows.
*
* When unhandled exception raised,
* That internal function will output error stacktrace in standard output
* and log file (located in temp folder), and also generate a dump file
* in temp folder (for convenient debugging of developer when reporting bugs) if it can.
* That internal function will output error stacktrace in standard output,
* and generate log file and dump file in \c \%APPDATA\%/CrashDumps folder if it is possible.
* (for convenient debugging of developer when reporting bugs.)
*
* This function usually is called at the start of program.
*/
@ -33,7 +30,7 @@ namespace YYCC::ExceptionHelper {
* The reverse operation of Register().
*
* This function and Register() should always be used as a pair.
* You must call this function if you have called Register() before.
* You must call this function to release reources if you have called Register().
*
* This function usually is called at the end of program.
*/

View File

@ -3,21 +3,26 @@
#include <filesystem>
/**
* @brief \c std::filesystem::path related patches for UTF8 compatibility
* @details
* See also \ref fs_path_patch.
*/
namespace YYCC::FsPathPatch {
/**
* @brief Constructs the path from a UTF8 character sequence
* @param[in] u8_path UTF8 path string for building this std::filesystem::path.
* @return std::filesystem::path instance.
* @brief Constructs \c std::filesystem::path from UTF8 path.
* @param[in] u8_path UTF8 path string for building.
* @return \c std::filesystem::path instance.
* @exception std::invalid_argument Fail to parse given UTF8 string (maybe invalid?).
*/
std::filesystem::path FromUTF8Path(const yycc_char8_t* u8_path);
/**
* @brief Returns the UTF8 representation of the pathname
* @param path[in] The string to be output.
* @return UTF8 encoded string representing given path.
* @exception std::invalid_argument Fail to parse to UTF8 string.
* @brief Returns the UTF8 representation of given \c std::filesystem::path.
* @param[in] path The \c std::filesystem::path instance converting to UTF8 path.
* @return The UTF8 representation of given \c std::filesystem::path.
* @exception std::invalid_argument Fail to convert to UTF8 string.
*/
yycc_u8string ToUTF8Path(const std::filesystem::path& path);

View File

@ -4,6 +4,11 @@
#include <cstdio>
#include <filesystem>
/**
* @brief Some IO related stuff
* @details
* See also \ref io_helper.
*/
namespace YYCC::IOHelper {
#if UINTPTR_MAX == UINT32_MAX
@ -24,13 +29,13 @@ namespace YYCC::IOHelper {
#endif
/**
* @brief The UTF8 version of std::fopen.
* @brief The UTF8 version of \c std::fopen.
* @param[in] u8_filepath The UTF8 encoded path to the file to be opened.
* @param[in] u8_mode UTF8 encoded mode string of the file to be opened.
* @remarks
* This function is suit for Windows because std::fopen do not support UTF8 on Windows.
* On other platforms, this function will delegate request directly to std::fopen.
* @return FILE* of the file to be opened, or nullptr if failed.
* @return \c FILE* of the file to be opened, or nullptr if failed.
*/
FILE* UTF8FOpen(const yycc_char8_t* u8_filepath, const yycc_char8_t* u8_mode);

View File

@ -9,10 +9,24 @@
#include <charconv>
#include <array>
/**
* @brief The helper involving convertion between arithmetic types (integral, floating point and bool) and string
* @details
* See also \ref parser_helper.
*/
namespace YYCC::ParserHelper {
// Reference: https://zh.cppreference.com/w/cpp/utility/from_chars
/**
* @brief Try parsing given string to floating point types.
* @tparam _Ty The type derived from floating point type.
* @param[in] strl The string need to be parsed.
* @param[out] num
* The variable receiving result.
* There is no guarantee that the content is not modified when parsing failed.
* @return True if success, otherwise false.
*/
template<typename _Ty, std::enable_if_t<std::is_floating_point_v<_Ty>, int> = 0>
bool TryParse(const yycc_u8string_view& strl, _Ty& num) {
auto [ptr, ec] = std::from_chars(
@ -34,6 +48,16 @@ namespace YYCC::ParserHelper {
throw std::runtime_error("unreachable code.");
}
}
/**
* @brief Try parsing given string to integral types.
* @tparam _Ty The type derived from integral type.
* @param[in] strl The string need to be parsed.
* @param[out] num
* The variable receiving result.
* There is no guarantee that the content is not modified when parsing failed.
* @param[in] base integer base to use: a value between 2 and 36 (inclusive).
* @return True if success, otherwise false.
*/
template<typename _Ty, std::enable_if_t<std::is_integral_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0>
bool TryParse(const yycc_u8string_view& strl, _Ty& num, int base = 10) {
auto [ptr, ec] = std::from_chars(
@ -55,6 +79,15 @@ namespace YYCC::ParserHelper {
throw std::runtime_error("unreachable code.");
}
}
/**
* @brief Try parsing given string to bool types.
* @tparam _Ty The type derived from bool type.
* @param[in] strl The string need to be parsed ("true" or "false").
* @param[out] num
* The variable receiving result.
* There is no guarantee that the content is not modified when parsing failed.
* @return True if success, otherwise false.
*/
template<typename _Ty, std::enable_if_t<std::is_same_v<_Ty, bool>, int> = 0>
bool TryParse(const yycc_u8string_view& strl, _Ty& num) {
if (strl == YYCC_U8("true")) num = true;
@ -63,6 +96,15 @@ namespace YYCC::ParserHelper {
return true;
}
/**
* @brief Parse given string to arithmetic types.
* @tparam _Ty The type derived from arithmetic type.
* @param[in] strl The string need to be parsed.
* @return
* The parsing result.
* There is no guarantee about the content of this return value when parsing failed.
* It may be any possible value but usually is its default value.
*/
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty>, int> = 0>
_Ty Parse(const yycc_u8string_view& strl) {
_Ty ret;
@ -72,6 +114,12 @@ namespace YYCC::ParserHelper {
// Reference: https://en.cppreference.com/w/cpp/utility/to_chars
/**
* @brief Return a string version of given arithmetic value.
* @tparam _Ty The type derived from arithmetic type.
* @param[in] num The value getting string version.
* @return The string version of given value.
*/
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0>
yycc_u8string ToString(_Ty num) {
std::array<yycc_char8_t, 64> buffer;
@ -91,6 +139,12 @@ namespace YYCC::ParserHelper {
throw std::runtime_error("unreachable code.");
}
}
/**
* @brief Return a string version of given bool value.
* @tparam _Ty The type derived from bool type.
* @param[in] num The value getting string version.
* @return The string version of given value ("true" or "false").
*/
template<typename _Ty, std::enable_if_t<std::is_same_v<_Ty, bool>, int> = 0>
yycc_u8string ToString(_Ty num) {
if (num) return yycc_u8string(YYCC_U8("true"));

View File

@ -170,7 +170,7 @@ namespace YYCC::StringHelper {
#pragma region Upper Lower
template<bool bIsToLower>
void GeneralStringLowerUpper(yycc_u8string& strl) {
static void GeneralStringLowerUpper(yycc_u8string& strl) {
// References:
// https://en.cppreference.com/w/cpp/algorithm/transform
// https://en.cppreference.com/w/cpp/string/byte/tolower

View File

@ -6,59 +6,141 @@
#include <functional>
#include <vector>
/**
* @brief The helper containing string operations
* @details
* See also \ref string_helper.
*/
namespace YYCC::StringHelper {
/**
* @brief Perform a string formatting operation.
* @param[out] strl
* The string container receiving the result.
* There is no guarantee that the content is not modified when function failed.
* @param[in] format The format string.
* @param[in] ... Argument list of format string.
* @return True if success, otherwise false.
*/
bool Printf(yycc_u8string& strl, const yycc_char8_t* format, ...);
/**
* @brief Perform a string formatting operation.
* @param[out] strl
* The string container receiving the result.
* There is no guarantee that the content is not modified when function failed.
* @param[in] format The format string.
* @param[in] argptr Argument list of format string.
* @return True if success, otherwise false.
*/
bool VPrintf(yycc_u8string& strl, const yycc_char8_t* format, va_list argptr);
/**
* @brief Perform a string formatting operation.
* @param[in] format The format string.
* @param[in] ... Argument list of format string.
* @return The formatting result. Empty string if error happened.
*/
yycc_u8string Printf(const yycc_char8_t* format, ...);
/**
* @brief Perform a string formatting operation.
* @param[in] format The format string.
* @param[in] argptr Argument list of format string.
* @return The formatting result. Empty string if error happened.
*/
yycc_u8string VPrintf(const yycc_char8_t* format, va_list argptr);
/**
* @brief Modify given string with all occurrences of substring \e old replaced by \e new.
* @param[in,out] strl The string for replacing
* @param[in] _from_strl The \e old string.
* @param[in] _to_strl The \e new string.
*/
void Replace(yycc_u8string& strl, const yycc_char8_t* _from_strl, const yycc_char8_t* _to_strl);
/**
* @brief Return a copy with all occurrences of substring \e old replaced by \e new.
* @param[in] _strl The string for replacing
* @param[in] _from_strl The \e old string.
* @param[in] _to_strl The \e new string.
* @return The result of replacement.
*/
yycc_u8string Replace(const yycc_char8_t* _strl, const yycc_char8_t* _from_strl, const yycc_char8_t* _to_strl);
/**
* @brief The data provider of general Join function.
* For the implementation of this function:
* Function return true to continue join. otherwise return false to terminate join.
* The argument assigned in the calling returning false is not included.
* During calling, implementation should assign the string view to the string need to be joined in given argument.
* @brief The data provider of general join function.
* @details
* For programmer using lambda to implement this function pointer:
* \li During calling, implementation should assign the reference of string view passed in argument
* to the string which need to be joined.
* \li Function return true to continue joining. otherwise return false to stop joining.
* The argument content assigned in the calling returning false is not included in join process.
*/
using JoinDataProvider = std::function<bool(yycc_u8string_view&)>;
/**
* @brief General Join function.
* @details This function use function pointer as a general data provider interface,
* so this function suit for all types container, the user only need write a little bit adaption code.
* @param fct_data[in] The function pointer to data provider.
* @param decilmer[in] The decilmer.
* @return A std::string instance which containing the join result.
* @brief Universal join function.
* @details
* This function use function pointer as a general data provider interface,
* so this function suit for all types container.
* You can use this universal join function for any custom container by
* using C++ lambda syntax to create a code block adapted to this function pointer.
* @param[in] fct_data The function pointer in JoinDataProvider type prividing the data to be joined.
* @param[in] decilmer The decilmer used for joining.
* @return The result string of joining.
*/
yycc_u8string Join(JoinDataProvider fct_data, const yycc_char8_t* decilmer);
/**
* @brief Specialized Join function for common used container.
* @param data
* @param decilmer
* @param reversed
* @return
* @brief Specialized join function for \c std::vector.
* @param[in] data The list to be joined.
* @param[in] decilmer The decilmer used for joining.
* @param[in] reversed True if this list should be joined in reversed order.
* @return The result string of joining.
*/
yycc_u8string Join(const std::vector<yycc_u8string>& data, const yycc_char8_t* decilmer, bool reversed = false);
/**
* @brief Return a copy of the string converted to lowercase.
* @param[in] strl The string to be lowercase.
* @return The copy of the string converted to lowercase.
*/
yycc_u8string Lower(const yycc_char8_t* strl);
/**
* @brief Convert given string to lowercase.
* @param[in,out] strl The string to be lowercase.
*/
void Lower(yycc_u8string& strl);
/**
* @brief Return a copy of the string converted to uppercase.
* @param[in] strl The string to be uppercase.
* @return The copy of the string converted to uppercase.
*/
yycc_u8string Upper(const yycc_char8_t* strl);
/**
* @brief Convert given string to uppercase.
* @param[in,out] strl The string to be uppercase.
*/
void Upper(yycc_u8string& strl);
/**
* @brief General Split function.
* @param strl[in] The string need to be splitting.
* If this is nullptr, the result will be empty.
* @param _decilmer[in] The decilmer for splitting.
* If decilmer is nullptr or zero length, the result will only have 1 element which is original string.
* @return
* @remarks This function may be low performance because it just a homebrew Split functon.
* It can works in most toy cases but not suit for high performance scenario.
* Also, this function will produce a copy of original string because it is not zero copy.
* @brief Split given string with specified decilmer.
* @param[in] strl The string need to be splitting.
* @param[in] _decilmer The decilmer for splitting.
* @return
* The split result.
* \par
* If given string is empty, or decilmer is nullptr or empty,
* the result container will only contain 1 entry which is equal to given string.
*/
std::vector<yycc_u8string> Split(const yycc_u8string_view& strl, const yycc_char8_t* _decilmer);
/**
* @brief Split given string with specified decilmer as string view.
* @param[in] strl The string need to be splitting.
* @param[in] _decilmer The decilmer for splitting.
* @return
* The split result with string view format.
* This will not produce any copy of original string.
* \par
* If given string is empty, or decilmer is nullptr or empty,
* the result container will only contain 1 entry which is equal to given string.
* @see Split(const yycc_u8string_view&, const yycc_char8_t*)
*/
std::vector<yycc_u8string_view> SplitView(const yycc_u8string_view& strl, const yycc_char8_t* _decilmer);
}

View File

@ -9,10 +9,11 @@
#include "WinImportSuffix.hpp"
/**
* @brief The helper providing assistance to Win32 functions.
* @brief The helper providing assistance of Win32 functions.
* @details
* This helper is Windows specific.
* If current environment is not Windows, the whole namespace will be unavailable.
* See also \ref win_fct_helper
*/
namespace YYCC::WinFctHelper {
@ -24,16 +25,16 @@ namespace YYCC::WinFctHelper {
*
* This function is frequently used by DLL.
* Because some design need the HANDLE of current module, not the host EXE loading your DLL.
* For example, you may want to get the name of your built DLL at runtime, then you should pass current module HANDLE, not the HANDLE of EXE.
* Or, if you want to get the path to your DLL, you also should pass current module HANDLE.
* For example, you may want to get the path of your built DLL, or fetch resources from your DLL at runtime,
* then you should pass current module HANDLE, not NULL or the HANDLE of EXE.
* @return A Windows HANDLE pointing to current module, NULL if failed.
*/
HMODULE GetCurrentModule();
/**
* @brief Get path to Windows temp folder.
* @param[out] ret
* The variable receiving UTF8 encoded path to Windows temp folder.
* @brief Get path to Windows temporary folder.
* @details Windows temporary folder usually is the target of \%TEMP\%.
* @param[out] ret The variable receiving UTF8 encoded path to Windows temp folder.
* @return True if success, otherwise false.
*/
bool GetTempDirectory(yycc_u8string& ret);
@ -41,20 +42,18 @@ namespace YYCC::WinFctHelper {
/**
* @brief Get the file name of given module HANDLE
* @param[in] hModule
* The HANDLE to the module where we want get file name.
* It is same as the HANDLE parameter of \c GetModuleFileName.
* @param[out] ret
* The variable receiving UTF8 encoded file name of given module.
* The HANDLE to the module where you want to get file name.
* It is same as the HANDLE parameter of Win32 \c GetModuleFileName.
* @param[out] ret The variable receiving UTF8 encoded file name of given module.
* @return True if success, otherwise false.
*/
bool GetModuleFileName(HINSTANCE hModule, yycc_u8string& ret);
/**
* @brief Get the path to LOCALAPPDATA.
* @details LOCALAPPDATA usually was used as putting local app data files
* @param[out] ret
* The variable receiving UTF8 encoded path to LOCALAPPDATA.
* @return
* @brief Get the path to \%LOCALAPPDATA\%.
* @details \%LOCALAPPDATA\% usually was used as putting local app data files
* @param[out] ret The variable receiving UTF8 encoded path to LOCALAPPDATA.
* @return True if success, otherwise false.
*/
bool GetLocalAppData(yycc_u8string& ret);

View File

@ -26,8 +26,14 @@
// Define the UTF8 char type we used.
// And do a polyfill if no embedded char8_t type.
#include <string>
#include <string_view>
/**
* @brief Library core namespace
* @details Almost library functions are located in this namespace.
*/
namespace YYCC {
#if defined(__cpp_char8_t)
using yycc_char8_t = char8_t;
@ -38,6 +44,27 @@ namespace YYCC {
using yycc_u8string = std::basic_string<yycc_char8_t>;
using yycc_u8string_view = std::basic_string_view<yycc_char8_t>;
#endif
}
/**
\typedef yycc_char8_t
\brief YYCC UTF8 char type.
\details
This char type is an alias to \c std::char8_t if your current C++ standard support it.
Otherwise it is defined as <TT>unsigned char</TT> as C++ 20 stdandard does.
*/
/**
\typedef yycc_u8string
\brief YYCC UTF8 string container type.
\details
This type is defined as \c std::basic_string<yycc_char8_t>.
It is equal to \c std::u8string if your current C++ standard support it.
*/
/**
\typedef yycc_u8string_view
\brief YYCC UTF8 string view type.
\details
This type is defined as \c std::basic_string_view<yycc_char8_t>.
It is equal to \c std::u8string_view if your current C++ standard support it.
*/