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 15 static 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 23 static 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 38 static 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 56 static void freeAll(char* array[256]) 57 { 58 for (int i = 0; i < 256; i++) 59 sk_free(array[i]); 60 } 61 62 struct 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 86 static 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 121 static 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 164 void BML_XMLParser::Read(SkStream& s, SkXMLWriter& writer) 165 { 166 BMLW rec; 167 writer.writeHeader(); 168 relem(rbyte(s), s, rec, writer); 169 } 170 171 void BML_XMLParser::Read(SkStream& s, SkWStream& output) 172 { 173 SkXMLStreamWriter writer(&output); 174 Read(s, writer); 175 } 176 177 void BML_XMLParser::Read(SkStream& s, SkXMLParser& output) 178 { 179 SkXMLParserWriter writer(&output); 180 Read(s, writer); 181 } 182