• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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 
rbyte(SkStream & s)23 static 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 
rdata(SkStream & s,int data)31 static 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 
set(char * array[256],int index,SkStream & s,int data)46 static 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 
freeAll(char * array[256])64 static void freeAll(char* array[256])
65 {
66     for (int i = 0; i < 256; i++)
67         sk_free(array[i]);
68 }
69 
70 struct 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 
BMLWBMLW78     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     }
~BMLWBMLW86     ~BMLW()
87     {
88         freeAll(fElems);
89         freeAll(fNames);
90         freeAll(fValues);
91     }
92 };
93 
rattr(unsigned verb,SkStream & s,BMLW & rec,SkXMLWriter & writer)94 static 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 
relem(unsigned verb,SkStream & s,BMLW & rec,SkXMLWriter & writer)129 static 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 
Read(SkStream & s,SkXMLWriter & writer)172 void BML_XMLParser::Read(SkStream& s, SkXMLWriter& writer)
173 {
174     BMLW rec;
175     writer.writeHeader();
176     relem(rbyte(s), s, rec, writer);
177 }
178 
Read(SkStream & s,SkWStream & output)179 void BML_XMLParser::Read(SkStream& s, SkWStream& output)
180 {
181     SkXMLStreamWriter writer(&output);
182     Read(s, writer);
183 }
184 
Read(SkStream & s,SkXMLParser & output)185 void BML_XMLParser::Read(SkStream& s, SkXMLParser& output)
186 {
187     SkXMLParserWriter writer(&output);
188     Read(s, writer);
189 }
190 
191 
192 
193