Win32のUUID(GUID)構造体のラッパークラス。VS.NET2003付属STLのhashコンテナ(hash_map/hash_set /hash_multimap/hash_multiset)用比較関数、SGI系STLのhashコンテナ用ハッシュ関数オブジェクト付き。システムの用意した構造体を継承してクラスを作るというのは割とよくやる方法で、継承した場合vtableが無ければメモリレイアウトの先頭に継承元が入るので、後ろに追加のデータをペイロードとして付けた上で、親の構造体を引数とするAPIの引数に使えるという利点がある。換言すれば、templateと、template policyを利用したmix-inによって、C++における継承は、Java等のクラスライブラリに顕著な、現実世界やデザインパターンとして観念されるモデルのマッピングに近いカテゴリ概念の素朴な具体化のための道具というよりは、本来の意味でのデータ抽象/アルゴリズム抽象に向けての手段として、あるいはCOMのバイナリ仕様の表現として活用(exploit)される箇所しか出る幕が無くなってしまった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | // ComponentID クラス (c) RyuK #ifndef CALC_COMPONENTID_H #define CALC_COMPONENTID_H #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 // Windows 2000 以降の機能を使用 #endif _WIN32_WINNT #include <windows.h> // あくまでMS Windows依存。UUID<=>文字列変換はわざわざプラットフォーム // 依存のAPIに頼る必然性は無いものの、適当なGUIDの生成だけは依存せざる // を得ない。 // Windowsの場合、最近になってMACアドレスが生成結果から判別できないように // UUIDを生成できるようになった。Windowsは必要な物は大概 // Platform SDKの中に道具が用意されているので手間の節約のためにできる // だけ依存することにする。 #include <rpc.h> // UUID #include <string> #include <functional> #include <hash_map> #include <hash_set> #ifdef _STLPORT_VERSION // STLport使用時 using namespace std; #else // VS.NET2003付属STL(Dinkumware)使用時 using namespace std; using namespace stdext; #endif // CスタイルUUID文字列クラス(ASCII)(間のハイフン無し) struct ComponentIDString { ComponentIDString() { m_szBuffer[32] = 0x00; } ~ComponentIDString() {} char m_szBuffer[36]; }; struct ComponentID : public UUID { typedef unsigned __int64 UInt64; // デフォルトのコンストラクタ。UUID生成有り ComponentID() { UuidCreate( this ); } // UUID生成無し ComponentID( bool init) {} ~ComponentID() {} // (STLportなどのSGI系STL向けに)hash_mapのキーとするために必要な等 // 値演算子を定義する // MicrosoftがData1等抽象的なメンバ名を付けた理由は不明である __forceinline bool operator==( const ComponentID& right) const { return ( (* reinterpret_cast < const UInt64*>(&Data1) == * reinterpret_cast < const UInt64*>(&(right.Data1))) && (* reinterpret_cast < const UInt64*>(&Data4) == * reinterpret_cast < const UInt64*>(&(right.Data4))) ); } // (VS.NET2003付属STL - Dinkumware STL向けに)hash_mapのキーとする // ために必要な比較演算子を定義する。 __forceinline bool operator<( const ComponentID& right) const { if (* reinterpret_cast < const UInt64*>(&Data4) < * reinterpret_cast < const UInt64*>(&(right.Data4))) return true ; else if (* reinterpret_cast < const UInt64*>(&Data4) > * reinterpret_cast < const UInt64*>(&(right.Data4))) return false ; else { return (* reinterpret_cast < const UInt64*>(&Data1) < * reinterpret_cast < const UInt64*>(&(right.Data1))); } } // VS.NET2003付属STL - Dinkumware STL向けに必要なハッシュ関数をsize_t // へのキャスト演算子として定義する #ifndef _STLPORT_VERSION __forceinline operator size_t () const { // Win32APIをUnix上で実装するWine ProjectがUuidHashで借用している // FreeDCEのコードを又借り const BYTE * data = reinterpret_cast < const BYTE *>( this ); short c0 = 0; short c1 = 0; for ( DWORD i = 0; i < sizeof (UUID); ++i) { c0 += data[i]; c1 += c0; } short x = -c1 % 255; if (x < 0) x += 255; short y = (c1 - c0) % 255; if (y < 0) y += 255; return y * 256 + x; } #endif __forceinline ComponentID& operator=( const ComponentID& right) { if (&right != this ) { CopyMemory( this , &right, sizeof (ComponentID)); } return * this ; } __forceinline const ComponentID& initialize() { UuidCreate( this ); return * this ; } // ハイフン入りASCII文字列として文字列化。sprintfなんかより実はこちら // の方がかなり速い string toString() const { unsigned char * pszUuid; UuidToStringA( const_cast <ComponentID*>( this ), &pszUuid ); string result( reinterpret_cast < char *>(pszUuid)); RpcStringFreeA(&pszUuid); return result; } // ハイフン無し文字列としてComponentIDStringへエクスポート // (バイトオーダーを変換) void toString(ComponentIDString& dst) const { const char szHexTable[] = "0123456789abcdef" ; const BYTE * s = reinterpret_cast < BYTE *>( const_cast <ComponentID*>( this )); dst.m_szBuffer[0] = szHexTable[s[3] >> 4]; dst.m_szBuffer[1] = szHexTable[s[3] & 15]; dst.m_szBuffer[2] = szHexTable[s[2] >> 4]; dst.m_szBuffer[3] = szHexTable[s[2] & 15]; dst.m_szBuffer[4] = szHexTable[s[1] >> 4]; dst.m_szBuffer[5] = szHexTable[s[1] & 15]; dst.m_szBuffer[6] = szHexTable[s[0] >> 4]; dst.m_szBuffer[7] = szHexTable[s[0] & 15]; dst.m_szBuffer[8] = szHexTable[s[5] >> 4]; dst.m_szBuffer[9] = szHexTable[s[5] & 15]; dst.m_szBuffer[10] = szHexTable[s[4] >> 4]; dst.m_szBuffer[11] = szHexTable[s[4] & 15]; dst.m_szBuffer[12] = szHexTable[s[7] >> 4]; dst.m_szBuffer[13] = szHexTable[s[7] & 15]; dst.m_szBuffer[14] = szHexTable[s[6] >> 4]; dst.m_szBuffer[15] = szHexTable[s[6] & 15]; dst.m_szBuffer[16] = szHexTable[Data4[0] >> 4]; dst.m_szBuffer[17] = szHexTable[Data4[0] & 15]; dst.m_szBuffer[18] = szHexTable[Data4[1] >> 4]; dst.m_szBuffer[19] = szHexTable[Data4[1] & 15]; dst.m_szBuffer[20] = szHexTable[Data4[2] >> 4]; dst.m_szBuffer[21] = szHexTable[Data4[2] & 15]; dst.m_szBuffer[22] = szHexTable[Data4[3] >> 4]; dst.m_szBuffer[23] = szHexTable[Data4[3] & 15]; dst.m_szBuffer[24] = szHexTable[Data4[4] >> 4]; dst.m_szBuffer[25] = szHexTable[Data4[4] & 15]; dst.m_szBuffer[26] = szHexTable[Data4[5] >> 4]; dst.m_szBuffer[27] = szHexTable[Data4[5] & 15]; dst.m_szBuffer[28] = szHexTable[Data4[6] >> 4]; dst.m_szBuffer[29] = szHexTable[Data4[6] & 15]; dst.m_szBuffer[30] = szHexTable[Data4[7] >> 4]; dst.m_szBuffer[31] = szHexTable[Data4[7] & 15]; } // ハイフン入りASCII文字列からインポート __forceinline bool importFromString( const string& s) { return (UuidFromStringA( reinterpret_cast <unsigned char *>( const_cast < char *>(s.c_str())), (UUID*) this ) == RPC_S_OK); } // ハイフン無しASCII文字列からインポート。s.size() >= 32に留意せよ bool importFromStringWithoutHyphen( const string& s) { char szBuffer[] = {0, 0, 0, 0, 0, 0, 0, 0, '-' , 0, 0, 0, 0, '-' , 0, 0, 0, 0, '-' , 0, 0, 0, 0, '-' , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; CopyMemory(&szBuffer[0], s.data(), 8); CopyMemory(&szBuffer[9], s.data() + 8, 4); CopyMemory(&szBuffer[14], s.data() + 12, 4); CopyMemory(&szBuffer[19], s.data() + 16, 4); CopyMemory(&szBuffer[24], s.data() + 20, 12); return (UuidFromStringA( reinterpret_cast <unsigned char *>(&szBuffer[0]), (UUID*) this ) == RPC_S_OK); } }; // SGI系STL(STLport他)でhash_map等のキーとしてComponentIDを使用するためのhasher // 関数オブジェクト #include <functional> #include <hash_map> #include <hash_set> struct ComponentIDHasher : public unary_function<ComponentID, size_t > { // Win32APIをUnix上で実装するWine ProjectがUuidHashで借用している // FreeDCEのコードを又借り __forceinline size_t operator()( const ComponentID& arg) const { const BYTE * data = reinterpret_cast < const BYTE *>(&arg); short c0 = 0; short c1 = 0; for ( DWORD i = 0; i < sizeof (UUID); ++i) { c0 += data[i]; c1 += c0; } short x = -c1 % 255; if (x < 0) x += 255; short y = (c1 - c0) % 255; if (y < 0) y += 255; return y * 256 + x; } }; /* // 別バージョン - UuidHash使用 class ComponentIDHasher : public unary_function<ComponentID, size_t> { private: mutable RPC_STATUS m_rpc_status; public: ComponentIDHasher() {} ~ComponentIDHasher() {} // 都合良くUuidHashなるAPI(128bit->16bit)が用意されているのでそれを使用。 // C++のconstは重要なDesign by Contractの手段である。 // ここではテンプレートの要求に応えるために引数のみならず関数もconst指定する // 必要がある size_t operator()(const ComponentID& arg) const { return static_cast<size_t>( UuidHash( reinterpret_cast<UUID*>(const_cast<ComponentID*>(&arg)), &m_rpc_status ) ); } }; */ #ifdef _STLPORT_VERSION typedef hash_set<ComponentID, ComponentIDHasher> ComponentIDSet; typedef hash_map<ComponentID, DWORD , ComponentIDHasher> ComponentID2DWORD; typedef hash_map<ComponentID, ComponentID, ComponentIDHasher> ComponentID2ComponentID; typedef hash_map<string, ComponentID> String2ComponentID; typedef hash_map<ComponentID, string, ComponentIDHasher> ComponentID2String; #else typedef hash_set<ComponentID> ComponentIDSet; typedef hash_map<ComponentID, DWORD > ComponentID2DWORD; typedef hash_map<ComponentID, ComponentID> ComponentID2ComponentID; typedef hash_map<string, ComponentID> String2ComponentID; typedef hash_map<ComponentID, string> ComponentID2String; #endif #endif CALC_COMPONENTID_H |
コメント
コメントを投稿