15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- GCFactory.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//===----------------------------------------------------------------------===// 987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#ifndef MCLD_SUPPORT_GCFACTORY_H 1087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#define MCLD_SUPPORT_GCFACTORY_H 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/ADT/TypeTraits.h" 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/Support/Allocators.h" 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <assert.h> 15f767be5432ccac097334be48698e48621d730190Shih-wei Liao#include <cstddef> 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <iterator> 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace mcld 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/** \class DataIteratorBase 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * \brief DataIteratorBase provides the basic functions of DataIterator 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * @see DataIterator 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ChunkType> 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostruct DataIteratorBase 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ChunkType* m_pChunk; 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int m_Pos; 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao DataIteratorBase(ChunkType* X, unsigned int pPos) 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : m_pChunk(X), m_Pos(pPos) 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao inline void advance() { 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++m_Pos; 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if ((m_Pos == m_pChunk->bound) && (0 == m_pChunk->next)) 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (m_Pos == m_pChunk->bound) { 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_pChunk = m_pChunk->next; 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Pos = 0; 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool operator==(const DataIteratorBase& y) const 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return ((this->m_pChunk == y.m_pChunk) && (this->m_Pos == y.m_Pos)); } 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool operator!=(const DataIteratorBase& y) const 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return ((this->m_pChunk != y.m_pChunk) || (this->m_Pos != y.m_Pos)); } 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/** \class DataIterator 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * \brief DataIterator provides STL compatible iterator for allocators 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename ChunkType, class Traits> 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoclass DataIterator : public DataIteratorBase<ChunkType> 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename ChunkType::value_type value_type; 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef Traits traits; 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename traits::pointer pointer; 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename traits::reference reference; 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef DataIterator<ChunkType, Traits> Self; 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef DataIteratorBase<ChunkType> Base; 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename traits::nonconst_traits nonconst_traits; 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef DataIterator<ChunkType, nonconst_traits> iterator; 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename traits::const_traits const_traits; 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef DataIterator<ChunkType, const_traits> const_iterator; 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef std::forward_iterator_tag iterator_category; 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef size_t size_type; 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef ptrdiff_t difference_type; 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao DataIterator() 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : Base(0, 0) 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao DataIterator(ChunkType* pChunk, unsigned int pPos) 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : Base(pChunk, pPos) 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao DataIterator(const DataIterator& pCopy) 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : Base(pCopy.m_pChunk, pCopy.m_Pos) 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ~DataIterator() 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // ----- operators ----- // 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reference operator*() { 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0 == this->m_pChunk) 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "data iterator goes to a invalid position"); 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return this->m_pChunk->data[Base::m_Pos]; 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Self& operator++() { 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->Base::advance(); 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return *this; 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Self operator++(int) { 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Self tmp = *this; 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao this->Base::advance(); 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return tmp; 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename Alloc> 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoclass GCFactoryBase : public Alloc 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef DataIterator<typename Alloc::chunk_type, 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao NonConstTraits< 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Alloc::value_type> > iterator; 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef DataIterator<typename Alloc::chunk_type, 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ConstTraits< 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typename Alloc::value_type> > const_iterator; 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename Alloc::value_type value_type; 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename Alloc::pointer pointer; 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename Alloc::reference reference; 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef typename Alloc::size_type size_type; 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoprotected: 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GCFactoryBase() 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : Alloc(), m_NumAllocData(0) 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GCFactoryBase(size_t pNum) 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : Alloc(pNum), m_NumAllocData(0) 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao virtual ~GCFactoryBase() 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { Alloc::clear(); } 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // ----- modifiers ----- // 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao value_type* allocate(size_t N) { 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao value_type* result = Alloc::allocate(N); 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0 != result) 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_NumAllocData += N; 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return result; 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao value_type* allocate() { 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++m_NumAllocData; 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return Alloc::allocate(); 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void deallocate(pointer &pPtr, size_type N) { 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Alloc::deallocate(pPtr, N); 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0 == pPtr) 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_NumAllocData -= N; 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void deallocate(pointer &pPtr) { 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Alloc::deallocate(pPtr); 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (0 == pPtr) 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao --m_NumAllocData; 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao void reset() { 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Alloc::reset(); 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_NumAllocData = 0; 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // ----- iterators ----- // 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao iterator begin() 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return iterator(Alloc::m_pRoot, 0); } 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const_iterator begin() const 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return const_iterator(Alloc::m_pRoot, 0); } 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao iterator end() { 178f767be5432ccac097334be48698e48621d730190Shih-wei Liao return (0 == Alloc::m_pCurrent)? 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao begin(): 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound); 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const_iterator end() const { 184f767be5432ccac097334be48698e48621d730190Shih-wei Liao return (0 == Alloc::m_pCurrent)? 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao begin(): 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const_iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound); 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // ----- observers ----- // 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool empty() const 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return Alloc::empty(); } 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int capacity() const 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return Alloc::max_size(); } 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int size() const 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { return m_NumAllocData; } 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoprotected: 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int m_NumAllocData; 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/** \class GCFactory 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * \brief GCFactory provides a factory that guaratees to remove all allocated 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * data. 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename DataType, size_t ChunkSize> 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoclass GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> > 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GCFactory() 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >() 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<typename DataType> 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoclass GCFactory<DataType, 0> : public GCFactoryBase<LinearAllocator<DataType, 0> > 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaopublic: 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GCFactory(size_t pNum) 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : GCFactoryBase<LinearAllocator<DataType, 0> >(pNum) 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { } 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // namespace of mcld 2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#endif 228affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 229