15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- StringUnorderedMap.h -----------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#ifndef MCLD_SEARCH_TABLE_H 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define MCLD_SEARCH_TABLE_H 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <vector> 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// For std::allocate. 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <memory> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// For uint32_t. 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <stdint.h> 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cassert> 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// For memset. 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstring> 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#ifdef ENABLE_UNITTEST 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <gtest.h> 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#endif 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/* FIXME: Move StringUnorderedMap under ADT. */ 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace mcld 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostruct StringUnorderedMapDefaultHash 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t operator()(const char *pStr) { 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t hashVal = 31; 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (*pStr) 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao hashVal = hashVal * 131 + (*pStr++); 335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return hashVal; 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ValueType, 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename KeyType> 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostruct StringUnorderedMapEntryInit 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao template <typename InitType> 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void operator()(KeyType &pKey, ValueType &pValue, 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const KeyType &pStr, InitType pInitVal) { 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ::new ((void*)&pKey) KeyStorageType(pStr); 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ::new ((void*)&pValue) ValueType(pInitVal); 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint32_t findNextPrime(uint32_t x); 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/** \class StringUnorderedMap 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * \brief The most simple hash of linked list version. 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * \see 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename KeyType, 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename ValueType, 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename KeyCompareFunctor, 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename HashFunction = StringUnorderedMapDefaultHash, 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Allocator = std::allocator<std::pair<KeyType, ValueType> > > 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoclass StringUnorderedMap 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao explicit StringUnorderedMap(size_t pCapacity = 17) 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : m_Impl(pCapacity) 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao {} 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ~StringUnorderedMap(); 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void reserve(size_t pCapacity); 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ValueType &getOrCreate(const KeyType &pStr, const ValueType &pInitVal); 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ValueType &getOrCreate(const KeyType &pStr); 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool empty() 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return m_Size == 0; } 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t capacity() const 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return m_Capacity; } 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void clear(); 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoprivate: 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao struct HashEntry { 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t hashVal; 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::pair<KeyType, ValueType> 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashEntry *next; 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao }; 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef Allocator::template rebind<HashEntry>::other HashEntryAllocator; 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void rehash(size_t pCapacity); 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoprivate: 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t m_Capacity; 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t m_Size; 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // array of pointers to hash entries 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashEntry **m_HashTable; 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashEntryAllocator m_HashEntryAllocator; 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// =================================implementation============================ 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// StringUnorderedMap::StringUnorderedMapImpl 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ValueType, 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename KeyStorageType, 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename HashFunction, 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Allocator> 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>:: 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMapImpl::StringUnorderedMapImpl(size_t pCapacity) 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : m_Capacity(0), m_Size(0), m_HashTable(0) 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->reserve(pCapacity); 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ValueType, 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename KeyStorageType, 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename HashFunction, 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Allocator> 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>:: 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMapImpl::reserve(size_t pCapacity) 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pCapacity < this->m_Capacity) 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t nextSize = findNextPrime(static_cast<uint32_t>(pCapacity)); 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // FIXME: Error handling. 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(nextSize > this->m_Capacity && "findNextPrime error."); 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (this->m_Capacity != nextSize) 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->rehash(nextSize); 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ValueType, 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename KeyStorageType, 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename HashFunction, 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Allocator> 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>:: 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMapImpl::rehash(size_t pCapacity) 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashEntry **tmpTable = new HashEntry*[pCapacity]; 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::memset(tmpTable, 0, pCapacity * sizeof(HashEntry*)); 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (this->m_HashTable) { 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (size_t i = 0; i < this->m_Capacity; ++i) 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (HashEntry *j = this->m_HashTable[i]; j != 0; ) { 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashEntry *nextJ = j->next; 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao j->next = tmpTable[j->hashVal % pCapacity]; 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao tmpTable[j->hashVal % pCapacity] = j; 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao j = nextJ; 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao delete[] m_HashTable; 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->m_Capacity = pCapacity; 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->m_HashTable = tmpTable; 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ValueType, 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename KeyStorageType, 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename HashFunction, 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Allocator> 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename InitType> 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoValueType & 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>:: 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMapImpl::getOrCreate(const KeyType &pStr, ValueType &pInitVal) 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashFunction hash; 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t hashVal = hash(pStr); 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashEntry *&head = this->m_HashTable[hashVal % this->m_Capacity]; 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashEntry *ans = 0; 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for(HashEntry *ptr = head; ptr != 0; ptr = ptr->next) 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(hashVal == ptr->hashVal && pStr.equals(ptr->str)) { 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ans = ptr; 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (ans == 0) { 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ans = this->allocate(1); 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ans->hashVal = hashVal; 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao StringUnorderedMapEntryInit<ValueType, KeyStorageType> init; 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao init(ans->str, ans->value, pStr, pInitVal); 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ans->next = head; 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao head = ans; 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++m_Size; 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(this->m_Size * 4LL >= this->m_Capacity * 3LL) // load factor = 0.75 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->reserve(this->m_Capacity+1); 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ans->value; 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ValueType, 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename KeyStorageType, 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename HashFunction, 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Allocator> 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>:: 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMapImpl::clear() 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (this->m_HashTable) { 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (size_t i = 0; i < this->m_Capacity; ++i) 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (HashEntry *j = this->m_HashTable[i]; j != 0; ) { 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao HashEntry *nextJ = j->next; 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->destroy(j); 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->deallocate(j, 1); 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao j = nextJ; 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao delete[] m_HashTable; 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ValueType, 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename KeyStorageType, 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename HashFunction, 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Allocator> 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>:: 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoStringUnorderedMapImpl::~StringUnorderedMapImpl() 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->clear(); 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // namespace of mcld 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#endif 225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 226