1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: ut_ResDictionary.h 4 5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Revision: 23585 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NW_UT_RESDICTIONARY_H_ 17 #define NW_UT_RESDICTIONARY_H_ 18 19 #include <nw/types.h> 20 #include <nw/ut/ut_ResTypes.h> 21 #include <nw/ut/ut_ResUtil.h> 22 #include <nw/ut/ut_ResArray.h> 23 24 namespace nw { 25 namespace ut { 26 27 #if 0 28 // 辞書インターフェイス (テンプレートで実現する場合は、このクラスは継承しない) 29 class IResDic 30 { 31 public: 32 // 辞書データが有効かどうかを返します。 33 virtual bool IsValid() const = 0; 34 35 // 辞書に登録されている要素数です。 36 virtual s32 GetCount() const = 0; 37 38 // インデクスやキー文字列の値から要素を取得します。 39 // 辞書中に指定の要素が見つからなかった場合にはNULLを返します。 40 virtual void* operator[](int idx) const = 0; 41 virtual void* operator[](u32 idx) const = 0; 42 virtual void* operator[](const char* key) const = 0; 43 virtual void* operator[](const ResName key) const = 0; 44 45 // キー文字列の値で辞書を検索し、インデクスを取得します。 46 // 指定のキーが見つからなかった場合には、負の数を返します。 47 virtual s32 GetIndex(const char* key) const = 0; 48 virtual s32 GetIndex(const ResName n ) const = 0; 49 50 // インデクス番目の要素のキー文字列を取得します。 51 virtual const ResName GetResName(u32 idx) const = 0; 52 virtual const char* GetName(u32 idx) const = 0; 53 }; 54 55 #endif 56 57 #if 0 58 // 包含クラスを挟む場合 59 template <class TDic> 60 class ResDic 61 { 62 public: 63 /* ctor */ ResDic(TDic& dic) : m_Dic( dic ) {} 64 65 bool IsValid() const { m_Dic.IsValid(); } 66 s32 GetCount() const { return m_Dic.GetCount(); } 67 void* operator[](int idx) const { return m_Dic[ idx ]; } 68 void* operator[](u32 idx) const { return m_Dic[ idx ]; } 69 void* operator[](const char* key) const { return m_Dic[ key ]; } 70 void* operator[](const ResName key) const { return m_Dic[ key ]; } 71 72 // キー文字列の値で辞書を検索し、インデクスを取得します。 73 // 指定のキーが見つからなかった場合には、負の数を返します。 74 s32 GetIndex(const char* key) const { return m_Dic.GetIndex( key ); } 75 s32 GetIndex(const ResName n ) const { return m_Dic.GetIndex( n ); } 76 77 // インデクス番目の要素のキー文字列を取得します。 78 const ResName GetResName(u32 idx) const { return m_Dic.GetResName( idx ); } 79 const char* GetName(u32 idx) const { return m_Dic.GetName( idx ); } 80 81 private: 82 TDic& m_Dic; 83 }; 84 #endif 85 86 87 //! @details :private 88 // 線形探索辞書 89 struct ResDicLinearData : public DataBlockHeader 90 { 91 Size numData; 92 struct ResDicNodeData 93 { 94 BinString toName; 95 Offset ofsData; 96 } 97 data[1]; // numData個ある 98 GetBeginNodeResDicLinearData99 ResDicNodeData* GetBeginNode() { return data; } GetBeginNodeResDicLinearData100 const ResDicNodeData* GetBeginNode() const { return data; } 101 }; 102 103 //! @details :private 104 class ResDicLinear : public ResCommon<ResDicLinearData> 105 { 106 public: NW_RES_CTOR(ResDicLinear)107 NW_RES_CTOR( ResDicLinear ) 108 109 s32 GetCount() const { return ref().numData; } 110 111 // インデクスやキー文字列の値から要素を取得します。 112 // 辞書中に指定の要素が見つからなかった場合にはNULLを返します。 113 void* operator[](int idx) const 114 { 115 if ( ! this->IsValid() ) { return NULL; } 116 if ( idx < 0 || s32(ref().numData) <= idx ) { return NULL; } 117 return const_cast<void*>( ref().data[idx].ofsData.to_ptr() ); 118 } 119 void* operator[](u32 idx) const { return operator[](int(idx)); } 120 void* operator[](const char* key) const 121 { 122 s32 idx = this->GetIndex(key); 123 if ( idx < 0 ) { return NULL; } 124 return const_cast<void*>( ref().data[ idx ].ofsData.to_ptr() ); 125 } 126 127 void* operator[](const ResName key) const 128 { 129 s32 idx = this->GetIndex(key); 130 if ( idx < 0 ) { return NULL; } 131 return const_cast<void*>( ref().data[ idx ].ofsData.to_ptr() ); 132 } 133 134 // キー文字列の値で辞書を検索し、インデクスを取得します。 135 // 指定のキーが見つからなかった場合には、負の数を返します。 136 s32 GetIndex(const char* key) const; GetIndex(const ResName key)137 s32 GetIndex(const ResName key) const 138 { 139 if ( (! this->IsValid()) || (! key.IsValid()) ) { return -1; } 140 return this->GetIndex(key.GetName()); 141 } 142 143 // インデクス番目の要素のキー文字列を取得します。 GetResName(u32)144 const ResName GetResName(u32 /*idx*/) const { return ResName(); } GetName(u32)145 const char* GetName(u32 /*idx*/) const { return NULL; } 146 }; 147 148 //! @details :private 149 // パトリシア木探索辞書 150 struct ResDicPatriciaData : public DataBlockHeader 151 { 152 ResU32 numData; 153 struct ResDicNodeData 154 { 155 ResU32 ref; 156 ResU16 idxLeft; 157 ResU16 idxRight; 158 Offset ofsString; 159 Offset ofsData; 160 } 161 data[1]; // numData + 1個ある 162 GetBeginNodeResDicPatriciaData163 ResDicNodeData* GetBeginNode() { return &data[1]; } GetBeginNodeResDicPatriciaData164 const ResDicNodeData* GetBeginNode() const { return &data[1]; } 165 }; 166 167 //! @details :private 168 // パトリシア辞書アクセサクラス。 169 class ResDicPatricia : public ResCommon< ResDicPatriciaData > 170 { 171 public: 172 enum { NOT_FOUND = -1 }; 173 174 NW_RES_CTOR( ResDicPatricia ); 175 GetCount()176 s32 GetCount() const { return ref().numData; } 177 178 void* operator[](int idx) const 179 { 180 if (!this->IsValid()) { return NULL; } 181 182 NW_MINMAX_ASSERT( idx, 0, static_cast<int>(ref().numData - 1) ); 183 // 辞書引き関連についてはconst correctnessを維持しなくても問題ないだろう 184 return const_cast<void*>(ref().data[idx + 1].ofsData.to_ptr()); 185 } 186 187 void* operator[](u32 idx) const { return operator[](int(idx)); } 188 189 void* operator[](const char* s) const 190 { 191 // sがNULLでもOK 192 if (this->IsValid() && s) 193 { 194 ResDicPatriciaData::ResDicNodeData* x = Get(s, std::strlen(s)); 195 196 // 辞書にはNULLの行き先を仮定しなくてよい 197 if (x) 198 { 199 return const_cast<void*>(x->ofsData.to_ptr()); 200 } 201 } 202 203 return NULL; 204 } 205 operator()206 void* operator()(const char* s, size_t len) const 207 { 208 // lenを文字列長として設定しているので文字列がNULLというのはNG 209 NW_NULL_ASSERT(s); 210 if (this->IsValid()) 211 { 212 ResDicPatriciaData::ResDicNodeData* x = Get(s, len); 213 214 // 辞書にはNULLの行き先を仮定しなくてよい 215 if (x) 216 { 217 return const_cast<void*>(x->ofsData.to_ptr()); 218 } 219 } 220 return NULL; 221 } 222 223 void* operator[](const ResName n) const 224 { 225 // 入力が無効でも止まらないようにする 226 if (IsValid() && n.IsValid()) 227 { 228 ResDicPatriciaData::ResDicNodeData* x = Get(n); 229 230 // 辞書にはNULLの行き先を仮定しなくてよい 231 if (x) 232 { 233 return const_cast<void*>(x->ofsData.to_ptr()); 234 } 235 } 236 237 return NULL; 238 } 239 GetIndex(const char * s)240 s32 GetIndex(const char* s) const 241 { 242 // sがNULLでもOK 243 if (IsValid() && s) 244 { 245 size_t len = std::strlen(s); 246 ResDicPatriciaData::ResDicNodeData* x = Get(s, len); 247 248 if (x) 249 { 250 return static_cast<s32>(x - &ptr()->data[1]); 251 // エントリ 0 はルートノードであるので 1 との差を取る 252 } 253 } 254 255 return -1; 256 } 257 GetIndex(const ResName n)258 s32 GetIndex(const ResName n) const 259 { 260 // 入力が無効でも止まらないようにする 261 if (IsValid() && n.IsValid()) 262 { 263 ResDicPatriciaData::ResDicNodeData* x = Get(n); 264 265 if (x) 266 { 267 return static_cast<s32>(x - &ptr()->data[1]); 268 // エントリ 0 はルートノードであるので 1 との差を取る 269 } 270 } 271 272 return -1; 273 } 274 GetResName(u32 idx)275 const ResName GetResName(u32 idx) const 276 { 277 if (!IsValid()) { return ResName(NULL); } 278 279 NW_MINMAX_ASSERT( idx, 0, ptr()->numData - 1 ); 280 return ofs_to_obj<ResName>(ptr()->data[idx + 1].ofsString - s32(sizeof(u32))); 281 } 282 GetName(u32 idx)283 const char* GetName(u32 idx) const 284 { 285 if (!IsValid()) { return NULL; } 286 return GetResName(idx).GetName(); 287 } 288 GetNumData()289 u32 GetNumData() const 290 { 291 if ( !IsValid() ) { return 0; } 292 return ptr()->numData; 293 } 294 GetLength()295 u32 GetLength() const { return ref().length; } 296 297 protected: 298 ResDicPatriciaData::ResDicNodeData* Get(const char* s, size_t len) const; 299 ResDicPatriciaData::ResDicNodeData* Get(const ResName rhs) const; 300 }; 301 302 303 namespace internal { 304 305 //--------------------------------------------------------------------------- 306 //! @brief 要素が空のパトリシア辞書リソースを生成します。 307 //! 308 //! @param[out] resData 初期化をするパトリシア辞書構造体へのポインタです。 309 //! 310 //! @return resData へのポインタを返します。 311 //--------------------------------------------------------------------------- 312 inline ResDicPatriciaData* InitializeResDicPatricia(ResDicPatriciaData * resData)313 InitializeResDicPatricia(ResDicPatriciaData* resData) 314 { 315 resData->signature = NW_RES_SIGNATURE32('DICT'); 316 resData->length = sizeof(ResDicPatriciaData); 317 resData->numData = 0; 318 resData->data[0].ref = 0xFFFFFFFF; 319 resData->data[0].idxLeft = 0; 320 resData->data[0].idxRight = 0; 321 resData->data[0].ofsString.set_ptr(NULL); 322 resData->data[0].ofsData.set_ptr(NULL); 323 324 return resData; 325 } 326 327 328 } /* namespace internal */ 329 330 } /* namespace ut */ 331 } /* namespace nw */ 332 333 #endif /* NW_UT_RESDICTIONARY_H_ */ 334