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