protected void createStateMachine(final String[] originalItems, final String className, final ClassFile file, final ClassMethod sctor, final AtomicInteger fieldCounter, final String methodName, final CustomStateMachine stateMachine, boolean expectNewline) { //list of all states except the initial final List<State> allStates = new ArrayList<State>(); final State initial = new State((byte) 0, ""); for (String value : originalItems) { addStates(initial, value, allStates); } //we want initial to be number 0 final AtomicInteger stateCounter = new AtomicInteger(-1); setupStateNo(initial, stateCounter, fieldCounter); for (State state : allStates) { setupStateNo(state, stateCounter, fieldCounter); createStateField(state, file, sctor.getCodeAttribute()); } final int noStates = stateCounter.get(); final ClassMethod handle = file.addMethod(Modifier.PROTECTED | Modifier.FINAL, methodName, "V", DescriptorUtils.makeDescriptor(ByteBuffer.class), parseStateDescriptor, httpExchangeDescriptor); handle.addCheckedExceptions(BAD_REQUEST_EXCEPTION); writeStateMachine(className, file, handle.getCodeAttribute(), initial, allStates, noStates, stateMachine, expectNewline); }
stateNotFound(c, builder); setupLocalVariables(c); final CodeLocation returnIncompleteCode = c.mark(); c.aload(PARSE_STATE_VAR); c.putfield(parseStateClass, "parseState", "I"); c.returnInstruction(); setupLocalVariables(c); final CodeLocation returnCompleteCode = c.mark(); c.aload(PARSE_STATE_VAR); handleReturnIfNoMoreBytes(c, returnIncompleteCode); handleReturnIfNoMoreBytes(c, returnIncompleteCode); c.gotoInstruction(prefixLoop); tokenDone(c, returnCompleteCode, stateMachine); tokenDone(c, returnCompleteCode, stateMachine); handleReturnIfNoMoreBytes(c, returnIncompleteCode); tokenDone(c, returnCompleteCode, stateMachine); invokeState(className, file, c, initial, initial, noStateLoop, prefixLoop, returnIncompleteCode, returnCompleteCode, stateMachine, expectNewline); for (final State s : allStates) { if (s.stateno >= 0) { c.branchEnd(ends.get(s).get());
c.pop(); handleReturnIfNoMoreBytes(c, returnIncompleteCode); c.aload(BYTE_BUFFER_VAR); c.invokevirtual(ByteBuffer.class.getName(), "get", "()B"); handleReturnIfNoMoreBytes(c, returnIncompleteCode); stateMachine.handleStateMachineMatchedToken(c); tokenDone(c, returnCompleteCode, stateMachine); } else { if (stateMachine.initialNewlineMeansRequestDone()) { c.pop(); setupLocalVariables(c); handleReturnIfNoMoreBytes(c, returnIncompleteCode); initialState.jumpTo(c);
private static void addStates(final State initial, final String value, final List<State> allStates) { addStates(initial, value, 0, allStates); }
public byte[] createTokenizer(final String[] httpVerbs, String[] httpVersions, String[] standardHeaders) { final String className = existingClassName + CLASS_NAME_SUFFIX; final ClassFile file = new ClassFile(className, existingClassName); final ClassMethod ctor = file.addMethod(AccessFlag.PUBLIC, "<init>", "V", DescriptorUtils.parameterDescriptors(constructorDescriptor)); ctor.getCodeAttribute().aload(0); ctor.getCodeAttribute().loadMethodParameters(); ctor.getCodeAttribute().invokespecial(existingClassName, "<init>", constructorDescriptor); ctor.getCodeAttribute().returnInstruction(); final ClassMethod sctor = file.addMethod(AccessFlag.PUBLIC | AccessFlag.STATIC, "<clinit>", "V"); final AtomicInteger fieldCounter = new AtomicInteger(1); sctor.getCodeAttribute().invokestatic(existingClassName, "httpStrings", "()" + DescriptorUtils.makeDescriptor(Map.class)); sctor.getCodeAttribute().astore(CONSTRUCTOR_HTTP_STRING_MAP_VAR); createStateMachines(httpVerbs, httpVersions, standardHeaders, className, file, sctor, fieldCounter); sctor.getCodeAttribute().returnInstruction(); return file.toBytecode(); }
private static void addStates(final State current, final String value, final int i, final List<State> allStates) { if (i == value.length()) { return; } byte[] bytes = value.getBytes(StandardCharsets.UTF_8); final byte currentByte = bytes[i]; State newState = current.next.get(currentByte); if (newState == null) { current.next.put(currentByte, newState = new State(currentByte, value.substring(0, i + 1))); allStates.add(newState); } addStates(newState, value, i + 1, allStates); }