/*---------------------------------------------------------------------------* Project: NintendoWare File: ut_ResDictionary.h Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. The content herein is highly confidential and should be handled accordingly. $Revision: 31311 $ *---------------------------------------------------------------------------*/ #ifndef NW_UT_RESDICTIONARY_H_ #define NW_UT_RESDICTIONARY_H_ #include #include #include #include namespace nw { namespace ut { #if 0 // 辞書インターフェイス (テンプレートで実現する場合は、このクラスは継承しない) class IResDic { public: // 辞書データが有効かどうかを返します。 virtual bool IsValid() const = 0; // 辞書に登録されている要素数です。 virtual s32 GetCount() const = 0; // インデクスやキー文字列の値から要素を取得します。 // 辞書中に指定の要素が見つからなかった場合にはNULLを返します。 virtual void* operator[](int idx) const = 0; virtual void* operator[](u32 idx) const = 0; virtual void* operator[](const char* key) const = 0; virtual void* operator[](const ResName key) const = 0; // キー文字列の値で辞書を検索し、インデクスを取得します。 // 指定のキーが見つからなかった場合には、負の数を返します。 virtual s32 GetIndex(const char* key) const = 0; virtual s32 GetIndex(const ResName n ) const = 0; // インデクス番目の要素のキー文字列を取得します。 virtual const ResName GetResName(u32 idx) const = 0; virtual const char* GetName(u32 idx) const = 0; }; #endif #if 0 // 包含クラスを挟む場合 template class ResDic { public: /* ctor */ ResDic(TDic& dic) : m_Dic( dic ) {} bool IsValid() const { m_Dic.IsValid(); } s32 GetCount() const { return m_Dic.GetCount(); } void* operator[](int idx) const { return m_Dic[ idx ]; } void* operator[](u32 idx) const { return m_Dic[ idx ]; } void* operator[](const char* key) const { return m_Dic[ key ]; } void* operator[](const ResName key) const { return m_Dic[ key ]; } // キー文字列の値で辞書を検索し、インデクスを取得します。 // 指定のキーが見つからなかった場合には、負の数を返します。 s32 GetIndex(const char* key) const { return m_Dic.GetIndex( key ); } s32 GetIndex(const ResName n ) const { return m_Dic.GetIndex( n ); } // インデクス番目の要素のキー文字列を取得します。 const ResName GetResName(u32 idx) const { return m_Dic.GetResName( idx ); } const char* GetName(u32 idx) const { return m_Dic.GetName( idx ); } private: TDic& m_Dic; }; #endif //! @details :private // 線形探索辞書 struct ResDicLinearData : public DataBlockHeader { Size numData; struct ResDicNodeData { BinString toName; Offset ofsData; } data[1]; // numData個ある ResDicNodeData* GetBeginNode() { return data; } const ResDicNodeData* GetBeginNode() const { return data; } }; //! @details :private class ResDicLinear : public ResCommon { public: NW_RES_CTOR( ResDicLinear ) s32 GetCount() const { return ref().numData; } // インデクスやキー文字列の値から要素を取得します。 // 辞書中に指定の要素が見つからなかった場合にはNULLを返します。 void* operator[](int idx) const { if ( ! this->IsValid() ) { return NULL; } if ( idx < 0 || s32(ref().numData) <= idx ) { return NULL; } return const_cast( ref().data[idx].ofsData.to_ptr() ); } void* operator[](u32 idx) const { return operator[](int(idx)); } void* operator[](const char* key) const { s32 idx = this->GetIndex(key); if ( idx < 0 ) { return NULL; } return const_cast( ref().data[ idx ].ofsData.to_ptr() ); } void* operator[](const ResName key) const { s32 idx = this->GetIndex(key); if ( idx < 0 ) { return NULL; } return const_cast( ref().data[ idx ].ofsData.to_ptr() ); } // キー文字列の値で辞書を検索し、インデクスを取得します。 // 指定のキーが見つからなかった場合には、負の数を返します。 s32 GetIndex(const char* key) const; s32 GetIndex(const ResName key) const { if ( (! this->IsValid()) || (! key.IsValid()) ) { return -1; } return this->GetIndex(key.GetName()); } // インデクス番目の要素のキー文字列を取得します。 const ResName GetResName(u32 /*idx*/) const { return ResName(); } const char* GetName(u32 /*idx*/) const { return NULL; } }; //! @details :private // パトリシア木探索辞書 struct ResDicPatriciaData : public DataBlockHeader { ResU32 numData; struct ResDicNodeData { ResU32 ref; ResU16 idxLeft; ResU16 idxRight; Offset ofsString; Offset ofsData; } data[1]; // numData + 1個ある ResDicNodeData* GetBeginNode() { return &data[1]; } const ResDicNodeData* GetBeginNode() const { return &data[1]; } }; //! @details :private // パトリシア辞書アクセサクラス。 class ResDicPatricia : public ResCommon< ResDicPatriciaData > { public: enum { NOT_FOUND = -1 }; NW_RES_CTOR( ResDicPatricia ); s32 GetCount() const { return ref().numData; } void* operator[](int idx) const { if (!this->IsValid()) { return NULL; } NW_MINMAX_ASSERT( idx, 0, static_cast(ref().numData - 1) ); // 辞書引き関連についてはconst correctnessを維持しなくても問題ないだろう return const_cast(ref().data[idx + 1].ofsData.to_ptr()); } void* operator[](u32 idx) const { return operator[](int(idx)); } void* operator[](const char* s) const { // sがNULLでもOK if (this->IsValid() && s) { ResDicPatriciaData::ResDicNodeData* x = Get(s, std::strlen(s)); // 辞書にはNULLの行き先を仮定しなくてよい if (x) { return const_cast(x->ofsData.to_ptr()); } } return NULL; } void* operator()(const char* s, size_t len) const { // lenを文字列長として設定しているので文字列がNULLというのはNG NW_NULL_ASSERT(s); if (this->IsValid()) { ResDicPatriciaData::ResDicNodeData* x = Get(s, len); // 辞書にはNULLの行き先を仮定しなくてよい if (x) { return const_cast(x->ofsData.to_ptr()); } } return NULL; } void* operator[](const ResName n) const { // 入力が無効でも止まらないようにする if (IsValid() && n.IsValid()) { ResDicPatriciaData::ResDicNodeData* x = Get(n); // 辞書にはNULLの行き先を仮定しなくてよい if (x) { return const_cast(x->ofsData.to_ptr()); } } return NULL; } s32 GetIndex(const char* s) const { // sがNULLでもOK if (IsValid() && s) { size_t len = std::strlen(s); ResDicPatriciaData::ResDicNodeData* x = Get(s, len); if (x) { return static_cast(x - &ptr()->data[1]); // エントリ 0 はルートノードであるので 1 との差を取る } } return -1; } s32 GetIndex(const ResName n) const { // 入力が無効でも止まらないようにする if (IsValid() && n.IsValid()) { ResDicPatriciaData::ResDicNodeData* x = Get(n); if (x) { return static_cast(x - &ptr()->data[1]); // エントリ 0 はルートノードであるので 1 との差を取る } } return -1; } const ResName GetResName(u32 idx) const { if (!IsValid()) { return ResName(NULL); } NW_MINMAX_ASSERT( idx, 0, ptr()->numData - 1 ); return ofs_to_obj(ptr()->data[idx + 1].ofsString - s32(sizeof(u32))); } const char* GetName(u32 idx) const { if (!IsValid()) { return NULL; } return GetResName(idx).GetName(); } u32 GetNumData() const { if ( !IsValid() ) { return 0; } return ptr()->numData; } u32 GetLength() const { return ref().length; } protected: ResDicPatriciaData::ResDicNodeData* Get(const char* s, size_t len) const; ResDicPatriciaData::ResDicNodeData* Get(const ResName rhs) const; }; namespace internal { //--------------------------------------------------------------------------- //! @brief 要素が空のパトリシア辞書リソースを生成します。 //! //! @param[out] resData 初期化をするパトリシア辞書構造体へのポインタです。 //! //! @return resData へのポインタを返します。 //--------------------------------------------------------------------------- inline ResDicPatriciaData* InitializeResDicPatricia(ResDicPatriciaData* resData) { resData->signature = NW_RES_SIGNATURE32('DICT'); resData->length = sizeof(ResDicPatriciaData); resData->numData = 0; resData->data[0].ref = 0xFFFFFFFF; resData->data[0].idxLeft = 0; resData->data[0].idxRight = 0; resData->data[0].ofsString.set_ptr(NULL); resData->data[0].ofsData.set_ptr(NULL); return resData; } } /* namespace internal */ } /* namespace ut */ } /* namespace nw */ #endif /* NW_UT_RESDICTIONARY_H_ */