Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package software.amazon.event.ruler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Represents a state in a state machine and maps utf-8 bytes to transitions. One byte can have many transitions,
* meaning this is an NFA state as opposed to a DFA state.
*/
@ThreadSafe
class ByteState extends SingleByteTransition {
/**
* The field is a {@link ByteMap}, however, to optimize on memory, this field may be {@code null} when this state
* contains no transitions, and may be a {@link SingleByteTransitionEntry} when this state contains one transition.
*/
@Nullable
private volatile Object transitionStore;
/* True if this state's placement in the machine means there is more than one possible value that can be matched on
* a traversal from the start state to this state. This will happen, for example, when a wildcard or regex
* expression occurs between the start state and this state.
*/
private boolean hasIndeterminatePrefix = false;
ByteState getNextByteState() {
return this;
}
@Override
public SingleByteTransition setNextByteState(ByteState nextState) {
return nextState;
}
@Override
ByteMatch getMatch() {
return null;
}
@Override
public SingleByteTransition setMatch(ByteMatch match) {
return match == null ? this : new CompositeByteTransition(this, match);
}
@Override
public Set getShortcuts() {
return Collections.emptySet();
}
/**
* Returns {@code true} if this state contains no transitions.
*
* @return {@code true} if this state contains no transitions
*/
boolean hasNoTransitions() {
return transitionStore == null;
}
/**
* Returns the transition to which the given byte value is mapped, or {@code null} if this state contains no
* transitions for the given byte value.
*
* @param utf8byte the byte value whose associated transition is to be returned
* @return the transition to which the given byte value is mapped, or {@code null} if this state contains no
* transitions for the given byte value
*/
@Override
ByteTransition getTransition(byte utf8byte) {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null) {
return null;
} else if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
return utf8byte == entry.utf8byte ? entry.transition : null;
}
ByteMap map = (ByteMap) transitionStore;
return map.getTransition(utf8byte);
}
@Override
ByteTransition getTransitionForAllBytes() {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null || transitionStore instanceof SingleByteTransitionEntry) {
return ByteMachine.EmptyByteTransition.INSTANCE;
}
ByteMap map = (ByteMap) transitionStore;
return map.getTransitionForAllBytes();
}
@Override
Iterable getTransitions() {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null) {
return Collections.emptySet();
} else if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
return entry.transition;
}
ByteMap map = (ByteMap) transitionStore;
return map.getTransitions();
}
/**
* Associates the given transition with the given byte value in this state. If the state previously contained any
* transitions for the byte value, the old transitions are replaced by the given transition.
*
* @param utf8byte the byte value with which the given transition is to be associated
* @param transition the transition to be associated with the given byte value
*/
void putTransition(byte utf8byte, @Nonnull SingleByteTransition transition) {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null) {
this.transitionStore = new SingleByteTransitionEntry(utf8byte, transition);
} else if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
if (utf8byte == entry.utf8byte) {
entry.transition = transition;
} else {
ByteMap map = new ByteMap();
map.putTransition(entry.utf8byte, entry.transition);
map.putTransition(utf8byte, transition);
this.transitionStore = map;
}
} else {
ByteMap map = (ByteMap) transitionStore;
map.putTransition(utf8byte, transition);
}
}
/**
* Associates the given transition with all possible byte values in this state. If the state previously contained
* any transitions for any of the byte values, the old transitions are replaced by the given transition.
*
* @param transition the transition to be associated with the given byte value
*/
void putTransitionForAllBytes(@Nonnull SingleByteTransition transition) {
ByteMap map = new ByteMap();
map.putTransitionForAllBytes(transition);
this.transitionStore = map;
}
/**
* Associates the given transition with the given byte value in this state. If the state previously contained any
* transitions for the byte value, the given transition is added to these old transitions.
*
* @param utf8byte the byte value with which the given transition is to be associated
* @param transition the transition to be associated with the given byte value
*/
void addTransition(byte utf8byte, @Nonnull SingleByteTransition transition) {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null) {
this.transitionStore = new SingleByteTransitionEntry(utf8byte, transition);
} else if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
ByteMap map = new ByteMap();
map.addTransition(entry.utf8byte, entry.transition);
map.addTransition(utf8byte, transition);
this.transitionStore = map;
} else {
ByteMap map = (ByteMap) transitionStore;
map.addTransition(utf8byte, transition);
}
}
/**
* Associates the given transition with all possible byte values in this state. If the state previously contained
* any transitions for any of the byte values, the given transition is added to these old transitions.
*
* @param transition the transition to be associated with all possible byte values
*/
void addTransitionForAllBytes(final SingleByteTransition transition) {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
ByteMap map;
if (transitionStore instanceof ByteMap) {
map = (ByteMap) transitionStore;
} else {
map = new ByteMap();
}
if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
map.addTransition(entry.utf8byte, entry.transition);
}
map.addTransitionForAllBytes(transition);
this.transitionStore = map;
}
/**
* Removes provided transition for the given byte value from this state.
*
* @param utf8byte the byte value for which to remove transition from the state
* @param transition remove this transition for provided byte value from the state
*/
void removeTransition(byte utf8byte, SingleByteTransition transition) {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null) {
return;
}
if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
if (utf8byte == entry.utf8byte && transition.equals(entry.transition)) {
this.transitionStore = null;
}
} else {
ByteMap map = (ByteMap) transitionStore;
map.removeTransition(utf8byte, transition);
if (map.isEmpty()) {
this.transitionStore = null;
}
}
}
/**
* Removes the given transition for all possible byte values from this state.
*
* @param transition the transition to be removed for all possible byte values
*/
void removeTransitionForAllBytes(final SingleByteTransition transition) {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null) {
return;
}
if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
if (transition.equals(entry.transition)) {
this.transitionStore = null;
}
} else {
ByteMap map = (ByteMap) transitionStore;
map.removeTransitionForAllBytes(transition);
if (map.isEmpty()) {
this.transitionStore = null;
}
}
}
@Override
boolean hasIndeterminatePrefix() {
return hasIndeterminatePrefix;
}
void setIndeterminatePrefix(boolean hasIndeterminatePrefix) {
this.hasIndeterminatePrefix = hasIndeterminatePrefix;
}
/**
* Return true if this state has a self-referential transition and no others.
*
* @return True if this state has a self-referential transition and no others, false otherwise.
*/
boolean hasOnlySelfReferentialTransition() {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null) {
return false;
} else if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
return this.equals(entry.transition);
}
ByteMap map = (ByteMap) transitionStore;
return map.numberOfTransitions() == 1 && map.hasTransition(this);
}
/**
* Gets all the ceiling values contained in the ByteMap or SingleByteTransitionEntry.
*
* @return All the ceiling values contained in the ByteMap or SingleByteTransitionEntry.
*/
Set getCeilings() {
// Saving the value to avoid reading an updated value
Object transitionStore = this.transitionStore;
if (transitionStore == null) {
return Collections.emptySet();
} else if (transitionStore instanceof SingleByteTransitionEntry) {
SingleByteTransitionEntry entry = (SingleByteTransitionEntry) transitionStore;
int index = entry.utf8byte & 0xFF;
if (index == 0) {
return Stream.of(index + 1, 256).collect(Collectors.toSet());
} else if (index == 255) {
return Stream.of(index, index + 1).collect(Collectors.toSet());
} else {
return Stream.of(index, index + 1, 256).collect(Collectors.toSet());
}
}
ByteMap map = (ByteMap) transitionStore;
return map.getCeilings();
}
@Override
public String toString() {
return "BS: " + transitionStore;
}
private static final class SingleByteTransitionEntry {
final byte utf8byte;
volatile SingleByteTransition transition;
SingleByteTransitionEntry(byte utf8byte, SingleByteTransition transition) {
this.utf8byte = utf8byte;
this.transition = transition;
}
@Override
public String toString() {
ByteState next = transition.getNextByteState();
String nextLabel = (next == null) ? "null" : Integer.toString(next.hashCode());
return "SBTE: " + (char) utf8byte + "=>" + nextLabel;
}
}
}