1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xerces.internal.impl.dtd.models;
23
24
25/**
26 * This class is a very simple bitset class. The DFA content model code needs
27 * to support a bit set, but the java BitSet class is way, way overkill. Our
28 * bitset never needs to be expanded after creation, hash itself, etc...
29 *
30 * Since the vast majority of content models will never require more than 64
31 * bits, and since allocation of anything in Java is expensive, this class
32 * provides a hybrid implementation that uses two ints for instances that use
33 * 64 bits or fewer. It has a byte array reference member which will only be
34 * used if more than 64 bits are required.
35 *
36 * Note that the code that uses this class will never perform operations
37 * on sets of different sizes, so that check does not have to be made here.
38 *
39 * @xerces.internal
40 *
41 */
42// made this class public so it can be accessed by
43// the XS content models from the schema package -neilg.
44public class CMStateSet
45{
46    // -------------------------------------------------------------------
47    //  Constructors
48    // -------------------------------------------------------------------
49    public CMStateSet(int bitCount)
50    {
51        // Store the required bit count and insure its legal
52        fBitCount = bitCount;
53        if (fBitCount < 0)
54            throw new RuntimeException("ImplementationMessages.VAL_CMSI");
55
56        //
57        //  See if we need to allocate the byte array or whether we can live
58        //  within the 64 bit high performance scheme.
59        //
60        if (fBitCount > 64)
61        {
62            fByteCount = fBitCount / 8;
63            if (fBitCount % 8 != 0)
64                fByteCount++;
65            fByteArray = new byte[fByteCount];
66        }
67
68        // Init all the bits to zero
69        zeroBits();
70    }
71
72
73    // -------------------------------------------------------------------
74    //  Public inherited methods
75    // -------------------------------------------------------------------
76    public String toString()
77    {
78        StringBuffer strRet = new StringBuffer();
79        try
80        {
81            strRet.append("{");
82            for (int index = 0; index < fBitCount; index++)
83            {
84                if (getBit(index))
85                    strRet.append(" " + index);
86            }
87            strRet.append(" }");
88        }
89
90        catch(RuntimeException exToCatch)
91        {
92            //
93            //  We know this won't happen but we have to catch it to avoid it
94            //  having to be in our 'throws' list.
95            //
96        }
97        return strRet.toString();
98    }
99
100
101    // -------------------------------------------------------------------
102    //  Package final methods
103    // -------------------------------------------------------------------
104// the XS content models from the schema package -neilg.
105    public final void intersection(CMStateSet setToAnd)
106    {
107        if (fBitCount < 65)
108        {
109            fBits1 &= setToAnd.fBits1;
110            fBits2 &= setToAnd.fBits2;
111        }
112         else
113        {
114            for (int index = fByteCount - 1; index >= 0; index--)
115                fByteArray[index] &= setToAnd.fByteArray[index];
116        }
117    }
118
119    public final boolean getBit(int bitToGet)
120    {
121        if (bitToGet >= fBitCount)
122            throw new RuntimeException("ImplementationMessages.VAL_CMSI");
123
124        if (fBitCount < 65)
125        {
126            final int mask = (0x1 << (bitToGet % 32));
127            if (bitToGet < 32)
128                return (fBits1 & mask) != 0;
129            else
130                return (fBits2 & mask) != 0;
131        }
132         else
133        {
134            // Create the mask and byte values
135            final byte mask = (byte)(0x1 << (bitToGet % 8));
136            final int ofs = bitToGet >> 3;
137
138            // And access the right bit and byte
139            return ((fByteArray[ofs] & mask) != 0);
140        }
141    }
142
143    public final boolean isEmpty()
144    {
145        if (fBitCount < 65)
146        {
147            return ((fBits1 == 0) && (fBits2 == 0));
148        }
149         else
150        {
151            for (int index = fByteCount - 1; index >= 0; index--)
152            {
153                if (fByteArray[index] != 0)
154                    return false;
155            }
156        }
157        return true;
158    }
159
160    final boolean isSameSet(CMStateSet setToCompare)
161    {
162        if (fBitCount != setToCompare.fBitCount)
163            return false;
164
165        if (fBitCount < 65)
166        {
167            return ((fBits1 == setToCompare.fBits1)
168            &&      (fBits2 == setToCompare.fBits2));
169        }
170
171        for (int index = fByteCount - 1; index >= 0; index--)
172        {
173            if (fByteArray[index] != setToCompare.fByteArray[index])
174                return false;
175        }
176        return true;
177    }
178
179// the XS content models from the schema package -neilg.
180    public final void union(CMStateSet setToOr)
181    {
182        if (fBitCount < 65)
183        {
184            fBits1 |= setToOr.fBits1;
185            fBits2 |= setToOr.fBits2;
186        }
187         else
188        {
189            for (int index = fByteCount - 1; index >= 0; index--)
190                fByteArray[index] |= setToOr.fByteArray[index];
191        }
192    }
193
194    public final void setBit(int bitToSet)
195    {
196        if (bitToSet >= fBitCount)
197            throw new RuntimeException("ImplementationMessages.VAL_CMSI");
198
199        if (fBitCount < 65)
200        {
201            final int mask = (0x1 << (bitToSet % 32));
202            if (bitToSet < 32)
203            {
204                fBits1 &= ~mask;
205                fBits1 |= mask;
206            }
207             else
208            {
209                fBits2 &= ~mask;
210                fBits2 |= mask;
211            }
212        }
213         else
214        {
215            // Create the mask and byte values
216            final byte mask = (byte)(0x1 << (bitToSet % 8));
217            final int ofs = bitToSet >> 3;
218
219            // And access the right bit and byte
220            fByteArray[ofs] &= ~mask;
221            fByteArray[ofs] |= mask;
222        }
223    }
224
225// the XS content models from the schema package -neilg.
226    public final void setTo(CMStateSet srcSet)
227    {
228        // They have to be the same size
229        if (fBitCount != srcSet.fBitCount)
230            throw new RuntimeException("ImplementationMessages.VAL_CMSI");
231
232        if (fBitCount < 65)
233        {
234            fBits1 = srcSet.fBits1;
235            fBits2 = srcSet.fBits2;
236        }
237         else
238        {
239            for (int index = fByteCount - 1; index >= 0; index--)
240                fByteArray[index] = srcSet.fByteArray[index];
241        }
242    }
243
244    // had to make this method public so it could be accessed from
245    // schema package - neilg.
246    public final void zeroBits()
247    {
248        if (fBitCount < 65)
249        {
250            fBits1 = 0;
251            fBits2 = 0;
252        }
253         else
254        {
255            for (int index = fByteCount - 1; index >= 0; index--)
256                fByteArray[index] = 0;
257        }
258    }
259
260
261    // -------------------------------------------------------------------
262    //  Private data members
263    //
264    //  fBitCount
265    //      The count of bits that the outside world wants to support,
266    //      so its the max bit index plus one.
267    //
268    //  fByteCount
269    //      If the bit count is > 64, then we use the fByteArray member to
270    //      store the bits, and this indicates its size in bytes. Otherwise
271    //      its value is meaningless.
272    //
273    //  fBits1
274    //  fBits2
275    //      When the bit count is < 64 (very common), these hold the bits.
276    //      Otherwise, the fByteArray member holds htem.
277    // -------------------------------------------------------------------
278    int         fBitCount;
279    int         fByteCount;
280    int         fBits1;
281    int         fBits2;
282    byte[]      fByteArray;
283    /* Optimization(Jan, 2001) */
284    public boolean equals(Object o) {
285        if (!(o instanceof CMStateSet)) return false;
286        return isSameSet((CMStateSet)o);
287    }
288
289    public int hashCode() {
290        if (fBitCount < 65)
291        {
292            return fBits1+ fBits2 * 31;
293        }
294         else
295        {
296            int hash = 0;
297            for (int index = fByteCount - 1; index >= 0; index--)
298                hash = fByteArray[index] + hash * 31;
299            return hash;
300        }
301    }
302   /* Optimization(Jan, 2001) */
303};
304