Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 10:31:17

0001 /*
0002  * Licensed to the Apache Software Foundation (ASF) under one or more
0003  * contributor license agreements.  See the NOTICE file distributed with
0004  * this work for additional information regarding copyright ownership.
0005  * The ASF licenses this file to You under the Apache License, Version 2.0
0006  * (the "License"); you may not use this file except in compliance with
0007  * the License.  You may obtain a copy of the License at
0008  *
0009  *      http://www.apache.org/licenses/LICENSE-2.0
0010  *
0011  * Unless required by applicable law or agreed to in writing, software
0012  * distributed under the License is distributed on an "AS IS" BASIS,
0013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014  * See the License for the specific language governing permissions and
0015  * limitations under the License.
0016  */
0017 
0018 /*
0019  * $Id$
0020  */
0021 
0022 #if !defined(XERCESC_INCLUDE_GUARD_CMSTATESET_HPP)
0023 #define XERCESC_INCLUDE_GUARD_CMSTATESET_HPP
0024 
0025 //  DESCRIPTION:
0026 //
0027 //  This class is a specialized bitset class for the content model code of
0028 //  the validator. It assumes that its never called with two objects of
0029 //  different bit counts, and that bit sets smaller than a threshold are far
0030 //  and away the most common. So it can be a lot more optimized than a general
0031 //  purpose utility bitset class
0032 //
0033 
0034 #include <xercesc/util/ArrayIndexOutOfBoundsException.hpp>
0035 #include <xercesc/util/OutOfMemoryException.hpp>
0036 #include <xercesc/util/RuntimeException.hpp>
0037 #include <xercesc/util/PlatformUtils.hpp>
0038 #include <xercesc/framework/MemoryManager.hpp>
0039 #include <string.h>
0040 
0041 #if XERCES_HAVE_EMMINTRIN_H
0042 #   include <emmintrin.h>
0043 #endif
0044 
0045 XERCES_CPP_NAMESPACE_BEGIN
0046 
0047 class CMStateSetEnumerator;
0048 
0049 // This value must be 4 in order to use the SSE2 instruction set
0050 #define CMSTATE_CACHED_INT32_SIZE  4
0051 
0052 // This value must be a multiple of 128 in order to use the SSE2 instruction set
0053 #define CMSTATE_BITFIELD_CHUNK  1024
0054 #define CMSTATE_BITFIELD_INT32_SIZE (1024 / 32)
0055 
0056 struct CMDynamicBuffer
0057 {
0058     //  fArraySize
0059     //      This indicates the number of elements of the fBitArray vector
0060     //
0061     //  fBitArray
0062     //      A vector of arrays of XMLInt32; each array is allocated on demand
0063     //      if a bit needs to be set in that range
0064     //
0065     //  fMemoryManager
0066     //      The memory manager used to allocate and deallocate memory
0067     //
0068     XMLSize_t       fArraySize;
0069     XMLInt32**      fBitArray;
0070     MemoryManager*  fMemoryManager;
0071 };
0072 
0073 class CMStateSet : public XMemory
0074 {
0075 public :
0076     // -----------------------------------------------------------------------
0077     //  Constructors and Destructor
0078     // -----------------------------------------------------------------------
0079     CMStateSet( const XMLSize_t bitCount
0080               , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) :
0081 
0082         fBitCount(bitCount)
0083         , fDynamicBuffer(0)
0084     {
0085         //
0086         //  See if we need to allocate the byte array or whether we can live
0087         //  within the cached bit high performance scheme.
0088         //
0089         if (fBitCount > (CMSTATE_CACHED_INT32_SIZE * 32))
0090         {
0091             fDynamicBuffer = (CMDynamicBuffer*)manager->allocate(sizeof(CMDynamicBuffer));
0092             fDynamicBuffer->fMemoryManager = manager;
0093             // allocate an array of vectors, each one containing CMSTATE_BITFIELD_CHUNK bits
0094             fDynamicBuffer->fArraySize = fBitCount / CMSTATE_BITFIELD_CHUNK;
0095             if (fBitCount % CMSTATE_BITFIELD_CHUNK)
0096                 fDynamicBuffer->fArraySize++;
0097             try
0098             {
0099                 fDynamicBuffer->fBitArray = (XMLInt32**) fDynamicBuffer->fMemoryManager->allocate(fDynamicBuffer->fArraySize*sizeof(XMLInt32*));
0100             }
0101             catch( const OutOfMemoryException& )
0102             {
0103                 fDynamicBuffer->fMemoryManager->deallocate(fDynamicBuffer);
0104                 throw;
0105             }
0106             for(XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
0107                 fDynamicBuffer->fBitArray[index]=NULL;
0108         }
0109         else
0110         {
0111             for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
0112                 fBits[index] = 0;
0113         }
0114     }
0115 
0116     CMStateSet(const CMStateSet& toCopy) :
0117         XMemory(toCopy)
0118       , fBitCount(toCopy.fBitCount)
0119       , fDynamicBuffer(0)
0120     {
0121         //
0122         //  See if we need to allocate the byte array or whether we can live
0123         //  within the cahced bit high performance scheme.
0124         //
0125         if (fBitCount > (CMSTATE_CACHED_INT32_SIZE * 32))
0126         {
0127             fDynamicBuffer = (CMDynamicBuffer*) toCopy.fDynamicBuffer->fMemoryManager->allocate(sizeof(CMDynamicBuffer));
0128             fDynamicBuffer->fMemoryManager = toCopy.fDynamicBuffer->fMemoryManager;
0129             fDynamicBuffer->fArraySize = fBitCount / CMSTATE_BITFIELD_CHUNK;
0130             if (fBitCount % CMSTATE_BITFIELD_CHUNK)
0131                 fDynamicBuffer->fArraySize++;
0132             fDynamicBuffer->fBitArray = (XMLInt32**) fDynamicBuffer->fMemoryManager->allocate(fDynamicBuffer->fArraySize*sizeof(XMLInt32*));
0133             for(XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
0134             {
0135                 if(toCopy.fDynamicBuffer->fBitArray[index]!=NULL)
0136                 {
0137                     allocateChunk(index);
0138                     memcpy((void *) fDynamicBuffer->fBitArray[index],
0139                            (const void *) toCopy.fDynamicBuffer->fBitArray[index],
0140                            CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32));
0141                 }
0142                 else
0143                     fDynamicBuffer->fBitArray[index]=NULL;
0144             }
0145         }
0146         else
0147         {
0148             memcpy((void *) fBits,
0149                    (const void *) toCopy.fBits,
0150                    CMSTATE_CACHED_INT32_SIZE * sizeof(XMLInt32));
0151         }
0152     }
0153 
0154     ~CMStateSet()
0155     {
0156         if(fDynamicBuffer)
0157         {
0158             for(XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
0159                 if(fDynamicBuffer->fBitArray[index]!=NULL)
0160                     deallocateChunk(index);
0161             fDynamicBuffer->fMemoryManager->deallocate(fDynamicBuffer->fBitArray);
0162             fDynamicBuffer->fMemoryManager->deallocate(fDynamicBuffer);
0163         }
0164     }
0165 
0166 
0167     // -----------------------------------------------------------------------
0168     //  Set manipulation methods
0169     // -----------------------------------------------------------------------
0170     void operator|=(const CMStateSet& setToOr)
0171     {
0172         if(fDynamicBuffer==0)
0173         {
0174 #ifdef XERCES_HAVE_SSE2_INTRINSIC
0175             if(XMLPlatformUtils::fgSSE2ok)
0176             {
0177                 __m128i xmm1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(fBits));
0178                 __m128i xmm2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(setToOr.fBits));
0179                 __m128i xmm3 = _mm_or_si128(xmm1, xmm2);     //  OR  4 32-bit words
0180                 _mm_storeu_si128(reinterpret_cast<__m128i*>(fBits), xmm3);
0181             }
0182             else
0183 #endif
0184             {
0185                 for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
0186                     if(setToOr.fBits[index])
0187                     {
0188                         if(fBits[index])
0189                             fBits[index] |= setToOr.fBits[index];
0190                         else
0191                             fBits[index] = setToOr.fBits[index];
0192                     }
0193             }
0194         }
0195         else
0196         {
0197             for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
0198             {
0199                 XMLInt32 *& other = setToOr.fDynamicBuffer->fBitArray[index];
0200                 if(other!=NULL)
0201                 {
0202                     // if we haven't allocated the subvector yet, allocate it and copy
0203                     if(fDynamicBuffer->fBitArray[index]==NULL)
0204                     {
0205                         allocateChunk(index);
0206                         memcpy((void *) fDynamicBuffer->fBitArray[index],
0207                                (const void *) other,
0208                                CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32));
0209                     }
0210                     else
0211                     {
0212                         // otherwise, merge them
0213                         XMLInt32*& mine = fDynamicBuffer->fBitArray[index];
0214 #ifdef XERCES_HAVE_SSE2_INTRINSIC
0215                         if(XMLPlatformUtils::fgSSE2ok)
0216                         {
0217                             for(XMLSize_t subIndex = 0; subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex+=4)
0218                             {
0219                                __m128i xmm1 = _mm_load_si128(reinterpret_cast<const __m128i*>(&other[subIndex]));
0220                                __m128i xmm2 = _mm_load_si128(reinterpret_cast<const __m128i*>(&mine[subIndex]));
0221                                __m128i xmm3 = _mm_or_si128(xmm1, xmm2);     //  OR  4 32-bit words
0222                                _mm_store_si128(reinterpret_cast<__m128i*>(&mine[subIndex]), xmm3);
0223                             }
0224                         }
0225                         else
0226 #endif
0227                         {
0228                             for(XMLSize_t subIndex = 0; subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
0229                                 if(setToOr.fDynamicBuffer->fBitArray[index][subIndex])
0230                                 {
0231                                     if(fDynamicBuffer->fBitArray[index][subIndex])
0232                                         fDynamicBuffer->fBitArray[index][subIndex] |= setToOr.fDynamicBuffer->fBitArray[index][subIndex];
0233                                     else
0234                                         fDynamicBuffer->fBitArray[index][subIndex] = setToOr.fDynamicBuffer->fBitArray[index][subIndex];
0235                                 }
0236                         }
0237                     }
0238                 }
0239             }
0240         }
0241     }
0242 
0243     bool operator==(const CMStateSet& setToCompare) const
0244     {
0245         if (fBitCount != setToCompare.fBitCount)
0246             return false;
0247 
0248         if(fDynamicBuffer==0)
0249         {
0250             for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
0251             {
0252                 if (fBits[index] != setToCompare.fBits[index])
0253                     return false;
0254             }
0255         }
0256         else
0257         {
0258             for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
0259             {
0260                 XMLInt32 *& other = setToCompare.fDynamicBuffer->fBitArray[index],
0261                          *& mine = fDynamicBuffer->fBitArray[index];
0262                 if(mine==NULL && other==NULL)
0263                     continue;
0264                 else if(mine==NULL || other==NULL) // the other should have been empty too
0265                     return false;
0266                 else
0267                 {
0268                     for(XMLSize_t subIndex = 0; subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
0269                         if(mine[subIndex]!=other[subIndex])
0270                             return false;
0271                 }
0272             }
0273         }
0274         return true;
0275     }
0276 
0277     CMStateSet& operator=(const CMStateSet& srcSet)
0278     {
0279         if (this == &srcSet)
0280             return *this;
0281 
0282         // They have to be the same size
0283         if (fBitCount != srcSet.fBitCount)
0284         {
0285             if(fDynamicBuffer)
0286                 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Bitset_NotEqualSize, fDynamicBuffer->fMemoryManager);
0287             else
0288                 ThrowXML(RuntimeException, XMLExcepts::Bitset_NotEqualSize);
0289         }
0290 
0291         if(fDynamicBuffer==0)
0292         {
0293             for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
0294                 fBits[index] = srcSet.fBits[index];
0295         }
0296         else
0297         {
0298             for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
0299                 if(srcSet.fDynamicBuffer->fBitArray[index]==NULL)
0300                 {
0301                     // delete this subentry
0302                     if(fDynamicBuffer->fBitArray[index]!=NULL)
0303                         deallocateChunk(index);
0304                 }
0305                 else
0306                 {
0307                     // if we haven't allocated the subvector yet, allocate it and copy
0308                     if(fDynamicBuffer->fBitArray[index]==NULL)
0309                         allocateChunk(index);
0310                     memcpy((void *) fDynamicBuffer->fBitArray[index],
0311                            (const void *) srcSet.fDynamicBuffer->fBitArray[index],
0312                            CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32));
0313                 }
0314         }
0315         return *this;
0316     }
0317 
0318     XMLSize_t getBitCountInRange(XMLSize_t start, XMLSize_t end) const
0319     {
0320         XMLSize_t count = 0;
0321         end /= 32;
0322         if(fDynamicBuffer==0)
0323         {
0324             if(end > CMSTATE_CACHED_INT32_SIZE)
0325                 end = CMSTATE_CACHED_INT32_SIZE;
0326             for (XMLSize_t index = start / 32; index < end; index++)
0327             {
0328                 if (fBits[index] != 0)
0329                     for(int i=0;i<32;i++)
0330                     {
0331                         const XMLInt32 mask = 1UL << i;
0332                         if(fBits[index] & mask)
0333                             count++;
0334                     }
0335             }
0336         }
0337         else
0338         {
0339             if(end > fDynamicBuffer->fArraySize)
0340                 end = fDynamicBuffer->fArraySize;
0341             for (XMLSize_t index = start / 32; index < end; index++)
0342             {
0343                 if(fDynamicBuffer->fBitArray[index]==NULL)
0344                     continue;
0345                 for(XMLSize_t subIndex=0;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
0346                 {
0347                     if (fDynamicBuffer->fBitArray[index][subIndex] != 0)
0348                         for(int i=0;i<32;i++)
0349                         {
0350                             const XMLInt32 mask = 1UL << i;
0351                             if(fDynamicBuffer->fBitArray[index][subIndex] & mask)
0352                                 count++;
0353                         }
0354                 }
0355             }
0356         }
0357         return count;
0358     }
0359 
0360     bool getBit(const XMLSize_t bitToGet) const
0361     {
0362         if (bitToGet >= fBitCount)
0363         {
0364             if(fDynamicBuffer)
0365                 ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Bitset_BadIndex, fDynamicBuffer->fMemoryManager);
0366             else
0367                 ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Bitset_BadIndex);
0368         }
0369 
0370         // And access the right bit and byte
0371         if(fDynamicBuffer==0)
0372         {
0373             const XMLInt32 mask = 1UL << (bitToGet % 32);
0374             const XMLSize_t byteOfs = bitToGet / 32;
0375             return (fBits[byteOfs]!=0 && (fBits[byteOfs] & mask) != 0);
0376         }
0377         else
0378         {
0379             const XMLSize_t vectorOfs = bitToGet / CMSTATE_BITFIELD_CHUNK;
0380             if(fDynamicBuffer->fBitArray[vectorOfs]==NULL)
0381                 return false;
0382             const XMLInt32 mask = 1UL << (bitToGet % 32);
0383             const XMLSize_t byteOfs = (bitToGet % CMSTATE_BITFIELD_CHUNK) / 32;
0384             return (fDynamicBuffer->fBitArray[vectorOfs][byteOfs]!=0 && (fDynamicBuffer->fBitArray[vectorOfs][byteOfs] & mask) != 0);
0385         }
0386     }
0387 
0388     bool isEmpty() const
0389     {
0390         if(fDynamicBuffer==0)
0391         {
0392             for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
0393             {
0394                 if (fBits[index] != 0)
0395                     return false;
0396             }
0397         }
0398         else
0399         {
0400             for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
0401             {
0402                 if(fDynamicBuffer->fBitArray[index]==NULL)
0403                     continue;
0404                 for(XMLSize_t subIndex=0;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
0405                 {
0406                     if (fDynamicBuffer->fBitArray[index][subIndex] != 0)
0407                         return false;
0408                 }
0409             }
0410         }
0411         return true;
0412     }
0413 
0414     void setBit(const XMLSize_t bitToSet)
0415     {
0416         if (bitToSet >= fBitCount)
0417         {
0418             if(fDynamicBuffer)
0419                 ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Bitset_BadIndex, fDynamicBuffer->fMemoryManager);
0420             else
0421                 ThrowXML(ArrayIndexOutOfBoundsException, XMLExcepts::Bitset_BadIndex);
0422         }
0423 
0424         const XMLInt32 mask = 1UL << (bitToSet % 32);
0425 
0426         // And access the right bit and byte
0427         if(fDynamicBuffer==0)
0428         {
0429             const XMLSize_t byteOfs = bitToSet / 32;
0430             fBits[byteOfs] &= ~mask;
0431             fBits[byteOfs] |= mask;
0432         }
0433         else
0434         {
0435             const XMLSize_t vectorOfs = bitToSet / CMSTATE_BITFIELD_CHUNK;
0436             if(fDynamicBuffer->fBitArray[vectorOfs]==NULL)
0437             {
0438                 allocateChunk(vectorOfs);
0439                 for(XMLSize_t index=0;index < CMSTATE_BITFIELD_INT32_SIZE; index++)
0440                     fDynamicBuffer->fBitArray[vectorOfs][index]=0;
0441             }
0442             const XMLSize_t byteOfs = (bitToSet % CMSTATE_BITFIELD_CHUNK) / 32;
0443             fDynamicBuffer->fBitArray[vectorOfs][byteOfs] &= ~mask;
0444             fDynamicBuffer->fBitArray[vectorOfs][byteOfs] |= mask;
0445         }
0446     }
0447 
0448     void zeroBits()
0449     {
0450         if(fDynamicBuffer==0)
0451         {
0452             for (XMLSize_t index = 0; index < CMSTATE_CACHED_INT32_SIZE; index++)
0453                 fBits[index] = 0;
0454         }
0455         else
0456         {
0457             for (XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
0458                 // delete this subentry
0459                 if(fDynamicBuffer->fBitArray[index]!=NULL)
0460                     deallocateChunk(index);
0461         }
0462     }
0463 
0464     XMLSize_t hashCode() const
0465     {
0466         XMLSize_t hash = 0;
0467         if(fDynamicBuffer==0)
0468         {
0469             for (XMLSize_t index = 0; index<CMSTATE_CACHED_INT32_SIZE; index++)
0470                 hash = fBits[index] + hash * 31;
0471         }
0472         else
0473         {
0474             for (XMLSize_t index = 0; index<fDynamicBuffer->fArraySize; index++)
0475             {
0476                 if(fDynamicBuffer->fBitArray[index]==NULL)
0477                     // simulates the iteration on the missing bits
0478                     for(XMLSize_t subIndex=0;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
0479                         hash *= 31;
0480                 else
0481                     for(XMLSize_t subIndex=0;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
0482                         hash = fDynamicBuffer->fBitArray[index][subIndex] + hash * 31;
0483             }
0484         }
0485         return hash;
0486     }
0487 
0488 private :
0489     // -----------------------------------------------------------------------
0490     //  Unimplemented constructors and operators
0491     // -----------------------------------------------------------------------
0492     CMStateSet();
0493 
0494     // -----------------------------------------------------------------------
0495     // Helpers
0496     // -----------------------------------------------------------------------
0497     void allocateChunk(const XMLSize_t index)
0498     {
0499 #ifdef XERCES_HAVE_SSE2_INTRINSIC
0500         if(XMLPlatformUtils::fgSSE2ok)
0501             fDynamicBuffer->fBitArray[index]=(XMLInt32*)_mm_malloc(CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32), 16);
0502         else
0503 #endif
0504             fDynamicBuffer->fBitArray[index]=(XMLInt32*)fDynamicBuffer->fMemoryManager->allocate(CMSTATE_BITFIELD_INT32_SIZE * sizeof(XMLInt32));
0505     }
0506 
0507     void deallocateChunk(const XMLSize_t index)
0508     {
0509 #ifdef XERCES_HAVE_SSE2_INTRINSIC
0510         if(XMLPlatformUtils::fgSSE2ok)
0511             _mm_free(fDynamicBuffer->fBitArray[index]);
0512         else
0513 #endif
0514             fDynamicBuffer->fMemoryManager->deallocate(fDynamicBuffer->fBitArray[index]);
0515         fDynamicBuffer->fBitArray[index]=NULL;
0516     }
0517 
0518     // -----------------------------------------------------------------------
0519     //  Private data members
0520     //
0521     //  fBitCount
0522     //      The count of bits that the outside world wants to support,
0523     //      so its the max bit index plus one.
0524     //
0525     //  fBits
0526     //      When the bit count is less than a threshold (very common), these hold the bits.
0527     //      Otherwise, the fDynamicBuffer member holds htem.
0528     //
0529     //  fDynamicBuffer
0530     //      If the bit count is greater than the threshold, then we allocate this structure to
0531     //      store the bits, the length, and the memory manager to allocate/deallocate
0532     //      the memory
0533     //
0534     // -----------------------------------------------------------------------
0535     XMLSize_t        fBitCount;
0536     XMLInt32         fBits[CMSTATE_CACHED_INT32_SIZE];
0537     CMDynamicBuffer* fDynamicBuffer;
0538 
0539     friend class CMStateSetEnumerator;
0540 };
0541 
0542 class CMStateSetEnumerator : public XMemory
0543 {
0544 public:
0545     CMStateSetEnumerator(const CMStateSet* toEnum, XMLSize_t start = 0) :
0546       fToEnum(toEnum),
0547       fIndexCount((XMLSize_t)-1),
0548       fLastValue(0)
0549     {
0550         // if a starting bit is specified, place fIndexCount at the beginning of the previous 32 bit area
0551         // so the findNext moves to the one where 'start' is located
0552         if(start > 32)
0553             fIndexCount = (start/32 - 1) * 32;
0554         findNext();
0555         // if we found data, and fIndexCount is still pointing to the area where 'start' is located, erase the bits before 'start'
0556         if(hasMoreElements() && fIndexCount < start)
0557         {
0558             for(XMLSize_t i=0;i< (start - fIndexCount);i++)
0559             {
0560                 XMLInt32 mask=1UL << i;
0561                 if(fLastValue & mask)
0562                     fLastValue &= ~mask;
0563             }
0564             // in case the 32 bit area contained only bits before 'start', advance
0565             if(fLastValue==0)
0566                 findNext();
0567         }
0568     }
0569 
0570     bool hasMoreElements()
0571     {
0572         return fLastValue!=0;
0573     }
0574 
0575     unsigned int nextElement()
0576     {
0577         for(int i=0;i<32;i++)
0578         {
0579             XMLInt32 mask=1UL << i;
0580             if(fLastValue & mask)
0581             {
0582                 fLastValue &= ~mask;
0583                 unsigned int retVal=(unsigned int)fIndexCount+i;
0584                 if(fLastValue==0)
0585                     findNext();
0586                 return retVal;
0587             }
0588         }
0589         return 0;
0590     }
0591 
0592 private:
0593     void findNext()
0594     {
0595         if(fToEnum->fDynamicBuffer==0)
0596         {
0597             XMLSize_t nOffset=((fIndexCount==(XMLSize_t)-1)?0:(fIndexCount/32)+1);
0598             for(XMLSize_t index=nOffset;index<CMSTATE_CACHED_INT32_SIZE;index++)
0599             {
0600                 if(fToEnum->fBits[index]!=0)
0601                 {
0602                     fIndexCount=index*32;
0603                     fLastValue=fToEnum->fBits[index];
0604                     return;
0605                 }
0606             }
0607         }
0608         else
0609         {
0610             XMLSize_t nOffset=((fIndexCount==(XMLSize_t)-1)?0:(fIndexCount/CMSTATE_BITFIELD_CHUNK));
0611             XMLSize_t nSubOffset=((fIndexCount==(XMLSize_t)-1)?0:((fIndexCount % CMSTATE_BITFIELD_CHUNK) /32)+1);
0612             for (XMLSize_t index = nOffset; index<fToEnum->fDynamicBuffer->fArraySize; index++)
0613             {
0614                 if(fToEnum->fDynamicBuffer->fBitArray[index]!=NULL)
0615                 {
0616                     for(XMLSize_t subIndex=nSubOffset;subIndex < CMSTATE_BITFIELD_INT32_SIZE; subIndex++)
0617                         if(fToEnum->fDynamicBuffer->fBitArray[index][subIndex]!=0)
0618                         {
0619                             fIndexCount=index*CMSTATE_BITFIELD_CHUNK + subIndex*32;
0620                             fLastValue=fToEnum->fDynamicBuffer->fBitArray[index][subIndex];
0621                             return;
0622                         }
0623                 }
0624                 nSubOffset = 0; // next chunks will be processed from the beginning
0625             }
0626         }
0627     }
0628 
0629     const CMStateSet*   fToEnum;
0630     XMLSize_t           fIndexCount;
0631     XMLInt32            fLastValue;
0632 };
0633 
0634 XERCES_CPP_NAMESPACE_END
0635 
0636 #endif