internal BitIndexEnumerator(BitIndexImpl index, int setBits, int clearBits)
#endif
            {
                sp      = 0;
                counter = index.updateCounter;
                int h = index.height;

                if (h == 0)
                {
                    return;
                }
                db = (StorageImpl)index.Storage;
                if (db == null)
                {
                    throw new StorageError(StorageError.ErrorCode.DELETED_OBJECT);
                }
                this.index     = index;
                this.setBits   = setBits;
                this.clearBits = clearBits;

                pageStack = new int[h];
                posStack  = new int[h];

                Reset();
            }
            internal BitIndexEnumerable(BitIndexImpl index, int setBits, int clearBits)
#endif
            {
                this.index     = index;
                this.setBits   = setBits;
                this.clearBits = clearBits;
            }
 internal BitIndexEnumerator(BitIndexImpl <T> index, int setBits, int clearBits)
        internal void  createIndex(String indexType)
        {
            XMLScanner.Token tkn;
            int oid = 0;
            bool     unique = false;
            String   className = null;
            String   fieldName = null;
            String[] fieldNames = null;
            long     autoinc = 0;
            String   type = null;
            ClassDescriptor.FieldType[] types = null;

            while ((tkn = scanner.scan()) == XMLScanner.Token.IDENT)
            {
                string attrName = scanner.Identifier;
                if (scanner.scan() != XMLScanner.Token.EQ || scanner.scan() != XMLScanner.Token.SCONST)
                {
                    throwException("Attribute value expected");
                }
                string attrValue = scanner.String;
                if (attrName.Equals("id"))
                {
                    oid = mapId(parseInt(attrValue));
                }
                else if (attrName.Equals("unique"))
                {
                    unique = parseInt(attrValue) != 0;
                }
                else if (attrName.Equals("class"))
                {
                    className = attrValue;
                }
                else if (attrName.Equals("type"))
                {
                    type = attrValue;
                }
                else if (attrName.Equals("autoinc"))
                {
                    autoinc = parseInt(attrValue);
                }
                else if (attrName.Equals("field"))
                {
                    fieldName = attrValue;
                }
                else if (attrName.StartsWith("field"))
                {
                    int fieldNo = Int32.Parse(attrName.Substring(5));
                    if (fieldNames == null || fieldNames.Length <= fieldNo) 
                    { 
                        String[] newFieldNames = new String[fieldNo+1];
                        if (fieldNames != null) 
                        { 
                            Array.Copy(fieldNames, 0, newFieldNames, 0, fieldNames.Length);
                        }
                        fieldNames = newFieldNames;
                     }
                     fieldNames[fieldNo] = attrValue;
                }
                else if (attrName.StartsWith("type"))
                {
                    int typeNo = Int32.Parse(attrName.Substring(4));
                    if (types == null || types.Length <= typeNo) 
                    { 
                        ClassDescriptor.FieldType[] newTypes = new ClassDescriptor.FieldType[typeNo+1];
                        if (types != null) 
                        { 
                            Array.Copy(types, 0, newTypes, 0, types.Length);
                        }
                        types = newTypes;
                     }
                     types[typeNo] = mapType(attrValue);
                }
            }
            if (tkn != XMLScanner.Token.GT)
            {
                throwException("Unclosed element tag");
            }
            if (oid == 0)
            {
                throwException("ID is not specified or index");
            }
#if USE_GENERICS
            ClassDescriptor desc = storage.getClassDescriptor(findClassByName(indexType));
            Btree btree = (Btree)desc.newInstance();
#else
            Btree btree = null;
#endif            
            if (className != null)
            {
                Type cls = findClassByName(className);
                if (fieldName != null) 
                { 
#if USE_GENERICS
                    btree.init(cls, null, new string[]{fieldName}, unique, autoinc);
#else
                    btree = indexType.StartsWith("Perst.Impl.BtreeCaseInsensitiveFieldIndex")
                        ? (Btree)new BtreeCaseInsensitiveFieldIndex(cls, fieldName, unique, autoinc)
                        : (Btree)new BtreeFieldIndex(cls, fieldName, unique, autoinc);
#endif
                } 
                else if (fieldNames != null) 
                { 
#if USE_GENERICS
                    btree.init(cls, null, fieldNames, unique, autoinc);
#else
                    btree = indexType.StartsWith("Perst.Impl.BtreeCaseInsensitiveMultiFieldIndex")
                        ? (Btree)new BtreeCaseInsensitiveMultiFieldIndex(cls, fieldNames, unique)
                        : (Btree)new BtreeMultiFieldIndex(cls, fieldNames, unique);
#endif
                } 
                else
                {
                    throwException("Field name is not specified for field index");
                }
            }
            else
            {
                if (types != null) 
                { 
#if USE_GENERICS
                    btree.init(null, types, null, unique, autoinc);
#else
                    btree = new BtreeCompoundIndex(types, unique);
#endif
                } 
                else if (type == null)
                {
                    if (indexType.StartsWith("Perst.Impl.PersistentSet")) 
                    { 
#if !USE_GENERICS
                        btree = new PersistentSet(unique);
#endif
                    } 
                    else 
                    {
                        throwException("Key type is not specified for index");
                    }
                } 
                else 
                {
                    if (indexType.StartsWith("org.garret.perst.impl.BitIndexImpl")) 
                    { 
#if !USE_GENERICS
                        btree = new BitIndexImpl();
#endif
                    } 
                    else 
                    { 
#if USE_GENERICS
                        btree.init(null, new ClassDescriptor.FieldType[]{mapType(type)}, null, unique, autoinc);
#else
                        btree = new Btree(mapType(type), unique);
#endif
                    }
                }
            }
            storage.AssignOid(btree, oid, false);
			
            while ((tkn = scanner.scan()) == XMLScanner.Token.LT)
            {
                if (scanner.scan() != XMLScanner.Token.IDENT || !scanner.Identifier.Equals("ref"))
                {
                    throwException("<ref> element expected");
                }
                XMLElement refElem = readElement("ref");
                Key key;
                if (fieldNames != null) 
                { 
                    String[] values = new String[fieldNames.Length];                
#if USE_GENERICS
                    types = btree.FieldTypes;
#else
                    types = ((BtreeMultiFieldIndex)btree).types;
#endif
                    for (int i = 0; i < values.Length; i++) 
                    { 
                        values[i] = getAttribute(refElem, "key"+i);
                    }
                    key = createCompoundKey(types, values);
                } 
                else if (types != null) 
                { 
                    String[] values = new String[fieldNames.Length];                
                    for (int i = 0; i < values.Length; i++) 
                    { 
                        values[i] = getAttribute(refElem, "key"+i);
                    }
                    key = createCompoundKey(types, values);
                } 
                else 
                { 
                    key = createKey(btree.FieldType, getAttribute(refElem, "key"));
                }
                object obj = new PersistentStub(storage, mapId(getIntAttribute(refElem, "id")));
                btree.insert(key, obj, false);
            }
            if (tkn != XMLScanner.Token.LTS 
                || scanner.scan() != XMLScanner.Token.IDENT 
                || !scanner.Identifier.Equals(indexType) 
                || scanner.scan() != XMLScanner.Token.GT)
            {
                throwException("Element is not closed");
            }
#if USE_GENERICS
            ByteBuffer buf = new ByteBuffer();
            buf.extend(ObjectHeader.Sizeof);
            int size = storage.packObject(btree, desc, ObjectHeader.Sizeof, buf);
            byte[] data = buf.arr;
            ObjectHeader.setSize(data, 0, size);
            ObjectHeader.setType(data, 0, desc.Oid);
#else
            byte[] data = storage.packObject(btree, false);
            int size = ObjectHeader.getSize(data, 0);
#endif
            long pos = storage.allocate(size, 0);
            storage.setPos(oid, pos | StorageImpl.dbModifiedFlag);
			
            storage.pool.put(pos & ~ StorageImpl.dbFlagsMask, data, size);
        }