1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * in the Software without restriction, including without limitation the rights
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sell copies of the Software, and to permit persons to whom the Software is
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * furnished to do so, subject to the following conditions:
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The  above copyright notice and this permission notice shall be included in
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * all copies or substantial portions of the Software.
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * IN THE SOFTWARE. */
20f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.kxml2.io;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.*;
2578e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughesimport java.util.Locale;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xmlpull.v1.*;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class KXmlSerializer implements XmlSerializer {
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //    static final String UNDEFINED = ":";
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // BEGIN android-added
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /** size (in characters) for the write buffer */
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int WRITE_BUFFER_SIZE = 500;
35f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // END android-added
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // BEGIN android-changed
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // (Guarantee that the writer is always buffered.)
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private BufferedWriter writer;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // END android-changed
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean pending;
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int auto;
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int depth;
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String[] elementStack = new String[12];
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //nsp/prefix/name
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int[] nspCounts = new int[4];
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String[] nspStack = new String[8];
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //prefix/nsp; both empty are ""
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean[] indent = new boolean[4];
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean unicode;
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String encoding;
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final void check(boolean close) throws IOException {
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!pending)
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        depth++;
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        pending = false;
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (indent.length <= depth) {
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean[] hlp = new boolean[depth + 4];
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(indent, 0, hlp, 0, depth);
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            indent = hlp;
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        indent[depth] = indent[depth - 1];
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6980a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes        for (int i = nspCounts[depth - 1]; i < nspCounts[depth]; i++) {
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write(' ');
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("xmlns");
7280a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            if (!nspStack[i * 2].isEmpty()) {
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                writer.write(':');
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                writer.write(nspStack[i * 2]);
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
7680a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            else if (getNamespace().isEmpty() && !nspStack[i * 2 + 1].isEmpty())
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("=\"");
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writeEscaped(nspStack[i * 2 + 1], '"');
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write('"');
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (nspCounts.length <= depth + 1) {
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int[] hlp = new int[depth + 8];
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(nspCounts, 0, hlp, 0, depth + 1);
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nspCounts = hlp;
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspCounts[depth + 1] = nspCounts[depth];
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //   nspCounts[depth + 2] = nspCounts[depth];
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(close ? " />" : ">");
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
95866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes    private final void writeEscaped(String s, int quot) throws IOException {
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < s.length(); i++) {
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            char c = s.charAt(i);
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            switch (c) {
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case '\n':
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case '\r':
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case '\t':
102f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    if(quot == -1)
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        writer.write(c);
104f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    else
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        writer.write("&#"+((int) c)+';');
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case '&' :
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writer.write("&amp;");
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case '>' :
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writer.write("&gt;");
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case '<' :
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writer.write("&lt;");
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
116866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes                default:
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (c == quot) {
118866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes                        writer.write(c == '"' ? "&quot;" : "&apos;");
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break;
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
121ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    // BEGIN android-changed: refuse to output invalid characters
122ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    // See http://www.w3.org/TR/REC-xml/#charsets for definition.
123ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    // No other Java XML writer we know of does this, but no Java
124ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    // XML reader we know of is able to parse the bad output we'd
125ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    // otherwise generate.
126ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    // Note: tab, newline, and carriage return have already been
127ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    // handled above.
1283f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                    boolean allowedInXml = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
1293f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                    if (allowedInXml) {
1303f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                        if (unicode || c < 127) {
1313f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                            writer.write(c);
1323f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                        } else {
1333f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                            writer.write("&#" + ((int) c) + ";");
1343f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                        }
1353f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                    } else if (Character.isHighSurrogate(c) && i < s.length() - 1) {
1363f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                        writeSurrogate(c, s.charAt(i + 1));
1373f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                        ++i;
138ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    } else {
1393f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                        reportInvalidCharacter(c);
140ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    }
141ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    // END android-changed
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
146ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes    // BEGIN android-added
147ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes    private static void reportInvalidCharacter(char ch) {
1483f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        throw new IllegalArgumentException("Illegal character (U+" + Integer.toHexString((int) ch) + ")");
149ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes    }
150ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes    // END android-added
151ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private final void writeIndent() throws IOException {
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("\r\n");
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < depth; i++)
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                writer.write(' ');
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }*/
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void docdecl(String dd) throws IOException {
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write("<!DOCTYPE");
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(dd);
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(">");
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void endDocument() throws IOException {
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (depth > 0) {
167866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes            endTag(elementStack[depth * 3 - 3], elementStack[depth * 3 - 1]);
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        flush();
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void entityRef(String name) throws IOException {
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check(false);
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write('&');
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(name);
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(';');
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getFeature(String name) {
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //return false;
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            "http://xmlpull.org/v1/doc/features.html#indent-output"
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                .equals(
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                name))
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ? indent[depth]
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            : false;
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getPrefix(String namespace, boolean create) {
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return getPrefix(namespace, false, create);
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        catch (IOException e) {
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new RuntimeException(e.toString());
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final String getPrefix(
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String namespace,
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean includeDefault,
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean create)
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = nspCounts[depth + 1] * 2 - 2;
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            i >= 0;
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            i -= 2) {
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (nspStack[i + 1].equals(namespace)
20880a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes                && (includeDefault || !nspStack[i].isEmpty())) {
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String cand = nspStack[i];
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (int j = i + 2;
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    j < nspCounts[depth + 1] * 2;
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    j++) {
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (nspStack[j].equals(cand)) {
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        cand = null;
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break;
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (cand != null)
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return cand;
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!create)
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String prefix;
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
22880a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes        if (namespace.isEmpty())
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            prefix = "";
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        else {
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            do {
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                prefix = "n" + (auto++);
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (int i = nspCounts[depth + 1] * 2 - 2;
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    i >= 0;
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    i -= 2) {
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (prefix.equals(nspStack[i])) {
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        prefix = null;
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break;
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (prefix == null);
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean p = pending;
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        pending = false;
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setPrefix(prefix, namespace);
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        pending = p;
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return prefix;
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Object getProperty(String name) {
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new RuntimeException("Unsupported property");
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void ignorableWhitespace(String s)
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        text(s);
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setFeature(String name, boolean value) {
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ("http://xmlpull.org/v1/doc/features.html#indent-output"
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            .equals(name)) {
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            indent[depth] = value;
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        else
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new RuntimeException("Unsupported Feature");
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setProperty(String name, Object value) {
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new RuntimeException(
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            "Unsupported Property:" + value);
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setPrefix(String prefix, String namespace)
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check(false);
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (prefix == null)
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            prefix = "";
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (namespace == null)
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            namespace = "";
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String defined = getPrefix(namespace, true, false);
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // boil out if already defined
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (prefix.equals(defined))
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int pos = (nspCounts[depth + 1]++) << 1;
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (nspStack.length < pos + 1) {
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String[] hlp = new String[nspStack.length + 16];
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(nspStack, 0, hlp, 0, pos);
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nspStack = hlp;
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspStack[pos++] = prefix;
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspStack[pos] = namespace;
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setOutput(Writer writer) {
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // BEGIN android-changed
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Guarantee that the writer is always buffered.
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (writer instanceof BufferedWriter) {
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.writer = (BufferedWriter) writer;
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE);
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // END android-changed
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // elementStack = new String[12]; //nsp/prefix/name
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //nspCounts = new int[4];
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //nspStack = new String[8]; //prefix/nsp
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //indent = new boolean[4];
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspCounts[0] = 2;
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspCounts[1] = 2;
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspStack[0] = "";
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspStack[1] = "";
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspStack[2] = "xml";
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspStack[3] = "http://www.w3.org/XML/1998/namespace";
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        pending = false;
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        auto = 0;
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        depth = 0;
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        unicode = false;
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setOutput(OutputStream os, String encoding)
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (os == null)
334cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes            throw new IllegalArgumentException("os == null");
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setOutput(
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            encoding == null
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ? new OutputStreamWriter(os)
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                : new OutputStreamWriter(os, encoding));
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.encoding = encoding;
34078e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes        if (encoding != null && encoding.toLowerCase(Locale.US).startsWith("utf")) {
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            unicode = true;
34278e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes        }
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34578e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes    public void startDocument(String encoding, Boolean standalone) throws IOException {
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write("<?xml version='1.0' ");
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (encoding != null) {
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.encoding = encoding;
35078e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes            if (encoding.toLowerCase(Locale.US).startsWith("utf")) {
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                unicode = true;
35278e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes            }
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (this.encoding != null) {
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("encoding='");
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write(this.encoding);
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("' ");
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (standalone != null) {
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("standalone='");
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write(
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                standalone.booleanValue() ? "yes" : "no");
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("' ");
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write("?>");
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public XmlSerializer startTag(String namespace, String name)
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check(false);
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        if (namespace == null)
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //            namespace = "";
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (indent[depth]) {
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("\r\n");
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < depth; i++)
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                writer.write("  ");
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int esp = depth * 3;
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (elementStack.length < esp + 3) {
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String[] hlp = new String[elementStack.length + 12];
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(elementStack, 0, hlp, 0, esp);
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            elementStack = hlp;
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String prefix =
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            namespace == null
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ? ""
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                : getPrefix(namespace, true, true);
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
396b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        if (namespace != null && namespace.isEmpty()) {
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = nspCounts[depth];
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                i < nspCounts[depth + 1];
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                i++) {
40080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes                if (nspStack[i * 2].isEmpty() && !nspStack[i * 2 + 1].isEmpty()) {
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        elementStack[esp++] = namespace;
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        elementStack[esp++] = prefix;
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        elementStack[esp] = name;
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write('<');
41180a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes        if (!prefix.isEmpty()) {
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write(prefix);
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write(':');
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(name);
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        pending = true;
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public XmlSerializer attribute(
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String namespace,
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String name,
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String value)
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!pending)
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalStateException("illegal position for attribute");
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        int cnt = nspCounts[depth];
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (namespace == null)
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            namespace = "";
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        depth--;
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        pending = false;
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String prefix =
44080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            namespace.isEmpty()
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ? ""
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                : getPrefix(namespace, false, true);
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        pending = true;
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        depth++;
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*        if (cnt != nspCounts[depth]) {
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writer.write(' ');
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writer.write("xmlns");
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (nspStack[cnt * 2] != null) {
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        writer.write(':');
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        writer.write(nspStack[cnt * 2]);
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writer.write("=\"");
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writeEscaped(nspStack[cnt * 2 + 1], '"');
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writer.write('"');
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                */
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(' ');
46180a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes        if (!prefix.isEmpty()) {
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write(prefix);
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write(':');
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(name);
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write('=');
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        char q = value.indexOf('"') == -1 ? '"' : '\'';
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(q);
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writeEscaped(value, q);
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(q);
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void flush() throws IOException {
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check(false);
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.flush();
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void close() throws IOException {
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            check();
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.close();
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    */
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public XmlSerializer endTag(String namespace, String name)
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!pending)
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            depth--;
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        if (namespace == null)
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //          namespace = "";
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((namespace == null
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            && elementStack[depth * 3] != null)
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            || (namespace != null
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && !namespace.equals(elementStack[depth * 3]))
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            || !elementStack[depth * 3 + 2].equals(name))
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException("</{"+namespace+"}"+name+"> does not match start");
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (pending) {
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            check(true);
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            depth--;
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        else {
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (indent[depth + 1]) {
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                writer.write("\r\n");
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (int i = 0; i < depth; i++)
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    writer.write("  ");
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write("</");
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String prefix = elementStack[depth * 3 + 1];
51380a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            if (!prefix.isEmpty()) {
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                writer.write(prefix);
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                writer.write(':');
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write(name);
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            writer.write('>');
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nspCounts[depth + 1] = nspCounts[depth];
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getNamespace() {
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3];
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getName() {
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1];
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getDepth() {
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return pending ? depth + 1 : depth;
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public XmlSerializer text(String text) throws IOException {
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check(false);
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        indent[depth] = false;
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writeEscaped(text, -1);
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public XmlSerializer text(char[] text, int start, int len)
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        text(new String(text, start, len));
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this;
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void cdsect(String data) throws IOException {
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check(false);
552ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes        // BEGIN android-changed: ]]> is not allowed within a CDATA,
553ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes        // so break and start a new one when necessary.
554ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes        data = data.replace("]]>", "]]]]><![CDATA[>");
5553f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        writer.write("<![CDATA[");
5563f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        for (int i = 0; i < data.length(); ++i) {
5573f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes            char ch = data.charAt(i);
5583f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes            boolean allowedInCdata = (ch >= 0x20 && ch <= 0xd7ff) ||
559ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    (ch == '\t' || ch == '\n' || ch == '\r') ||
560ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                    (ch >= 0xe000 && ch <= 0xfffd);
5613f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes            if (allowedInCdata) {
5623f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                writer.write(ch);
5633f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes            } else if (Character.isHighSurrogate(ch) && i < data.length() - 1) {
5643f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                // Character entities aren't valid in CDATA, so break out for this.
5653f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                writer.write("]]>");
5663f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                writeSurrogate(ch, data.charAt(++i));
5673f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                writer.write("<![CDATA[");
5683f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes            } else {
569ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes                reportInvalidCharacter(ch);
570ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes            }
571ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes        }
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write("]]>");
573ff42219e3ea3d712f931ae7f26af236339b5cf23Elliott Hughes        // END android-changed
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5763f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes    // BEGIN android-added
5773f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes    private void writeSurrogate(char high, char low) throws IOException {
5783f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        if (!Character.isLowSurrogate(low)) {
5793f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes            throw new IllegalArgumentException("Bad surrogate pair (U+" + Integer.toHexString((int) high) +
5803f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes                                               " U+" + Integer.toHexString((int) low) + ")");
5813f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        }
5823f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        // Java-style surrogate pairs aren't allowed in XML. We could use the > 3-byte encodings, but that
5833f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        // seems likely to upset anything expecting modified UTF-8 rather than "real" UTF-8. It seems more
5843f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        // conservative in a Java environment to use an entity reference instead.
5853f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        int codePoint = Character.toCodePoint(high, low);
5863f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes        writer.write("&#" + codePoint + ";");
5873f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes    }
5883f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes    // END android-added
5893f1a5ebc337e896977bbc75aa2dc370e97805794Elliott Hughes
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void comment(String comment) throws IOException {
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check(false);
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write("<!--");
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(comment);
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write("-->");
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void processingInstruction(String pi)
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check(false);
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write("<?");
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write(pi);
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        writer.write("?>");
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
605