View Javadoc
1   /*
2    * License : The MIT License
3    * Copyright(c) 2022 Olyutorskii
4    */
5   
6   package io.github.olyutorskii.aletojio.idling;
7   
8   import java.util.BitSet;
9   
10  /**
11   * Monitor the occurrence of consecutive unique byte values.
12   */
13  public class UniqRunMonitor extends AbstractRndMonitor {
14  
15      private static final int CARDINALITY_BYTE = 1 << Byte.SIZE;
16      private static final int MASK_BYTE = (1 << Byte.SIZE) - 1;
17  
18      private static final int DEF_GOALLEN = 32;
19  
20  
21      private final int goalLen;
22      private final BitSet bitMap = new BitSet(CARDINALITY_BYTE);
23      private int uniqLen;
24  
25  
26      /**
27       * Constructor.
28       *
29       * @param goalArg goal length of unique byte value sequence
30       * @throws IllegalArgumentException max must be between 1 and 256
31       */
32      public UniqRunMonitor(int goalArg) {
33          super();
34  
35          if (goalArg < 1) {
36              throw new IllegalArgumentException();
37          }
38          if (CARDINALITY_BYTE < goalArg) {
39              throw new IllegalArgumentException();
40          }
41  
42          this.goalLen = goalArg;
43          this.bitMap.clear();
44          this.uniqLen = 0;
45  
46          return;
47      }
48  
49      /**
50       * Constructor.
51       *
52       * <p>unique bytes goal length is 32.
53       */
54      public UniqRunMonitor() {
55          this(DEF_GOALLEN);
56          return;
57      }
58  
59  
60      /**
61       * {@inheritDoc}
62       */
63      @Override
64      protected void resetImpl() {
65          this.bitMap.clear();
66          this.uniqLen = 0;
67          return;
68      }
69  
70      /**
71       * {@inheritDoc}
72       *
73       * @param iVal {@inheritDoc}
74       * @return {@inheritDoc}
75       */
76      @Override
77      protected boolean probeImpl(int iVal) {
78          int bVal3 = (iVal >>> 24) & MASK_BYTE;
79          int bVal2 = (iVal >>> 16) & MASK_BYTE;
80          int bVal1 = (iVal >>>  8) & MASK_BYTE;
81          int bVal0 =  iVal         & MASK_BYTE;
82  
83          boolean result =
84                     probeByte(bVal3)
85                  || probeByte(bVal2)
86                  || probeByte(bVal1)
87                  || probeByte(bVal0);
88  
89          return result;
90      }
91  
92      /**
93       * probe byte value.
94       *
95       * @param bVal byte value
96       * @return true if uniq length reaches goal.
97       */
98      private boolean probeByte(int bVal) {
99          boolean collision = this.bitMap.get(bVal);
100 
101         boolean result = false;
102 
103         if (collision) {
104             this.bitMap.clear();
105             this.bitMap.set(bVal);
106             this.uniqLen = 1;
107         } else {
108             this.bitMap.set(bVal);
109             this.uniqLen++;
110             if (this.uniqLen >= this.goalLen) {
111                 result = true;
112             }
113         }
114 
115         return result;
116     }
117 
118 }