/** * Converts this pipe into a {@link ParserReader}. * * @return The converted pipe. * @throws Exception */ public ParserReader getParserReader() throws Exception { if (input == null) return null; if (input instanceof ParserReader) parserReader = (ParserReader)input; else parserReader = new ParserReader(this); return parserReader; }
/** * Reads a numeric string from the specified reader. * * @param r The reader to read form. * @return The parsed number string. * @throws Exception */ public static String parseNumberString(ParserReader r) throws Exception { r.mark(); int c = 0; while (true) { c = r.read(); if (c == -1) break; if (! numberChars.contains((char)c)) { r.unread(); break; } } return r.getMarked(); }
/** * Peeks the next character in the stream. * * <p> * This is equivalent to doing a {@code read()} followed by an {@code unread()}. * * @return The peeked character, or (char)-1 if the end of the stream has been reached. * @throws IOException If a problem occurred trying to read from the reader. */ public final int peek() throws IOException { int c = read(); if (c != -1) unread(); return c; }
private String parseString(ParserReader r) throws Exception { r.mark(); int qc = r.read(); // The quote character being used (" or ') if (qc != '"' && isStrict()) { String msg = ( int c = 0; while (c != -1) { c = r.read(); if (isInEscape) { switch (c) { case 'n': r.replace('\n'); break; case 'r': r.replace('\r'); break; case 't': r.replace('\t'); break; case 'f': r.replace('\f'); break; case 'b': r.replace('\b'); break; case '\\': r.replace('\\'); break; case '/': r.replace('/'); break; case '\'': r.replace('\''); break; case '"': r.replace('"'); break; case 'u': { String n = r.read(4); try { r.replace(Integer.parseInt(n, 16), 6); } catch (NumberFormatException e) { throw new ParseException(this, "Invalid Unicode escape sequence in string."); if (c == '\\') { isInEscape = true;
@Test public void testReadStrings() throws Exception { String t = "a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789"; // Min buff size is 20. ParserReader pr = createParserReader(t); assertEquals("a123456789", pr.read(10)); pr.mark(); assertEquals("b123456789c123456789", pr.read(20)); assertEquals("d123456789e123456789f123456789", pr.read(30)); assertEquals("123456789c123456789d123456789e123456789f12345678", pr.getMarked(1, -1)); assertEquals("g123456789h123456789i123456789j123456789", pr.read(100)); assertEquals("", pr.read(100)); pr.close(); }
@Test public void test() throws Exception { ParserReader r = new ParserReader(new ParserPipe("abc123")); try { assertEquals('a', r.read()); r.unread(); assertEquals('a', r.read()); assertEquals('b', r.read()); r.unread(); assertEquals("bc", r.read(2)); assertEquals('1', r.read()); r.unread(); r.read(); assertEquals('2', r.peek()); assertEquals('2', r.peek()); assertEquals('2', r.read()); assertEquals('3', r.read()); assertEquals(-1, r.read()); assertEquals(-1, r.read()); } finally { r.close(); } } }
/** * Same as {@link #read()} but detects and combines extended unicode characters (characters above 0x10000). * * @return The character read, or -1 if the end of the stream has been reached. * @throws IOException If a problem occurred trying to read from the reader. */ public final int readCodePoint() throws IOException { int c = read(); // Characters that take up 2 chars. if (c >= 0xd800 && c <= 0xdbff) { int low = read(); if (low >= 0xdc00 && low <= 0xdfff) c = 0x10000 + ((c - 0xd800) << 10) + (low - 0xdc00); } return c; }
private Boolean parseBoolean(ParserReader r) throws Exception { int c = r.peek(); if (c == '\'' || c == '"') return Boolean.valueOf(parseString(r)); if (c == 't') { parseKeyword("true", r); return Boolean.TRUE; } else if (c == 'f') { parseKeyword("false", r); return Boolean.FALSE; } else { throw new ParseException(this, "Unrecognized syntax. Expected boolean value, actual=''{0}''", r.read(100)); } }
@Test public void testMarking() throws Exception { String t = "a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789"; String r = null; // Min buff size is 20. ParserReader pr = createParserReader(t); read(pr, 5); pr.mark(); read(pr, 10); r = pr.getMarked(); assertEquals("56789b1234", r); r = read(pr); assertEquals("56789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789", r); // Force doubling of buffer size pr =createParserReader(t); read(pr, 5); pr.mark(); read(pr, 20); r = pr.getMarked(); assertEquals("56789b123456789c1234", r); r = read(pr); assertEquals("56789d123456789e123456789f123456789g123456789h123456789i123456789j123456789", r); }
private Number parseNumber(ParserReader r, Class<? extends Number> type) throws Exception { int c = r.peek(); if (c == '\'' || c == '"') return parseNumber(r, parseString(r), type); return parseNumber(r, parseNumberString(r), type); }
/** * Replace the last read character in the buffer with the specified character. * * @param c The new character. * @return This object (for method chaining). * @throws IOException */ public final ParserReader replace(char c) throws IOException { return replace(c, 1); }
/** * Trims off the last character in the marking buffer. * * <p> * Useful for removing escape characters from sequences. * * @return This object (for method chaining). */ public final ParserReader delete() { return delete(1); }
/** * Returns the contents of the reusable character buffer as a string, and resets the buffer for next usage. * * @return The contents of the reusable character buffer as a string. */ public final String getMarked() { return getMarked(0, 0); }
@Override /* ParserReader */ public final UonReader unread() throws IOException { super.unread(); return this; } }
/** * Reads a single character. * * <p> * Note that this method does NOT process extended unicode characters (i.e. characters above 0x10000), but rather * returns them as two <jk>char</jk>s. * Use {@link #readCodePoint()} to ensure proper handling of extended unicode. * * @return The character read, or -1 if the end of the stream has been reached. * @throws IOException If a problem occurred trying to read from the reader. */ @Override /* Reader */ public final int read() throws IOException { int c = readFromBuff(); if (c == -1) return -1; if (c == '\n') { line++; column = 0; } else { column++; } return c; }
private String parseString(ParserReader r) throws Exception { r.mark(); int qc = r.read(); // The quote character being used (" or ') if (qc != '"' && isStrict()) { String msg = ( int c = 0; while (c != -1) { c = r.read(); if (isInEscape) { switch (c) { case 'n': r.replace('\n'); break; case 'r': r.replace('\r'); break; case 't': r.replace('\t'); break; case 'f': r.replace('\f'); break; case 'b': r.replace('\b'); break; case '\\': r.replace('\\'); break; case '/': r.replace('/'); break; case '\'': r.replace('\''); break; case '"': r.replace('"'); break; case 'u': { String n = r.read(4); try { r.replace(Integer.parseInt(n, 16), 6); } catch (NumberFormatException e) { throw new ParseException(this, "Invalid Unicode escape sequence in string."); if (c == '\\') { isInEscape = true;
/** * Peeks the next character in the stream. * * <p> * This is equivalent to doing a {@code read()} followed by an {@code unread()}. * * @return The peeked character, or (char)-1 if the end of the stream has been reached. * @throws IOException If a problem occurred trying to read from the reader. */ public final int peek() throws IOException { int c = read(); if (c != -1) unread(); return c; }
@Test public void testReplace() throws Exception { String t = "a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789j123456789"; // Min buff size is 20. ParserReader pr = createParserReader(t); assertEquals("a123456789", pr.read(10)); pr.mark(); assertEquals("b123456789", pr.read(10)); pr.replace('x'); assertEquals("c123456789", pr.read(10)); assertEquals("b12345678xc123456789", pr.getMarked()); pr.close(); pr = createParserReader(t); assertEquals("a123456789", pr.read(10)); pr.mark(); assertEquals("b123456789", pr.read(10)); pr.replace('x', 5); assertEquals("c123456789", pr.read(10)); assertEquals("b1234xc123456789", pr.getMarked()); pr.close(); }
@Test public void testBasic() throws Exception { String t = "01234567890123456789012345678901234567890123456789"; // Min buff size is 20. ParserReader pr = createParserReader(t); String r = read(pr); assertEquals(t, r); pr.close(); pr = createParserReader(t); pr.read(); pr.unread(); r = read(pr); assertEquals(t, r); pr.close(); pr = createParserReader(t); assertEquals('0', (char)pr.peek()); assertEquals('0', (char)pr.peek()); r = read(pr); assertEquals(t, r); pr = createParserReader(t); pr.read(); pr.unread(); try { pr.unread(); fail("Exception expected"); } catch (IOException e) { // Good } }