1
0

3 Commits

Author SHA1 Message Date
ff2600c8fb fix: fix libcom top headers 2026-01-24 17:49:59 +08:00
9228f343ff chore: change build script to make BMap can be used by CMake
- change script for installing BMap like LibCmo although no one will use it.
- move package install command into respective cmake script.
- change BMap project layout
2026-01-24 17:32:22 +08:00
f9ab66dfc2 chore: update build script
- change project layout for better understanding.
- update build script for more close to standard cmake way.
2026-01-24 17:16:13 +08:00
85 changed files with 371 additions and 1147 deletions

22
.gitignore vendored
View File

@@ -1,22 +1,24 @@
# -------------------- Personal --------------------
## ======== Personal ========
# Ignore build resources
out/
build/
install/
extern/
temp/
# Ignore all possible test used Virtools files
*.nmo
*.cmo
*.nms
*.vmo
# Ignore CMake generated version header
LibCmo/VTVersion.hpp
# Ignore temporary Visual Studio files and folders
temp/
out/
# Ignore CMake generated stuff
CMakeSettings.json
# -------------------- VSCode --------------------
## ======== VSCode ========
.vscode/
# -------------------- CMake --------------------
## ======== CMake ========
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
@@ -29,7 +31,7 @@ compile_commands.json
CTestTestfile.cmake
_deps
# -------------------- Visual Studio --------------------
## ======== Visual Studio ========
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##

View File

@@ -3,21 +3,22 @@ add_library(BMap SHARED "")
# Setup sources
target_sources(BMap
PRIVATE
BMap.cpp
BMExports.cpp
BMap/BMap.cpp
BMap/BMExports.cpp
)
# Setup headers
target_sources(BMap
PRIVATE
PUBLIC
FILE_SET HEADERS
FILES
BMap.hpp
BMExports.hpp
BMap/BMap.hpp
BMap/BMExports.hpp
)
# Setup header infomation
target_include_directories(BMap
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}"
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
# Setup linked library infomation
target_link_libraries(BMap
@@ -25,31 +26,42 @@ PRIVATE
YYCC::YYCCommonplace
LibCmo
)
# Setup C++ standard
set_target_properties(BMap
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
)
# Setup project macros
target_compile_definitions(BMap
# Enable export macro
target_compile_definitions(BMap
PRIVATE
BMAP_EXPORTING
# Order Unicode charset for private using
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:UNICODE>
$<$<CXX_COMPILER_ID:MSVC>:_UNICODE>
)
# Order build as UTF-8 in MSVC
target_compile_options(BMap
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
)
# Install BMap only on Release mode
# Install binary and headers
install(TARGETS BMap
CONFIGURATIONS Release RelWithDebInfo MinSizeRel
RUNTIME DESTINATION ${YYCC_INSTALL_BIN_PATH}
EXPORT BMapTargets
LIBRARY DESTINATION ${NEMO_INSTALL_LIB_PATH}
ARCHIVE DESTINATION ${NEMO_INSTALL_LIB_PATH}
INCLUDES DESTINATION ${NEMO_INSTALL_INCLUDE_PATH}
FILE_SET HEADERS DESTINATION ${NEMO_INSTALL_INCLUDE_PATH}
)
# Install target
install(EXPORT BMapTargets
FILE BMapTargets.cmake
NAMESPACE NeMo::
DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/BMap
)
# Package configuration file
write_basic_package_version_file(
BMapConfigVersion.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY SameMinorVersion
)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/../CMake/BMapConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/BMapConfig.cmake"
INSTALL_DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/BMap
)
# Copy package files to install destination
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/BMapConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/BMapConfigVersion.cmake"
DESTINATION
${NEMO_INSTALL_LIB_PATH}/cmake/BMap
)

View File

@@ -0,0 +1,7 @@
@PACKAGE_INIT@
# Include targets file
include("${CMAKE_CURRENT_LIST_DIR}/BMapTargets.cmake")
check_required_components(BMap)

52
CMake/FindSTB.cmake Normal file
View File

@@ -0,0 +1,52 @@
# - Find STB library
# Find the STB headers
#
# This module defines the following variables:
# STB_FOUND - True if STB was found
# STB_INCLUDE_DIRS - Location of the STB headers
#
# This module defines the following imported targets:
# STB::STB - Header-only interface library for STB
# STB_ROOT must be specified by the user
if (NOT DEFINED STB_ROOT)
set(STB_FOUND FALSE)
else ()
# Look for STB_image.h in the specified STB_ROOT directory
find_path(STB_INCLUDE_DIR
NAMES STB_image.h
HINTS ${STB_ROOT}
NO_DEFAULT_PATH
)
# Check find status
if(STB_INCLUDE_DIR)
set(STB_FOUND TRUE)
set(STB_INCLUDE_DIRS ${STB_INCLUDE_DIR})
else()
set(STB_FOUND FALSE)
endif()
# Hide intermediate variables
mark_as_advanced(STB_INCLUDE_DIR)
endif ()
# Check find result
if (STB_FOUND)
# Add library
message(STATUS "Found STB library")
# Add library
add_library(STB INTERFACE IMPORTED)
# Add alias to it
add_library(STB::STB ALIAS STB)
# Setup header files
set_target_properties(STB PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${STB_INCLUDE_DIRS}"
)
else ()
# If it is required, show infomations.
if (std_FIND_REQUIRED)
message(FATAL_ERROR "Fail to find STB library.")
endif ()
endif ()

View File

@@ -1,9 +0,0 @@
if (WIN32)
# In Windows, we should not import Iconv.
# Send a notice to programmer.
message("Windows environment detected, skip finding Iconv!")
else ()
# In non-Windows, we simply import Iconv from CMake preset.
# It will produce Iconv::Iconv target for including and linking.
find_package(Iconv REQUIRED)
endif ()

View File

@@ -1,14 +0,0 @@
# Check stb path variable
if (NOT DEFINED STB_IMAGE_PATH)
message(FATAL_ERROR "You must set STB_IMAGE_PATH variable to the root directory of std-image repository.")
endif()
# Add library
add_library(stb-image INTERFACE IMPORTED)
# Add alias for it
add_library(stb::stb-image ALIAS stb-image)
# Setup header files
set_target_properties(stb-image PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${STB_IMAGE_PATH}"
)

View File

@@ -1,15 +0,0 @@
# Check YYCC path environment variable
if (NOT DEFINED YYCC_PATH)
message(FATAL_ERROR "You must set YYCC_PATH variable to one of YYCC CMake distribution installation path.")
endif()
# Find YYCC library
# It will produce YYCC::YYCCommonplace target for including and linking.
#
# Please note we MUST set CMake variable YYCCommonplace_ROOT to make sure CMake can found YYCC in out given path.
# The cache status of YYCCommonplace_ROOT is doesn't matter.
# CMake will throw error if we use HINTS feature in find_package to find YYCC.
set(YYCCommonplace_ROOT ${YYCC_PATH} CACHE PATH
"The path to YYCC CMake distribution installation path.")
find_package(YYCCommonplace REQUIRED)

View File

@@ -1,34 +0,0 @@
if (WIN32)
# In Windows, we use custom way to import ZLib.
# Before using this CMake file in Windows, you should do following steps first.
# 1. Get ZLib repository: https://github.com/madler/zlib
# 2. Navigate to `contrib/vstudio` and choose a proper Visual Studio project according to your environment.
# 3. Open project file and build. Then you will get the built binary.
# 4. The directory binary located is the argument you should passed to ZLIB_BINARY_PATH, for example: `contrib/vstudio/vc14/x64/ZlibDllRelease`
# Check ZLib path variable
if (NOT DEFINED ZLIB_HEADER_PATH)
message(FATAL_ERROR "You must set ZLIB_HEADER_PATH to the root directory of ZLib repository.")
endif()
if (NOT DEFINED ZLIB_BINARY_PATH)
message(FATAL_ERROR "You must set ZLIB_BINARY_PATH to the directory where include binary built by contributed Visual Studio project.")
endif()
# Add imported library
add_library(ZLIB INTERFACE IMPORTED)
# Add alias for it to let it has the same behavior with CMake imported ZLib.
add_library(ZLIB::ZLIB ALIAS ZLIB)
# Setup header files
set_target_properties(ZLIB PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${ZLIB_HEADER_PATH}"
)
# Setup lib files
set_target_properties(ZLIB PROPERTIES
INTERFACE_LINK_LIBRARIES
"${ZLIB_BINARY_PATH}/zlibwapi.lib"
)
else ()
# In non-Windows, we simply import ZLib from CMake preset.
# It will produce ZLIB::ZLIB target for including and linking.
find_package(ZLIB REQUIRED)
endif ()

View File

