blob: 53b7f61164bce582d2a6c4d855ee75d268f34e74 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/xml/SkBML_XMLParser.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkBML_XMLParser.h"
19#include "SkBML_Verbs.h"
20#include "SkStream.h"
21#include "SkXMLWriter.h"
22
23static uint8_t rbyte(SkStream& s)
24{
25 uint8_t b;
26 size_t size = s.read(&b, 1);
27 SkASSERT(size == 1);
28 return b;
29}
30
31static int rdata(SkStream& s, int data)
32{
33 SkASSERT((data & ~31) == 0);
34 if (data == 31)
35 {
36 data = rbyte(s);
37 if (data == 0xFF)
38 {
39 data = rbyte(s);
40 data = (data << 8) | rbyte(s);
41 }
42 }
43 return data;
44}
45
46static void set(char* array[256], int index, SkStream& s, int data)
47{
48 SkASSERT((unsigned)index <= 255);
49
50 size_t size = rdata(s, data);
51
52 if (array[index] == NULL)
53 array[index] = (char*)sk_malloc_throw(size + 1);
54 else
55 {
56 if (strlen(array[index]) < size)
57 array[index] = (char*)sk_realloc_throw(array[index], size + 1);
58 }
59
60 s.read(array[index], size);
61 array[index][size] = 0;
62}
63
64static void freeAll(char* array[256])
65{
66 for (int i = 0; i < 256; i++)
67 sk_free(array[i]);
68}
69
70struct BMLW {
71 char* fElems[256];
72 char* fNames[256];
73 char* fValues[256];
74
75 // important that these are uint8_t, so we get automatic wrap-around
76 uint8_t fNextElem, fNextName, fNextValue;
77
78 BMLW()
79 {
80 memset(fElems, 0, sizeof(fElems));
81 memset(fNames, 0, sizeof(fNames));
82 memset(fValues, 0, sizeof(fValues));
83
84 fNextElem = fNextName = fNextValue = 0;
85 }
86 ~BMLW()
87 {
88 freeAll(fElems);
89 freeAll(fNames);
90 freeAll(fValues);
91 }
92};
93
94static void rattr(unsigned verb, SkStream& s, BMLW& rec, SkXMLWriter& writer)
95{
96 int data = verb & 31;
97 verb >>= 5;
98
99 int nameIndex, valueIndex;
100
101 switch (verb) {
102 case kAttr_Value_Value_Verb:
103 nameIndex = rec.fNextName; // record before the ++
104 set(rec.fNames, rec.fNextName++, s, data);
105 valueIndex = rec.fNextValue; // record before the ++
106 set(rec.fValues, rec.fNextValue++, s, 31);
107 break;
108 case kAttr_Value_Index_Verb:
109 nameIndex = rec.fNextName; // record before the ++
110 set(rec.fNames, rec.fNextName++, s, data);
111 valueIndex = rbyte(s);
112 break;
113 case kAttr_Index_Value_Verb:
114 nameIndex = rdata(s, data);
115 valueIndex = rec.fNextValue; // record before the ++
116 set(rec.fValues, rec.fNextValue++, s, 31);
117 break;
118 case kAttr_Index_Index_Verb:
119 nameIndex = rdata(s, data);
120 valueIndex = rbyte(s);
121 break;
122 default:
123 SkASSERT(!"bad verb");
124 return;
125 }
126 writer.addAttribute(rec.fNames[nameIndex], rec.fValues[valueIndex]);
127}
128
129static void relem(unsigned verb, SkStream& s, BMLW& rec, SkXMLWriter& writer)
130{
131 int data = verb & 31;
132 verb >>= 5;
133
134 int elemIndex;
135
136 if (verb == kStartElem_Value_Verb)
137 {
138 elemIndex = rec.fNextElem; // record before the ++
139 set(rec.fElems, rec.fNextElem++, s, data);
140 }
141 else
142 {
143 SkASSERT(verb == kStartElem_Index_Verb);
144 elemIndex = rdata(s, data);
145 }
146
147 writer.startElement(rec.fElems[elemIndex]);
148
149 for (;;)
150 {
151 verb = rbyte(s);
152 switch (verb >> 5) {
153 case kAttr_Value_Value_Verb:
154 case kAttr_Value_Index_Verb:
155 case kAttr_Index_Value_Verb:
156 case kAttr_Index_Index_Verb:
157 rattr(verb, s, rec, writer);
158 break;
159 case kStartElem_Value_Verb:
160 case kStartElem_Index_Verb:
161 relem(verb, s, rec, writer);
162 break;
163 case kEndElem_Verb:
164 writer.endElement();
165 return;
166 default:
167 SkASSERT(!"bad verb");
168 }
169 }
170}
171
172void BML_XMLParser::Read(SkStream& s, SkXMLWriter& writer)
173{
174 BMLW rec;
175 writer.writeHeader();
176 relem(rbyte(s), s, rec, writer);
177}
178
179void BML_XMLParser::Read(SkStream& s, SkWStream& output)
180{
181 SkXMLStreamWriter writer(&output);
182 Read(s, writer);
183}
184
185void BML_XMLParser::Read(SkStream& s, SkXMLParser& output)
186{
187 SkXMLParserWriter writer(&output);
188 Read(s, writer);
189}
190
191
192