1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkBML_XMLParser.h"
11#include "SkBML_Verbs.h"
12#include "SkStream.h"
13#include "SkXMLWriter.h"
14
15static uint8_t rbyte(SkStream& s)
16{
17    uint8_t b;
18    SkDEBUGCODE(size_t size = ) s.read(&b, 1);
19    SkASSERT(size == 1);
20    return b;
21}
22
23static int rdata(SkStream& s, int data)
24{
25    SkASSERT((data & ~31) == 0);
26    if (data == 31)
27    {
28        data = rbyte(s);
29        if (data == 0xFF)
30        {
31            data = rbyte(s);
32            data = (data << 8) | rbyte(s);
33        }
34    }
35    return data;
36}
37
38static void set(char* array[256], int index, SkStream& s, int data)
39{
40    SkASSERT((unsigned)index <= 255);
41
42    size_t size = rdata(s, data);
43
44    if (array[index] == nullptr)
45        array[index] = (char*)sk_malloc_throw(size + 1);
46    else
47    {
48        if (strlen(array[index]) < size)
49            array[index] = (char*)sk_realloc_throw(array[index], size + 1);
50    }
51
52    s.read(array[index], size);
53    array[index][size] = 0;
54}
55
56static void freeAll(char* array[256])
57{
58    for (int i = 0; i < 256; i++)
59        sk_free(array[i]);
60}
61
62struct BMLW {
63    char*   fElems[256];
64    char*   fNames[256];
65    char*   fValues[256];
66
67    // important that these are uint8_t, so we get automatic wrap-around
68    uint8_t  fNextElem, fNextName, fNextValue;
69
70    BMLW()
71    {
72        memset(fElems, 0, sizeof(fElems));
73        memset(fNames, 0, sizeof(fNames));
74        memset(fValues, 0, sizeof(fValues));
75
76        fNextElem = fNextName = fNextValue = 0;
77    }
78    ~BMLW()
79    {
80        freeAll(fElems);
81        freeAll(fNames);
82        freeAll(fValues);
83    }
84};
85
86static void rattr(unsigned verb, SkStream& s, BMLW& rec, SkXMLWriter& writer)
87{
88    int data = verb & 31;
89    verb >>= 5;
90
91    int nameIndex, valueIndex;
92
93    switch (verb) {
94    case kAttr_Value_Value_Verb:
95        nameIndex = rec.fNextName;      // record before the ++
96        set(rec.fNames, rec.fNextName++, s, data);
97        valueIndex = rec.fNextValue;    // record before the ++
98        set(rec.fValues, rec.fNextValue++, s, 31);
99        break;
100    case kAttr_Value_Index_Verb:
101        nameIndex = rec.fNextName;      // record before the ++
102        set(rec.fNames, rec.fNextName++, s, data);
103        valueIndex = rbyte(s);
104        break;
105    case kAttr_Index_Value_Verb:
106        nameIndex = rdata(s, data);
107        valueIndex = rec.fNextValue;    // record before the ++
108        set(rec.fValues, rec.fNextValue++, s, 31);
109        break;
110    case kAttr_Index_Index_Verb:
111        nameIndex = rdata(s, data);
112        valueIndex = rbyte(s);
113        break;
114    default:
115        SkDEBUGFAIL("bad verb");
116        return;
117    }
118    writer.addAttribute(rec.fNames[nameIndex], rec.fValues[valueIndex]);
119}
120
121static void relem(unsigned verb, SkStream& s, BMLW& rec, SkXMLWriter& writer)
122{
123    int data = verb & 31;
124    verb >>= 5;
125
126    int elemIndex;
127
128    if (verb == kStartElem_Value_Verb)
129    {
130        elemIndex = rec.fNextElem;      // record before the ++
131        set(rec.fElems, rec.fNextElem++, s, data);
132    }
133    else
134    {
135        SkASSERT(verb == kStartElem_Index_Verb);
136        elemIndex = rdata(s, data);
137    }
138
139    writer.startElement(rec.fElems[elemIndex]);
140
141    for (;;)
142    {
143        verb = rbyte(s);
144        switch (verb >> 5) {
145        case kAttr_Value_Value_Verb:
146        case kAttr_Value_Index_Verb:
147        case kAttr_Index_Value_Verb:
148        case kAttr_Index_Index_Verb:
149            rattr(verb, s, rec, writer);
150            break;
151        case kStartElem_Value_Verb:
152        case kStartElem_Index_Verb:
153            relem(verb, s, rec, writer);
154            break;
155        case kEndElem_Verb:
156            writer.endElement();
157            return;
158        default:
159            SkDEBUGFAIL("bad verb");
160        }
161    }
162}
163
164void BML_XMLParser::Read(SkStream& s, SkXMLWriter& writer)
165{
166    BMLW rec;
167    writer.writeHeader();
168    relem(rbyte(s), s, rec, writer);
169}
170
171void BML_XMLParser::Read(SkStream& s, SkWStream& output)
172{
173    SkXMLStreamWriter writer(&output);
174    Read(s, writer);
175}
176
177void BML_XMLParser::Read(SkStream& s, SkXMLParser& output)
178{
179    SkXMLParserWriter writer(&output);
180    Read(s, writer);
181}
182