@@ -1,6 +1,8 @@
# Minimum required CMake version
cmake_minimum_required(VERSION 3.23)
# Project definition
project(NeMo
VERSION 0.3.0
VERSION 0.4.0
LANGUAGES CXX
)
@@ -9,6 +11,11 @@ option(NEMO_BUILD_UNVIRT "Build Unvirt, the console interface operator of LibCmo
option(NEMO_BUILD_BMAP "Build BMap, the example use of LibCmo which can read and write Ballance game map." OFF)
option(NEMO_BUILD_DOC "Build document of LibCmo and all related stuff." OFF)
# Set C++ standards
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Setup install path from CMake provided install path for convenient use.
include(GNUInstallDirs)
set(NEMO_INSTALL_INCLUDE_PATH ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH
@@ -20,11 +27,17 @@ set(NEMO_INSTALL_BIN_PATH ${CMAKE_INSTALL_BINDIR} CACHE PATH
set(NEMO_INSTALL_DOC_PATH ${CMAKE_INSTALL_DOCDIR} CACHE PATH
"Non-arch doc install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.")
# Import essential packages
include(${CMAKE_CURRENT_LIST_DIR}/CMake/custom_import_zlib.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMake/custom_import_iconv.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMake/custom_import_yycc.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMake/custom_import_stb.cmake)
# Add our CMake in module found path
set(CMAKE_MODULE_PATH
"${CMAKE_CURRENT_LIST_DIR}/CMake"
)
# Find required packages
find_package(ZLIB REQUIRED)
find_package(YYCCommonplace REQUIRED)
find_package(STB REQUIRED)
# Import package helper
include(CMakePackageConfigHelpers)
# If we are not in Windows environment, and we need to build shared library BMap,
# we should enable PIC (position independent code), otherwise build process will fail.
@@ -36,7 +49,7 @@ if ((NOT WIN32) AND NEMO_BUILD_BMAP)
set(CMAKE_POSITION_INDEPENDENT_CODE True)
endif ()
# Import build targets
# Include build targets by options
add_subdirectory(LibCmo)
if (NEMO_BUILD_UNVIRT)
add_subdirectory(Unvirt)
@@ -47,31 +60,3 @@ endif ()
if (NEMO_BUILD_DOC)
add_subdirectory(Documents)
endif ()
# Install target and package
# Install target
install(EXPORT LibCmoTargets
FILE LibCmoTargets.cmake
NAMESPACE NeMo::
DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)
# Package configuration file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
LibCmoConfigVersion.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY SameMinorVersion
)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/CMake/LibCmoConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfig.cmake"
INSTALL_DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)
# Copy package files to install destination
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfigVersion.cmake"
DESTINATION
${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)

View File

@@ -1,35 +1,43 @@
# Compile Manual
## Choose Version
We suggest that you only use stable version (tagged commit).
The latest commit always present current works.
It means that it is not stable and work in progress.
## Requirements
This project require:
* CMake 3.23 at least.
* The common compiler supporting C++ 20 (GCC / Clang / MSVC).
* The common compiler supporting C++ 23 (GCC / Clang / MSVC).
* Littile-endian architecture system.
* zlib.
* iconv (non-Windows system required).
* [stb](https://github.com/nothings/stb): For image read and write.
* [YYCCommonplace](https://github.com/yyc12345/YYCCommonplace): My personal invented library concentrating some common functions for mine.
Since libcmo21 0.2.0, we only provide it in CMake build system. So Windows user should install CMake first or use Visual Studio directly (Visual Studio provides CMake build system supports).
* [stb](https://github.com/nothings/stb).
* [YYCCommonplace](https://github.com/yyc12345/YYCCommonplace).
* Doxygen (Required if you build documentation).
## Preparations
### YYCCommonplace
You should clone YYCCommonplace and switch to the latest release tag (or specified commit hash provided with libcmo21 release infos if you are building for specific libcmo21 version). When configuring YYCCommonplace, you should notice following infos:
Following these steps to prepare YYCCommonplace:
* Please make sure that you have specified C++ 20 explicitly by passing `-DCMAKE_CXX_STANDARD=20` in command line. This is crucial because libcmo21 use C++ 20, and YYCCommonplace's ABI is incompatible between C++ 17 version and C++ 20 version.
* If you need `BMap` in final libcmo21 built artifacts, and you are in non-Windows system now, please specify position independent code flag by passing `-DCMAKE_POSITION_INDEPENDENT_CODE=True` in command line. GCC and Clang will reject linking if you don't flag it.
1. Clone YYCCommonplace first.
1. Switch to the latest **release** tag, or **specified commit hash** provided with libcmo21 release infos if you are building for specific libcmo21 version.
1. Following compile manual provided by YYCCommonplace to configure, compile and install it.
After configuring, you can normally build YYCCommonplace like a common CMake project.
Please note if your final program or dynamic library is provided for end user, please choose `RelWithDebInfo` build type (`Release` is not suggested because it will strip all debug infos and it is not good for bug reporter, which is embedded in program, to report crash). If final program is served for programmer debugging, please choose `Debug` build type.
> [!IMPORTANT]
> If you need `BMap` component in final libcmo21 built artifacts, and you are in non-Windows system now, please specify position independent code flag by passing `-DCMAKE_POSITION_INDEPENDENT_CODE=True` in command line when configuring YYCCommonplace. Otherwise GCC and Clang will reject linking.
### stb
You should clone stb repository first, then switch to a specific commit hash `2e2bef463a5b53ddf8bb788e25da6b8506314c08`. In ideally scenario, people like to choose the latest commit. However, I not frequently update this dependency.
Following these steps to prepare stb:
1. Clone stb repository first.
1. Switch to a **specific commit hash** `2e2bef463a5b53ddf8bb788e25da6b8506314c08`. I do not frequently update this dependency so using the latest commit is inviable.
> [!NOTE]
> std is a header-only C project. So we don't need compile it. libcmo21 will use homemade CMake script to find it.
### zlib
@@ -37,47 +45,109 @@ If you are in Windows, you should download zlib source code and build it with gi
If you are running on non-Windows system. You usually do not need to do anything. Because zlib development environment may be configured by your package manager correctly.
## Compile
If you are in Windows, or in Linux but want to use specific zlib version due to various reasons, following these steps to prepare zlib:
### Directory Hierarchy
1. Download zlib source code from its official.
1. Extract it into a directory.
1. Enter this directory and create 2 subdirectory `build` and `install` for CMake build and install respectively.
1. Enter `build` directory and configure CMake with extra `-DCMAKE_CXX_STANDARD=23 -DZLIB_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=<path-to-install>` parameters. And `<path-to-install>` is the absolute path to your created `install` directory in previous step (Idk why `--prefix` argument is not works for zlib).
1. Use CMake to build zlib
1. Use CMake to install zlib into previous we created `install` directory.
First, create subdirectory `Bin/build` and `Bin/install` at the root directory of libcmo21.
> [!NOTE]
> We use CMake, rather than any other to compile zlib because zlib provide it, and we also use CMake as our build system, so that we do not need to write any extra files for adaption.
### Configuration
> [!CAUTION]
> Windows developer should highly notice that please do NOT use Visual Studio file located in `contrib/vstudio` directory to produce binary zlib on Windows. That project will produce `zlibwapi.dll` which is not our expected `zlib.dll`. Please use Visual Studio embedded CMake to configure zlib and compile it directly.
Then enter subdirectory `Bin/build` and use following command to configure CMake:
### Doxygen
- Windows (MSVC): `cmake -DNEMO_BUILD_UNVIRT=ON -DNEMO_BUILD_BMAP=ON -DNEMO_BUILD_DOC=OFF -DSTB_IMAGE_PATH=<path-to-stb> -DYYCC_PATH=<path-to-yycc-install> -DZLIB_HEADER_PATH=<path-to-zlib-hdr> -DZLIB_BINARY_PATH=<path-to-zlib-bin> ../..`
- non-Windows: `cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DNEMO_BUILD_UNVIRT=ON -DNEMO_BUILD_BMAP=ON -DNEMO_BUILD_DOC=OFF -DSTB_IMAGE_PATH=<path-to-stb> -DYYCC_PATH=<path-to-yycc-install> ../..`
Doxygen is required only if you need to build documentation.
If you don't need this please skip this chapter.
The arguments in command should be replaced by:
We use Doxygen 1.9.7.
It would be okey use other versions but I have not test on them.
* `<path-to-stb>`: The root directory of your cloned stb repository.
* `<path-to-yycc-install>`: The directory to installed CMake package you chosen when building YYCCommonplace.
* `<path-to-zlib-hdr>` (Windows only): The root directory of downloaded zlib source code.
* `<path-to-zlib-bin>` (Windows only): The directory where you can find built `zlibwapi.dll`.
YYCCommonplace use Doxygen as its documentation system.
So before compiling, you must make sure `doxygen` are presented in your environment.
The switches in command can be switched as you wish:
## Build and Install
* `NEMO_BUILD_UNVIRT`: Build `Unvirt`, a command line application debugging Virtools files.
* `NEMO_BUILD_BMAP`: Build `BMap`, a dynamic library specific used for loading Ballance map file. If you are coming from my another project [BallanceBlenderPlugin](https://github.com/yyc12345/BallanceBlenderHelper), this is what you need.
* `NEMO_BUILD_DOC`: Build the document of libcmo21.
There are 2 different ways to build this project.
If you are the user of this project (just want this project to make something works), please choose "User Build".
If you are a developer (developer of this project, or use this project as dependency to develop your project), please choose "Developer Build".
### Build
### User Build
Execute following command to build libcmo21.
"User Build" is basically how GitHub Action build this project.
* Windows: `cmake --build . --config RelWithDebInfo`
* non-Windows: `cmake --build .`
Under **the root directory** of this project, execute:
### Build Type
- `Script/windows_build.bat` on Windows
- or `Script/linux_build.sh` on Linux
- or `Script/macos_build.sh` on macOS
Like YYCCommonplace, we suggest `RelWithDebInfo` for end user. If you want to build for programmer debugging, please replace all `RelWithDebInfo` to `Debug`. The build type between YYCCommonplace and libcmo21 should keep same to reduce any possibility about ABI incompatible issue.
The final built artifact is under `Bin/install` directory.
## Install
### Developer Build
Currently the CMake install script still has some bugs and can not work as expected. So as the alternative, just go into build directory and find your final program please. It's pretty simple.
#### Configurable Variables
## Note
First, there is a list listing all variables you may configure during compiling.
You may face issue when compiling this program on Linux or macOS because I develop this project on Windows frequently. The compatibility with Linux will only be checked just before releasing. And I don't have any Apple device to check the compatibility with macOS. So, for Linux issue, please report it directly and I will try to fix. For macOS bug, PR is welcomed.
* `NEMO_BUILD_UNVIRT`: Set it to `ON` to build `Unvirt`. `ON` in default.
This is an interactive tool for loading, saving Virtools file.
It is extremely useful for debugging this project.
* `NEMO_BUILD_BMAP`: Set it to `ON` to build `BMap`. `OFF` in default.
It is a dynamic library specific used for loading Ballance map file.
If you are coming from my another project [BallanceBlenderPlugin](https://github.com/yyc12345/BallanceBlenderHelper), this is what you need.
* `NEMO_BUILD_DOC`: Set it to `ON` to build documentation. `OFF` in default.
It may be useful for the developer who firstly use this project in their own projects.
Please note that generated documentation is different in different platforms.
* `YYCCommonplace_ROOT`: Set to the install path of YYCCommonplace.
* `stb_ROOT`: Set to the root directory of stb.
* `ZLIB_ROOT`: Set to the install path of zlib.
If you are using zlib which is not build by your own, you usually do not need specify this variable.
#### Configure CMake
When configure CMake, you may use different options on different platforms.
Following list may help you.
- On Windows:
* `-A Win32` or `-A x64` to specify architecture.
- On Linux or other POSIX systems:
* `-DCMAKE_BUILD_TYPE=Debug` or `-DCMAKE_BUILD_TYPE=Release` to specify build type.
Additionally, you can attach any variables introduced above with `-D` option during CMake configurations.
> [!NOTE]
> Position independent code flag is automatically added if you enable `BMap` so you don't need manually specify it. You just need to make sure that all dependencies enable this.
#### Build with CMake
After configuration, you can use `cmake --build .` to build project,
with additional options on different platforms.
Following list may help you.
- On Windows:
* `--config Debug` or `--config Release` to specify build type.
- On Linux or other POSIX systems:
* None
#### Install with CMake
After building, you can use `cmake --install . --prefix <path-to-prefix>`
to install project into given path, with additional options on different platforms.
Following list may help you.
- On Windows:
* `--config Debug` or `--config Release` to specify build type.
- On Linux or other POSIX systems:
* None
## Compatibility Notes
You may face issue when compiling this program on Linux or macOS because I develop this project on Windows frequently.
The compatibility with Linux and macOS will only be checked just before releasing.
And, I don't have any Apple devices, so the compatibility with macOS is checked by GitHub Action.

View File

@@ -1,7 +1,7 @@
# Configure version file
configure_file(
${CMAKE_CURRENT_LIST_DIR}/../CMake/VTVersion.hpp.in
${CMAKE_CURRENT_LIST_DIR}/VTVersion.hpp
${CMAKE_CURRENT_LIST_DIR}/LibCmo/VTVersion.hpp.in
${CMAKE_CURRENT_LIST_DIR}/LibCmo/VTVersion.hpp
@ONLY
)
@@ -10,93 +10,92 @@ add_library(LibCmo STATIC "")
# Setup static library sources
target_sources(LibCmo
PRIVATE
# Assistant source files
VTEncoding.cpp
VTImage.cpp
# NeMo Shared
LibCmo/VTUtils.cpp
LibCmo/VTImage.cpp
# CK2
CK2/CKBitmapData.cpp
CK2/CKContext.cpp
CK2/CKFileOthers.cpp
CK2/CKFileReader.cpp
CK2/CKFileWriter.cpp
CK2/CKGlobals.cpp
CK2/CKStateChunkOthers.cpp
CK2/CKStateChunkReader.cpp
CK2/CKStateChunkWriter.cpp
LibCmo/CK2/CKBitmapData.cpp
LibCmo/CK2/CKContext.cpp
LibCmo/CK2/CKFileOthers.cpp
LibCmo/CK2/CKFileReader.cpp
LibCmo/CK2/CKFileWriter.cpp
LibCmo/CK2/CKGlobals.cpp
LibCmo/CK2/CKStateChunkOthers.cpp
LibCmo/CK2/CKStateChunkReader.cpp
LibCmo/CK2/CKStateChunkWriter.cpp
# CK2 Data Handler
CK2/DataHandlers/CKBitmapHandler.cpp
LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp
# CK2 Manager
CK2/MgrImpls/CKBaseManager.cpp
CK2/MgrImpls/CKObjectManager.cpp
CK2/MgrImpls/CKPathManager.cpp
LibCmo/CK2/MgrImpls/CKBaseManager.cpp
LibCmo/CK2/MgrImpls/CKObjectManager.cpp
LibCmo/CK2/MgrImpls/CKPathManager.cpp
# CK2 Object
CK2/ObjImpls/CK3dEntity.cpp
CK2/ObjImpls/CKBeObject.cpp
CK2/ObjImpls/CKGroup.cpp
CK2/ObjImpls/CKMaterial.cpp
CK2/ObjImpls/CKMesh.cpp
CK2/ObjImpls/CKObject.cpp
CK2/ObjImpls/CKTexture.cpp
CK2/ObjImpls/CKLight.cpp
CK2/ObjImpls/CKTargetLight.cpp
CK2/ObjImpls/CKCamera.cpp
CK2/ObjImpls/CKTargetCamera.cpp
LibCmo/CK2/ObjImpls/CK3dEntity.cpp
LibCmo/CK2/ObjImpls/CKBeObject.cpp
LibCmo/CK2/ObjImpls/CKGroup.cpp
LibCmo/CK2/ObjImpls/CKMaterial.cpp
LibCmo/CK2/ObjImpls/CKMesh.cpp
LibCmo/CK2/ObjImpls/CKObject.cpp
LibCmo/CK2/ObjImpls/CKTexture.cpp
LibCmo/CK2/ObjImpls/CKLight.cpp
LibCmo/CK2/ObjImpls/CKTargetLight.cpp
LibCmo/CK2/ObjImpls/CKCamera.cpp
LibCmo/CK2/ObjImpls/CKTargetCamera.cpp
# VxMath
VxMath/VxMemoryMappedFile.cpp
VxMath/VxTypes.cpp
VxMath/VxMath.cpp
LibCmo/VxMath/VxMemoryMappedFile.cpp
LibCmo/VxMath/VxTypes.cpp
LibCmo/VxMath/VxMath.cpp
# X Container
XContainer/XTypes.cpp
LibCmo/XContainer/XTypes.cpp
)
# Setup static library headers
target_sources(LibCmo
PUBLIC
FILE_SET HEADERS
FILES
# Asststant header files
VTVersion.hpp
VTInternal.hpp
VTEncoding.hpp
VTUtils.hpp
# NeMo Shared
VTAll.hpp
LibCmo/VTVersion.hpp
LibCmo/VTInternal.hpp
LibCmo/VTUtils.hpp
# CK2
CK2/CKDefines.hpp
CK2/CKEnums.hpp
CK2/CKGlobals.hpp
CK2/CKIdentifiers.hpp
CK2/CKTypes.hpp
CK2/CKBitmapData.hpp
CK2/CKContext.hpp
CK2/CKFile.hpp
CK2/CKStateChunk.hpp
LibCmo/CK2/CKDefines.hpp
LibCmo/CK2/CKEnums.hpp
LibCmo/CK2/CKGlobals.hpp
LibCmo/CK2/CKIdentifiers.hpp
LibCmo/CK2/CKTypes.hpp
LibCmo/CK2/CKBitmapData.hpp
LibCmo/CK2/CKContext.hpp
LibCmo/CK2/CKFile.hpp
LibCmo/CK2/CKStateChunk.hpp
# CK2 Data Handler
CK2/DataHandlers/CKBitmapHandler.hpp
LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp
# CK2 Manager
CK2/MgrImpls/CKBaseManager.hpp
CK2/MgrImpls/CKObjectManager.hpp
CK2/MgrImpls/CKPathManager.hpp
LibCmo/CK2/MgrImpls/CKBaseManager.hpp
LibCmo/CK2/MgrImpls/CKObjectManager.hpp
LibCmo/CK2/MgrImpls/CKPathManager.hpp
# CK2 Object
CK2/ObjImpls/CK3dEntity.hpp
CK2/ObjImpls/CKBeObject.hpp
CK2/ObjImpls/CKGroup.hpp
CK2/ObjImpls/CKMaterial.hpp
CK2/ObjImpls/CKMesh.hpp
CK2/ObjImpls/CKObject.hpp
CK2/ObjImpls/CKTexture.hpp
CK2/ObjImpls/CK3dObject.hpp
CK2/ObjImpls/CKRenderObject.hpp
CK2/ObjImpls/CKSceneObject.hpp
CK2/ObjImpls/CKLight.hpp
CK2/ObjImpls/CKTargetLight.hpp
CK2/ObjImpls/CKCamera.hpp
CK2/ObjImpls/CKTargetCamera.hpp
LibCmo/CK2/ObjImpls/CK3dEntity.hpp
LibCmo/CK2/ObjImpls/CKBeObject.hpp
LibCmo/CK2/ObjImpls/CKGroup.hpp
LibCmo/CK2/ObjImpls/CKMaterial.hpp
LibCmo/CK2/ObjImpls/CKMesh.hpp
LibCmo/CK2/ObjImpls/CKObject.hpp
LibCmo/CK2/ObjImpls/CKTexture.hpp
LibCmo/CK2/ObjImpls/CK3dObject.hpp
LibCmo/CK2/ObjImpls/CKRenderObject.hpp
LibCmo/CK2/ObjImpls/CKSceneObject.hpp
LibCmo/CK2/ObjImpls/CKLight.hpp
LibCmo/CK2/ObjImpls/CKTargetLight.hpp
LibCmo/CK2/ObjImpls/CKCamera.hpp
LibCmo/CK2/ObjImpls/CKTargetCamera.hpp
# VxMath
VxMath/VxTypes.hpp
VxMath/VxMath.hpp
VxMath/VxEnums.hpp
VxMath/VxMemoryMappedFile.hpp
LibCmo/VxMath/VxTypes.hpp
LibCmo/VxMath/VxMath.hpp
LibCmo/VxMath/VxEnums.hpp
LibCmo/VxMath/VxMemoryMappedFile.hpp
# X Container
XContainer/XTypes.hpp
LibCmo/XContainer/XTypes.hpp
)
# Setup include and linked library infomation
target_include_directories(LibCmo
@@ -109,32 +108,13 @@ PUBLIC
YYCC::YYCCommonplace
PRIVATE
ZLIB::ZLIB
stb::stb-image
)
if (NOT WIN32)
target_link_libraries(LibCmo PRIVATE Iconv::Iconv)
endif ()
# Setup C++ standard
set_target_properties(LibCmo
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
STB::STB
)
target_compile_definitions(LibCmo
# Expose LibCmo build type
PUBLIC
"$<$<CONFIG:Debug>:LIBCMO_BUILD_DEBUG>"
"$<$<CONFIG:Release,RelWithDebInfo,MinSize>:LIBCMO_BUILD_RELEASE>"
# Unicode charset for private using
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:UNICODE>
$<$<CXX_COMPILER_ID:MSVC>:_UNICODE>
)
target_compile_options(LibCmo
# Order build as UTF-8 in MSVC
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
)
# Install binary and headers
@@ -145,3 +125,28 @@ install(TARGETS LibCmo
INCLUDES DESTINATION ${NEMO_INSTALL_INCLUDE_PATH}
FILE_SET HEADERS DESTINATION ${NEMO_INSTALL_INCLUDE_PATH}
)
# Install target
install(EXPORT LibCmoTargets
FILE LibCmoTargets.cmake
NAMESPACE NeMo::
DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)
# Package configuration file
write_basic_package_version_file(
LibCmoConfigVersion.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY SameMinorVersion
)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/../CMake/LibCmoConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfig.cmake"
INSTALL_DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)
# Copy package files to install destination
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/LibCmoConfigVersion.cmake"
DESTINATION
${NEMO_INSTALL_LIB_PATH}/cmake/LibCmo
)

2
LibCmo/LibCmo/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# Ignore CMake generated version header
VTVersion.hpp

View File

@@ -27,10 +27,6 @@
// - General LibCmo specific custom exception.
// - Enum Helper for convenient C++ enum class type logic operations.
#include "VTUtils.hpp"
// Platform independent encoding system.
// Use native Win32 functions in Windows,
// or Iconv in non-Windows to provide encoding convertion services.
#include "VTEncoding.hpp"
// Include CK2 types first.
// Because it also include some types or structs used by other module.
@@ -56,6 +52,3 @@
// Last, load some custom struct used in program.
#include "CK2/CKDefines.hpp"

View File

@@ -0,0 +1,7 @@
#include "VTUtils.hpp"
// Check YYCC library version
#include <yycc/macro/version_cmp.hpp>
#if YYCC_VERCMP_NE(YYCC_VER_MAJOR, YYCC_VER_MINOR, YYCC_VER_PATCH, 2, 0, 0)
#error "YYCC library version is not matched with our expected version. Please check your library configuration."
#endif

View File

@@ -5,11 +5,8 @@
#error "You must define ONE of LIBCMO_BUILD_DEBUG and LIBCMO_BUILD_RELEASE to indicate build type!"
#endif
// Include YYCC helper library and check its version
#include <YYCCommonplace.hpp>
#if YYCC_VERCMP_NE(YYCC_VER_MAJOR, YYCC_VER_MINOR, YYCC_VER_PATCH, 1, 3, 0)
#error "YYCC library version is not matched with our expected version. Please check your library configuration."
#endif
// Include YYCC library core header for all headers
#include <yycc.hpp>
// Header for this namespace implementation
#include <string>

View File

@@ -13,33 +13,33 @@
*/
// Include internal header
#include "VTInternal.hpp"
#include "LibCmo/VTInternal.hpp"
// CK2 Misc
#include "CK2/CKContext.hpp"
#include "CK2/CKStateChunk.hpp"
#include "CK2/CKFile.hpp"
#include "LibCmo/CK2/CKContext.hpp"
#include "LibCmo/CK2/CKStateChunk.hpp"
#include "LibCmo/CK2/CKFile.hpp"
// CK2 Data handlers
#include "CK2/DataHandlers/CKBitmapHandler.hpp"
#include "LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp"
// CK2 Objects
#include "CK2/ObjImpls/CKObject.hpp"
#include "CK2/ObjImpls/CKSceneObject.hpp"
#include "CK2/ObjImpls/CKBeObject.hpp"
#include "CK2/ObjImpls/CKGroup.hpp"
#include "CK2/ObjImpls/CKRenderObject.hpp"
#include "CK2/ObjImpls/CK3dEntity.hpp"
#include "CK2/ObjImpls/CK3dObject.hpp"
#include "CK2/ObjImpls/CKTexture.hpp"
#include "CK2/ObjImpls/CKMaterial.hpp"
#include "CK2/ObjImpls/CKMesh.hpp"
#include "CK2/ObjImpls/CKLight.hpp"
#include "CK2/ObjImpls/CKTargetLight.hpp"
#include "CK2/ObjImpls/CKCamera.hpp"
#include "CK2/ObjImpls/CKTargetCamera.hpp"
#include "LibCmo/CK2/ObjImpls/CKObject.hpp"
#include "LibCmo/CK2/ObjImpls/CKSceneObject.hpp"
#include "LibCmo/CK2/ObjImpls/CKBeObject.hpp"
#include "LibCmo/CK2/ObjImpls/CKGroup.hpp"
#include "LibCmo/CK2/ObjImpls/CKRenderObject.hpp"
#include "LibCmo/CK2/ObjImpls/CK3dEntity.hpp"
#include "LibCmo/CK2/ObjImpls/CK3dObject.hpp"
#include "LibCmo/CK2/ObjImpls/CKTexture.hpp"
#include "LibCmo/CK2/ObjImpls/CKMaterial.hpp"
#include "LibCmo/CK2/ObjImpls/CKMesh.hpp"
#include "LibCmo/CK2/ObjImpls/CKLight.hpp"
#include "LibCmo/CK2/ObjImpls/CKTargetLight.hpp"
#include "LibCmo/CK2/ObjImpls/CKCamera.hpp"
#include "LibCmo/CK2/ObjImpls/CKTargetCamera.hpp"
// CK2 Managers
#include "CK2/MgrImpls/CKBaseManager.hpp"
#include "CK2/MgrImpls/CKObjectManager.hpp"
#include "CK2/MgrImpls/CKPathManager.hpp"
#include "LibCmo/CK2/MgrImpls/CKBaseManager.hpp"
#include "LibCmo/CK2/MgrImpls/CKObjectManager.hpp"
#include "LibCmo/CK2/MgrImpls/CKPathManager.hpp"

View File

@@ -1,643 +0,0 @@
#include "VTEncoding.hpp"
#include <map>
#if YYCC_OS == YYCC_OS_WINDOWS
#include <YYCC/WinImportPrefix.hpp>
#include <Windows.h>
#include <fileapi.h>
#include <YYCC/WinImportSuffix.hpp>
#else
#include <iconv.h>
#endif
namespace LibCmo::EncodingHelper {
#pragma region Constant Map
static const std::map<std::u8string, std::u8string> c_AliasMap {
{ u8"646", u8"ascii" },
{ u8"us-ascii", u8"ascii" },
{ u8"big5-tw", u8"big5" },
{ u8"csbig5", u8"big5" },
{ u8"big5-hkscs", u8"big5hkscs" },
{ u8"hkscs", u8"big5hkscs" },
{ u8"ibm037", u8"cp037" },
{ u8"ibm039", u8"cp037" },
{ u8"273", u8"cp273" },
{ u8"ibm273", u8"cp273" },
{ u8"csibm273", u8"cp273" },
{ u8"ebcdic-cp-he", u8"cp424" },
{ u8"ibm424", u8"cp424" },
{ u8"437", u8"cp437" },
{ u8"ibm437", u8"cp437" },
{ u8"ebcdic-cp-be", u8"cp500" },
{ u8"ebcdic-cp-ch", u8"cp500" },
{ u8"ibm500", u8"cp500" },
{ u8"ibm775", u8"cp775" },
{ u8"850", u8"cp850" },
{ u8"ibm850", u8"cp850" },
{ u8"852", u8"cp852" },
{ u8"ibm852", u8"cp852" },
{ u8"855", u8"cp855" },
{ u8"ibm855", u8"cp855" },
{ u8"857", u8"cp857" },
{ u8"ibm857", u8"cp857" },
{ u8"858", u8"cp858" },
{ u8"ibm858", u8"cp858" },
{ u8"860", u8"cp860" },
{ u8"ibm860", u8"cp860" },
{ u8"861", u8"cp861" },
{ u8"cp-is", u8"cp861" },
{ u8"ibm861", u8"cp861" },
{ u8"862", u8"cp862" },
{ u8"ibm862", u8"cp862" },
{ u8"863", u8"cp863" },
{ u8"ibm863", u8"cp863" },
{ u8"ibm864", u8"cp864" },
{ u8"865", u8"cp865" },
{ u8"ibm865", u8"cp865" },
{ u8"866", u8"cp866" },
{ u8"ibm866", u8"cp866" },
{ u8"869", u8"cp869" },
{ u8"cp-gr", u8"cp869" },
{ u8"ibm869", u8"cp869" },
{ u8"932", u8"cp932" },
{ u8"ms932", u8"cp932" },
{ u8"mskanji", u8"cp932" },
{ u8"ms-kanji", u8"cp932" },
{ u8"windows-31j", u8"cp932" },
{ u8"949", u8"cp949" },
{ u8"ms949", u8"cp949" },
{ u8"uhc", u8"cp949" },
{ u8"950", u8"cp950" },
{ u8"ms950", u8"cp950" },
{ u8"ibm1026", u8"cp1026" },
{ u8"1125", u8"cp1125" },
{ u8"ibm1125", u8"cp1125" },
{ u8"cp866u", u8"cp1125" },
{ u8"ruscii", u8"cp1125" },
{ u8"ibm1140", u8"cp1140" },
{ u8"windows-1250", u8"cp1250" },
{ u8"windows-1251", u8"cp1251" },
{ u8"windows-1252", u8"cp1252" },
{ u8"windows-1253", u8"cp1253" },
{ u8"windows-1254", u8"cp1254" },
{ u8"windows-1255", u8"cp1255" },
{ u8"windows-1256", u8"cp1256" },
{ u8"windows-1257", u8"cp1257" },
{ u8"windows-1258", u8"cp1258" },
{ u8"eucjp", u8"euc_jp" },
{ u8"ujis", u8"euc_jp" },
{ u8"u-jis", u8"euc_jp" },
{ u8"jisx0213", u8"euc_jis_2004" },
{ u8"eucjis2004", u8"euc_jis_2004" },
{ u8"eucjisx0213", u8"euc_jisx0213" },
{ u8"euckr", u8"euc_kr" },
{ u8"korean", u8"euc_kr" },
{ u8"ksc5601", u8"euc_kr" },
{ u8"ks_c-5601", u8"euc_kr" },
{ u8"ks_c-5601-1987", u8"euc_kr" },
{ u8"ksx1001", u8"euc_kr" },
{ u8"ks_x-1001", u8"euc_kr" },
{ u8"chinese", u8"gb2312" },
{ u8"csiso58gb231280", u8"gb2312" },
{ u8"euc-cn", u8"gb2312" },
{ u8"euccn", u8"gb2312" },
{ u8"eucgb2312-cn", u8"gb2312" },
{ u8"gb2312-1980", u8"gb2312" },
{ u8"gb2312-80", u8"gb2312" },
{ u8"iso-ir-58", u8"gb2312" },
{ u8"936", u8"gbk" },
{ u8"cp936", u8"gbk" },
{ u8"ms936", u8"gbk" },
{ u8"gb18030-2000", u8"gb18030" },
{ u8"hzgb", u8"hz" },
{ u8"hz-gb", u8"hz" },
{ u8"hz-gb-2312", u8"hz" },
{ u8"csiso2022jp", u8"iso2022_jp" },
{ u8"iso2022jp", u8"iso2022_jp" },
{ u8"iso-2022-jp", u8"iso2022_jp" },
{ u8"iso2022jp-1", u8"iso2022_jp_1" },
{ u8"iso-2022-jp-1", u8"iso2022_jp_1" },
{ u8"iso2022jp-2", u8"iso2022_jp_2" },
{ u8"iso-2022-jp-2", u8"iso2022_jp_2" },
{ u8"iso2022jp-2004", u8"iso2022_jp_2004" },
{ u8"iso-2022-jp-2004", u8"iso2022_jp_2004" },
{ u8"iso2022jp-3", u8"iso2022_jp_3" },
{ u8"iso-2022-jp-3", u8"iso2022_jp_3" },
{ u8"iso2022jp-ext", u8"iso2022_jp_ext" },
{ u8"iso-2022-jp-ext", u8"iso2022_jp_ext" },
{ u8"csiso2022kr", u8"iso2022_kr" },
{ u8"iso2022kr", u8"iso2022_kr" },
{ u8"iso-2022-kr", u8"iso2022_kr" },
{ u8"iso-8859-1", u8"latin_1" },
{ u8"iso8859-1", u8"latin_1" },
{ u8"8859", u8"latin_1" },
{ u8"cp819", u8"latin_1" },
{ u8"latin", u8"latin_1" },
{ u8"latin1", u8"latin_1" },
{ u8"l1", u8"latin_1" },
{ u8"iso-8859-2", u8"iso8859_2" },
{ u8"latin2", u8"iso8859_2" },
{ u8"l2", u8"iso8859_2" },
{ u8"iso-8859-3", u8"iso8859_3" },
{ u8"latin3", u8"iso8859_3" },
{ u8"l3", u8"iso8859_3" },
{ u8"iso-8859-4", u8"iso8859_4" },
{ u8"latin4", u8"iso8859_4" },
{ u8"l4", u8"iso8859_4" },
{ u8"iso-8859-5", u8"iso8859_5" },
{ u8"cyrillic", u8"iso8859_5" },
{ u8"iso-8859-6", u8"iso8859_6" },
{ u8"arabic", u8"iso8859_6" },
{ u8"iso-8859-7", u8"iso8859_7" },
{ u8"greek", u8"iso8859_7" },
{ u8"greek8", u8"iso8859_7" },
{ u8"iso-8859-8", u8"iso8859_8" },
{ u8"hebrew", u8"iso8859_8" },
{ u8"iso-8859-9", u8"iso8859_9" },
{ u8"latin5", u8"iso8859_9" },
{ u8"l5", u8"iso8859_9" },
{ u8"iso-8859-10", u8"iso8859_10" },
{ u8"latin6", u8"iso8859_10" },
{ u8"l6", u8"iso8859_10" },
{ u8"iso-8859-11", u8"iso8859_11" },
{ u8"thai", u8"iso8859_11" },
{ u8"iso-8859-13", u8"iso8859_13" },
{ u8"latin7", u8"iso8859_13" },
{ u8"l7", u8"iso8859_13" },
{ u8"iso-8859-14", u8"iso8859_14" },
{ u8"latin8", u8"iso8859_14" },
{ u8"l8", u8"iso8859_14" },
{ u8"iso-8859-15", u8"iso8859_15" },
{ u8"latin9", u8"iso8859_15" },
{ u8"l9", u8"iso8859_15" },
{ u8"iso-8859-16", u8"iso8859_16" },
{ u8"latin10", u8"iso8859_16" },
{ u8"l10", u8"iso8859_16" },
{ u8"cp1361", u8"johab" },
{ u8"ms1361", u8"johab" },
{ u8"kz_1048", u8"kz1048" },
{ u8"strk1048_2002", u8"kz1048" },
{ u8"rk1048", u8"kz1048" },
{ u8"maccyrillic", u8"mac_cyrillic" },
{ u8"macgreek", u8"mac_greek" },
{ u8"maciceland", u8"mac_iceland" },
{ u8"maclatin2", u8"mac_latin2" },
{ u8"maccentraleurope", u8"mac_latin2" },
{ u8"mac_centeuro", u8"mac_latin2" },
{ u8"macroman", u8"mac_roman" },
{ u8"macintosh", u8"mac_roman" },
{ u8"macturkish", u8"mac_turkish" },
{ u8"csptcp154", u8"ptcp154" },
{ u8"pt154", u8"ptcp154" },
{ u8"cp154", u8"ptcp154" },
{ u8"cyrillic-asian", u8"ptcp154" },
{ u8"csshiftjis", u8"shift_jis" },
{ u8"shiftjis", u8"shift_jis" },
{ u8"sjis", u8"shift_jis" },
{ u8"s_jis", u8"shift_jis" },
{ u8"shiftjis2004", u8"shift_jis_2004" },
{ u8"sjis_2004", u8"shift_jis_2004" },
{ u8"sjis2004", u8"shift_jis_2004" },
{ u8"shiftjisx0213", u8"shift_jisx0213" },
{ u8"sjisx0213", u8"shift_jisx0213" },
{ u8"s_jisx0213", u8"shift_jisx0213" },
{ u8"u32", u8"utf_32" },
{ u8"utf32", u8"utf_32" },
{ u8"utf-32be", u8"utf_32_be" },
{ u8"utf-32le", u8"utf_32_le" },
{ u8"u16", u8"utf_16" },
{ u8"utf16", u8"utf_16" },
{ u8"utf-16be", u8"utf_16_be" },
{ u8"utf-16le", u8"utf_16_le" },
{ u8"u7", u8"utf_7" },
{ u8"unicode-1-1-utf-7", u8"utf_7" },
{ u8"u8", u8"utf_8" },
{ u8"utf", u8"utf_8" },
{ u8"utf8", u8"utf_8" },
{ u8"utf-8", u8"utf_8" },
{ u8"cp65001", u8"utf_8" },
};
/**
* @brief Resolve encoding name alias and fetch real encoding name.
* @param[in] lang The encoding name for finding.
* @return
* The given encoding name if given name not present in alias map.
* Otherwise the found encoding name by given name.
*/
static std::u8string ResolveEncodingAlias(const std::u8string_view& enc_name) {
std::u8string name(enc_name);
YYCC::StringHelper::Lower(name);
auto finder = c_AliasMap.find(name);
if (finder == c_AliasMap.end()) return std::u8string(enc_name); // not found, use original encoding name.
else return std::u8string(finder->second); // found, use found encoding name.
}
#if YYCC_OS == YYCC_OS_WINDOWS
static const std::map<std::u8string, UINT> c_WinCPMap {
{ u8"ascii", static_cast<UINT>(437u) },
{ u8"big5", static_cast<UINT>(950u) },
{ u8"cp037", static_cast<UINT>(037u) },
{ u8"cp437", static_cast<UINT>(437u) },
{ u8"cp500", static_cast<UINT>(500u) },
{ u8"cp720", static_cast<UINT>(720u) },
{ u8"cp737", static_cast<UINT>(737u) },
{ u8"cp775", static_cast<UINT>(775u) },
{ u8"cp850", static_cast<UINT>(850u) },
{ u8"cp852", static_cast<UINT>(852u) },
{ u8"cp855", static_cast<UINT>(855u) },
{ u8"cp857", static_cast<UINT>(857u) },
{ u8"cp858", static_cast<UINT>(858u) },
{ u8"cp860", static_cast<UINT>(860u) },
{ u8"cp861", static_cast<UINT>(861u) },
{ u8"cp862", static_cast<UINT>(862u) },
{ u8"cp863", static_cast<UINT>(863u) },
{ u8"cp864", static_cast<UINT>(864u) },
{ u8"cp865", static_cast<UINT>(865u) },
{ u8"cp866", static_cast<UINT>(866u) },
{ u8"cp869", static_cast<UINT>(869u) },
{ u8"cp874", static_cast<UINT>(874u) },
{ u8"cp875", static_cast<UINT>(875u) },
{ u8"cp932", static_cast<UINT>(932u) },
{ u8"cp949", static_cast<UINT>(949u) },
{ u8"cp950", static_cast<UINT>(950u) },
{ u8"cp1026", static_cast<UINT>(1026u) },
{ u8"cp1140", static_cast<UINT>(1140u) },
{ u8"cp1250", static_cast<UINT>(1250u) },
{ u8"cp1251", static_cast<UINT>(1251u) },
{ u8"cp1252", static_cast<UINT>(1252u) },
{ u8"cp1253", static_cast<UINT>(1253u) },
{ u8"cp1254", static_cast<UINT>(1254u) },
{ u8"cp1255", static_cast<UINT>(1255u) },
{ u8"cp1256", static_cast<UINT>(1256u) },
{ u8"cp1257", static_cast<UINT>(1257u) },
{ u8"cp1258", static_cast<UINT>(1258u) },
{ u8"euc_jp", static_cast<UINT>(20932u) },
{ u8"euc_kr", static_cast<UINT>(51949u) },
{ u8"gb2312", static_cast<UINT>(936u) },
{ u8"gbk", static_cast<UINT>(936u) },
{ u8"gb18030", static_cast<UINT>(54936u) },
{ u8"hz", static_cast<UINT>(52936u) },
{ u8"iso2022_jp", static_cast<UINT>(50220u) },
{ u8"iso2022_kr", static_cast<UINT>(50225u) },
{ u8"latin_1", static_cast<UINT>(28591u) },
{ u8"iso8859_2", static_cast<UINT>(28592u) },
{ u8"iso8859_3", static_cast<UINT>(28593u) },
{ u8"iso8859_4", static_cast<UINT>(28594u) },
{ u8"iso8859_5", static_cast<UINT>(28595u) },
{ u8"iso8859_6", static_cast<UINT>(28596u) },
{ u8"iso8859_7", static_cast<UINT>(28597u) },
{ u8"iso8859_8", static_cast<UINT>(28598u) },
{ u8"iso8859_9", static_cast<UINT>(28599u) },
{ u8"iso8859_13", static_cast<UINT>(28603u) },
{ u8"iso8859_15", static_cast<UINT>(28605u) },
{ u8"johab", static_cast<UINT>(1361u) },
{ u8"mac_cyrillic", static_cast<UINT>(10007u) },
{ u8"mac_greek", static_cast<UINT>(10006u) },
{ u8"mac_iceland", static_cast<UINT>(10079u) },
{ u8"mac_turkish", static_cast<UINT>(10081u) },
{ u8"shift_jis", static_cast<UINT>(932u) },
{ u8"utf_7", static_cast<UINT>(65000u) },
{ u8"utf_8", static_cast<UINT>(65001u) },
};
static bool GetWindowsCodePage(const std::u8string_view& enc_name, UINT& out_cp) {
// resolve alias
std::u8string resolved_name = ResolveEncodingAlias(enc_name);
// find code page
YYCC::StringHelper::Lower(resolved_name);
auto finder = c_WinCPMap.find(resolved_name);
if (finder == c_WinCPMap.end()) return false;
// okey, we found it.
out_cp = finder->second;
return true;
}
#else
static const std::map<std::u8string, std::string> c_IconvMap {
{ u8"ascii", "ASCII" },
{ u8"big5", "BIG5" },
{ u8"big5hkscs", "BIG5-HKSCS" },
{ u8"cp850", "CP850" },
{ u8"cp862", "CP862" },
{ u8"cp866", "CP866" },
{ u8"cp874", "CP874" },
{ u8"cp932", "CP932" },
{ u8"cp949", "CP949" },
{ u8"cp950", "CP950" },
{ u8"cp1250", "CP1250" },
{ u8"cp1251", "CP1251" },
{ u8"cp1252", "CP1252" },
{ u8"cp1253", "CP1253" },
{ u8"cp1254", "CP1254" },
{ u8"cp1255", "CP1255" },
{ u8"cp1256", "CP1256" },
{ u8"cp1257", "CP1257" },
{ u8"cp1258", "CP1258" },
{ u8"euc_jp", "EUC-JP" },
{ u8"euc_kr", "EUC-KR" },
{ u8"gb2312", "CP936" },
{ u8"gbk", "GBK" },
{ u8"gb18030", "GB18030" },
{ u8"hz", "HZ" },
{ u8"iso2022_jp", "ISO-2022-JP" },
{ u8"iso2022_jp_1", "ISO-2022-JP-1" },
{ u8"iso2022_jp_2", "ISO-2022-JP-2" },
{ u8"iso2022_kr", "ISO-2022-KR" },
{ u8"latin_1", "ISO-8859-1" },
{ u8"iso8859_2", "ISO-8859-2" },
{ u8"iso8859_3", "ISO-8859-3" },
{ u8"iso8859_4", "ISO-8859-4" },
{ u8"iso8859_5", "ISO-8859-5" },
{ u8"iso8859_6", "ISO-8859-6" },
{ u8"iso8859_7", "ISO-8859-7" },
{ u8"iso8859_8", "ISO-8859-8" },
{ u8"iso8859_9", "ISO-8859-9" },
{ u8"iso8859_10", "ISO-8859-10" },
{ u8"iso8859_11", "ISO-8859-11" },
{ u8"iso8859_13", "ISO-8859-13" },
{ u8"iso8859_14", "ISO-8859-14" },
{ u8"iso8859_15", "ISO-8859-15" },
{ u8"iso8859_16", "ISO-8859-16" },
{ u8"johab", "JOHAB" },
{ u8"koi8_t", "KOI8-T" },
{ u8"mac_cyrillic", "MacCyrillic" },
{ u8"mac_greek", "MacGreek" },
{ u8"mac_iceland", "MacIceland" },
{ u8"mac_roman", "MacRoman" },
{ u8"mac_turkish", "MacTurkish" },
{ u8"ptcp154", "PT154" },
{ u8"shift_jis", "SHIFT_JIS" },
{ u8"utf_32", "UTF-32" },
{ u8"utf_32_be", "UTF-32BE" },
{ u8"utf_32_le", "UTF-32LE" },
{ u8"utf_16", "UTF16" },
{ u8"utf_16_be", "UTF-16BE" },
{ u8"utf_16_le", "UTF-16LE" },
{ u8"utf_7", "UTF-7" },
{ u8"utf_8", "UTF-8" },
};
static bool GetIconvCode(const std::u8string_view& enc_name, std::string& out_code) {
// resolve alias
std::u8string resolved_name = ResolveEncodingAlias(enc_name);
// find code page
YYCC::StringHelper::Lower(resolved_name);
auto finder = c_IconvMap.find(resolved_name);
if (finder == c_IconvMap.end()) return false;
// okey, we found it.
out_code = finder->second;
return true;
}
#endif
#pragma endregion
#pragma region Internal Functions
#if YYCC_OS == YYCC_OS_WINDOWS
struct WindowsEncodingToken {
WindowsEncodingToken(const std::u8string_view& universal_code, UINT cp) :
m_Name(universal_code), m_CodePage(cp) {}
std::u8string m_Name;
UINT m_CodePage;
};
#else
static constexpr const size_t c_IconvIncUnit = 16u;
static const iconv_t c_InvalidIconvType = reinterpret_cast<iconv_t>(-1);
struct IconvEncodingToken {
IconvEncodingToken(const std::u8string_view& universal_code, const std::string_view& _iconv_code) :
m_Name(universal_code),
m_FromUTF8(c_InvalidIconvType), m_ToUTF8(c_InvalidIconvType) {
// if iconv code is empty, do nothing
std::string iconv_code(_iconv_code);
if (iconv_code.empty()) return;
// setup iconv_t
this->m_FromUTF8 = iconv_open(iconv_code.c_str(), "UTF-8");
this->m_ToUTF8 = iconv_open("UTF-8", iconv_code.c_str());
}
~IconvEncodingToken() {
if (this->m_FromUTF8 != c_InvalidIconvType)
iconv_close(this->m_FromUTF8);
if (this->m_ToUTF8 != c_InvalidIconvType)
iconv_close(this->m_ToUTF8);
}
std::u8string m_Name;
iconv_t m_FromUTF8;
iconv_t m_ToUTF8;
};
// Reference: https://stackoverflow.com/questions/13297458/simple-utf8-utf16-string-conversion-with-iconv
static bool DoIconv(iconv_t& cd, const std::string_view& str_from, std::string& str_to) {
char* inbuf = nullptr, * outbuf = nullptr;
size_t inbytesleft, outbytesleft, nchars, result_len;
// check empty
if (str_from.empty()) {
str_to.clear();
return true;
}
// check iconv descriptor
if (cd == c_InvalidIconvType) {
// invalid iconv descriptor
return false;
}
// pre-resize
str_to.resize(str_from.size() + c_IconvIncUnit);
// setup some variables
inbytesleft = str_from.size();
inbuf = const_cast<char*>(str_from.data());
outbytesleft = str_to.size();
outbuf = str_to.data();
result_len = str_to.size();
// conv core
nchars = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
while (nchars == (size_t)-1 && errno == E2BIG) {
// record the length has been converted
size_t len = outbuf - str_to.data();
// resize for variables
result_len += c_IconvIncUnit;
outbytesleft += c_IconvIncUnit;
// resize for container
str_to.resize(result_len);
// assign new outbuf from failed position
outbuf = str_to.data() + len;
nchars = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
}
// restore descriptor initial state
iconv(cd, nullptr, nullptr, nullptr, nullptr);
// check error
if (nchars == (size_t)-1) {
// failed
return false;
} else {
// success
// resize result to get correct data
str_to.resize(result_len - outbytesleft);
return true;
}
}
#endif
#pragma endregion
#pragma region Encoding Token
EncodingToken CreateEncodingToken(const std::u8string_view& enc_name) {
#if YYCC_OS == YYCC_OS_WINDOWS
// get code page first
UINT cp = CP_ACP;
if (!GetWindowsCodePage(enc_name, cp))
return INVALID_ENCODING_TOKEN;
// validate code page
if (!YYCC::WinFctHelper::IsValidCodePage(cp))
return INVALID_ENCODING_TOKEN;
// create token and return
WindowsEncodingToken* token = new WindowsEncodingToken(enc_name, cp);
return token;
#else
// get iconv code first
std::string code;
if (!GetIconvCode(enc_name, code))
return INVALID_ENCODING_TOKEN;
// create token and set default value
IconvEncodingToken* token = new IconvEncodingToken(enc_name, code);
// check whether token has been initialized correctly
if (token->m_FromUTF8 == c_InvalidIconvType || token->m_ToUTF8 == c_InvalidIconvType) {
// failed. free resource and return
delete token;
return INVALID_ENCODING_TOKEN;
}
// okey, return
return token;
#endif
}
void DestroyEncodingToken(EncodingToken token) {
// if token is invalid, return directly
if (token == INVALID_ENCODING_TOKEN) return;
#if YYCC_OS == YYCC_OS_WINDOWS
WindowsEncodingToken* token_cast = static_cast<WindowsEncodingToken*>(token);
delete token_cast;
#else
IconvEncodingToken* token_cast = static_cast<IconvEncodingToken*>(token);
delete token_cast;
#endif
}
std::u8string GetEncodingTokenAssociatedName(EncodingToken token) {
// prepare return value
std::u8string ret;
// if token is invalid, return directly
if (token == INVALID_ENCODING_TOKEN) return ret;
// get associated name
#if YYCC_OS == YYCC_OS_WINDOWS
WindowsEncodingToken* token_cast = static_cast<WindowsEncodingToken*>(token);
ret = token_cast->m_Name;
#else
IconvEncodingToken* token_cast = static_cast<IconvEncodingToken*>(token);
ret = token_cast->m_Name;
#endif
// return value
return ret;
}
bool IsValidEncodingName(const std::u8string_view& enc_name) {
#if YYCC_OS == YYCC_OS_WINDOWS
UINT cp = CP_ACP;
return GetWindowsCodePage(enc_name, cp);
#else
std::string code;
return GetIconvCode(enc_name, code);
#endif
}
#pragma endregion
#pragma region Exposed Convertion Functions
bool ToOrdinary(const std::u8string_view& src, std::string& dst, EncodingToken token) {
// if token is invalid, return false
if (token == INVALID_ENCODING_TOKEN) return false;
#if YYCC_OS == YYCC_OS_WINDOWS
WindowsEncodingToken* token_cast = static_cast<WindowsEncodingToken*>(token);
return YYCC::EncodingHelper::UTF8ToChar(src, dst, token_cast->m_CodePage);
#else
IconvEncodingToken* token_cast = static_cast<IconvEncodingToken*>(token);
return DoIconv(token_cast->m_FromUTF8, YYCC::EncodingHelper::ToOrdinaryView(src), dst);
#endif
}
bool ToOrdinary(const char8_t* src, std::string& dst, EncodingToken token) {
if (src == nullptr) return false;
return ToOrdinary(std::u8string_view(src), dst, token);
}
std::string ToOrdinary(const std::u8string_view& src, EncodingToken token) {
std::string ret;
if (!ToOrdinary(src, ret, token)) ret.clear();
return ret;
}
std::string ToOrdinary(const char8_t* src, EncodingToken token) {
std::string ret;
if (!ToOrdinary(src, ret, token)) ret.clear();
return ret;
}
bool ToUTF8(const std::string_view& src, std::u8string& dst, EncodingToken token) {
// if token is invalid, return false
if (token == INVALID_ENCODING_TOKEN) return false;
#if YYCC_OS == YYCC_OS_WINDOWS
WindowsEncodingToken* token_cast = static_cast<WindowsEncodingToken*>(token);
return YYCC::EncodingHelper::CharToUTF8(src, dst, token_cast->m_CodePage);
#else
IconvEncodingToken* token_cast = static_cast<IconvEncodingToken*>(token);
std::string dst_cache;
bool ret = DoIconv(token_cast->m_ToUTF8, src, dst_cache);
if (ret) dst = YYCC::EncodingHelper::ToUTF8(dst_cache);
return ret;
#endif
}
bool ToUTF8(const char* src, std::u8string& dst, EncodingToken token) {
if (src == nullptr) return false;
return ToUTF8(std::string_view(src), dst, token);
}
std::u8string ToUTF8(const std::string_view& src, EncodingToken token) {
std::u8string ret;
if (!ToUTF8(src, ret, token)) ret.clear();
return ret;
}
std::u8string ToUTF8(const char* src, EncodingToken token) {
std::u8string ret;
if (!ToUTF8(src, ret, token)) ret.clear();
return ret;
}
#pragma endregion
}

View File

@@ -1,174 +0,0 @@
#pragma once
#include "VTUtils.hpp"
#include <string>
#include <string_view>
/**
* @brief The namespace providing platform independent encoding convertion solution.
* @details
* LibCmo is a cross-platform library.
* In different platform, they have their own encoding solution.
* So we create a universal encoding solution in this namespace like Python does.
* User only need input our universal language name,
* then they can convert same strings in different platforms.
*/
namespace LibCmo::EncodingHelper {
/**
* @brief The token for encoding convertion.
* @details
* If you want to use any encoding function provided by this namespace,
* you should fetch a proper token for it.
* This token records the encoding which you want to convert from / to.
*
* In underlying implementation, this token type is a pointer
* pointing to an allocated memory space recording you specified encoding infomations.
* So this token should only be fetched from CreateEncodingToken()
* and must be freed by DestroyEncodingToken() if you don't need it.
* Otherwise it will cause memory leak.
*/
using EncodingToken = void*;
/**
* @brief The invalid value of #EncodingToken.
* @details
* It represents an invalid encoding token.
* Any encoding token which equals to this value should not be used.
* In underlying implementation, it actually is \c nullptr.
* Because EncodingToken is just a raw pointer.
*/
inline constexpr EncodingToken INVALID_ENCODING_TOKEN = nullptr;
/**
* @brief Create encoding token by given universal encoding name.
* @param[in] enc_name Universal encoding name.
* @return
* The generated encoding token.
* #INVALID_ENCODING_TOKEN if fail to generate encoding token.
* Usually it means that your given encoding name is invalid.
* Please note any successfully generated encoding token must be freed by DestroyEncodingToken().
*/
EncodingToken CreateEncodingToken(const std::u8string_view& enc_name);
/**
* @brief Destroy given encoding token and free its associated resources.
* @param[in] token
* The encoding token to be destroyed.
* If token is #INVALID_ENCODING_TOKEN, this function does nothing.
*/
void DestroyEncodingToken(EncodingToken token);
/**
* @brief Get associated universal encoding name of given encoding token.
* @param[in] token The encoding token for getting name.
* @return Encoding token associated name (the universal encoding name used to create this token).
* Blank if given token is invalid or fail to get.
*/
std::u8string GetEncodingTokenAssociatedName(EncodingToken token);
/**
* @brief Check whether given universal encoding name can be used to produce token.
* @param[in] enc_name Universal encoding name.
* @return True if it is, otherwise false.
* @remarks
* Please note this function only check whether given encoding name is acceptable by token creator.
* Hoewver it doesn't mean that the token must be created if this function return true.
* Because there are some runtime issues which can cause that fail to create encoding token.
*/
bool IsValidEncodingName(const std::u8string_view& enc_name);
/**
* @brief Convert native string to UTF8 string by given encoding.
* @param[in] src The native string view to be converted.
* @param[out] dst The variable holding converted UTF8 string result.
* @param[in] token
* The encoding used when converting.
* #INVALID_ENCODING_TOKEN causes function returns false.
* @return True if success, otherwise false.
*/
bool ToOrdinary(const std::u8string_view& src, std::string& dst, EncodingToken token);
/**
* @brief Convert native string to UTF8 string by given encoding.
* @param[in] src
* The pointer to native string to be converted.
* nullptr is allowed but it will result in that function returns false.
* @param[out] dst The variable holding converted UTF8 string result.
* @param[in] token
* The encoding used when converting.
* #INVALID_ENCODING_TOKEN causes function returns false.
* @return True if success, otherwise false.
*/
bool ToOrdinary(const char8_t* src, std::string& dst, EncodingToken token);
/**
* @brief Convert native string to UTF8 string by given encoding.
* @param[in] src The native string view to be converted.
* @param[in] token
* The encoding used when converting.
* #INVALID_ENCODING_TOKEN causes function returns false.
* @return
* Converted UTF8 string result. Empty string if function failed.
* Please note empty input will also produce empty result.
* For preventing this ambiguity, please use other overloads.
*/
std::string ToOrdinary(const std::u8string_view& src, EncodingToken token);
/**
* @brief Convert native string to UTF8 string by given encoding.
* @param[in] src
* The pointer to native string to be converted.
* nullptr is allowed but it will result in that function returns false.
* @param[in] token
* The encoding used when converting.
* #INVALID_ENCODING_TOKEN causes function returns false.
* @return
* Converted UTF8 string result. Empty string if function failed.
* Please note empty input will also produce empty result.
* For preventing this ambiguity, please use other overloads.
*/
std::string ToOrdinary(const char8_t* src, EncodingToken token);
/**
* @brief Convert UTF8 string to native string by given encoding.
* @param[in] src The UTF8 string view to be converted.
* @param[out] dst The variable holding converted native string result.
* @param[in] token
* The encoding used when converting.
* #INVALID_ENCODING_TOKEN causes function returns false.
* @return True if success, otherwise false.
*/
bool ToUTF8(const std::string_view& src, std::u8string& dst, EncodingToken token);
/**
* @brief Convert UTF8 string to native string by given encoding.
* @param[in] src
* The pointer to UTF8 string to be converted.
* nullptr is allowed but it will result in that function returns false.
* @param[out] dst The variable holding converted native string result.
* @param[in] token
* The encoding used when converting.
* #INVALID_ENCODING_TOKEN causes function returns false.
* @return True if success, otherwise false.
*/
bool ToUTF8(const char* src, std::u8string& dst, EncodingToken token);
/**
* @brief Convert UTF8 string to native string by given encoding.
* @param[in] src The UTF8 string view to be converted.
* @param[in] token
* The encoding used when converting.
* #INVALID_ENCODING_TOKEN causes function returns false.
* @return
* Converted native string result. Empty string if function failed.
* Please note empty input will also produce empty result.
* For preventing this ambiguity, please use other overloads.
*/
std::u8string ToUTF8(const std::string_view& src, EncodingToken token);
/**
* @brief Convert UTF8 string to native string by given encoding.
* @param[in] src
* The pointer to UTF8 string to be converted.
* nullptr is allowed but it will result in that function returns false.
* @param[in] token
* The encoding used when converting.
* #INVALID_ENCODING_TOKEN causes function returns false.
* @return
* Converted native string result. Empty string if function failed.
* Please note empty input will also produce empty result.
* For preventing this ambiguity, please use other overloads.
*/
std::u8string ToUTF8(const char* src, EncodingToken token);
}

View File

@@ -30,27 +30,8 @@ PRIVATE
YYCC::YYCCommonplace
LibCmo
)
# Setup C++ standard
set_target_properties(Unvirt
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
)
# Order Unicode charset for private using
target_compile_definitions(Unvirt
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:UNICODE>
$<$<CXX_COMPILER_ID:MSVC>:_UNICODE>
)
# Order build as UTF-8 in MSVC
target_compile_options(Unvirt
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
)
# Install Unvirt only on Release mode
# Install Unvirt
install(TARGETS Unvirt
CONFIGURATIONS Release RelWithDebInfo MinSizeRel
RUNTIME DESTINATION ${YYCC_INSTALL_BIN_PATH}
)