1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.databinding.tool.writer; 18 19 import java.util.BitSet; 20 21 /** 22 * Used for code generation. A BitSet can be converted into a flag set, 23 * which is basically a list of longs that can be divided into pieces. 24 */ 25 public class FlagSet { 26 public static final int sBucketSize = 64;// long 27 public final String type; 28 public final long[] buckets; 29 private String mLocalName; 30 private boolean mIsDynamic = false; 31 FlagSet(BitSet bitSet, int bucketCount)32 public FlagSet(BitSet bitSet, int bucketCount) { 33 buckets = new long[bucketCount]; 34 for (int i = bitSet.nextSetBit(0); 35 i != -1; i = bitSet.nextSetBit(i + 1)) { 36 buckets[i / sBucketSize] |= 1L << (i % sBucketSize); 37 } 38 type = "long"; 39 } 40 FlagSet(long[] buckets)41 public FlagSet(long[] buckets) { 42 this.buckets = new long[buckets.length]; 43 System.arraycopy(buckets, 0, this.buckets, 0, buckets.length); 44 type = "long"; 45 } 46 FlagSet(long[] buckets, int minBucketCount)47 public FlagSet(long[] buckets, int minBucketCount) { 48 this.buckets = new long[Math.max(buckets.length, minBucketCount)]; 49 System.arraycopy(buckets, 0, this.buckets, 0, buckets.length); 50 type = "long"; 51 } 52 FlagSet(int... bits)53 public FlagSet(int... bits) { 54 int max = 0; 55 for (int i = 0 ; i < bits.length; i ++) { 56 max = Math.max(i, bits[i]); 57 } 58 buckets = new long[1 + (max / sBucketSize)]; 59 for (int x = 0 ; x < bits.length; x ++) { 60 final int i = bits[x]; 61 buckets[i / sBucketSize] |= 1L << (i % sBucketSize); 62 } 63 type = "long"; 64 } 65 intersect(FlagSet other, int bucketIndex)66 public boolean intersect(FlagSet other, int bucketIndex) { 67 return (buckets[bucketIndex] & other.buckets[bucketIndex]) != 0; 68 } 69 getLocalName()70 public String getLocalName() { 71 return mLocalName; 72 } 73 setLocalName(String localName)74 public void setLocalName(String localName) { 75 mLocalName = localName; 76 } 77 hasLocalName()78 public boolean hasLocalName() { 79 return mLocalName != null; 80 } 81 isDynamic()82 public boolean isDynamic() { 83 return mIsDynamic; 84 } 85 setDynamic(boolean isDynamic)86 public void setDynamic(boolean isDynamic) { 87 mIsDynamic = isDynamic; 88 } 89 andNot(FlagSet other)90 public FlagSet andNot(FlagSet other) { 91 FlagSet result = new FlagSet(buckets); 92 final int min = Math.min(buckets.length, other.buckets.length); 93 for (int i = 0; i < min; i ++) { 94 result.buckets[i] &= ~(other.buckets[i]); 95 } 96 return result; 97 } 98 or(FlagSet other)99 public FlagSet or(FlagSet other) { 100 final FlagSet result = new FlagSet(buckets, other.buckets.length); 101 for (int i = 0; i < other.buckets.length; i ++) { 102 result.buckets[i] |= other.buckets[i]; 103 } 104 return result; 105 } 106 isEmpty()107 public boolean isEmpty() { 108 for (int i = 0; i < buckets.length; i ++) { 109 if (buckets[i] != 0) { 110 return false; 111 } 112 } 113 return true; 114 } 115 116 @Override toString()117 public String toString() { 118 StringBuilder sb = new StringBuilder(); 119 for (int i = 0; i < buckets.length; i ++) { 120 sb.append(Long.toBinaryString(buckets[i])).append(" "); 121 } 122 return sb.toString(); 123 } 124 getBucket(int bucketIndex)125 private long getBucket(int bucketIndex) { 126 if (bucketIndex >= buckets.length) { 127 return 0; 128 } 129 return buckets[bucketIndex]; 130 } 131 bitsEqual(FlagSet other)132 public boolean bitsEqual(FlagSet other) { 133 final int max = Math.max(buckets.length, other.buckets.length); 134 for (int i = 0; i < max; i ++) { 135 if (getBucket(i) != other.getBucket(i)) { 136 return false; 137 } 138 } 139 return true; 140 } 141 142 @Override hashCode()143 public int hashCode() { 144 int hash = 1; 145 for (long bucket : buckets) { 146 hash = (hash * 7) ^ (int)(bucket >>> 32); 147 hash = (hash * 13) ^ (int)(bucket & 0xFFFF); 148 } 149 return hash; 150 } 151 152 @Override equals(Object obj)153 public boolean equals(Object obj) { 154 if (obj instanceof FlagSet) { 155 FlagSet other = (FlagSet) obj; 156 if (other.buckets.length != buckets.length) { 157 return false; 158 } 159 for (int i = 0; i < buckets.length; i++) { 160 if (buckets[i] != other.buckets[i]) { 161 return false; 162 } 163 } 164 return true; 165 } else { 166 return false; 167 } 168 } 169 } 170