diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/mk/link-dll-rule.mk b/mk/link-dll-rule.mk new file mode 100644 index 0000000..0084d31 --- /dev/null +++ b/mk/link-dll-rule.mk @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .dllファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,--out-implib,$(TARGET:.dll=).lib -o $(TARGET) $^ $(LIBS) + + +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/mk/link-dll-rule.mk b/mk/link-dll-rule.mk new file mode 100644 index 0000000..0084d31 --- /dev/null +++ b/mk/link-dll-rule.mk @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .dllファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,--out-implib,$(TARGET:.dll=).lib -o $(TARGET) $^ $(LIBS) + + +endif +endif + diff --git a/mk/link-exe-rule.mk b/mk/link-exe-rule.mk new file mode 100644 index 0000000..322c4a3 --- /dev/null +++ b/mk/link-exe-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# 実行ファイル 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) + +# For Linux +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +# For Windows (or ut.exe) +ifeq ($(strip $(NAME).exe),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/mk/link-dll-rule.mk b/mk/link-dll-rule.mk new file mode 100644 index 0000000..0084d31 --- /dev/null +++ b/mk/link-dll-rule.mk @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .dllファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,--out-implib,$(TARGET:.dll=).lib -o $(TARGET) $^ $(LIBS) + + +endif +endif + diff --git a/mk/link-exe-rule.mk b/mk/link-exe-rule.mk new file mode 100644 index 0000000..322c4a3 --- /dev/null +++ b/mk/link-exe-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# 実行ファイル 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) + +# For Linux +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +# For Windows (or ut.exe) +ifeq ($(strip $(NAME).exe),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +endif + diff --git a/mk/link-so-conf.mk b/mk/link-so-conf.mk new file mode 100644 index 0000000..6eb9a6e --- /dev/null +++ b/mk/link-so-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) + +ifneq ($(strip $(USE_SO_VERSION)),) +# +# バージョン番号付きの so ファイルを削除対象に追加する。 +# +CLEAN_FILES += $(TARGET).* $(TOP_TARGET).* +endif + + +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/mk/link-dll-rule.mk b/mk/link-dll-rule.mk new file mode 100644 index 0000000..0084d31 --- /dev/null +++ b/mk/link-dll-rule.mk @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .dllファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,--out-implib,$(TARGET:.dll=).lib -o $(TARGET) $^ $(LIBS) + + +endif +endif + diff --git a/mk/link-exe-rule.mk b/mk/link-exe-rule.mk new file mode 100644 index 0000000..322c4a3 --- /dev/null +++ b/mk/link-exe-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# 実行ファイル 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) + +# For Linux +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +# For Windows (or ut.exe) +ifeq ($(strip $(NAME).exe),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +endif + diff --git a/mk/link-so-conf.mk b/mk/link-so-conf.mk new file mode 100644 index 0000000..6eb9a6e --- /dev/null +++ b/mk/link-so-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) + +ifneq ($(strip $(USE_SO_VERSION)),) +# +# バージョン番号付きの so ファイルを削除対象に追加する。 +# +CLEAN_FILES += $(TARGET).* $(TOP_TARGET).* +endif + + +endif +endif + diff --git a/mk/link-so-rule.mk b/mk/link-so-rule.mk new file mode 100644 index 0000000..1369c43 --- /dev/null +++ b/mk/link-so-rule.mk @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +ifneq ($(strip $(USE_SO_VERSION)),) +## ----------------------------------------------------------------------------- +## バージョン番号付き so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 (シンボリックリンク) +$(TARGET): $(TARGET).$(MAJOR) + $(LN) -fs $^ $@ +# .so.X ファイル生成 (シンボリックリンク) +$(TARGET).$(MAJOR): $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) + $(LN) -fs $^ $@ +# .so.X.X.X ファイル生成 +$(TARGET).$(MAJOR).$(MINOR).$(RELEASE): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET).$(MAJOR) -o $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) $^ $(LIBS) + +else +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET) -o $(TARGET) $^ $(LIBS) + +endif + + +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/mk/link-dll-rule.mk b/mk/link-dll-rule.mk new file mode 100644 index 0000000..0084d31 --- /dev/null +++ b/mk/link-dll-rule.mk @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .dllファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,--out-implib,$(TARGET:.dll=).lib -o $(TARGET) $^ $(LIBS) + + +endif +endif + diff --git a/mk/link-exe-rule.mk b/mk/link-exe-rule.mk new file mode 100644 index 0000000..322c4a3 --- /dev/null +++ b/mk/link-exe-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# 実行ファイル 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) + +# For Linux +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +# For Windows (or ut.exe) +ifeq ($(strip $(NAME).exe),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +endif + diff --git a/mk/link-so-conf.mk b/mk/link-so-conf.mk new file mode 100644 index 0000000..6eb9a6e --- /dev/null +++ b/mk/link-so-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) + +ifneq ($(strip $(USE_SO_VERSION)),) +# +# バージョン番号付きの so ファイルを削除対象に追加する。 +# +CLEAN_FILES += $(TARGET).* $(TOP_TARGET).* +endif + + +endif +endif + diff --git a/mk/link-so-rule.mk b/mk/link-so-rule.mk new file mode 100644 index 0000000..1369c43 --- /dev/null +++ b/mk/link-so-rule.mk @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +ifneq ($(strip $(USE_SO_VERSION)),) +## ----------------------------------------------------------------------------- +## バージョン番号付き so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 (シンボリックリンク) +$(TARGET): $(TARGET).$(MAJOR) + $(LN) -fs $^ $@ +# .so.X ファイル生成 (シンボリックリンク) +$(TARGET).$(MAJOR): $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) + $(LN) -fs $^ $@ +# .so.X.X.X ファイル生成 +$(TARGET).$(MAJOR).$(MINOR).$(RELEASE): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET).$(MAJOR) -o $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) $^ $(LIBS) + +else +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET) -o $(TARGET) $^ $(LIBS) + +endif + + +endif +endif + diff --git a/mk/release-conf.mk b/mk/release-conf.mk new file mode 100644 index 0000000..a9bf6d9 --- /dev/null +++ b/mk/release-conf.mk @@ -0,0 +1,6 @@ +# ============================================================================== +# release 設定 +# ============================================================================== +ifeq ($(strip $(TOPDIR)),.) +CLEAN_DIRS += $(TOPDIR)/$(RELEASEDIR) +endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/mk/link-dll-rule.mk b/mk/link-dll-rule.mk new file mode 100644 index 0000000..0084d31 --- /dev/null +++ b/mk/link-dll-rule.mk @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .dllファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,--out-implib,$(TARGET:.dll=).lib -o $(TARGET) $^ $(LIBS) + + +endif +endif + diff --git a/mk/link-exe-rule.mk b/mk/link-exe-rule.mk new file mode 100644 index 0000000..322c4a3 --- /dev/null +++ b/mk/link-exe-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# 実行ファイル 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) + +# For Linux +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +# For Windows (or ut.exe) +ifeq ($(strip $(NAME).exe),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +endif + diff --git a/mk/link-so-conf.mk b/mk/link-so-conf.mk new file mode 100644 index 0000000..6eb9a6e --- /dev/null +++ b/mk/link-so-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) + +ifneq ($(strip $(USE_SO_VERSION)),) +# +# バージョン番号付きの so ファイルを削除対象に追加する。 +# +CLEAN_FILES += $(TARGET).* $(TOP_TARGET).* +endif + + +endif +endif + diff --git a/mk/link-so-rule.mk b/mk/link-so-rule.mk new file mode 100644 index 0000000..1369c43 --- /dev/null +++ b/mk/link-so-rule.mk @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +ifneq ($(strip $(USE_SO_VERSION)),) +## ----------------------------------------------------------------------------- +## バージョン番号付き so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 (シンボリックリンク) +$(TARGET): $(TARGET).$(MAJOR) + $(LN) -fs $^ $@ +# .so.X ファイル生成 (シンボリックリンク) +$(TARGET).$(MAJOR): $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) + $(LN) -fs $^ $@ +# .so.X.X.X ファイル生成 +$(TARGET).$(MAJOR).$(MINOR).$(RELEASE): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET).$(MAJOR) -o $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) $^ $(LIBS) + +else +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET) -o $(TARGET) $^ $(LIBS) + +endif + + +endif +endif + diff --git a/mk/release-conf.mk b/mk/release-conf.mk new file mode 100644 index 0000000..a9bf6d9 --- /dev/null +++ b/mk/release-conf.mk @@ -0,0 +1,6 @@ +# ============================================================================== +# release 設定 +# ============================================================================== +ifeq ($(strip $(TOPDIR)),.) +CLEAN_DIRS += $(TOPDIR)/$(RELEASEDIR) +endif diff --git a/mk/release-rule.mk b/mk/release-rule.mk new file mode 100644 index 0000000..8862c62 --- /dev/null +++ b/mk/release-rule.mk @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------------------ +# release ルール +# ------------------------------------------------------------------------------ +.PHONY: release +release: +ifeq ($(strip $(TOPDIR)),.) + $(MAKE) clean + $(MAKE) all + $(MKDIR) -p $(TOPDIR)/$(RELEASEDIR)/bin + $(MKDIR) -p $(TOPDIR)/$(RELEASEDIR)/lib +endif + @for subdir in $(SUBDIRS); do \ + $(MAKE) release -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +# .so ファイル + $(CP) -d $(TARGET)* $(TOPDIR)/$(RELEASEDIR)/lib/ +endif +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +# 実行ファイル + $(CP) $(TARGET) $(TOPDIR)/$(RELEASEDIR)/bin/ +endif +endif + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/mk/link-dll-rule.mk b/mk/link-dll-rule.mk new file mode 100644 index 0000000..0084d31 --- /dev/null +++ b/mk/link-dll-rule.mk @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .dllファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,--out-implib,$(TARGET:.dll=).lib -o $(TARGET) $^ $(LIBS) + + +endif +endif + diff --git a/mk/link-exe-rule.mk b/mk/link-exe-rule.mk new file mode 100644 index 0000000..322c4a3 --- /dev/null +++ b/mk/link-exe-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# 実行ファイル 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) + +# For Linux +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +# For Windows (or ut.exe) +ifeq ($(strip $(NAME).exe),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +endif + diff --git a/mk/link-so-conf.mk b/mk/link-so-conf.mk new file mode 100644 index 0000000..6eb9a6e --- /dev/null +++ b/mk/link-so-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) + +ifneq ($(strip $(USE_SO_VERSION)),) +# +# バージョン番号付きの so ファイルを削除対象に追加する。 +# +CLEAN_FILES += $(TARGET).* $(TOP_TARGET).* +endif + + +endif +endif + diff --git a/mk/link-so-rule.mk b/mk/link-so-rule.mk new file mode 100644 index 0000000..1369c43 --- /dev/null +++ b/mk/link-so-rule.mk @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +ifneq ($(strip $(USE_SO_VERSION)),) +## ----------------------------------------------------------------------------- +## バージョン番号付き so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 (シンボリックリンク) +$(TARGET): $(TARGET).$(MAJOR) + $(LN) -fs $^ $@ +# .so.X ファイル生成 (シンボリックリンク) +$(TARGET).$(MAJOR): $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) + $(LN) -fs $^ $@ +# .so.X.X.X ファイル生成 +$(TARGET).$(MAJOR).$(MINOR).$(RELEASE): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET).$(MAJOR) -o $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) $^ $(LIBS) + +else +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET) -o $(TARGET) $^ $(LIBS) + +endif + + +endif +endif + diff --git a/mk/release-conf.mk b/mk/release-conf.mk new file mode 100644 index 0000000..a9bf6d9 --- /dev/null +++ b/mk/release-conf.mk @@ -0,0 +1,6 @@ +# ============================================================================== +# release 設定 +# ============================================================================== +ifeq ($(strip $(TOPDIR)),.) +CLEAN_DIRS += $(TOPDIR)/$(RELEASEDIR) +endif diff --git a/mk/release-rule.mk b/mk/release-rule.mk new file mode 100644 index 0000000..8862c62 --- /dev/null +++ b/mk/release-rule.mk @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------------------ +# release ルール +# ------------------------------------------------------------------------------ +.PHONY: release +release: +ifeq ($(strip $(TOPDIR)),.) + $(MAKE) clean + $(MAKE) all + $(MKDIR) -p $(TOPDIR)/$(RELEASEDIR)/bin + $(MKDIR) -p $(TOPDIR)/$(RELEASEDIR)/lib +endif + @for subdir in $(SUBDIRS); do \ + $(MAKE) release -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +# .so ファイル + $(CP) -d $(TARGET)* $(TOPDIR)/$(RELEASEDIR)/lib/ +endif +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +# 実行ファイル + $(CP) $(TARGET) $(TOPDIR)/$(RELEASEDIR)/bin/ +endif +endif + diff --git a/mk/test-rule.mk b/mk/test-rule.mk new file mode 100644 index 0000000..4bd8655 --- /dev/null +++ b/mk/test-rule.mk @@ -0,0 +1,12 @@ +# ------------------------------------------------------------------------------ +# test ルール +# ------------------------------------------------------------------------------ +.PHONY: test +test: + @for subdir in $(SUBDIRS); do \ + $(MAKE) test -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(MAKE) ut.exe + ./ut.exe +endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aae770b --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= . +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = j +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..9410b18 --- /dev/null +++ b/config.mk @@ -0,0 +1,98 @@ +# vim: ts=4 sw=4 sts=4 +################################################################################ +## +## コンパイル設定 +## + +# +# DEBUG モード +# +# make DEBUG=1 にてコンパイルすることで、DEBUG モードでコンパイルします。 +# TARGET=ut.exe の場合は、常に DEBUG モードでコンパイルします。 +# + +# +# OS指定 +# +OS = linux +#OS = windows + +# +# アーキテクチャ指定 +# +ARCH ?= +#ARCH ?= aarch64 +#ARCH ?= i686-w64-mingw32 + +# +# クロスコンパイラ指定 +# +CROSS_COMPILE=$(ARCH)- + +# +# コンパイラ +# +# +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +#CC = $(CROSS_COMPILE)clang +#CXX = $(CROSS_COMPILE)clang++ +#CC = $(CROSS_COMPILE)clang-16 +#CXX = $(CROSS_COMPILE)clang++16 + +# +# オプション設定 +# +ifeq ($(strip $(OS)),windows) +LIBS ?= -liphlpapi -lws2_32 +DEBUG_OPTIONS ?= +else +LIBS ?= -lpthread -lrt +DEBUG_OPTIONS ?= -fstack-protector +endif + +# +# C/C++ 言語規格指定 +# +# 指定された言語規格に従ってコンパイルします。 +# C_VERSION [-std=cXX|-std=gnuXX] (XX=89,90,99,11) +# CXX_VERSION [-std=c++XX|-std=gnu++XX] (XX=03,11,14,17) +# +C_VERSION = -std=gnu11 +CXX_VERSION = -std=gnu++17 + +# +# 共通のインクルードパスを指定します。 +# +INCLUDES += -Iinclude +INCLUDES += -I$(TOPDIR)/include + +# +# 共通のライブラリパスを指定します。 +# +LDFLAGS += -Llib +LDFLAGS += -L$(TOPDIR)/lib + +# +# 共通でリンクするライブラリを指定します。 +# +LIBS += + + +CFLAGS += -DKC_MEMORY_ENABLED=1 +CXXFLAGS += -DKCPP_MEMORY_ENABLED=1 + + +# ------------------------------------------------------------------------------ +# TARGET 調整 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(OS)),windows) +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +TARGET = $(NAME).exe +else +ifeq ($(strip $(NAME)).so,$(strip $(TARGET))) +TARGET = $(NAME).dll +endif +endif +endif + diff --git a/include/j.hpp b/include/j.hpp new file mode 100644 index 0000000..65c889f --- /dev/null +++ b/include/j.hpp @@ -0,0 +1,25 @@ +/** + * @file j.hpp + * @brief J Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/os.hpp + */ +#ifndef J_HPP +#define J_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include + +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // J_HPP diff --git a/include/j/lang/assertion_error.hpp b/include/j/lang/assertion_error.hpp new file mode 100644 index 0000000..cd76829 --- /dev/null +++ b/include/j/lang/assertion_error.hpp @@ -0,0 +1,40 @@ +/** + * @file assertion_error.hpp + * @brief J Library AssertionError ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ASSERTION_ERROR_HPP +#define J_LANG_ASSERTION_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class AssertionError : public Error + { + public: + // デフォルトコンストラクタ + AssertionError() noexcept; + + // コンストラクタ + AssertionError(const String &msg) noexcept; + + // コピーコンストラクタ + AssertionError(const AssertionError &t) noexcept; + + // ムーブコンストラクタ + AssertionError(AssertionError &&t) noexcept; + + // デストラクタ + ~AssertionError() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ASSERTION_ERROR_HPP diff --git a/include/j/lang/dl.hpp b/include/j/lang/dl.hpp new file mode 100644 index 0000000..9642c3b --- /dev/null +++ b/include/j/lang/dl.hpp @@ -0,0 +1,62 @@ +/** + * @file dl.hpp + * @brief J Library DL ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_DL_HPP +#define J_LANG_DL_HPP + +#include + +#include + +namespace j +{ + namespace lang + { + +#if (IS_WINDOWS) + typedef HINSTANCE dl_handle_t; + typedef FARPROC WINAPI dl_func_t; +#else + typedef void *dl_handle_t; + typedef void *dl_func_t; +#endif + + class Dl final : public Object + { + public: + // コンストラクタ + Dl(const String &fileName) noexcept; + + // コピーコンストラクタ + Dl(const Dl &obj) noexcept; + + // ムーブコンストラクタ + Dl(Dl &&obj) noexcept; + + // デストラクタ + ~Dl() noexcept; + + // コピー代入演算子 + Dl &operator=(const Dl &obj) noexcept; + + // ムーブ代入演算子 + Dl &operator=(Dl &&obj) noexcept; + + // 文字列表現取得 + String toString() const noexcept; + + // 関数取得 + dl_func_t sym(const String &symbol); + + private: + dl_handle_t handle; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_DL_HPP diff --git a/include/j/lang/errno.hpp b/include/j/lang/errno.hpp new file mode 100644 index 0000000..defde7b --- /dev/null +++ b/include/j/lang/errno.hpp @@ -0,0 +1,33 @@ +/** + * @file errno.hpp + * @brief J Library Errno ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_ERRNO_HPP +#define J_LANG_ERRNO_HPP + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { + // エラー番号を設定する。 + void set(int errnum); + + // エラー番号を取得する。 + int get(); + + // メッセージを取得する。 + String message(int errnum); + + } // namespace Errno + } // namespace lang +} // namespace j + +#endif // J_LANG_ERRNO_HPP \ No newline at end of file diff --git a/include/j/lang/error.hpp b/include/j/lang/error.hpp new file mode 100644 index 0000000..7657695 --- /dev/null +++ b/include/j/lang/error.hpp @@ -0,0 +1,40 @@ +/** + * @file error.hpp + * @brief J Library Error ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ERROR_HPP +#define J_LANG_ERROR_HPP + +#include + +namespace j +{ + namespace lang + { + + class Error : public Throwable + { + public: + // デフォルトコンストラクタ + Error() noexcept; + + // コンストラクタ + Error(const String &msg) noexcept; + + // コピーコンストラクタ + Error(const Error &t) noexcept; + + // ムーブコンストラクタ + Error(Error &&t) noexcept; + + // デストラクタ + ~Error() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ERROR_HPP diff --git a/include/j/lang/exception.hpp b/include/j/lang/exception.hpp new file mode 100644 index 0000000..6326588 --- /dev/null +++ b/include/j/lang/exception.hpp @@ -0,0 +1,40 @@ +/** + * @file exception.hpp + * @brief J Library Exception ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_EXCEPTION_HPP +#define J_LANG_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class Exception : public Throwable + { + public: + // デフォルトコンストラクタ + Exception() noexcept; + + // コンストラクタ + Exception(const String &msg) noexcept; + + // コピーコンストラクタ + Exception(const Exception &t) noexcept; + + // ムーブコンストラクタ + Exception(Exception &&t) noexcept; + + // デストラクタ + ~Exception() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_EXCEPTION_HPP diff --git a/include/j/lang/illegal_argument_exception.hpp b/include/j/lang/illegal_argument_exception.hpp new file mode 100644 index 0000000..2371a36 --- /dev/null +++ b/include/j/lang/illegal_argument_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file illegal_argument_exception.hpp + * @brief J Library IllegalArgumentException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP +#define J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IllegalArgumentException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IllegalArgumentException() noexcept; + + // コンストラクタ + IllegalArgumentException(const String &msg) noexcept; + + // コピーコンストラクタ + IllegalArgumentException(const IllegalArgumentException &t) noexcept; + + // ムーブコンストラクタ + IllegalArgumentException(IllegalArgumentException &&t) noexcept; + + // デストラクタ + ~IllegalArgumentException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_ILLEGAL_ARGUMENT_EXCEPTION_HPP diff --git a/include/j/lang/index_out_of_bounds_exception.hpp b/include/j/lang/index_out_of_bounds_exception.hpp new file mode 100644 index 0000000..3b6a63e --- /dev/null +++ b/include/j/lang/index_out_of_bounds_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file index_out_of_bounds_exception.hpp + * @brief J Library IndexOutOfBoundsException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP +#define J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class IndexOutOfBoundsException : public RuntimeException + { + public: + // デフォルトコンストラクタ + IndexOutOfBoundsException() noexcept; + + // コンストラクタ + IndexOutOfBoundsException(const String &msg) noexcept; + + // コピーコンストラクタ + IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept; + + // ムーブコンストラクタ + IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept; + + // デストラクタ + ~IndexOutOfBoundsException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_INDEX_OUT_OF_BOUNDS_EXCEPTION_HPP diff --git a/include/j/lang/object.hpp b/include/j/lang/object.hpp new file mode 100644 index 0000000..ae42bcc --- /dev/null +++ b/include/j/lang/object.hpp @@ -0,0 +1,91 @@ +/** + * @file object.hpp + * @brief J Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_OBJECT_HPP +#define J_LANG_OBJECT_HPP + +#include +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String; + + /** + * + */ + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &obj) noexcept; + + // ムーブ代入演算子 + Object &operator=(Object &&obj) noexcept; + + // クラス名取得 + virtual String getClassName() const noexcept; + + // 文字列表現取得 + virtual String toString() const noexcept; + + // 同じクラスか否か + virtual bool isSameClass(const Object &obj) const noexcept; + + // 比較 + virtual bool equals(const Object &obj) const noexcept; + + // ハッシュコード + virtual int hashCode() const noexcept; + + // notify + void notify(); + + // notifyAll + void notifyAll(); + + // wait + void wait(); + + // wait + void wait(int msec); + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const Object &obj); + + protected: + // クローン + virtual std::unique_ptr clone() const noexcept; + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_OBJECT_HPP diff --git a/include/j/lang/os.hpp b/include/j/lang/os.hpp new file mode 100644 index 0000000..e1da1f5 --- /dev/null +++ b/include/j/lang/os.hpp @@ -0,0 +1,53 @@ +/** + * @file j_os.hpp + * @brief J Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef J_LANG_OS_HPP +#define J_LANG_OS_HPP +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__) +#define IS_WINDOWS (1) + +// DMC にて winsoc2.h を利用する場合、_WINSOCK_API_ が必要 +// 詳細は、下記URL参照 +// http://www.digitalmars.com/d/archives/c++/idde/326.html +#ifdef __DMC__ +#define _WINSOCKAPI_ +#include +#endif + +// サポートする OS バージョン指定として、Windows 10 以降を指定する。 +// 参考までに他バージョンの値は次の通り。 +// Windows 2000 0x05000 +// Windows XP 0x0501 +// Windows Server 2003 0x0502 +// Windows Server 2008 0x0600 +// Windows 7 0x0601 +// Windows 8 0x0602 +// Windows 10 0x0A00 +#ifndef WINVER +#define WINVER 0x0A00 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0A00 +#endif + +// よく利用されるヘッダファイルをインクルードする +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "iphlpapi.lib") +#endif + +#else +// ##### Windows 以外 ##### +#define IS_WINDOWS (0) + +#endif // Windows 判定 +#endif // J_LANG_OS_HPP diff --git a/include/j/lang/runtime_exception.hpp b/include/j/lang/runtime_exception.hpp new file mode 100644 index 0000000..13bdd73 --- /dev/null +++ b/include/j/lang/runtime_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file runtime_exception.hpp + * @brief J Library RuntimeException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_RUNTIME_EXCEPTION_HPP +#define J_LANG_RUNTIME_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class RuntimeException : public Throwable + { + public: + // デフォルトコンストラクタ + RuntimeException() noexcept; + + // コンストラクタ + RuntimeException(const String &msg) noexcept; + + // コピーコンストラクタ + RuntimeException(const RuntimeException &t) noexcept; + + // ムーブコンストラクタ + RuntimeException(RuntimeException &&t) noexcept; + + // デストラクタ + ~RuntimeException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_RUNTIME_EXCEPTION_HPP diff --git a/include/j/lang/string.hpp b/include/j/lang/string.hpp new file mode 100644 index 0000000..4f1cc08 --- /dev/null +++ b/include/j/lang/string.hpp @@ -0,0 +1,124 @@ +/** + * @file string.hpp + * @brief J Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + */ +#ifndef J_LANG_STRING_HPP +#define J_LANG_STRING_HPP + +#include +#include +#include + +#include + +namespace j +{ + namespace lang + { + + class String final : public Object + { + public: + // デフォルトコンストラクタ + String(const char *str = "") noexcept; + + // コピーコンストラクタ + String(const String &str) noexcept; + + // ムーブコンストラクタ + String(String &&str) noexcept; + + // デストラクタ + ~String() noexcept; + + // コピー代入演算子 + String &operator=(const String &str) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&str) noexcept; + + // 文字列結合用 + String &operator+=(const String &str) noexcept; + + // C言語文字列表現 + operator const char *() const; + + // 文字列長を返す。 + int length() const noexcept; + + // 指定された位置の文字を返す。 + char charAt(int index) const; + + // 部分文字列を返す。 + String substring(int beginIndex, int endIndex) const; + + // 指定文字列が含まれるかい否かを返す。 + bool contains(const String &str) const noexcept; + + // 文字置換 + String replace(char oldChar, char newChar) const noexcept; + + // 文字列置換 + String replace(const String ®ex, const String &replacement) const; + + // 文字列置換 + String replaceAll(const String ®ex, const String &replacement) const; + + // 分割 + std::unique_ptr split(const String ®ex) const noexcept; + + // 先頭の文字列が一致するか + bool startsWith(const String &prefix) const noexcept; + + // 末尾の文字列が一致するか + bool endsWith(const String &suffix) const noexcept; + + // 小文字変換 + String toLowerCase() const noexcept; + + // 大文字変換 + String toUpperCase() const noexcept; + + // trim + String trim() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + // 比較 + bool equals(const Object &obj) const noexcept override; + + // ハッシュコード + int hashCode() const noexcept override; + + // 文字列結合用 + friend String operator+(const String &str1, const String &str2) noexcept; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + private: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_STRING_HPP \ No newline at end of file diff --git a/include/j/lang/system.hpp b/include/j/lang/system.hpp new file mode 100644 index 0000000..826cd28 --- /dev/null +++ b/include/j/lang/system.hpp @@ -0,0 +1,29 @@ +/** + * @file system.hpp + * @brief J Library System ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j.hpp + */ +#ifndef J_LANG_SYSTEM_HPP +#define J_LANG_SYSTEM_HPP + +#include +#include +#include + +namespace j +{ + namespace lang + { + + namespace System + { + // ライブラリロード + // @see j/lang/Dl + + } // namespace System + } // namespace lang +} // namespace j + +#endif // J_LANG_SYSTEM_HPP diff --git a/include/j/lang/throwable.hpp b/include/j/lang/throwable.hpp new file mode 100644 index 0000000..f98c71a --- /dev/null +++ b/include/j/lang/throwable.hpp @@ -0,0 +1,60 @@ +/** + * @file throwable.hpp + * @brief J Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/object.hpp + * j/lang/string.hpp + */ +#ifndef J_LANG_THROWABLE_HPP +#define J_LANG_THROWABLE_HPP + +#include + +namespace j +{ + namespace lang + { + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable() noexcept; + + // コンストラクタ + Throwable(const String &msg) noexcept; + + // コピーコンストラクタ + Throwable(const Throwable &t) noexcept; + + // ムーブコンストラクタ + Throwable(Throwable &&t) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + Throwable &operator=(const Throwable &t) noexcept; + + // ムーブ代入演算子 + Throwable &operator=(Throwable &&t) noexcept; + + // エラーメッセージ取得 + String getMessage() const noexcept; + + // 文字列表現取得 + String toString() const noexcept override; + + protected: + // クローン + std::unique_ptr clone() const noexcept override; + + // メッセージ + String message; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_THROWABLE_HPP diff --git a/include/j/lang/unsupported_operation_exception.hpp b/include/j/lang/unsupported_operation_exception.hpp new file mode 100644 index 0000000..09039fe --- /dev/null +++ b/include/j/lang/unsupported_operation_exception.hpp @@ -0,0 +1,40 @@ +/** + * @file unsupported_operation_exception.hpp + * @brief J Library UnsupportedOperationException ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * j/lang/throwable.hpp + */ +#ifndef J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP +#define J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP + +#include + +namespace j +{ + namespace lang + { + + class UnsupportedOperationException : public RuntimeException + { + public: + // デフォルトコンストラクタ + UnsupportedOperationException() noexcept; + + // コンストラクタ + UnsupportedOperationException(const String &msg) noexcept; + + // コピーコンストラクタ + UnsupportedOperationException(const UnsupportedOperationException &t) noexcept; + + // ムーブコンストラクタ + UnsupportedOperationException(UnsupportedOperationException &&t) noexcept; + + // デストラクタ + ~UnsupportedOperationException() noexcept; + }; + + } // namespace lang +} // namespace j + +#endif // J_LANG_UNSUPPORTED_OPERATION_EXCEPTION_HPP diff --git a/j/Makefile b/j/Makefile new file mode 100644 index 0000000..b2cf1d5 --- /dev/null +++ b/j/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = +TARGET = $(NAME) +SUBDIRS = lang +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/Makefile b/j/lang/Makefile new file mode 100644 index 0000000..1da5e45 --- /dev/null +++ b/j/lang/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = libj +TARGET = $(NAME) +SUBDIRS = +USE_SO_VERSION = + +# ------------------------------------------------------------------------------ +# *-cmd.mk : コマンド +# *-conf.mk : 設定 +# *-auto.mk : 自動設定 +# ------------------------------------------------------------------------------ +include $(TOPDIR)/config.mk +include $(RULEDIR)/*-cmd.mk +include $(RULEDIR)/*-conf.mk +include $(RULEDIR)/*-auto.mk +# ------------------------------------------------------------------------------ +# +# 以下、オプションを適宜変更してください。 +# + +INCLUDES += -I$(TOPDIR)/include +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/j/lang/src/assertion_error.cpp b/j/lang/src/assertion_error.cpp new file mode 100644 index 0000000..663ff73 --- /dev/null +++ b/j/lang/src/assertion_error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * AssertionError を構築します。 + */ + AssertionError::AssertionError() noexcept : Error() + { + // NOP + } + + /** + * AssertionError を構築します。 + * + * @param msg メッセージ + */ + AssertionError::AssertionError(const String &msg) noexcept : Error(msg) + { + // NOP + } + + /** + * AssertionError のコピーコンストラクタ。 + * + * @param t コピー元 AssertionError + */ + AssertionError::AssertionError(const AssertionError &t) noexcept : Error(t) + { + // NOP + } + + /** + * AssertionError のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + AssertionError::AssertionError(AssertionError &&t) noexcept : Error(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + AssertionError::~AssertionError() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/dl.cpp b/j/lang/src/dl.cpp new file mode 100644 index 0000000..c95ce33 --- /dev/null +++ b/j/lang/src/dl.cpp @@ -0,0 +1,128 @@ +#include + +#if (!IS_WINDOWS) +#include +#endif + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Dl を構築します。 + */ + Dl::Dl(const String &fileName) noexcept + { +#if (IS_WINDOWS) + handle = ::LoadLibraryEx(fileName); +#else + handle = ::dlopen(fileName, RTLD_LAZY); +#endif + // TODO : handle == 0 の場合エラー + } + + /** + * Dl のコピーコンストラクタ。 + * + * @param dl コピー元オブジェクト + */ + Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle) + { /* NOP */ + } + + /** + * Dl のムーブコンストラクタ。 + * + * @param dl ムーブ元オブジェクト + */ + Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle)) + { /* NOP */ + } + + // デストラクタ + Dl::~Dl() noexcept + { +#if (IS_WINDOWS) + ::FreeLibrary(handle); +#else + ::dlclose(handle); +#endif + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param dl コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(const Dl &dl) noexcept + { + if (this != &dl) + { + Object::operator=(dl); + handle = dl.handle; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param dl ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Dl &Dl::operator=(Dl &&dl) noexcept + { + if (this != &dl) + { + Object::operator=(std::move(dl)); + handle = std::move(dl.handle); + handle = nullptr; + } + return *this; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Dl::toString() const noexcept + { + return Object::toString(); + } + + /** + * 指定されたシンボルがロードされたメモリのアドレスを返します。 + * + * @code + * typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash); + * Dl dl("kernel32.dll"); + * RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast(dl.sym("RtlCaptureStackBackTrace")); + * void* buffer[64]; + * int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0); + * for (int i = 0; i < cnt; i++) + * { + * std::cout << buffer[i] << std::endl; + * } + * @endcode + * + * @param symbol シンボル名 + * @return シンボルのアドレス + */ + dl_func_t Dl::sym(const String &symbol) + { +#if (IS_WINDOWS) + return ::GetProcAddress(handle, symbol); +#else + return ::dlsym(handle, symbol); +#endif + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/errno.cpp b/j/lang/src/errno.cpp new file mode 100644 index 0000000..510625e --- /dev/null +++ b/j/lang/src/errno.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace j +{ + namespace lang + { + namespace Errno + { +#if (IS_WINDOWS) + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows + // + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + SetLastError(errnum); + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return GetLastError(); + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + LPVOID lpMsgBuf; + int ret = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // 動作フラグ + 0, // メッセージ定義位置 + errnum, // エラーコード + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 言語ID + (LPSTR)&lpMsgBuf, // バッファアドレス + 0, // バッファサイズ + 0); // 挿入句 + + if (ret != 0) + { + String msg((char *)lpMsgBuf); + LocalFree(lpMsgBuf); + return msg; + } + else + { + String msg(); + return msg; + } + } +#else + //////////////////////////////////////////////////////////////////////////////// + // + // For Windows 以外 + // + + /** + * エラー番号を設定します。 + * + * @param errnum エラー番号 + */ + void set(int errnum) + { + errno = errnum; + } + + /** + * エラー番号を取得します。 + * + * @return エラー番号 + */ + int get() + { + return errno; + } + + /** + * エラー番号に対応するエラーメッセージを取得します。 + * + * @param errnum エラー番号 + * @return エラーメッセージ + */ + String message(int errnum) + { + String msg(strerror(errnum)); + return msg; + } +#endif // IS_WINDOWS + + } // namespace Errno + } // namespace lang +} // namespace j diff --git a/j/lang/src/error.cpp b/j/lang/src/error.cpp new file mode 100644 index 0000000..bf8dacb --- /dev/null +++ b/j/lang/src/error.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Error を構築します。 + */ + Error::Error() noexcept : Throwable() + { + // NOP + } + + /** + * Error を構築します。 + * + * @param msg メッセージ + */ + Error::Error(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Error のコピーコンストラクタ。 + * + * @param t コピー元 Error + */ + Error::Error(const Error &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Error のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Error::Error(Error &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Error::~Error() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/exception.cpp b/j/lang/src/exception.cpp new file mode 100644 index 0000000..98aafb5 --- /dev/null +++ b/j/lang/src/exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * Exception を構築します。 + */ + Exception::Exception() noexcept : Throwable() + { + // NOP + } + + /** + * Exception を構築します。 + * + * @param msg メッセージ + */ + Exception::Exception(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * Exception のコピーコンストラクタ。 + * + * @param t コピー元 Exception + */ + Exception::Exception(const Exception &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * Exception のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Exception::Exception(Exception &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + Exception::~Exception() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/illegal_argument_exception.cpp b/j/lang/src/illegal_argument_exception.cpp new file mode 100644 index 0000000..445f866 --- /dev/null +++ b/j/lang/src/illegal_argument_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IllegalArgumentException を構築します。 + */ + IllegalArgumentException::IllegalArgumentException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IllegalArgumentException を構築します。 + * + * @param msg メッセージ + */ + IllegalArgumentException::IllegalArgumentException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IllegalArgumentException のコピーコンストラクタ。 + * + * @param t コピー元 IllegalArgumentException + */ + IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IllegalArgumentException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IllegalArgumentException::IllegalArgumentException(IllegalArgumentException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IllegalArgumentException::~IllegalArgumentException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/index_out_of_bounds_exception.cpp b/j/lang/src/index_out_of_bounds_exception.cpp new file mode 100644 index 0000000..eabe527 --- /dev/null +++ b/j/lang/src/index_out_of_bounds_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * IndexOutOfBoundsException を構築します。 + */ + IndexOutOfBoundsException::IndexOutOfBoundsException() noexcept : RuntimeException() + { + // NOP + } + + /** + * IndexOutOfBoundsException を構築します。 + * + * @param msg メッセージ + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * IndexOutOfBoundsException のコピーコンストラクタ。 + * + * @param t コピー元 IndexOutOfBoundsException + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(const IndexOutOfBoundsException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * IndexOutOfBoundsException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + IndexOutOfBoundsException::IndexOutOfBoundsException(IndexOutOfBoundsException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + IndexOutOfBoundsException::~IndexOutOfBoundsException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/main.cpp b/j/lang/src/main.cpp new file mode 100644 index 0000000..928dc08 --- /dev/null +++ b/j/lang/src/main.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include +#include +#include +#include + +using namespace j; +using namespace j::lang; + +class X : public Object +{ +public: + String toString() const noexcept override + { + String str("This is X"); + return str; + } +}; + +int main(int, char **) +{ + /* + String str = "AbcdefAbaBcdefGhI"; + bool ret = str.startsWith("Abc"); + std::cout << "startsWith:[ok] " << ret << std::endl; + + ret = str.startsWith("Abd"); + std::cout << "startsWith:[ng] " << ret << std::endl; + + ret = str.endsWith("GhI"); + std::cout << "endsWith:[ok] " << ret << std::endl; + + ret = str.endsWith("xGhi"); + std::cout << "endsWith:[ng] " << ret << std::endl; + + std::cout << str.toLowerCase() << std::endl; + std::cout << str.toUpperCase() << std::endl; + + String str2 = " a a daf\t"; + std::cout << str2 << std::endl; + std::cout << str2.trim() << std::endl; + + std::cout << str << std::endl; + std::cout << str.replace('A', '-') << std::endl; + std::cout << str.replace("Ab", "--") << std::endl; + std::cout << str.replaceAll("Ab", "--") << std::endl; + */ + String t1 = "Hello"; + String t2 = "World"; + String t3 = t1 + " " + t2; + for (int i = 0; i < 100; i++) + { + t3 += "!"; + } + + std::cout << t3 << std::endl; + + std::cout << t1.equals(t2) << std::endl; + + String t4 = "World"; + String t5 = t2; + std::cout << "t2:hash=" << t2.hashCode() << std::endl; + std::cout << "t4:hash=" << t4.hashCode() << std::endl; + std::cout << t2.equals(t4) << std::endl; + std::cout << t5.equals(t2) << std::endl; + + Errno::set(EINVAL); + Throwable tt1; + Throwable tt2("MSG"); + Throwable tt3 = tt1; + Object *tt4 = &tt1; + + std::cout << tt1 << std::endl; + std::cout << tt2 << std::endl; + std::cout << tt1.equals(tt2) << std::endl; + std::cout << tt1.equals(tt3) << std::endl; + std::cout << "tt1 == tt4 : " << tt1.equals(*tt4) << std::endl; + std::cout << "tt4 == tt1 : " << tt4->equals(tt1) << std::endl; + + String str4 = tt3.getMessage(); + std::cout << str4 << std::endl; + + Error err("Error"); + Error err2 = err; + std::cout << err2 << std::endl; + return 0; +} diff --git a/j/lang/src/object.cpp b/j/lang/src/object.cpp new file mode 100644 index 0000000..ca0772e --- /dev/null +++ b/j/lang/src/object.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Object を構築します。 + */ + Object::Object() noexcept { /* NOP */ } + + /** + * Object のコピーコンストラクタ。 + * + * @param obj コピー元オブジェクト + */ + Object::Object(const Object &) noexcept { /* NOP */ } + + /** + * Object のムーブコンストラクタ。 + * + * @param obj ムーブ元オブジェクト + */ + Object::Object(Object &&) noexcept { /* NOP */ } + + // デストラクタ + // virtual Object::~Object() noexcept = default; + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param obj コピー元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(const Object &) noexcept + { // 特にコピーする要素はない。 + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Object &Object::operator=(Object &&) noexcept + { // 特に移すものはない。 + return *this; + } + + /** + * クラス名を取得します。 + * + * @return クラス名 + */ + String Object::getClassName() const noexcept + { + String str(typeid(*this).name()); + return str; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Object::toString() const noexcept + { + // String str(getClassName() + "@" + std::to_string(reinterpret_cast(this))); + return getClassName(); + } + + /** + * 指定されたオブジェクトが同じクラスか否かを返します。 + * + * @param obj オブジェクト + * @return true/false (同じクラス/異なるクラス) + */ + bool Object::isSameClass(const Object &obj) const noexcept + { + return (typeid(*this) == typeid(obj)); + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool Object::equals(const Object &obj) const noexcept + { + if (isSameClass(obj)) + { // 同じクラス + int ownHash = hashCode(); + int objHash = obj.hashCode(); + if (ownHash == objHash) + { // ハッシュコードが一緒 + String ownStr = toString(); + String objStr = obj.toString(); + return ownStr.equals(objStr); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 待機中のスレッドを再開します。 + */ + void Object::notify() + { + std::lock_guard lock(mtx); + cv.notify_one(); + } + + /** + * 待機中のすべてのスレッドを再開します。 + */ + void Object::notifyAll() + { + std::lock_guard lock(mtx); + cv.notify_all(); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait() + { + std::unique_lock lock(mtx); + cv.wait(lock); + } + + /** + * 現在のスレッドを待機させます。 + */ + void Object::wait(int msec) + { + std::unique_lock lock(mtx); + cv.wait_for(lock, std::chrono::milliseconds(msec)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*this); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/runtime_exception.cpp b/j/lang/src/runtime_exception.cpp new file mode 100644 index 0000000..16c609f --- /dev/null +++ b/j/lang/src/runtime_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * RuntimeException を構築します。 + */ + RuntimeException::RuntimeException() noexcept : Throwable() + { + // NOP + } + + /** + * RuntimeException を構築します。 + * + * @param msg メッセージ + */ + RuntimeException::RuntimeException(const String &msg) noexcept : Throwable(msg) + { + // NOP + } + + /** + * RuntimeException のコピーコンストラクタ。 + * + * @param t コピー元 RuntimeException + */ + RuntimeException::RuntimeException(const RuntimeException &t) noexcept : Throwable(t) + { + // NOP + } + + /** + * RuntimeException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + RuntimeException::RuntimeException(RuntimeException &&t) noexcept : Throwable(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + RuntimeException::~RuntimeException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/string.cpp b/j/lang/src/string.cpp new file mode 100644 index 0000000..6fa1ac4 --- /dev/null +++ b/j/lang/src/string.cpp @@ -0,0 +1,440 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace j +{ + namespace lang + { + // [補足] + // std::unique_ptr value; において、 + // インデックスに対する操作も多々あるため、value.get() + index ではなく、 + // 直観的にわかりやすい, &value[index] の表現にて実装している。 + + /** + * String を構築します。 + * + * @param str 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept : Object(str) + { + setValue(&str.value[0]); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : Object(std::move(str)), value(std::move(str.value)), len(str.len) + { + str.value = nullptr; + str.len = 0; + } + + /** + * デストラクタ。 + */ + String::~String() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + String &String::operator=(const String &str) noexcept + { + if (this != &str) + { + Object::operator=(str); + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + Object::operator=(std::move(str)); + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 指定された文字列を結合します。 + */ + String &String::operator+=(const String &str) noexcept + { + int newLen = len + str.len; + std::unique_ptr newStr = std::make_unique(newLen + 1); + std::strncpy(&newStr[0], &value[0], len); + std::strncpy(&newStr[len], &str.value[0], str.len); + newStr[newLen] = '\0'; + value = std::move(newStr); + len = newLen; + return *this; + } + + /** + * const char* 型に変換します。 + */ + String::operator const char *() const + { + return value.get(); + } + + /** + * 文字列の長さを返します。 + * + * @return 文字列の長さ + */ + int String::length() const noexcept + { + return len; + } + + /** + * 指定された位置の文字を返します。 + * + * @param index 位置 + * @return 文字 + */ + char String::charAt(int index) const + { + if ((index < 0) || (index >= len)) + { + // TODO: IndexOutOfBoundsException + } + return value[index]; + } + + /** + * 指定された部分文字列を返します。 + * + * @param beginIndex 開始位置 + * @param endIndex 終了位置 + * @return 部分文字列 + */ + String String::substring(int beginIndex, int endIndex) const + { + if ((0 <= beginIndex) && (beginIndex <= endIndex) && (endIndex <= len)) + { + int subLen = endIndex - beginIndex; + std::unique_ptr subStr = std::make_unique(subLen + 1); + std::strncpy(&subStr[0], &value[beginIndex], subLen); + subStr[subLen] = '\0'; + String result(&subStr[0]); + return result; + } + else + { + // TODO: IndexOutOfBoundsException + return nullptr; + } + } + + /** + * 指定された文字列が含まれるか否かを返します。 + * + * @param str 文字列 + * @return true/false (含まれる/含まれない) + */ + bool String::contains(const String &str) const noexcept + { + return (std::strstr(&value[0], &str.value[0]) != nullptr); + } + + /** + * 指定された文字を置換します。 + * + * @param oldChar 置換前文字 + * @param newChar 置換後文字 + * @return 置換された文字列 + */ + String String::replace(char oldChar, char newChar) const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + if (str.value[idx] == oldChar) + { + str.value[idx] = newChar; + } + } + return str; + } + + // 文字列置換 + String String::replace(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_continuous); + String str(res.c_str()); + return str; + } + + // 文字列置換 + String String::replaceAll(const String ®ex, const String &replacement) const + { + std::regex re(®ex.value[0]); + std::string res = std::regex_replace( + &value[0], re, &replacement.value[0], std::regex_constants::match_any); + String str(res.c_str()); + return str; + } + + // 分割 + std::unique_ptr String::split(const String &) const noexcept + { + return nullptr; + } + + // 先頭の文字列が一致するか + bool String::startsWith(const String &prefix) const noexcept + { + if (prefix.len > len) + { + return false; + } + for (int idx = 0; idx < prefix.len; idx++) + { + if (value[idx] != prefix.value[idx]) + { + return false; + } + } + return true; + } + + // 末尾の文字列が一致するか + bool String::endsWith(const String &suffix) const noexcept + { + if (suffix.len > len) + { + return false; + } + int value_idx = (len - suffix.len); + for (int idx = 0; idx < suffix.len; idx++) + { + if (value[value_idx] != suffix.value[idx]) + { + return false; + } + value_idx++; + } + return true; + } + + // 小文字変換 + String String::toLowerCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::tolower(str.value[idx]); + } + return str; + } + + // 大文字変換 + String String::toUpperCase() const noexcept + { + String str(*this); + for (int idx = 0; idx < len; idx++) + { + str.value[idx] = std::toupper(str.value[idx]); + } + return str; + } + + // trim + String String::trim() const noexcept + { + int beginIndex = 0; + for (; beginIndex < len; beginIndex++) + { + if (value[beginIndex] > 0x20) + { + break; + } + } + int endIndex = len; + for (; endIndex >= beginIndex; endIndex--) + { + if (value[endIndex] > 0x20) + { + break; + } + } + int trimedLen = endIndex - beginIndex; + std::unique_ptr trimedStr = std::make_unique(trimedLen + 1); + std::strncpy(&trimedStr[0], &value[beginIndex], trimedLen); + trimedStr[trimedLen] = '\0'; + String result(&trimedStr[0]); + return result; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String String::toString() const noexcept + { + String str(*this); + return str; + } + + /** + * 指定されたオブジェクトと合致するか否かを返します。 + * + * @param obj 比較するオブジェクト + * @return true/false (合致する/しない) + */ + bool String::equals(const Object &obj) const noexcept + { + bool isSame = isSameClass(obj); + if (isSame) + { + const String &str = dynamic_cast(obj); + if (len == str.len) + { + return (std::strcmp(&value[0], &str.value[0]) == 0); + } + } + return false; + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int String::hashCode() const noexcept + { + int hash = 0; + for (int idx = 0; idx < len; idx++) + { + hash = 31 * hash + value[idx]; + } + return hash; + } + + /** + * 2つの文字列を結合します。 + * + * @param str1 文字列 + * @param str2 文字列 + * @return 結合後の文字列 + */ + String operator+(const String &str1, const String &str2) noexcept + { + String str = str1; + str += str2; + return str; + } + + /** + * 出力用 + * + * @param os output stream + * @param str 出力文字列 + * @return output stream + */ + std::ostream &operator<<(std::ostream &os, const String &str) + { + if (str.value != nullptr) + { + os << &str.value[0]; + } + return os; + } + + /** + * 入力用 + * + * @param is input stream + * @param str 入力先 String + * @return input stream + */ + std::istream &operator>>(std::istream &is, String &str) + { + char buff[MAX_ISTREAM_BUFFER_SIZE]; + is >> buff; + str = String(buff); + return is; + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 文字列データを設定します。 + * + * @param str 設定する文字列 + */ + void String::setValue(const char *str) + { + if (str) + { + len = std::strlen(str); + value = std::make_unique(len + 1); + std::strcpy(&value[0], str); + } + else + { + len = 0; + value = std::make_unique(1); + value[0] = '\0'; + } + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr String::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/throwable.cpp b/j/lang/src/throwable.cpp new file mode 100644 index 0000000..e42b5d6 --- /dev/null +++ b/j/lang/src/throwable.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include + +namespace j +{ + namespace lang + { + + /** + * Throwable を構築します。 + */ + Throwable::Throwable() noexcept : message(Errno::message(Errno::get())) + { + // NOP + } + + /** + * Throwable を構築します。 + * + * @param msg メッセージ + */ + Throwable::Throwable(const String &msg) noexcept : message(msg) + { + // NOP + } + + /** + * Throwable のコピーコンストラクタ。 + * + * @param t コピー元 Throwable + */ + Throwable::Throwable(const Throwable &t) noexcept : Object(t), message(t.message) + { + // NOP + } + + /** + * Throwable のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + Throwable::Throwable(Throwable &&t) noexcept : Object(std::move(t)), message(std::move(t.message)) + { + t.message = nullptr; + } + + /** + * デストラクタ。 + */ + Throwable::~Throwable() noexcept + { + // NOP + } + + /** + * コピー代入演算子。 + * コピーして代入します。 + * + * @param str コピー元 String + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(const Throwable &t) noexcept + { + if (this != &t) + { + Object::operator=(t); + message = t.message; + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + Throwable &Throwable::operator=(Throwable &&t) noexcept + { + if (this != &t) + { + Object::operator=(std::move(t)); + message = std::move(t.message); + t.message = nullptr; + } + return *this; + } + + /** + * エラーメッセージを取得します。 + * + * @return エラーメッセージ + */ + String Throwable::getMessage() const noexcept + { + return message; + } + + /** + * 本オブジェクトの文字列表現を返します。 + * + * @return 本オブジェクトの文字列表現 + */ + String Throwable::toString() const noexcept + { + return getMessage(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // protected + // + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Throwable::clone() const noexcept + { + return std::make_unique(*this); + } + + } // namespace lang +} // namespace j diff --git a/j/lang/src/unsupported_operation_exception.cpp b/j/lang/src/unsupported_operation_exception.cpp new file mode 100644 index 0000000..4a9dd54 --- /dev/null +++ b/j/lang/src/unsupported_operation_exception.cpp @@ -0,0 +1,54 @@ +#include + +namespace j +{ + namespace lang + { + /** + * UnsupportedOperationException を構築します。 + */ + UnsupportedOperationException::UnsupportedOperationException() noexcept : RuntimeException() + { + // NOP + } + + /** + * UnsupportedOperationException を構築します。 + * + * @param msg メッセージ + */ + UnsupportedOperationException::UnsupportedOperationException(const String &msg) noexcept : RuntimeException(msg) + { + // NOP + } + + /** + * UnsupportedOperationException のコピーコンストラクタ。 + * + * @param t コピー元 UnsupportedOperationException + */ + UnsupportedOperationException::UnsupportedOperationException(const UnsupportedOperationException &t) noexcept : RuntimeException(t) + { + // NOP + } + + /** + * UnsupportedOperationException のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + UnsupportedOperationException::UnsupportedOperationException(UnsupportedOperationException &&t) noexcept : RuntimeException(std::move(t)) + { + // NOP + } + + /** + * デストラクタ。 + */ + UnsupportedOperationException::~UnsupportedOperationException() noexcept + { + // NOP + } + + } // namespace lang +} // namespace j diff --git a/mk/README.md b/mk/README.md new file mode 100644 index 0000000..c4474d3 --- /dev/null +++ b/mk/README.md @@ -0,0 +1,18 @@ +# Makefile 用 設定、ルール + +Makefile 用の設定、ルールを格納しているディレクトリ。 + +## 使い方 + +Makefile.tmpl を元に、Makefile を作成することで、 +本配下にあるルールを make に組み込むことができます。 + + +## ファイル命名規則 +新たなルールを追加する場合、下記ファイルの命名規則に従ってください。 +* *-cmd.mk コマンドを記載したファイル +* *-conf.mk 設定を記載したファイル +* *-rule.mk ルールを記載したファイル +* *-auto.mk 自動設定を記載したファイル + + diff --git a/mk/all-rule.mk b/mk/all-rule.mk new file mode 100644 index 0000000..f45e02f --- /dev/null +++ b/mk/all-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# all ルール +# ------------------------------------------------------------------------------ +# 次を実行します。 +# (1) 全サブディレクトリに対して make all 実行 +# (2) make $(TARGET) 実行 +# (3) make $(TOP_TARGET) 実行 +# +.PHONY: all +all: + @for subdir in $(SUBDIRS); do \ + $(MAKE) all -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + $(MAKE) $(TARGET) +ifneq ($(strip $(TOP_TARGET)),) + $(MAKE) $(TOP_TARGET) +endif +endif +endif diff --git a/mk/base-auto.mk b/mk/base-auto.mk new file mode 100644 index 0000000..1945456 --- /dev/null +++ b/mk/base-auto.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本自動設定 +# ============================================================================== +# 以下、基本設定に基づき自動的に設定されます。 +# (本ファイルは、基本的に変更不要です。) + + +# ------------------------------------------------------------------------------ +# SRCS, OBJS, DEPS ファイル群の自動設定 +# ------------------------------------------------------------------------------ +S_SRCS = $(wildcard $(addsuffix /*.s,$(SRCDIR))) +C_SRCS = $(wildcard $(addsuffix /*.c,$(SRCDIR))) +CXX_SRCS = $(wildcard $(addsuffix /*.cpp,$(SRCDIR))) +TMP_SRCS = $(C_SRCS) $(CXX_SRCS) $(S_SRCS) +VPATH = $(SRCDIR) +SRCS = $(filter-out $(EXCLUDES),$(TMP_SRCS)) +OBJS = $(addprefix $(OBJDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +DEPS = $(OBJS:$(OBJDIR)/%.o=$(OBJDIR)/%.d) + + +# ------------------------------------------------------------------------------ +# LINK : リンカー設定 +# C++ が含まれる場合、$(CXX) を使用する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(CXX_SRCS)),) + LINK = $(CC) +else + LINK = $(CXX) +endif + + +# ------------------------------------------------------------------------------ +# ターゲットが ut.exe の場合の設定 +# +# 1. DEBUG を常に有効に設定する。 +# 2. SRCDIR に、../src を追加する。 +# 3. INCLUDES に、../include を追加する。 +# 4. DEFINE に -DUNITTEST -DDEBUG を追加する。 +# ------------------------------------------------------------------------------ +ifeq ($(strip $(TARGET)),ut.exe) +DEBUG = 1 +SRCDIR += ../src +INCLUDES += -I../include +DEFINE += -DUNITTEST -DDEBUG +endif + + +ifeq ($(strip $(DEBUG)),) +# ------------------------------------------------------------------------------ +# DEBUG が無効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の OPTIMIZATION を有効にする +# ------------------------------------------------------------------------------ +CFLAGS += $(OPTIMIZATION) +CXXFLAGS += $(OPTIMIZATION) + +else +# ------------------------------------------------------------------------------ +# DEBUG が有効な場合の設定 +# CFLAGS, CXXFLAGS, LDFLAGS の DEBUG_OPTIONS を有効にする +# ------------------------------------------------------------------------------ +DEFINE += -DENABLED_MEMORY_MANAGE +CFLAGS += $(DEBUG_OPTIONS) +CXXFLAGS += $(DEBUG_OPTIONS) +LDFLAGS += $(DEBUG_LDFLAGS) + +endif + +# ------------------------------------------------------------------------------ +# CFLAGS, CXXFLAGS, LDFLAGS 設定 +# ------------------------------------------------------------------------------ +CFLAGS += $(INCLUDES) +CFLAGS += $(C_VERSION) +CFLAGS += $(C_WARNING_OPTIONS) +CFLAGS += $(DEFINE) +CFLAGS += $(DEPENDS_OPTIONS) + +CXXFLAGS += $(INCLUDES) +CXXFLAGS += $(CXX_VERSION) +CXXFLAGS += $(CXX_WARNING_OPTIONS) +CXXFLAGS += $(DEFINE) +CXXFLAGS += $(DEPENDS_OPTIONS) diff --git a/mk/base-cmd.mk b/mk/base-cmd.mk new file mode 100644 index 0000000..edde6de --- /dev/null +++ b/mk/base-cmd.mk @@ -0,0 +1,49 @@ +# ============================================================================== +# コマンド設定 +# ============================================================================== +AWK = awk +CAT = cat +CHMOD = chmod +CHOWN = chown +CP = cp +CPPCHECK = cppcheck +DATE = date +DOXYGEN = doxygen +ECHO = echo +GIT = git +GREP = grep +HEAD = head +INSTALL = install +KILL = kill +LS = ls +LN = ln +MAKE = make +MKDIR = mkdir +MKNOD = mknod +MV = mv +RM = rm +RMDIR = rmdir +PS = ps +PWD = pwd +SED = sed +SORT = sort +TAIL = tail +TAR = tar +TOUCH = touch + +CC ?= $(CROSS_COMPILE)gcc +CXX ?= $(CROSS_COMPILE)g++ +RANLIB = $(CROSS_COMPILE)ranlib +ADDR2LINE = $(CROSS_COMPILE)addr2line +AR = $(CROSS_COMPILE)ar +AS = $(CROSS_COMPILE)as +CPP = $(CROSS_COMPILE)cpp +GCOV = $(CROSS_COMPILE)gcov +GDB = $(CROSS_COMPILE)gdb +LD = $(CROSS_COMPILE)ld +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf +STRIP = $(CROSS_COMPILE)strip + diff --git a/mk/base-conf.mk b/mk/base-conf.mk new file mode 100644 index 0000000..6997761 --- /dev/null +++ b/mk/base-conf.mk @@ -0,0 +1,81 @@ +# ============================================================================== +# 基本設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# デフォルトディレクトリ/ファイル設定 +# ------------------------------------------------------------------------------ +SRCDIR ?= src +OBJDIR ?= obj +EXCLUDES ?= +RELEASEDIR ?= release + +# ------------------------------------------------------------------------------ +# 最適化オプション +# -O0 最適化無効。 +# -O1 速度最適化(低)。 +# -O2 速度最適化(中)[推奨]。 +# -O3 速度最適化(高)。 +# -Os サイズ最適化。 +# その他のフラグについては、gcc のヘルプを参照ください。 +# ------------------------------------------------------------------------------ +OPTIMIZATION = -O2 + +# ------------------------------------------------------------------------------ +# ヘッダー依存関係出力 +# 基本的に変更しないでください。 +# +# -MMD +# コンパイル時に依存関係を .d ファイルに出力する。 +# -MP +# .d ファイルにヘッダファイル用のターゲットも出力する。 +# ------------------------------------------------------------------------------ +DEPENDS_OPTIONS = -MMD -MP + +# ------------------------------------------------------------------------------ +# 警告オプション +# -pedantic +# ANSI C/ISO C++ により要求される警告をすべて出力する。 +# gcc の HELP にも記載されている通り、基本的に使べきではありません。 +# -pedantic-errors +# 警告ではなくエラーが出力される点を除けば -pedantic と同様です。 +# -w +# すべての警告メッセージの出力を禁止します。 +# -Wall +# 基本的な警告オプションを有効にします。 +# -Wextra +# 追加の警告オプションを有効にします。 +# -Weffc++ +# Effective C++ による方針に沿わない記述に警告を出します。 +# ------------------------------------------------------------------------------ +C_WARNING_OPTIONS += -Wall -Wextra -Werror +#CXX_WARNING_OPTIONS += -Wall -Wextra -Werror -Weffc++ +CXX_WARNING_OPTIONS += -Wall -Wextra -Werror + +# ------------------------------------------------------------------------------ +# デバッグ用オプション +# デバッグ、単体テストの際のオプションを指定します。 +# +# -fstack-protector スタック・オーバーフロー・セキュリティチェックを有効にします。 +# --coverage カバレッジ計測します。(-fprofile-arcs -ftest-coverage オプションと同じ) +# -g0 デバッグオプション無効。 +# -g1 最小限のデバッグ情報を生成します。 +# -g2 (-g) デバッグ情報を生成します。 +# -g3 マクロ定義を含んだデバッグ情報を生成します。 +# -ggdb gdb で使うためのデバッグ情報を生成します。 +# -D_FACTORY_SOURCE=[値] +# 文字列やメモリ操作を行う glibc の関数を使用する際に、バッファオーバーフローを検出します。 +# ※すべてのパターンではなく、よくある例についてのみ検出可能。 +# 値が1の場合、規格に準拠するプログラムの振る舞いを変化させないようなチェックが実行される。 +# 値が2の場合、さらなるチェックを追加するが、規格準拠のプログラムが失敗する可能性がある。 +# いくつかのチェックは、コンパイル時に実行され、コンパイラの警告として表示される。 +# ------------------------------------------------------------------------------ +# DEBUG_OPTIONS += -fstack-protector +DEBUG_OPTIONS += --coverage +DEBUG_OPTIONS += -g3 -ggdb +DEBUG_OPTIONS += -O0 +DEBUG_OPTIONS += -D_FACTORY_SOURCE=2 +DEBUG_OPTIONS += -D_DEBUG + +DEBUG_LDFLAGS += --coverage +DEBUG_LDFLAGS += -g3 -ggdb diff --git a/mk/check-cppcheck-conf.mk b/mk/check-cppcheck-conf.mk new file mode 100644 index 0000000..7a1797d --- /dev/null +++ b/mk/check-cppcheck-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# cppcheck 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +CPPCHECK = cppcheck +CPPCHECK_FLAGS = --inconclusive --xml --xml-version=2 --enable=all +CPPCHECK_REPORT_DIR = report/cppcheck +CPPCHECK_LOG = $(CPPCHECK_REPORT_DIR)/cppcheck.xml + +# ------------------------------------------------------------------------------ +# 警告抑止 +# ------------------------------------------------------------------------------ +# 次の警告を抑止します。 +# - システムヘッダー読み込み失敗 (読み込むと非常に時間がかかります。) +# - 未使用関数 (チェック単位が異なり、public な関数が呼び出されないと誤検知する) +CPPCHECK_SUPPRESS = --suppress=missingIncludeSystem +CPPCHECK_SUPPRESS += --suppress=unusedFunction + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) +CLEAN_DIRS += $(CPPCHECK_REPORT_DIR) +endif +endif + diff --git a/mk/check-cppcheck-rule.mk b/mk/check-cppcheck-rule.mk new file mode 100644 index 0000000..ffe1c0c --- /dev/null +++ b/mk/check-cppcheck-rule.mk @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------------------ +# cppcheck ルール +# ------------------------------------------------------------------------------ +.PHONY: cppcheck +cppcheck: + @for subdir in $(SUBDIRS); do \ + $(MAKE) cppcheck -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifneq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(CPPCHECK_REPORT_DIR) + $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_SUPPRESS) $(INCLUDES) $(SRCDIR) 2> $(CPPCHECK_LOG) +endif +endif diff --git a/mk/check-lcov-cobertura-conf.mk b/mk/check-lcov-cobertura-conf.mk new file mode 100644 index 0000000..1a9a6e8 --- /dev/null +++ b/mk/check-lcov-cobertura-conf.mk @@ -0,0 +1,10 @@ +# ============================================================================== +# lcov cobertura 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV_COBERTURA = lcov_cobertura +LCOV_COBERTURA_REPORT_DIR = report/lcov +LCOV_COBERTURA_INFO = $(LCOV_COBERTURA_REPORT_DIR)/lcov.info diff --git a/mk/check-lcov-cobertura-rule.mk b/mk/check-lcov-cobertura-rule.mk new file mode 100644 index 0000000..1e95c5a --- /dev/null +++ b/mk/check-lcov-cobertura-rule.mk @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------------------ +# lcov cobertura ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov-cobertura +lcov-cobertura: lcov + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov-cobertura -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(LCOV_COBERTURA) $(LCOV_COBERTURA_INFO) -b `pwd` -o $(LCOV_COBERTURA_REPORT_DIR)/lcov-coverage.xml +endif diff --git a/mk/check-lcov-conf.mk b/mk/check-lcov-conf.mk new file mode 100644 index 0000000..ad876ef --- /dev/null +++ b/mk/check-lcov-conf.mk @@ -0,0 +1,25 @@ +# ============================================================================== +# lcov 設定 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# 基本設定 +# ------------------------------------------------------------------------------ +LCOV = lcov +LCOV_REPORT_DIR = report/lcov +LCOV_INFO = $(LCOV_REPORT_DIR)/lcov.info + +GENHTML = genhtml +GENHTML_FLAGS += --function-coverage +GENHTML_FLAGS += --branch-coverage + +# ------------------------------------------------------------------------------ +# C1 Coverage 有効 +# ------------------------------------------------------------------------------ +LCOV_FLAGS += --rc lcov_branch_coverage=1 +LCOV_FLAGS += --rc genhtml_branch_coverage=1 + +# ------------------------------------------------------------------------------ +# CLEAN 時の削除ファイル追加 +# ------------------------------------------------------------------------------ +CLEAN_DIRS += $(LCOV_REPORT_DIR) diff --git a/mk/check-lcov-rule.mk b/mk/check-lcov-rule.mk new file mode 100644 index 0000000..b75e472 --- /dev/null +++ b/mk/check-lcov-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# lcov ルール +# ------------------------------------------------------------------------------ +.PHONY: lcov +lcov: + @for subdir in $(SUBDIRS); do \ + $(MAKE) lcov -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + -@$(MKDIR) -p $(LCOV_REPORT_DIR) + $(LCOV) -c -d $(OBJDIR) $(LCOV_FLAGS) -o $(LCOV_INFO) + $(LCOV) $(LCOV_FLAGS) -r $(LCOV_INFO) "*/test/*" -o $(LCOV_INFO) + $(GENHTML) $(GENHTML_FLAGS) -o $(LCOV_REPORT_DIR) $(LCOV_INFO) +endif + diff --git a/mk/clean-conf.mk b/mk/clean-conf.mk new file mode 100644 index 0000000..c0ceed7 --- /dev/null +++ b/mk/clean-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# clean 設定 +# ============================================================================== +ifneq ($(strip $(TARGET)),) +CLEAN_FILES += $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno $(OBJDIR)/*.gcda +CLEAN_FILES += $(TARGET) + +# $(TOPDIR) に置かれたファイルの削除 +ifneq ($(strip $(TARGET)),$(strip $(NAME))) + +# TARGET がライブラリの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/include/,$(notdir $(wildcard include/*.h))) +CLEAN_FILES += $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +else +# TARGET が実行ファイルの場合 +CLEAN_FILES += $(addprefix $(TOPDIR)/,$(TARGET)) + +endif +endif + diff --git a/mk/clean-rule.mk b/mk/clean-rule.mk new file mode 100644 index 0000000..ce2617c --- /dev/null +++ b/mk/clean-rule.mk @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# clean ルール +# ------------------------------------------------------------------------------ +.PHONY: clean +clean: + @for subdir in $(SUBDIRS); do \ + $(MAKE) clean -C $$subdir; \ + done +ifneq ($(strip $(CLEAN_FILES)),) + $(RM) -f $(CLEAN_FILES) +endif +ifneq ($(strip $(CLEAN_DIRS)),) + $(RM) -rf $(addprefix ./,$(CLEAN_DIRS)) +endif + diff --git a/mk/compile-c-rule.mk b/mk/compile-c-rule.mk new file mode 100644 index 0000000..afc8b00 --- /dev/null +++ b/mk/compile-c-rule.mk @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------------------ +# C言語 コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.c + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + +$(TESTOBJDIR)/%.o: %.c + -@$(MKDIR) -p $(TESTOBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/mk/compile-cpp-rule.mk b/mk/compile-cpp-rule.mk new file mode 100644 index 0000000..393dea2 --- /dev/null +++ b/mk/compile-cpp-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# C++ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.cpp + -@$(MKDIR) -p $(OBJDIR) + $(CXX) $(CXXFLAGS) -c -o $@ $< + diff --git a/mk/compile-s-rule.mk b/mk/compile-s-rule.mk new file mode 100644 index 0000000..c4a27a1 --- /dev/null +++ b/mk/compile-s-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# アセンブラ コンパイル ルール +# ------------------------------------------------------------------------------ +$(OBJDIR)/%.o: %.s + -@$(MKDIR) -p $(OBJDIR) + $(CC) $(CFLAGS) -c -o $@ $< + diff --git a/mk/git-info-conf.mk b/mk/git-info-conf.mk new file mode 100644 index 0000000..8937148 --- /dev/null +++ b/mk/git-info-conf.mk @@ -0,0 +1,31 @@ +# ============================================================================== +# git 情報 +# ============================================================================== + +# ------------------------------------------------------------------------------ +# git のタグなどから取得可能なバージョン情報を DEFINE に設定します。 +# +# VERSION : git tag (v[Major].[Minor].[Release] の [Major].[Minor].[Release] 部分) +# MAJOR : git tag (v[Major].[Minor].[Release] の [Major] 部分) +# MINOR : git tag (v[Major].[Minor].[Release] の [Minor] 部分) +# RELEASE : git tag (v[Major].[Minor].[Release] の [Release] 部分) +# REVISION : git revision +# DATETIME : datetime (ISO8601形式) +# ------------------------------------------------------------------------------ +VERSION := $(shell $(GIT) tag | $(SORT) -V | $(TAIL) -1 | $(SED) -e 's/^[^0-9]\+//') +REVISION := $(shell $(GIT) rev-parse --short HEAD) +DATETIME := $(shell $(DATE) "+%Y%m%dT%H%M%S") + +ifeq ($(strip $(VERSION)),) +VERSION := v0.0.1 +REVISION := 0 +endif + +MAJOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\1/') +MINOR := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\2/') +RELEASE := $(shell $(ECHO) $(VERSION) | $(SED) -e 's/^[a-zA-Z]*\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)$$/\3/') + +DEFINE += -DVERSION='"$(VERSION)"' -DMAJOR='"$(MAJOR)"' -DMINOR='"$(MINOR)"' -DRELEASE='"$(RELEASE)"' +DEFINE += -DREVISION='"$(REVISION)"' +DEFINE += -DDATETIME='"$(DATETIME)"' + diff --git a/mk/header-rule.mk b/mk/header-rule.mk new file mode 100644 index 0000000..82db9d4 --- /dev/null +++ b/mk/header-rule.mk @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------------ +# .h -> .c 依存関係ルール +# ------------------------------------------------------------------------------ +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + diff --git a/mk/link-a-conf.mk b/mk/link-a-conf.mk new file mode 100644 index 0000000..631e6d5 --- /dev/null +++ b/mk/link-a-conf.mk @@ -0,0 +1,21 @@ +# ============================================================================== +# 静的ライブラリ 生成に関する設定 +# ============================================================================== + +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +HEADER_FILES_WIN = $(wildcard include/win/*.h) $(wildcard include/win/*.hpp) +TOP_HEADER_FILES_WIN = $(addprefix $(TOPDIR)/include/win/,$(notdir $(HEADER_FILES_WIN))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) $(TOP_HEADER_FILES_WIN) + +endif +endif + diff --git a/mk/link-a-rule.mk b/mk/link-a-rule.mk new file mode 100644 index 0000000..d94a54a --- /dev/null +++ b/mk/link-a-rule.mk @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------------ +# 静的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).a),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f $(TARGET) $(TOPDIR)/lib/ + +endif +endif + diff --git a/mk/link-dll-conf.mk b/mk/link-dll-conf.mk new file mode 100644 index 0000000..d47c5dc --- /dev/null +++ b/mk/link-dll-conf.mk @@ -0,0 +1,23 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) +CLEAN_FILES += $(NAME).lib + +endif +endif + diff --git a/mk/link-dll-rule.mk b/mk/link-dll-rule.mk new file mode 100644 index 0000000..0084d31 --- /dev/null +++ b/mk/link-dll-rule.mk @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).dll),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .dllファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,--out-implib,$(TARGET:.dll=).lib -o $(TARGET) $^ $(LIBS) + + +endif +endif + diff --git a/mk/link-exe-rule.mk b/mk/link-exe-rule.mk new file mode 100644 index 0000000..322c4a3 --- /dev/null +++ b/mk/link-exe-rule.mk @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# 実行ファイル 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) + +# For Linux +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +# For Windows (or ut.exe) +ifeq ($(strip $(NAME).exe),$(strip $(TARGET))) +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -o $@ $^ $(LIBS) + +endif + +endif + diff --git a/mk/link-so-conf.mk b/mk/link-so-conf.mk new file mode 100644 index 0000000..6eb9a6e --- /dev/null +++ b/mk/link-so-conf.mk @@ -0,0 +1,30 @@ +# ============================================================================== +# 動的ライブラリ 生成に関する設定 +# ============================================================================== +# +# -fPIC オプションを付与する。 +# +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +CFLAGS += -fPIC +CXXFLAGS += -fPIC + +TOP_TARGET = $(addprefix $(TOPDIR)/lib/,$(TARGET)) + +HEADER_FILES = $(wildcard include/*.h) $(wildcard include/*.hpp) +TOP_HEADER_FILES = $(addprefix $(TOPDIR)/include/,$(notdir $(HEADER_FILES))) + +CLEAN_FILES += $(TOP_TARGET) +CLEAN_FILES += $(TOP_HEADER_FILES) + +ifneq ($(strip $(USE_SO_VERSION)),) +# +# バージョン番号付きの so ファイルを削除対象に追加する。 +# +CLEAN_FILES += $(TARGET).* $(TOP_TARGET).* +endif + + +endif +endif + diff --git a/mk/link-so-rule.mk b/mk/link-so-rule.mk new file mode 100644 index 0000000..1369c43 --- /dev/null +++ b/mk/link-so-rule.mk @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------------------ +# 動的ライブラリ 生成ルール +# ------------------------------------------------------------------------------ +ifneq ($(strip $(NAME)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) + +## ----------------------------------------------------------------------------- +## TOPディレクトリへのコピー +## ----------------------------------------------------------------------------- +$(TOP_TARGET): $(TARGET) +ifneq ($(strip $(HEADER_FILES)),) + $(CP) -f $(HEADER_FILES) $(TOPDIR)/include/ +endif + $(CP) -f -d $(TARGET)* $(TOPDIR)/lib/ + + +ifneq ($(strip $(USE_SO_VERSION)),) +## ----------------------------------------------------------------------------- +## バージョン番号付き so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 (シンボリックリンク) +$(TARGET): $(TARGET).$(MAJOR) + $(LN) -fs $^ $@ +# .so.X ファイル生成 (シンボリックリンク) +$(TARGET).$(MAJOR): $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) + $(LN) -fs $^ $@ +# .so.X.X.X ファイル生成 +$(TARGET).$(MAJOR).$(MINOR).$(RELEASE): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET).$(MAJOR) -o $(TARGET).$(MAJOR).$(MINOR).$(RELEASE) $^ $(LIBS) + +else +## ----------------------------------------------------------------------------- +## バージョン番号無し so ファイル生成 +## ----------------------------------------------------------------------------- +# .so ファイル生成 +$(TARGET): $(OBJS) + $(LINK) $(LDFLAGS) -shared -Wl,-soname,$(TARGET) -o $(TARGET) $^ $(LIBS) + +endif + + +endif +endif + diff --git a/mk/release-conf.mk b/mk/release-conf.mk new file mode 100644 index 0000000..a9bf6d9 --- /dev/null +++ b/mk/release-conf.mk @@ -0,0 +1,6 @@ +# ============================================================================== +# release 設定 +# ============================================================================== +ifeq ($(strip $(TOPDIR)),.) +CLEAN_DIRS += $(TOPDIR)/$(RELEASEDIR) +endif diff --git a/mk/release-rule.mk b/mk/release-rule.mk new file mode 100644 index 0000000..8862c62 --- /dev/null +++ b/mk/release-rule.mk @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------------------ +# release ルール +# ------------------------------------------------------------------------------ +.PHONY: release +release: +ifeq ($(strip $(TOPDIR)),.) + $(MAKE) clean + $(MAKE) all + $(MKDIR) -p $(TOPDIR)/$(RELEASEDIR)/bin + $(MKDIR) -p $(TOPDIR)/$(RELEASEDIR)/lib +endif + @for subdir in $(SUBDIRS); do \ + $(MAKE) release -C $$subdir; \ + done +ifneq ($(strip $(TARGET)),) +ifeq ($(strip $(NAME).so),$(strip $(TARGET))) +# .so ファイル + $(CP) -d $(TARGET)* $(TOPDIR)/$(RELEASEDIR)/lib/ +endif +ifeq ($(strip $(NAME)),$(strip $(TARGET))) +# 実行ファイル + $(CP) $(TARGET) $(TOPDIR)/$(RELEASEDIR)/bin/ +endif +endif + diff --git a/mk/test-rule.mk b/mk/test-rule.mk new file mode 100644 index 0000000..4bd8655 --- /dev/null +++ b/mk/test-rule.mk @@ -0,0 +1,12 @@ +# ------------------------------------------------------------------------------ +# test ルール +# ------------------------------------------------------------------------------ +.PHONY: test +test: + @for subdir in $(SUBDIRS); do \ + $(MAKE) test -C $$subdir; \ + done +ifeq ($(strip $(TARGET)),ut.exe) + $(MAKE) ut.exe + ./ut.exe +endif diff --git a/tool/copy-class.sh b/tool/copy-class.sh new file mode 100755 index 0000000..200cd8e --- /dev/null +++ b/tool/copy-class.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +I_CLASS=$1 +O_CLASS=$2 +EXT=$3 +if [ "${I_CLASS}" = "" ] || [ "${O_CLASS}" = "" ] || [ "${EXT}" = "" ]; then + echo "Usage) $0 in_class out_class ext > out_class_file" + echo "Ex) $0 \"Exception\" \"RuntimeException\" ".hpp" > runtime_exception.hpp" + exit 1 +fi + +I_SNAKE=`echo ${I_CLASS} | sed -E 's/(.)([A-Z])/\1_\2/g'` +O_SNAKE=`echo ${O_CLASS} | sed -E 's/(.)([A-Z])/\1_\2/g'` + +I_LOWER=`echo "${I_SNAKE}" | tr "[:upper:]" "[:lower:]"` +O_LOWER=`echo "${O_SNAKE}" | tr "[:upper:]" "[:lower:]"` + +I_UPPER=`echo "${I_SNAKE}" | tr "[:lower:]" "[:upper:]"` +O_UPPER=`echo "${O_SNAKE}" | tr "[:lower:]" "[:upper:]"` + +sed -e "s/${I_CLASS}/${O_CLASS}/g" -e "s/${I_LOWER}/${O_LOWER}/g" -e "s/${I_UPPER}/${O_UPPER}/g" "${I_LOWER}${EXT}" +