static Bitset() { for(int i = 0; i < categoryBits.Length; i++) categoryBits[i] = new Block[BLOCK_COUNT]; for(int i=char.MinValue;i<=char.MaxValue;i++){ int cat=(int)char.GetUnicodeCategory((char)i); int blockNo=(i>>8)&0xff; Block b=categoryBits[cat][blockNo]; if(b==null) categoryBits[cat][blockNo] = b = new Block(); b.Set(i&0xff); } }
private static int Subtract(Block target, Block subtrahend, bool inv) { bool[] targetbits,subbits; if(subtrahend.isFull){ if(inv) return 0; int s=0; if(target.isFull){ s=BLOCK_SIZE; } else{ s=Count(target.bits,0,BLOCK_SIZE-1); } target.isFull=false; target.bits=null; target.shared=false; return s; } else if((subbits=subtrahend.bits)==null){ if(!inv) return 0; int s=0; if(target.isFull){ s=BLOCK_SIZE; } else{ s=Count(target.bits,0,BLOCK_SIZE-1); } target.isFull=false; target.bits=null; target.shared=false; return s; } else{ if(target.isFull){ bool[] bits=FullBits(target.bits); int s=Bitset.Subtract(bits,subbits,0,BLOCK_SIZE-1,inv); target.isFull=false; target.shared=false; target.bits=bits; return s; } else{ if(target.shared) targetbits=CopyBits(target); else targetbits=target.bits; return Bitset.Subtract(targetbits,subbits,0,BLOCK_SIZE-1,inv); } } }
private static bool[] CopyBits(Block block) { bool[] bits = new bool[BLOCK_SIZE]; Array.Copy(block.bits,bits,BLOCK_SIZE); block.bits=bits; block.shared=false; return bits; }
private static int Add(Block target, Block addend, bool inv) { bool[] targetbits,addbits; if(addend==null){ if(!inv) return 0; int s=BLOCK_SIZE; if((targetbits=target.bits)!=null){ s -= Count(targetbits,0,BLOCK_SIZE-1); } target.isFull=true; target.bits=null; target.shared=false; return s; } else if(addend.isFull){ if(inv) return 0; int s=BLOCK_SIZE; if((targetbits=target.bits)!=null){ s -= Count(targetbits,0,BLOCK_SIZE-1); } target.isFull=true; target.bits=null; target.shared=false; return s; } else if((addbits=addend.bits)==null){ if(!inv) return 0; int s=BLOCK_SIZE; if((targetbits=target.bits)!=null){ s -= Count(targetbits,0,BLOCK_SIZE-1); } target.isFull=true; target.bits=null; target.shared=false; return s; } else{ if((targetbits=target.bits)==null){ if(!inv){ target.bits=addbits; target.shared=true; return Count(addbits,0,BLOCK_SIZE-1); } else{ target.bits=targetbits=EmptyBits(null); target.shared=false; return Bitset.Add(targetbits,addbits,0,BLOCK_SIZE-1,inv); } } else{ if(target.shared) targetbits=CopyBits(target); return Bitset.Add(targetbits,addbits,0,BLOCK_SIZE-1,inv); } } }
internal static bool[][] ToBitset2(Block[] blocks) { int len=blocks.Length; bool[][] result=new bool[len][]; for(int i=0;i<len;i++){ Block block=blocks[i]; if(block==null) continue; if(block.isFull){ result[i]=FULL_BITS; } else result[i]=block.bits; } return result; }
internal static int Subtract(Block[] targets,Block[] subtrahends,int from,int to,bool inv) { int s=0; for(int i=from;i<=to;i++){ Block target=targets[i]; if(target==null || (!target.isFull && target.bits==null)) continue; Block subtrahend=subtrahends[i]; if(subtrahend==null){ if(!inv) continue; else{ if(target.isFull){ s-=BLOCK_SIZE; } else{ s-=Count(target.bits,0,BLOCK_SIZE-1); } target.isFull=false; target.bits=null; target.shared=false; } } else{ s+=Subtract(target,subtrahend,inv); } } return s; }
internal static int Add(Block[] targets, Block[] addends, int from, int to, bool inv) { int s=0; for(int i=from;i<=to;i++){ Block addend=addends[i]; if(addend==null){ if(!inv) continue; } else if(addend.isFull && inv) continue; Block target=targets[i]; if(target==null) targets[i]=target=new Block(); else if(target.isFull) continue; s+=Add(target,addend,inv); } return s; }
private void EnableLargeMode() { if(isLarge) return; Block[] blocks = new Block[BLOCK_COUNT]; this.blocks = blocks; if(block0 != null) { blocks[0] = new Block(block0); } isLarge = true; }
internal void SetRange(char c1, char c2) { if(c2>=256 || isLarge){ int s=0; if(!isLarge){ EnableLargeMode(); } Block[] blocks = this.blocks; for(int c=c1;c<=c2;c++){ int i2=(c>>8)&0xff; int i=c&0xff; Block block = blocks[i2]; if(block == null){ blocks[i2] = block =new Block(); } if(block.Set(i)) s++; } weight+=s; } else { bool[] block0 = this.block0; if(block0 == null){ this.block0 = block0 = new bool[BLOCK_SIZE]; } weight += Set(block0,true,c1,c2); } }