/* ****************************************************************************** * Copyright (C) 2007-2010, International Business Machines Corporation and * * others. All Rights Reserved. * ****************************************************************************** */ package com.ibm.icu.impl.duration.impl; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.List; import com.ibm.icu.lang.UCharacter; public class XMLRecordReader implements RecordReader { private Reader r; private List nameStack; private boolean atTag; private String tag; // cache public XMLRecordReader(Reader r) { this.r = r; this.nameStack = new ArrayList(); // skip XML prologue if (getTag().startsWith("?xml")) { advance(); } // skip FIRST comment if (getTag().startsWith("!--")) { advance(); } } public boolean open(String title) { if (getTag().equals(title)) { nameStack.add(title); advance(); return true; } return false; } public boolean close() { int ix = nameStack.size() - 1; String name = nameStack.get(ix); if (getTag().equals("/" + name)) { nameStack.remove(ix); advance(); return true; } return false; } public boolean bool(String name) { String s = string(name); if (s != null) { return "true".equals(s); } return false; } public boolean[] boolArray(String name) { String[] sa = stringArray(name); if (sa != null) { boolean[] result = new boolean[sa.length]; for (int i = 0; i < sa.length; ++i) { result[i] = "true".equals(sa[i]); } return result; } return null; } public char character(String name) { String s = string(name); if (s != null) { return s.charAt(0); } return '\uffff'; } public char[] characterArray(String name) { String[] sa = stringArray(name); if (sa != null) { char[] result = new char[sa.length]; for (int i = 0; i < sa.length; ++i) { result[i] = sa[i].charAt(0); } return result; } return null; } public byte namedIndex(String name, String[] names) { String sa = string(name); if (sa != null) { for (int i = 0; i < names.length; ++i) { if (sa.equals(names[i])) { return (byte) i; } } } return (byte) -1; } public byte[] namedIndexArray(String name, String[] names) { String[] sa = stringArray(name); if (sa != null) { byte[] result = new byte[sa.length]; loop: for (int i = 0; i < sa.length; ++i) { String s = sa[i]; for (int j = 0; j < names.length; ++j) { if (names[j].equals(s)) { result[i] = (byte) j; continue loop; } } result[i] = (byte) -1; } return result; } return null; } public String string(String name) { if (match(name)) { String result = readData(); if (match("/" + name)) { return result; } } return null; } public String[] stringArray(String name) { if (match(name + "List")) { List list = new ArrayList(); String s; while (null != (s = string(name))) { if ("Null".equals(s)) { s = null; } list.add(s); } if (match("/" + name + "List")) { return list.toArray(new String[list.size()]); } } return null; } public String[][] stringTable(String name) { if (match(name + "Table")) { List list = new ArrayList(); String[] sa; while (null != (sa = stringArray(name))) { list.add(sa); } if (match("/" + name + "Table")) { return list.toArray(new String[list.size()][]); } } return null; } private boolean match(String target) { if (getTag().equals(target)) { // System.out.println("match '" + target + "'"); advance(); return true; } return false; } private String getTag() { if (tag == null) { tag = readNextTag(); } return tag; } private void advance() { tag = null; } private String readData() { StringBuilder sb = new StringBuilder(); boolean inWhitespace = false; // boolean inAmp = false; while (true) { int c = readChar(); if (c == -1 || c == '<') { atTag = c == '<'; break; } if (c == '&') { c = readChar(); if (c == '#') { StringBuilder numBuf = new StringBuilder(); int radix = 10; c = readChar(); if (c == 'x') { radix = 16; c = readChar(); } while (c != ';' && c != -1) { numBuf.append((char) c); c = readChar(); } try { int num = Integer.parseInt(numBuf.toString(), radix); c = (char) num; } catch (NumberFormatException ex) { System.err.println("numbuf: " + numBuf.toString() + " radix: " + radix); throw ex; } } else { StringBuilder charBuf = new StringBuilder(); while (c != ';' && c != -1) { charBuf.append((char) c); c = readChar(); } String charName = charBuf.toString(); if (charName.equals("lt")) { c = '<'; } else if (charName.equals("gt")) { c = '>'; } else if (charName.equals("quot")) { c = '"'; } else if (charName.equals("apos")) { c = '\''; } else if (charName.equals("amp")) { c = '&'; } else { System.err.println("unrecognized character entity: '" + charName + "'"); continue; } } } if (UCharacter.isWhitespace(c)) { if (inWhitespace) { continue; } c = ' '; inWhitespace = true; } else { inWhitespace = false; } sb.append((char) c); } //System.err.println("read data: '" + sb.toString() + "'"); return sb.toString(); } private String readNextTag() { int c = '\0'; while (!atTag) { c = readChar(); if (c == '<' || c == -1) { if (c == '<') { atTag = true; } break; } if (!UCharacter.isWhitespace(c)) { System.err.println("Unexpected non-whitespace character " + Integer.toHexString(c)); break; } } if (atTag) { atTag = false; StringBuilder sb = new StringBuilder(); while (true) { c = readChar(); if (c == '>' || c == -1) { break; } sb.append((char) c); } // System.err.println("read tag: '" + sb.toString() + "'"); return sb.toString(); } return null; } int readChar() { try { return r.read(); } catch (IOException e) { // assume end of input } return -1; } }