diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/include/kcpp_os.hpp b/modules/include/kcpp_os.hpp new file mode 100644 index 0000000..c6f0b0c --- /dev/null +++ b/modules/include/kcpp_os.hpp @@ -0,0 +1,54 @@ +/** + * @file kcpp_os.h + * @brief Kantan C++ Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef KCPP_OS_HPP +#define KCPP_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 // KCPP_OS_HPP diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/include/kcpp_os.hpp b/modules/include/kcpp_os.hpp new file mode 100644 index 0000000..c6f0b0c --- /dev/null +++ b/modules/include/kcpp_os.hpp @@ -0,0 +1,54 @@ +/** + * @file kcpp_os.h + * @brief Kantan C++ Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef KCPP_OS_HPP +#define KCPP_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 // KCPP_OS_HPP diff --git a/modules/include/kcpp_string.hpp b/modules/include/kcpp_string.hpp new file mode 100644 index 0000000..81350fc --- /dev/null +++ b/modules/include/kcpp_string.hpp @@ -0,0 +1,111 @@ +/** + * @file kcpp_string.h + * @brief Kantan C++ Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_STRING_HPP +#define KCPP_STRING_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + 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 &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/include/kcpp_os.hpp b/modules/include/kcpp_os.hpp new file mode 100644 index 0000000..c6f0b0c --- /dev/null +++ b/modules/include/kcpp_os.hpp @@ -0,0 +1,54 @@ +/** + * @file kcpp_os.h + * @brief Kantan C++ Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef KCPP_OS_HPP +#define KCPP_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 // KCPP_OS_HPP diff --git a/modules/include/kcpp_string.hpp b/modules/include/kcpp_string.hpp new file mode 100644 index 0000000..81350fc --- /dev/null +++ b/modules/include/kcpp_string.hpp @@ -0,0 +1,111 @@ +/** + * @file kcpp_string.h + * @brief Kantan C++ Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_STRING_HPP +#define KCPP_STRING_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + 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 &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/include/kcpp_throwable.hpp b/modules/include/kcpp_throwable.hpp new file mode 100644 index 0000000..08c1c85 --- /dev/null +++ b/modules/include/kcpp_throwable.hpp @@ -0,0 +1,107 @@ +/** + * @file kcpp_throwable.h + * @brief Kantan C++ Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_object.hpp + */ +#ifndef KCPP_THROWABLE_HPP +#define KCPP_THROWABLE_HPP + +#include + +namespace kcpp +{ + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable(const String &str = String()) noexcept; + + // コピーコンストラクタ + Throwable(const String &str) noexcept; + + // ムーブコンストラクタ + Throwable(String &&str) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + String &operator=(const String &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/include/kcpp_os.hpp b/modules/include/kcpp_os.hpp new file mode 100644 index 0000000..c6f0b0c --- /dev/null +++ b/modules/include/kcpp_os.hpp @@ -0,0 +1,54 @@ +/** + * @file kcpp_os.h + * @brief Kantan C++ Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef KCPP_OS_HPP +#define KCPP_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 // KCPP_OS_HPP diff --git a/modules/include/kcpp_string.hpp b/modules/include/kcpp_string.hpp new file mode 100644 index 0000000..81350fc --- /dev/null +++ b/modules/include/kcpp_string.hpp @@ -0,0 +1,111 @@ +/** + * @file kcpp_string.h + * @brief Kantan C++ Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_STRING_HPP +#define KCPP_STRING_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + 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 &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/include/kcpp_throwable.hpp b/modules/include/kcpp_throwable.hpp new file mode 100644 index 0000000..08c1c85 --- /dev/null +++ b/modules/include/kcpp_throwable.hpp @@ -0,0 +1,107 @@ +/** + * @file kcpp_throwable.h + * @brief Kantan C++ Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_object.hpp + */ +#ifndef KCPP_THROWABLE_HPP +#define KCPP_THROWABLE_HPP + +#include + +namespace kcpp +{ + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable(const String &str = String()) noexcept; + + // コピーコンストラクタ + Throwable(const String &str) noexcept; + + // ムーブコンストラクタ + Throwable(String &&str) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + String &operator=(const String &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/src/kcpp_object.cpp b/modules/src/kcpp_object.cpp new file mode 100644 index 0000000..5f237b7 --- /dev/null +++ b/modules/src/kcpp_object.cpp @@ -0,0 +1,169 @@ +#include + +#include +#include + +namespace kcpp +{ + + /** + * 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 + { + return (this == &obj); + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*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)); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } +} \ No newline at end of file diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/include/kcpp_os.hpp b/modules/include/kcpp_os.hpp new file mode 100644 index 0000000..c6f0b0c --- /dev/null +++ b/modules/include/kcpp_os.hpp @@ -0,0 +1,54 @@ +/** + * @file kcpp_os.h + * @brief Kantan C++ Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef KCPP_OS_HPP +#define KCPP_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 // KCPP_OS_HPP diff --git a/modules/include/kcpp_string.hpp b/modules/include/kcpp_string.hpp new file mode 100644 index 0000000..81350fc --- /dev/null +++ b/modules/include/kcpp_string.hpp @@ -0,0 +1,111 @@ +/** + * @file kcpp_string.h + * @brief Kantan C++ Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_STRING_HPP +#define KCPP_STRING_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + 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 &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/include/kcpp_throwable.hpp b/modules/include/kcpp_throwable.hpp new file mode 100644 index 0000000..08c1c85 --- /dev/null +++ b/modules/include/kcpp_throwable.hpp @@ -0,0 +1,107 @@ +/** + * @file kcpp_throwable.h + * @brief Kantan C++ Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_object.hpp + */ +#ifndef KCPP_THROWABLE_HPP +#define KCPP_THROWABLE_HPP + +#include + +namespace kcpp +{ + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable(const String &str = String()) noexcept; + + // コピーコンストラクタ + Throwable(const String &str) noexcept; + + // ムーブコンストラクタ + Throwable(String &&str) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + String &operator=(const String &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/src/kcpp_object.cpp b/modules/src/kcpp_object.cpp new file mode 100644 index 0000000..5f237b7 --- /dev/null +++ b/modules/src/kcpp_object.cpp @@ -0,0 +1,169 @@ +#include + +#include +#include + +namespace kcpp +{ + + /** + * 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 + { + return (this == &obj); + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*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)); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } +} \ No newline at end of file diff --git a/modules/src/kcpp_string.cpp b/modules/src/kcpp_string.cpp new file mode 100644 index 0000000..7b583c5 --- /dev/null +++ b/modules/src/kcpp_string.cpp @@ -0,0 +1,392 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace kcpp +{ + /** + * String を構築します。 + * + * @param 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept + { + setValue(&(str.value[0])); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : 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) + { + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 文字列の長さを返します。 + * + * @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; + } + + /** + * 出力用 + * + * @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); + } +} \ No newline at end of file diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/include/kcpp_os.hpp b/modules/include/kcpp_os.hpp new file mode 100644 index 0000000..c6f0b0c --- /dev/null +++ b/modules/include/kcpp_os.hpp @@ -0,0 +1,54 @@ +/** + * @file kcpp_os.h + * @brief Kantan C++ Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef KCPP_OS_HPP +#define KCPP_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 // KCPP_OS_HPP diff --git a/modules/include/kcpp_string.hpp b/modules/include/kcpp_string.hpp new file mode 100644 index 0000000..81350fc --- /dev/null +++ b/modules/include/kcpp_string.hpp @@ -0,0 +1,111 @@ +/** + * @file kcpp_string.h + * @brief Kantan C++ Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_STRING_HPP +#define KCPP_STRING_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + 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 &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/include/kcpp_throwable.hpp b/modules/include/kcpp_throwable.hpp new file mode 100644 index 0000000..08c1c85 --- /dev/null +++ b/modules/include/kcpp_throwable.hpp @@ -0,0 +1,107 @@ +/** + * @file kcpp_throwable.h + * @brief Kantan C++ Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_object.hpp + */ +#ifndef KCPP_THROWABLE_HPP +#define KCPP_THROWABLE_HPP + +#include + +namespace kcpp +{ + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable(const String &str = String()) noexcept; + + // コピーコンストラクタ + Throwable(const String &str) noexcept; + + // ムーブコンストラクタ + Throwable(String &&str) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + String &operator=(const String &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/src/kcpp_object.cpp b/modules/src/kcpp_object.cpp new file mode 100644 index 0000000..5f237b7 --- /dev/null +++ b/modules/src/kcpp_object.cpp @@ -0,0 +1,169 @@ +#include + +#include +#include + +namespace kcpp +{ + + /** + * 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 + { + return (this == &obj); + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*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)); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } +} \ No newline at end of file diff --git a/modules/src/kcpp_string.cpp b/modules/src/kcpp_string.cpp new file mode 100644 index 0000000..7b583c5 --- /dev/null +++ b/modules/src/kcpp_string.cpp @@ -0,0 +1,392 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace kcpp +{ + /** + * String を構築します。 + * + * @param 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept + { + setValue(&(str.value[0])); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : 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) + { + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 文字列の長さを返します。 + * + * @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; + } + + /** + * 出力用 + * + * @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); + } +} \ No newline at end of file diff --git a/modules/src/main.cpp b/modules/src/main.cpp new file mode 100644 index 0000000..b6e6ed2 --- /dev/null +++ b/modules/src/main.cpp @@ -0,0 +1,44 @@ +#include + +#include + +using namespace kcpp; + +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; + return 0; +} diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/include/kcpp_os.hpp b/modules/include/kcpp_os.hpp new file mode 100644 index 0000000..c6f0b0c --- /dev/null +++ b/modules/include/kcpp_os.hpp @@ -0,0 +1,54 @@ +/** + * @file kcpp_os.h + * @brief Kantan C++ Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef KCPP_OS_HPP +#define KCPP_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 // KCPP_OS_HPP diff --git a/modules/include/kcpp_string.hpp b/modules/include/kcpp_string.hpp new file mode 100644 index 0000000..81350fc --- /dev/null +++ b/modules/include/kcpp_string.hpp @@ -0,0 +1,111 @@ +/** + * @file kcpp_string.h + * @brief Kantan C++ Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_STRING_HPP +#define KCPP_STRING_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + 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 &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/include/kcpp_throwable.hpp b/modules/include/kcpp_throwable.hpp new file mode 100644 index 0000000..08c1c85 --- /dev/null +++ b/modules/include/kcpp_throwable.hpp @@ -0,0 +1,107 @@ +/** + * @file kcpp_throwable.h + * @brief Kantan C++ Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_object.hpp + */ +#ifndef KCPP_THROWABLE_HPP +#define KCPP_THROWABLE_HPP + +#include + +namespace kcpp +{ + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable(const String &str = String()) noexcept; + + // コピーコンストラクタ + Throwable(const String &str) noexcept; + + // ムーブコンストラクタ + Throwable(String &&str) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + String &operator=(const String &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/src/kcpp_object.cpp b/modules/src/kcpp_object.cpp new file mode 100644 index 0000000..5f237b7 --- /dev/null +++ b/modules/src/kcpp_object.cpp @@ -0,0 +1,169 @@ +#include + +#include +#include + +namespace kcpp +{ + + /** + * 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 + { + return (this == &obj); + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*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)); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } +} \ No newline at end of file diff --git a/modules/src/kcpp_string.cpp b/modules/src/kcpp_string.cpp new file mode 100644 index 0000000..7b583c5 --- /dev/null +++ b/modules/src/kcpp_string.cpp @@ -0,0 +1,392 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace kcpp +{ + /** + * String を構築します。 + * + * @param 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept + { + setValue(&(str.value[0])); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : 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) + { + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 文字列の長さを返します。 + * + * @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; + } + + /** + * 出力用 + * + * @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); + } +} \ No newline at end of file diff --git a/modules/src/main.cpp b/modules/src/main.cpp new file mode 100644 index 0000000..b6e6ed2 --- /dev/null +++ b/modules/src/main.cpp @@ -0,0 +1,44 @@ +#include + +#include + +using namespace kcpp; + +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; + return 0; +} diff --git a/modules/test/Makefile b/modules/test/Makefile new file mode 100644 index 0000000..9565fe9 --- /dev/null +++ b/modules/test/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = ut +TARGET = $(NAME).exe +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 -I../src +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..cb38359 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= .. +RULEDIR ?= $(TOPDIR)/mk +NAME = libkcpp +TARGET = $(NAME).exe +SUBDIRS = test +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/modules/include/kcpp.hpp b/modules/include/kcpp.hpp new file mode 100644 index 0000000..8a38d07 --- /dev/null +++ b/modules/include/kcpp.hpp @@ -0,0 +1,25 @@ +/** + * @file kcpp.h + * @brief Kantan C++ Library 共通ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_os.hpp + */ +#ifndef KCPP_HPP +#define KCPP_HPP + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +// For C++17 +#include +#include +#include +#include + +#else +// ============================================================================= +// C++17 より古い場合は、ERROR +// ============================================================================= +#error "supports C++17 or later" + +#endif // ddefined(__cplusplus) && (__cplusplus >= 201703L) +#endif // KCPP_HPP diff --git a/modules/include/kcpp_object.hpp b/modules/include/kcpp_object.hpp new file mode 100644 index 0000000..398fbaa --- /dev/null +++ b/modules/include/kcpp_object.hpp @@ -0,0 +1,83 @@ +/** + * @file kcpp_object.h + * @brief Kantan C++ Library Object ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_OBJECT_HPP +#define KCPP_OBJECT_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + class String; + + class Object + { + public: + // デフォルトコンストラクタ + Object() noexcept; + + // コピーコンストラクタ + Object(const Object &obj) noexcept; + + // ムーブコンストラクタ + Object(Object &&obj) noexcept; + + // デストラクタ + virtual ~Object() noexcept = default; + + // コピー代入演算子 + Object &operator=(const Object &other) 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; + + // クローン + virtual std::unique_ptr clone() 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); + + private: + mutable std::mutex mtx; + std::condition_variable cv; + }; + +} // namespace kcpp + +#endif // KCPP_OBJECT_HPP diff --git a/modules/include/kcpp_os.hpp b/modules/include/kcpp_os.hpp new file mode 100644 index 0000000..c6f0b0c --- /dev/null +++ b/modules/include/kcpp_os.hpp @@ -0,0 +1,54 @@ +/** + * @file kcpp_os.h + * @brief Kantan C++ Library OS 関連ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * + * + * Windows の場合、よく利用するヘッダをインクルードします。 + */ +#ifndef KCPP_OS_HPP +#define KCPP_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 // KCPP_OS_HPP diff --git a/modules/include/kcpp_string.hpp b/modules/include/kcpp_string.hpp new file mode 100644 index 0000000..81350fc --- /dev/null +++ b/modules/include/kcpp_string.hpp @@ -0,0 +1,111 @@ +/** + * @file kcpp_string.h + * @brief Kantan C++ Library String ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp.hpp + */ +#ifndef KCPP_STRING_HPP +#define KCPP_STRING_HPP + +#include +#include +#include + +#include + +namespace kcpp +{ + + 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 &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/include/kcpp_throwable.hpp b/modules/include/kcpp_throwable.hpp new file mode 100644 index 0000000..08c1c85 --- /dev/null +++ b/modules/include/kcpp_throwable.hpp @@ -0,0 +1,107 @@ +/** + * @file kcpp_throwable.h + * @brief Kantan C++ Library Throwable ヘッダファイル。 + * @copyright 2001 - 2024 Nomura Kei + * @depends + * kcpp_object.hpp + */ +#ifndef KCPP_THROWABLE_HPP +#define KCPP_THROWABLE_HPP + +#include + +namespace kcpp +{ + + class Throwable : public Object + { + public: + // デフォルトコンストラクタ + Throwable(const String &str = String()) noexcept; + + // コピーコンストラクタ + Throwable(const String &str) noexcept; + + // ムーブコンストラクタ + Throwable(String &&str) noexcept; + + // デストラクタ + ~Throwable() noexcept; + + // コピー代入演算子 + String &operator=(const String &other) noexcept; + + // ムーブ代入演算子 + String &operator=(String &&obj) noexcept; + + // 文字列長を返す。 + 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; + + // クローン + std::unique_ptr clone() const noexcept override; + + // 出力用 + friend std::ostream &operator<<(std::ostream &os, const String &str); + + // 入力用 + friend std::istream &operator>>(std::istream &is, String &str); + + protected: + // 値 + std::unique_ptr value; + + // 文字列の長さ + int len; + + // データ設定関数 + void setValue(const char *str); + }; + +} // namespace kcpp + +#endif // KCPP_STRING_HPP \ No newline at end of file diff --git a/modules/src/kcpp_object.cpp b/modules/src/kcpp_object.cpp new file mode 100644 index 0000000..5f237b7 --- /dev/null +++ b/modules/src/kcpp_object.cpp @@ -0,0 +1,169 @@ +#include + +#include +#include + +namespace kcpp +{ + + /** + * 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 + { + return (this == &obj); + } + + /** + * ハッシュコードを取得します。 + * + * @return ハッシュコード + */ + int Object::hashCode() const noexcept + { + return (reinterpret_cast(this)); + } + + /** + * 本オブジェクトの複製を取得します。 + * + * [備考] + * 派生クラスが、ポリモーフィズムをサポートするために、 + * unique_ptr を返すようにしています。 + * + * @return 本オブジェクトの複製 + */ + std::unique_ptr Object::clone() const noexcept + { + return std::make_unique(*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)); + } + + /** + * 出力用 + * + * @param os output stream + * @param obj オブジェクト + */ + std::ostream &operator<<(std::ostream &os, const Object &obj) + { + os << obj.toString(); + return os; + } +} \ No newline at end of file diff --git a/modules/src/kcpp_string.cpp b/modules/src/kcpp_string.cpp new file mode 100644 index 0000000..7b583c5 --- /dev/null +++ b/modules/src/kcpp_string.cpp @@ -0,0 +1,392 @@ +#include +#include + +#include + +// 入力ストリーム用バッファサイズ +static constexpr int MAX_ISTREAM_BUFFER_SIZE = 4096; + +namespace kcpp +{ + /** + * String を構築します。 + * + * @param 文字列 + */ + String::String(const char *str) noexcept + { + setValue(str); + } + + /** + * String のコピーコンストラクタ。 + * + * @param str コピー元 String + */ + String::String(const String &str) noexcept + { + setValue(&(str.value[0])); + } + + /** + * String のムーブコンストラクタ。 + * + * @param str ムーブ元 String + */ + String::String(String &&str) noexcept : 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) + { + setValue(&str.value[0]); + } + return *this; + } + + /** + * ムーブ代入演算子。 + * + * @param obj ムーブ元オブジェクト + * @return 本オブジェクトへの参照 + */ + String &String::operator=(String &&str) noexcept + { // 特に移すものはない。 + if (this != &str) + { + value = std::move(str.value); + len = str.len; + str.value = nullptr; + str.len = 0; + } + return *this; + } + + /** + * 文字列の長さを返します。 + * + * @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; + } + + /** + * 出力用 + * + * @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); + } +} \ No newline at end of file diff --git a/modules/src/main.cpp b/modules/src/main.cpp new file mode 100644 index 0000000..b6e6ed2 --- /dev/null +++ b/modules/src/main.cpp @@ -0,0 +1,44 @@ +#include + +#include + +using namespace kcpp; + +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; + return 0; +} diff --git a/modules/test/Makefile b/modules/test/Makefile new file mode 100644 index 0000000..9565fe9 --- /dev/null +++ b/modules/test/Makefile @@ -0,0 +1,48 @@ +# ============================================================================== +# Makefile +# ============================================================================== +# +# TOPDIR : トップディレクトリ +# RULEDIR : Meke のルール一式が格納されているディレクトリ +# NAME : モジュール名 (拡張子を含めないこと) +# TARGET : モジュールファイル名 (拡張子を含めること) +# SUBDIR : サブディレクトリ (処理したい順に空白区切りで記述すること) +# +TOPDIR ?= ../.. +RULEDIR ?= $(TOPDIR)/mk +NAME = ut +TARGET = $(NAME).exe +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 -I../src +CFLAGS += +CXXFLAGS += +LDFLAGS += +LIBS += -L$(TOPDIR)/lib + +CLEAN_FILES += +CLEAN_DIRS += + +.DEFAULT_GOAL := all + +# ------------------------------------------------------------------------------ +# *-rule : ルール +# ------------------------------------------------------------------------------ +include $(RULEDIR)/*-rule.mk +# ------------------------------------------------------------------------------ + diff --git a/modules/test/src/none.cpp b/modules/test/src/none.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/modules/test/src/none.cpp