blob: c0a5af55e56837ed36be5ff18c6ae773623a1157 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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;
humper@google.com0e515772013-01-07 19:54:40 +000018 SkDEBUGCODE(size_t size = ) s.read(&b, 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +000019 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] == NULL)
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:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000115 SkDEBUGFAIL("bad verb");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 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:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000159 SkDEBUGFAIL("bad verb");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 }
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}