Home | History | Annotate | Download | only in xml
      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 
     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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    179 void BML_XMLParser::Read(SkStream& s, SkWStream& output)
    180 {
    181     SkXMLStreamWriter writer(&output);
    182     Read(s, writer);
    183 }
    184 
    185 void BML_XMLParser::Read(SkStream& s, SkXMLParser& output)
    186 {
    187     SkXMLParserWriter writer(&output);
    188     Read(s, writer);
    189 }
    190 
    191 
    192 
    193