1 /* 2 * Copyright (C) 2010 Google Inc. 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 com.google.streamhtmlparser.impl; 18 19 import com.google.common.base.Preconditions; 20 21 import java.util.concurrent.atomic.AtomicInteger; 22 23 /** 24 * A very simple representation of the parser internal state. The state 25 * contains a small integer identifier (from 1 to 255) to allow for 26 * the implementation of a simple finite state machine. The name is 27 * purely informational. 28 * 29 * <p>In order to eliminate the possibility that different states have 30 * the same identifier, this class manages the idenitifiers themselves. 31 * The HTML and Javascript parser states are managed elsewhere in different 32 * "namespaces" hence will not clash and there is no current need for this 33 * class to disambiguate them further. 34 * 35 * <p>The methods to create new <code>InternalState</code> instances are 36 * package-scope only as they are only needed by <code>HtmlParserImpl</code> 37 * and <code>JavascriptParserImpl</code>. 38 */ 39 class InternalState { 40 41 // An InternalState to represent an error condition for all parsers. 42 static final InternalState INTERNAL_ERROR_STATE = new InternalState(); 43 44 // MAX_ID and FIRST_ID are only used for asserts against developer error. 45 private static final int MAX_ID = 255; 46 private static final int FIRST_ID = 1; 47 48 private static AtomicInteger htmlStates = new AtomicInteger(FIRST_ID); 49 private static AtomicInteger javascriptStates = new AtomicInteger(FIRST_ID); 50 private final String name; 51 private final int id; 52 53 /** 54 * @param name the {@code String} identifier for this state 55 * @param id the integer identiifer for this state, guaranteed to be unique 56 */ InternalState(String name, int id)57 private InternalState(String name, int id) { 58 Preconditions.checkNotNull(name); 59 Preconditions.checkArgument(id >= FIRST_ID); 60 Preconditions.checkArgument(id <= MAX_ID); 61 this.name = name; 62 this.id = id; 63 } 64 65 /** 66 * Used only for the error state. Bypasses assert checks. 67 */ InternalState()68 private InternalState() { 69 name = "InternalStateError"; 70 id = 0; 71 } 72 73 /** 74 * @return {@code String} name of that state. 75 */ getName()76 public String getName() { 77 return name; 78 } 79 80 /** 81 * @return {@code int} id of that state. 82 */ getId()83 public int getId() { 84 return id; 85 } 86 87 /** 88 * @return {@code String} representation of that object, the format 89 * may change. 90 */ 91 @Override toString()92 public String toString() { 93 return String.format("InternalState: Name: %s; Id: %d", name, id); 94 } 95 96 /** 97 * Obtain a new {@code InternalState} instance for the HTML parser. 98 * 99 * @param name a unique identifier for this state useful during debugging 100 * @return a new {@code InternalState} object 101 */ getInstanceHtml(String name)102 static InternalState getInstanceHtml(String name) { 103 int htmlStateId = htmlStates.getAndIncrement(); 104 return new InternalState(name, htmlStateId); 105 } 106 107 /** 108 * Obtain a new <code>InternalState</code> instance for the Javascript parser. 109 * 110 * @param name A unique identifier for this state useful during debugging 111 * @return a new {@code InternalState} object 112 */ getInstanceJavascript(String name)113 static InternalState getInstanceJavascript(String name) { 114 int javascriptStateId = javascriptStates.getAndIncrement(); 115 return new InternalState(name, javascriptStateId); 116 } 117 } 118