grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/xml/SkBML_XMLParser.cpp b/src/xml/SkBML_XMLParser.cpp
new file mode 100644
index 0000000..53b7f61
--- /dev/null
+++ b/src/xml/SkBML_XMLParser.cpp
@@ -0,0 +1,192 @@
+/* libs/graphics/xml/SkBML_XMLParser.cpp
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#include "SkBML_XMLParser.h"
+#include "SkBML_Verbs.h"
+#include "SkStream.h"
+#include "SkXMLWriter.h"
+
+static uint8_t rbyte(SkStream& s)
+{
+    uint8_t b;
+    size_t size = s.read(&b, 1);
+    SkASSERT(size == 1);
+    return b;
+}
+
+static int rdata(SkStream& s, int data)
+{
+    SkASSERT((data & ~31) == 0);
+    if (data == 31)
+    {
+        data = rbyte(s);
+        if (data == 0xFF)
+        {
+            data = rbyte(s);
+            data = (data << 8) | rbyte(s);
+        }
+    }
+    return data;
+}
+
+static void set(char* array[256], int index, SkStream& s, int data)
+{
+    SkASSERT((unsigned)index <= 255);
+
+    size_t size = rdata(s, data);
+
+    if (array[index] == NULL)
+        array[index] = (char*)sk_malloc_throw(size + 1);
+    else
+    {
+        if (strlen(array[index]) < size)
+            array[index] = (char*)sk_realloc_throw(array[index], size + 1);
+    }
+
+    s.read(array[index], size);
+    array[index][size] = 0;
+}
+
+static void freeAll(char* array[256])
+{
+    for (int i = 0; i < 256; i++)
+        sk_free(array[i]);
+}
+
+struct BMLW {
+    char*   fElems[256];
+    char*   fNames[256];
+    char*   fValues[256];
+
+    // important that these are uint8_t, so we get automatic wrap-around
+    uint8_t  fNextElem, fNextName, fNextValue;
+
+    BMLW()
+    {
+        memset(fElems, 0, sizeof(fElems));
+        memset(fNames, 0, sizeof(fNames));
+        memset(fValues, 0, sizeof(fValues));
+
+        fNextElem = fNextName = fNextValue = 0;
+    }
+    ~BMLW()
+    {
+        freeAll(fElems);
+        freeAll(fNames);
+        freeAll(fValues);
+    }
+};
+
+static void rattr(unsigned verb, SkStream& s, BMLW& rec, SkXMLWriter& writer)
+{
+    int data = verb & 31;
+    verb >>= 5;
+
+    int nameIndex, valueIndex;
+
+    switch (verb) {
+    case kAttr_Value_Value_Verb:
+        nameIndex = rec.fNextName;      // record before the ++
+        set(rec.fNames, rec.fNextName++, s, data);
+        valueIndex = rec.fNextValue;    // record before the ++
+        set(rec.fValues, rec.fNextValue++, s, 31);
+        break;
+    case kAttr_Value_Index_Verb:
+        nameIndex = rec.fNextName;      // record before the ++
+        set(rec.fNames, rec.fNextName++, s, data);
+        valueIndex = rbyte(s);
+        break;
+    case kAttr_Index_Value_Verb:
+        nameIndex = rdata(s, data);
+        valueIndex = rec.fNextValue;    // record before the ++
+        set(rec.fValues, rec.fNextValue++, s, 31);
+        break;
+    case kAttr_Index_Index_Verb:
+        nameIndex = rdata(s, data);
+        valueIndex = rbyte(s);
+        break;
+    default:
+        SkASSERT(!"bad verb");
+        return;
+    }
+    writer.addAttribute(rec.fNames[nameIndex], rec.fValues[valueIndex]);
+}
+
+static void relem(unsigned verb, SkStream& s, BMLW& rec, SkXMLWriter& writer)
+{
+    int data = verb & 31;
+    verb >>= 5;
+
+    int elemIndex;
+
+    if (verb == kStartElem_Value_Verb)
+    {
+        elemIndex = rec.fNextElem;      // record before the ++
+        set(rec.fElems, rec.fNextElem++, s, data);
+    }
+    else
+    {
+        SkASSERT(verb == kStartElem_Index_Verb);
+        elemIndex = rdata(s, data);
+    }
+
+    writer.startElement(rec.fElems[elemIndex]);
+
+    for (;;)
+    {
+        verb = rbyte(s);
+        switch (verb >> 5) {
+        case kAttr_Value_Value_Verb:
+        case kAttr_Value_Index_Verb:
+        case kAttr_Index_Value_Verb:
+        case kAttr_Index_Index_Verb:
+            rattr(verb, s, rec, writer);
+            break;
+        case kStartElem_Value_Verb:
+        case kStartElem_Index_Verb:
+            relem(verb, s, rec, writer);
+            break;
+        case kEndElem_Verb:
+            writer.endElement();
+            return;
+        default:
+            SkASSERT(!"bad verb");
+        }
+    }
+}
+
+void BML_XMLParser::Read(SkStream& s, SkXMLWriter& writer)
+{
+    BMLW rec;
+    writer.writeHeader();
+    relem(rbyte(s), s, rec, writer);
+}
+
+void BML_XMLParser::Read(SkStream& s, SkWStream& output)
+{
+    SkXMLStreamWriter writer(&output);
+    Read(s, writer);
+}
+
+void BML_XMLParser::Read(SkStream& s, SkXMLParser& output)
+{
+    SkXMLParserWriter writer(&output);
+    Read(s, writer);
+}
+
+
+