summaryrefslogtreecommitdiff
path: root/dicore3/core/src/main/java/io/dico/dicore/BitModifier.java
blob: ae251236a86d1240b6b6dd8e171130df00ea621d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package io.dico.dicore;

public interface BitModifier {
    
    long mask();
    
    long get(long x);
    
    long set(long x, long value);
    
    default int lowerBound() {
        return Long.numberOfTrailingZeros(mask());
    }
    
    default int upperBound() {
        return 64 - Long.numberOfLeadingZeros(mask());
    }
    
    default int bitCount() {
        return Long.bitCount(mask());
    }
    
    default boolean getBoolean(long x) {
        return get(x) == 1;
    }
    
    default long setBoolean(long x, boolean value) {
        return set(x, value ? 1 : 0);
    }
    
    default int getInt(long x) {
        return (int) (get(x) & 0xFFFFFFFFL);
    }
    
    default long setInt(long x, int value) {
        return set(x, value & 0xFFFFFFFFL);
    }
    
    default short getShort(long x) {
        return (short) (get(x) & 0xFFFFL);
    }
    
    default long setShort(long x, int value) {
        return set(x, value & 0xFFFFL);
    }
    
    default byte getByte(long x) {
        return (byte) (get(x) & 0xFFL);
    }
    
    default long setByte(long x, int value) {
        return set(x, value & 0xFFL);
    }
    
    final class OfSingle implements BitModifier {
        private final long mask;
        
        public OfSingle(int bit) {
            if (bit < 0 || bit >= 64) {
                throw new IndexOutOfBoundsException();
            }
            this.mask = 1L << bit;
        }
        
        @Override
        public int bitCount() {
            return 1;
        }
        
        @Override
        public long mask() {
            return mask;
        }
        
        public boolean getBoolean(long x) {
            return (x & mask) != 0;
        }
        
        public long setBoolean(long x, boolean value) {
            return value ? (x | mask) : (x & ~mask);
        }
        
        @Override
        public long get(long x) {
            return getBoolean(x) ? 1 : 0;
        }
        
        @Override
        public long set(long x, long value) {
            if (value < 0 || value > 1) {
                throw new IllegalArgumentException();
            }
            return setBoolean(x, value == 1);
        }
    }
    
    final class OfMultiple implements BitModifier {
        private final int lowerBound;
        private final int bitCount;
        private final long mask;
        
        public OfMultiple(int lowerBound, int bitCount) {
            int upperBound = lowerBound + bitCount;
            if (lowerBound < 0 || lowerBound >= 64 || upperBound < 1 || upperBound > 64 || upperBound < lowerBound) {
                throw new IndexOutOfBoundsException();
            }
            this.lowerBound = lowerBound;
            this.bitCount = bitCount;
            this.mask = (Long.MIN_VALUE >> (bitCount - 1)) >>> (64 - bitCount - lowerBound);
        }
        
        @Override
        public int lowerBound() {
            return lowerBound;
        }
        
        @Override
        public int bitCount() {
            return bitCount;
        }
        
        @Override
        public int upperBound() {
            return lowerBound + bitCount;
        }
        
        @Override
        public long mask() {
            return mask;
        }
        
        @Override
        public long get(long x) {
            return (x & mask) >>> lowerBound;
        }
        
        @Override
        public long set(long x, long value) {
            return (x & ~mask) | ((value << lowerBound) & mask);
        }
        
    }
    
    class Builder {
        int currentIndex;
    
        public int getCurrentIndex() {
            return currentIndex;
        }
        
        public int getRemaining() {
            return 64 - currentIndex;
        }
        
        public OfSingle single() {
            checkAvailable(1);
            return new OfSingle(currentIndex++);
        }
        
        public BitModifier size(int size) {
            if (size == 1) {
                return single();
            }
            checkAvailable(size);
            BitModifier result = new OfMultiple(currentIndex, size);
            currentIndex += size;
            return result;
        }
        
        public BitModifier remaining() {
            return size(getRemaining());
        }
        
        private void checkAvailable(int size) {
            if (size <= 0 || currentIndex + size > 64) {
                throw new IllegalStateException("Exceeding bit count of a long");
            }
        }
        
    }
    
}