Newer
Older
libj / modules / libj / src / object.cpp
#include <memory>

#include <j/lang/object.hpp>
#include <j/lang/string.hpp>

namespace j
{
    namespace lang
    {

        /**
         * Object を構築します。
         */
        Object::Object() noexcept { /* NOP */ }

        /**
         * Object のコピーコンストラクタ。
         *
         * @param obj コピー元オブジェクト
         */
        Object::Object(const Object &) noexcept { /* NOP */ }

        /**
         * Object のムーブコンストラクタ。
         *
         * @param obj ムーブ元オブジェクト
         */
        Object::Object(Object &&) noexcept { /* NOP */ }

        // デストラクタ
        // virtual Object::~Object() noexcept = default;

        /**
         * コピー代入演算子。
         * コピーして代入します。
         *
         * @param obj コピー元オブジェクト
         * @return 本オブジェクトへの参照
         */
        Object &Object::operator=(const Object &) noexcept
        { // 特にコピーする要素はない。
            return *this;
        }

        /**
         * ムーブ代入演算子。
         *
         * @param obj ムーブ元オブジェクト
         * @return 本オブジェクトへの参照
         */
        Object &Object::operator=(Object &&) noexcept
        { // 特に移すものはない。
            return *this;
        }

        /**
         * 比較演算子。
         *
         * @param obj 比較するオブジェクト
         * @return true/false (合致/不一致)
         */
        bool Object::operator==(const Object &obj) const noexcept
        {
            return equals(obj);
        }

        /**
         * 比較演算子。
         *
         * @param obj 比較するオブジェクト
         * @return true/false (合致/不一致)
         */
        bool Object::operator!=(const Object &obj) const noexcept
        {
            return !equals(obj);
        }

        /**
         * クラス名を取得します。
         *
         * @return クラス名
         */
        String Object::getClassName() const noexcept
        {
            return String(typeid(*this).name());
        }

        /**
         * 本オブジェクトの文字列表現を返します。
         *
         * @return 本オブジェクトの文字列表現
         */
        String Object::toString() const noexcept
        {
            // String str(getClassName() + "@" + std::to_string(reinterpret_cast<std::uintptr_t>(this)));
            return getClassName();
        }

        /**
         * 指定されたオブジェクトが同じクラスか否かを返します。
         *
         * @param obj オブジェクト
         * @return true/false (同じクラス/異なるクラス)
         */
        bool Object::isSameClass(const Object &obj) const noexcept
        {
            return (typeid(*this) == typeid(obj));
        }

        /**
         * 指定されたオブジェクトと合致するか否かを返します。
         *
         * @param obj 比較するオブジェクト
         * @return true/false (合致する/しない)
         */
        bool Object::equals(const Object &obj) const noexcept
        {
            if (isSameClass(obj))
            { // 同じクラス
                int ownHash = hashCode();
                int objHash = obj.hashCode();
                if (ownHash == objHash)
                { // ハッシュコードが一緒
                    String ownStr = toString();
                    String objStr = obj.toString();
                    return ownStr.equals(objStr);
                }
            }
            return false;
        }

        /**
         * ハッシュコードを取得します。
         *
         * @return ハッシュコード
         */
        int Object::hashCode() const noexcept
        {
            return (reinterpret_cast<std::intptr_t>(this));
        }

        /**
         * 待機中のスレッドを再開します。
         */
        void Object::notify()
        {
            std::lock_guard<std::mutex> lock(mtx);
            cv.notify_one();
        }

        /**
         * 待機中のすべてのスレッドを再開します。
         */
        void Object::notifyAll()
        {
            std::lock_guard<std::mutex> lock(mtx);
            cv.notify_all();
        }

        /**
         * 現在のスレッドを待機させます。
         */
        void Object::wait()
        {
            std::unique_lock<std::mutex> lock(mtx);
            cv.wait(lock);
        }

        /**
         * 現在のスレッドを待機させます。
         */
        void Object::wait(int msec)
        {
            std::unique_lock<std::mutex> lock(mtx);
            cv.wait_for(lock, std::chrono::milliseconds(msec));
        }

        /**
         * 本オブジェクトの複製を取得します。
         *
         * [備考]
         * 派生クラスが、ポリモーフィズムをサポートするために、
         * unique_ptr<Object> を返すようにしています。
         *
         * @return 本オブジェクトの複製
         */
        std::unique_ptr<Object> Object::clone() const noexcept
        {
            return std::make_unique<Object>(*this);
        }

        /**
         * 出力用
         *
         * @param os output stream
         * @param obj オブジェクト
         */
        std::ostream &operator<<(std::ostream &os, const Object &obj)
        {
            return operator<<(os, obj.toString());
        }

    } // namespace lang
} // namespace j