1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 2003-2004 Brian Wellington (bwelling@xbill.org) 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (C) 2003-2004 Nominum, Inc. 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Permission to use, copy, modify, and distribute this software for any 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// purpose with or without fee is hereby granted, provided that the above 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// copyright notice and this permission notice appear in all copies. 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR ANY 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS; 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.*; 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.*; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.utils.*; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Tokenizer is used to parse DNS records and zones from text format, 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Bob Halley 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class Tokenizer { 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static String delim = " \t\n;()\""; 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static String quotes = "\""; 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** End of file */ 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int EOF = 0; 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** End of line */ 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int EOL = 1; 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Whitespace; only returned when wantWhitespace is set */ 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int WHITESPACE = 2; 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** An identifier (unquoted string) */ 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int IDENTIFIER = 3; 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** A quoted string */ 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int QUOTED_STRING = 4; 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** A comment; only returned when wantComment is set */ 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int COMMENT = 5; 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate PushbackInputStream is; 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean ungottenToken; 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int multiline; 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean quoting; 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate String delimiters; 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Token current; 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate StringBuffer sb; 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean wantClose; 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate String filename; 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int line; 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static class Token { 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** The type of token. */ 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int type; 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** The value of the token, or null for tokens without values. */ 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String value; 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Token() { 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen type = -1; 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen value = null; 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Token 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen set(int type, StringBuffer value) { 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (type < 0) 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException(); 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.type = type; 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.value = value == null ? null : value.toString(); 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return this; 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the token to a string containing a representation useful 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * for debugging. 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen toString() { 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen switch (type) { 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen case EOF: 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "<eof>"; 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen case EOL: 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "<eol>"; 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen case WHITESPACE: 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "<whitespace>"; 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen case IDENTIFIER: 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "<identifier: " + value + ">"; 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen case QUOTED_STRING: 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "<quoted_string: " + value + ">"; 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen case COMMENT: 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "<comment: " + value + ">"; 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen default: 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "<unknown>"; 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** Indicates whether this token contains a string. */ 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen isString() { 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (type == IDENTIFIER || type == QUOTED_STRING); 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** Indicates whether this token contains an EOL or EOF. */ 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen isEOL() { 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (type == EOL || type == EOF); 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic class TokenizerException extends TextParseException { 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String message; 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen TokenizerException(String filename, int line, String message) { 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(filename + ":" + line + ": " + message); 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.message = message; 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen getBaseMessage() { 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return message; 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a Tokenizer from an arbitrary input stream. 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param is The InputStream to tokenize. 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenTokenizer(InputStream is) { 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!(is instanceof BufferedInputStream)) 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen is = new BufferedInputStream(is); 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.is = new PushbackInputStream(is, 2); 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ungottenToken = false; 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen multiline = 0; 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen quoting = false; 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen delimiters = delim; 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen current = new Token(); 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb = new StringBuffer(); 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen filename = "<none>"; 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen line = 1; 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a Tokenizer from a string. 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param s The String to tokenize. 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenTokenizer(String s) { 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this(new ByteArrayInputStream(s.getBytes())); 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a Tokenizer from a file. 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param f The File to tokenize. 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenTokenizer(File f) throws FileNotFoundException { 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this(new FileInputStream(f)); 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen wantClose = true; 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen filename = f.getName(); 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetChar() throws IOException { 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int c = is.read(); 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == '\r') { 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int next = is.read(); 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (next != '\n') 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen is.unread(next); 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen c = '\n'; 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == '\n') 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen line++; 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return c; 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenungetChar(int c) throws IOException { 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == -1) 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen is.unread(c); 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == '\n') 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen line--; 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenskipWhitespace() throws IOException { 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int skipped = 0; 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (true) { 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int c = getChar(); 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c != ' ' && c != '\t') { 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!(c == '\n' && multiline > 0)) { 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ungetChar(c); 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return skipped; 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen skipped++; 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckUnbalancedParens() throws TextParseException { 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (multiline > 0) 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("unbalanced parentheses"); 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer. 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param wantWhitespace If true, leading whitespace will be returned as a 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * token. 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param wantComment If true, comments are returned as tokens. 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream. 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid. 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Token 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenget(boolean wantWhitespace, boolean wantComment) throws IOException { 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int type; 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int c; 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (ungottenToken) { 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ungottenToken = false; 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (current.type == WHITESPACE) { 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (wantWhitespace) 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current; 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (current.type == COMMENT) { 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (wantComment) 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current; 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (current.type == EOL) 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen line++; 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current; 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int skipped = skipWhitespace(); 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (skipped > 0 && wantWhitespace) 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(WHITESPACE, null); 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen type = IDENTIFIER; 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.setLength(0); 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (true) { 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen c = getChar(); 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == -1 || delimiters.indexOf(c) != -1) { 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == -1) { 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (quoting) 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("EOF in " + 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "quoted string"); 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (sb.length() == 0) 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(EOF, null); 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(type, sb); 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sb.length() == 0 && type != QUOTED_STRING) { 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == '(') { 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen multiline++; 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen skipWhitespace(); 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (c == ')') { 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (multiline <= 0) 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("invalid " + 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "close " + 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "parenthesis"); 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen multiline--; 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen skipWhitespace(); 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (c == '"') { 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!quoting) { 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen quoting = true; 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen delimiters = quotes; 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen type = QUOTED_STRING; 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen quoting = false; 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen delimiters = delim; 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen skipWhitespace(); 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (c == '\n') { 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(EOL, null); 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (c == ';') { 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (true) { 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen c = getChar(); 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == '\n' || c == -1) 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append((char)c); 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (wantComment) { 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ungetChar(c); 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(COMMENT, sb); 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (c == -1 && 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen type != QUOTED_STRING) 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkUnbalancedParens(); 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(EOF, null); 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (multiline > 0) { 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen skipWhitespace(); 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.setLength(0); 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(EOL, null); 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException(); 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ungetChar(c); 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (c == '\\') { 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen c = getChar(); 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (c == -1) 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("unterminated escape sequence"); 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('\\'); 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (quoting && c == '\n') { 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("newline in quoted string"); 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append((char)c); 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sb.length() == 0 && type != QUOTED_STRING) { 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkUnbalancedParens(); 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(EOF, null); 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.set(type, sb); 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer, ignoring whitespace and comments. 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream. 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid. 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Token 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenget() throws IOException { 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return get(false, false); 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a token to the stream, so that it will be returned by the next call 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to get(). 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalStateException There are already ungotten tokens. 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenunget() { 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (ungottenToken) 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ("Cannot unget multiple tokens"); 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (current.type == EOL) 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen line--; 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ungottenToken = true; 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and converts it to a string. 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as a string. 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not a string. 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetString() throws IOException { 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Token next = get(); 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!next.isString()) { 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected a string"); 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return next.value; 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate String 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen_getIdentifier(String expected) throws IOException { 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Token next = get(); 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (next.type != IDENTIFIER) 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected " + expected); 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return next.value; 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer, ensures it is an unquoted string, 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and converts it to a string. 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as a string. 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not an unquoted string. 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetIdentifier() throws IOException { 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return _getIdentifier("an identifier"); 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and converts it to a long. 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as a long. 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not a long. 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic long 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetLong() throws IOException { 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String next = _getIdentifier("an integer"); 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!Character.isDigit(next.charAt(0))) 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected an integer"); 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Long.parseLong(next); 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (NumberFormatException e) { 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected an integer"); 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and converts it to an unsigned 32 bit 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * integer. 420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as an unsigned 32 bit integer. 421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not an unsigned 32 422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * bit integer. 423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic long 426d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetUInt32() throws IOException { 427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long l = getLong(); 428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (l < 0 || l > 0xFFFFFFFFL) 429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected an 32 bit unsigned integer"); 430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return l; 431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and converts it to an unsigned 16 bit 435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * integer. 436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as an unsigned 16 bit integer. 437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not an unsigned 16 438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * bit integer. 439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 442d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetUInt16() throws IOException { 443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long l = getLong(); 444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (l < 0 || l > 0xFFFFL) 445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected an 16 bit unsigned integer"); 446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (int) l; 447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and converts it to an unsigned 8 bit 451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * integer. 452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as an unsigned 8 bit integer. 453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not an unsigned 8 454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * bit integer. 455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 458d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetUInt8() throws IOException { 459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long l = getLong(); 460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (l < 0 || l > 0xFFL) 461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected an 8 bit unsigned integer"); 462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (int) l; 463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and parses it as a TTL. 467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as an unsigned 32 bit integer. 468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was not valid. 469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TTL 471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic long 473d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetTTL() throws IOException { 474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String next = _getIdentifier("a TTL value"); 475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return TTL.parseTTL(next); 477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (NumberFormatException e) { 479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected a TTL value"); 480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and parses it as if it were a TTL. 485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as an unsigned 32 bit integer. 486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was not valid. 487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TTL 489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic long 491d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetTTLLike() throws IOException { 492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String next = _getIdentifier("a TTL-like value"); 493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return TTL.parse(next, false); 495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (NumberFormatException e) { 497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected a TTL-like value"); 498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and converts it to a name. 503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param origin The origin to append to relative names. 504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as a name. 505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not a valid name. 506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws RelativeNameException The parsed name was relative, even with the 508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * origin. 509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Name 510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Name 512d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetName(Name origin) throws IOException { 513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String next = _getIdentifier("a name"); 514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Name name = Name.fromString(next, origin); 516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!name.isAbsolute()) 517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new RelativeNameException(name); 518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return name; 519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (TextParseException e) { 521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception(e.getMessage()); 522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and converts it to an IP Address. 527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param family The address family. 528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The next token in the stream, as an InetAddress 529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not a valid address. 530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Address 532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic InetAddress 534d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetAddress(int family) throws IOException { 535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String next = _getIdentifier("an address"); 536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Address.getByAddress(next, family); 538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (UnknownHostException e) { 540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception(e.getMessage()); 541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer, which must be an EOL or EOF. 546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid or not an EOL or EOF token. 547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 550d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetEOL() throws IOException { 551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Token next = get(); 552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (next.type != EOL && next.type != EOF) { 553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected EOL or EOF"); 554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a concatenation of the remaining strings from a Tokenizer. 559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate String 561d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenremainingStrings() throws IOException { 562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuffer buffer = null; 563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (true) { 564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Tokenizer.Token t = get(); 565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!t.isString()) 566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (buffer == null) 568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buffer = new StringBuffer(); 569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen buffer.append(t.value); 570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen unget(); 572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (buffer == null) 573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return buffer.toString(); 575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the remaining string tokens until an EOL/EOF is seen, concatenates 579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * them together, and converts the base64 encoded data to a byte array. 580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param required If true, an exception will be thrown if no strings remain; 581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * otherwise null be be returned. 582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The byte array containing the decoded strings, or null if there 583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * were no strings to decode. 584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid. 585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 588d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetBase64(boolean required) throws IOException { 589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String s = remainingStrings(); 590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (s == null) { 591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (required) 592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected base64 encoded string"); 593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] array = base64.fromString(s); 597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (array == null) 598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("invalid base64 encoding"); 599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return array; 600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the remaining string tokens until an EOL/EOF is seen, concatenates 604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * them together, and converts the base64 encoded data to a byte array. 605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The byte array containing the decoded strings, or null if there 606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * were no strings to decode. 607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid. 608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 611d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetBase64() throws IOException { 612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getBase64(false); 613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the remaining string tokens until an EOL/EOF is seen, concatenates 617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * them together, and converts the hex encoded data to a byte array. 618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param required If true, an exception will be thrown if no strings remain; 619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * otherwise null be be returned. 620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The byte array containing the decoded strings, or null if there 621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * were no strings to decode. 622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid. 623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 626d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetHex(boolean required) throws IOException { 627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String s = remainingStrings(); 628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (s == null) { 629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (required) 630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("expected hex encoded string"); 631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] array = base16.fromString(s); 635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (array == null) 636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("invalid hex encoding"); 637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return array; 638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the remaining string tokens until an EOL/EOF is seen, concatenates 642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * them together, and converts the hex encoded data to a byte array. 643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The byte array containing the decoded strings, or null if there 644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * were no strings to decode. 645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid. 646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 649d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetHex() throws IOException { 650d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getHex(false); 651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and decodes it as hex. 655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The byte array containing the decoded string. 656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid. 657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 660d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetHexString() throws IOException { 661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String next = _getIdentifier("a hex string"); 662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] array = base16.fromString(next); 663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (array == null) 664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("invalid hex encoding"); 665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return array; 666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next token from a tokenizer and decodes it as base32. 670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param b32 The base32 context to decode with. 671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The byte array containing the decoded string. 672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The input was invalid. 673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An I/O error occurred. 674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 676d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetBase32String(base32 b32) throws IOException { 677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String next = _getIdentifier("a base32 string"); 678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] array = b32.fromString(next); 679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (array == null) 680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw exception("invalid base32 encoding"); 681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return array; 682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 683d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates an exception which includes the current state in the error message 686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param s The error message to include. 687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The exception to be thrown 688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 689d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic TextParseException 690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenexception(String s) { 691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new TokenizerException(filename, line, s); 692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Closes any files opened by this tokenizer. 696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenclose() { 699d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (wantClose) { 700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen is.close(); 702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (IOException e) { 704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected void 709d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenfinalize() { 710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen close(); 711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 714