content: /*
   * Copyright 2008 Android4ME
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.googlecode.android4me.res;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.Reader;
  import org.xmlpull.v1.XmlPullParserException;
  import com.googlecode.android4me.util.TypedValue;
  
  /**
   * @author Dmitry Skiba
   *
   * Binary xml files parser.
   *
   * Parser has only two states:
   * (1) Operational state, which parser obtains after first successful call
   * to next() and retains until open(), close(), or failed call to next().
   * (2) Closed state, which parser obtains after open(), close(), or failed
   * call to next(). In this state methods return invalid values or throw exceptions.
   *
   * TODO:
   * 	* check all methods in closed state
   *
   */
  public class AXmlResourceParser implements XmlResourceParser {
  
      public AXmlResourceParser() {
          resetEventInfo();
      }
  
      public void open(InputStream stream) {
          close();
          if (stream != null) {
              m_reader = new IntReader(stream, false);
          }
      }
  
      public void close() {
          if (!m_operational) {
              return;
          }
          m_operational = false;
          m_reader.close();
          m_reader = null;
          m_strings = null;
          m_resourceIDs = null;
          m_namespaces.reset();
          resetEventInfo();
      }
  
      /////////////////////////////////// iteration
      public int next() throws XmlPullParserException, IOException {
          if (m_reader == null) {
              throw new XmlPullParserException("Parser is not opened.", this, null);
          }
          try {
              doNext();
              return m_event;
          } catch (IOException e) {
              close();
              throw e;
          }
      }
  
      public int nextToken() throws XmlPullParserException, IOException {
          return next();
      }
  
      public int nextTag() throws XmlPullParserException, IOException {
          int eventType = next();
          if (eventType == TEXT && isWhitespace()) {
              eventType = next();
          }
          if (eventType != START_TAG && eventType != END_TAG) {
              throw new XmlPullParserException("Expected start or end tag.", this, null);
          }
          return eventType;
      }
  
      public String nextText() throws XmlPullParserException, IOException {
          if (getEventType() != START_TAG) {
              throw new XmlPullParserException("Parser must be on START_TAG to read next text.", this, null);
          }
          int eventType = next();
          if (eventType == TEXT) {
              String result = getText();
              eventType = next();
              if (eventType != END_TAG) {
                  throw new XmlPullParserException("Event TEXT must be immediately followed by END_TAG.", this, null);
              }
              return result;
          } else if (eventType == END_TAG) {
              return "";
          } else {
              throw new XmlPullParserException("Parser must be on START_TAG or TEXT to read text.", this, null);
          }
      }
  
      public void require(int type, String namespace, String name) throws XmlPullParserException, IOException {
          if (type != getEventType()
                  || (namespace != null && !namespace.equals(getNamespace()))
                  || (name != null && !name.equals(getName()))) {
              throw new XmlPullParserException(TYPES[type] + " is expected.", this, null);
          }
      }
  
      public int getDepth() {
          return m_namespaces.getDepth() - 1;
      }
  
      public int getEventType() throws XmlPullParserException {
          return m_event;
      }
  
      public int getLineNumber() {
          return m_lineNumber;
      }
  
      public String getName() {
          if (m_name == -1 || (m_event != START_TAG && m_event != END_TAG)) {
              return null;
          }
          return m_strings.getString(m_name);
      }
  
      public String getText() {
          if (m_name == -1 || m_event != TEXT) {
              return null;
          }
          return m_strings.getString(m_name);
      }
  
      public char[] getTextCharacters(int[] holderForStartAndLength) {
          String text = getText();
          if (text == null) {
              return null;
          }
          holderForStartAndLength[0] = 0;
          holderForStartAndLength[1] = text.length();
          char[] chars = new char[text.length()];
          text.getChars(0, text.length(), chars, 0);
          return chars;
      }
  
      public String getNamespace() {
          return m_strings.getString(m_namespaceUri);
      }
  
      public String getPrefix() {
          int prefix = m_namespaces.findPrefix(m_namespaceUri);
          return m_strings.getString(prefix);
      }
  
      public String getPositionDescription() {
          return "XML line #" + getLineNumber();
      }
  
      public int getNamespaceCount(int depth) throws XmlPullParserException {
          return m_namespaces.getAccumulatedCount(depth);
      }
  
      public String getNamespacePrefix(int pos) throws XmlPullParserException {
          int prefix = m_namespaces.getPrefix(pos);
          return m_strings.getString(prefix);
      }
  
      public String getNamespaceUri(int pos) throws XmlPullParserException {
          int uri = m_namespaces.getUri(pos);
          return m_strings.getString(uri);
      }
  
      /////////////////////////////////// attributes
      public String getClassAttribute() {
          if (m_classAttribute == -1) {
              return null;
          }
          int offset = getAttributeOffset(m_classAttribute);
          int value = m_attributes[offset + ATTRIBUTE_IX_VALUE_STRING];
          return m_strings.getString(value);
      }
  
      public String getIdAttribute() {
          if (m_idAttribute == -1) {
              return null;
          }
          int offset = getAttributeOffset(m_idAttribute);
          int value = m_attributes[offset + ATTRIBUTE_IX_VALUE_STRING];
          return m_strings.getString(value);
      }
  
      public int getIdAttributeResourceValue(int defaultValue) {
          if (m_idAttribute == -1) {
              return defaultValue;
          }
          int offset = getAttributeOffset(m_idAttribute);
          int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
          if (valueType != TypedValue.TYPE_REFERENCE) {
              return defaultValue;
          }
          return m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
      }
  
      public int getStyleAttribute() {
          if (m_styleAttribute == -1) {
              return 0;
          }
          int offset = getAttributeOffset(m_styleAttribute);
          return m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
      }
  
      public int getAttributeCount() {
          if (m_event != START_TAG) {
              return -1;
          }
          return m_attributes.length / ATTRIBUTE_LENGHT;
      }
  
      public String getAttributeNamespace(int index) {
          int offset = getAttributeOffset(index);
          int namespace = m_attributes[offset + ATTRIBUTE_IX_NAMESPACE_URI];
          if (namespace == -1) {
              return "";
          }
          return m_strings.getString(namespace);
      }
  
      public String getAttributePrefix(int index) {
          int offset = getAttributeOffset(index);
          int uri = m_attributes[offset + ATTRIBUTE_IX_NAMESPACE_URI];
          int prefix = m_namespaces.findPrefix(uri);
          if (prefix == -1) {
              return "";
          }
          return m_strings.getString(prefix);
      }
  
      public String getAttributeName(int index) {
          int offset = getAttributeOffset(index);
          int name = m_attributes[offset + ATTRIBUTE_IX_NAME];
          if (name == -1) {
              return "";
          }
          return m_strings.getString(name);
      }
  
      public int getAttributeNameResource(int index) {
          int offset = getAttributeOffset(index);
          int name = m_attributes[offset + ATTRIBUTE_IX_NAME];
          if (m_resourceIDs == null
                  || name < 0 || name >= m_resourceIDs.length) {
              return 0;
          }
          return m_resourceIDs[name];
      }
  
      public int getAttributeValueType(int index) {
          int offset = getAttributeOffset(index);
          return m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
      }
  
      public int getAttributeValueData(int index) {
          int offset = getAttributeOffset(index);
          return m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
      }
  
      public String getAttributeValue(int index) {
          int offset = getAttributeOffset(index);
          int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
          if (valueType == TypedValue.TYPE_STRING) {
              int valueString = m_attributes[offset + ATTRIBUTE_IX_VALUE_STRING];
              return m_strings.getString(valueString);
          }
          int valueData = m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
          return "";//TypedValue.coerceToString(valueType,valueData);
      }
  
      public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
          return getAttributeIntValue(index, defaultValue ? 1 : 0) != 0;
      }
  
      public float getAttributeFloatValue(int index, float defaultValue) {
          int offset = getAttributeOffset(index);
          int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
          if (valueType == TypedValue.TYPE_FLOAT) {
              int valueData = m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
              return Float.intBitsToFloat(valueData);
          }
          return defaultValue;
      }
  
      public int getAttributeIntValue(int index, int defaultValue) {
          int offset = getAttributeOffset(index);
          int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
          if (valueType >= TypedValue.TYPE_FIRST_INT
                  && valueType <= TypedValue.TYPE_LAST_INT) {
              return m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
          }
          return defaultValue;
      }
  
      public int getAttributeUnsignedIntValue(int index, int defaultValue) {
          return getAttributeIntValue(index, defaultValue);
      }
  
      public int getAttributeResourceValue(int index, int defaultValue) {
          int offset = getAttributeOffset(index);
          int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
          if (valueType == TypedValue.TYPE_REFERENCE) {
              return m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
          }
          return defaultValue;
      }
  
      public String getAttributeValue(String namespace, String attribute) {
          int index = findAttribute(namespace, attribute);
          if (index == -1) {
              return null;
          }
          return getAttributeValue(index);
      }
  
      public boolean getAttributeBooleanValue(String namespace, String attribute, boolean defaultValue) {
          int index = findAttribute(namespace, attribute);
          if (index == -1) {
              return defaultValue;
          }
          return getAttributeBooleanValue(index, defaultValue);
      }
  
      public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) {
          int index = findAttribute(namespace, attribute);
          if (index == -1) {
              return defaultValue;
          }
          return getAttributeFloatValue(index, defaultValue);
      }
  
      public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
          int index = findAttribute(namespace, attribute);
          if (index == -1) {
              return defaultValue;
          }
          return getAttributeIntValue(index, defaultValue);
      }
  
      public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) {
          int index = findAttribute(namespace, attribute);
          if (index == -1) {
              return defaultValue;
          }
          return getAttributeUnsignedIntValue(index, defaultValue);
      }
  
      public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
          int index = findAttribute(namespace, attribute);
          if (index == -1) {
              return defaultValue;
          }
          return getAttributeResourceValue(index, defaultValue);
      }
  
      public int getAttributeListValue(int index, String[] options, int defaultValue) {
          // TODO implement
          return 0;
      }
  
      public int getAttributeListValue(String namespace, String attribute, String[] options, int defaultValue) {
          // TODO implement
          return 0;
      }
  
      public String getAttributeType(int index) {
          return "CDATA";
      }
  
      public boolean isAttributeDefault(int index) {
          return false;
      }
  
      /////////////////////////////////// dummies
      public void setInput(InputStream stream, String inputEncoding) throws XmlPullParserException {
          throw new XmlPullParserException(E_NOT_SUPPORTED);
      }
  
      public void setInput(Reader reader) throws XmlPullParserException {
          throw new XmlPullParserException(E_NOT_SUPPORTED);
      }
  
      public String getInputEncoding() {
          return null;
      }
  
      public int getColumnNumber() {
          return -1;
      }
  
      public boolean isEmptyElementTag() throws XmlPullParserException {
          return false;
      }
  
      public boolean isWhitespace() throws XmlPullParserException {
          return false;
      }
  
      public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException {
          throw new XmlPullParserException(E_NOT_SUPPORTED);
      }
  
      public String getNamespace(String prefix) {
          throw new RuntimeException(E_NOT_SUPPORTED);
      }
  
      public Object getProperty(String name) {
          return null;
      }
  
      public void setProperty(String name, Object value) throws XmlPullParserException {
          throw new XmlPullParserException(E_NOT_SUPPORTED);
      }
  
      public boolean getFeature(String feature) {
          return false;
      }
  
      public void setFeature(String name, boolean value) throws XmlPullParserException {
          throw new XmlPullParserException(E_NOT_SUPPORTED);
      }
  
      ///////////////////////////////////////////// implementation
      /**
       * Namespace stack, holds prefix+uri pairs, as well as
       * depth information.
       * All information is stored in one int[] array.
       * Array consists of depth frames:
       * Data=DepthFrame*;
       * DepthFrame=Count+[Prefix+Uri]*+Count;
       * Count='count of Prefix+Uri pairs';
       * Yes, count is stored twice, to enable bottom-up traversal.
       * increaseDepth adds depth frame, decreaseDepth removes it.
       * push/pop operations operate only in current depth frame.
       * decreaseDepth removes any remaining (not pop'ed) namespace pairs.
       * findXXX methods search all depth frames starting
       * from the last namespace pair of current depth frame.
       * All functions that operate with int, use -1 as 'invalid value'.
       *
       * !! functions expect 'prefix'+'uri' pairs, not 'uri'+'prefix' !!
       *
       */
      private static final class NamespaceStack {
  
          public NamespaceStack() {
              m_data = new int[32];
          }
  
          public void reset() {
              m_dataLength = 0;
              m_count = 0;
              m_depth = 0;
          }
  
          public int getTotalCount() {
              return m_count;
          }
  
          public int getCurrentCount() {
              if (m_dataLength == 0) {
                  return 0;
              }
              int offset = m_dataLength - 1;
              return m_data[offset];
          }
  
          public int getAccumulatedCount(int depth) {
              if (m_dataLength == 0 || depth < 0) {
                  return 0;
              }
              if (depth > m_depth) {
                  depth = m_depth;
              }
              int accumulatedCount = 0;
              int offset = 0;
              for (; depth > 0; --depth) {
                  int count = m_data[offset];
                  accumulatedCount += count;
                  offset += (2 + count * 2);
              }
              return accumulatedCount;
          }
  
          public void push(int prefix, int uri) {
              if (m_depth == 0) {
                  increaseDepth();
              }
              ensureDataCapacity(2);
              int offset = m_dataLength - 1;
              int count = m_data[offset];
              m_data[offset - 1 - count * 2] = count + 1;
              m_data[offset] = prefix;
              m_data[offset + 1] = uri;
              m_data[offset + 2] = count + 1;
              m_dataLength += 2;
              m_count += 1;
          }
  
          public boolean pop(int prefix, int uri) {
              if (m_dataLength == 0) {
                  return false;
              }
              int offset = m_dataLength - 1;
              int count = m_data[offset];
              for (int i = 0, o = offset - 2; i != count; ++i, o -= 2) {
                  if (m_data[o] != prefix || m_data[o + 1] != uri) {
                      continue;
                  }
                  count -= 1;
                  if (i == 0) {
                      m_data[o] = count;
                      o -= (1 + count * 2);
                      m_data[o] = count;
                  } else {
                      m_data[offset] = count;
                      offset -= (1 + 2 + count * 2);
                      m_data[offset] = count;
                      System.arraycopy(
                              m_data, o + 2,
                              m_data, o,
                              m_dataLength - o);
                  }
                  m_dataLength -= 2;
                  m_count -= 1;
                  return true;
              }
              return false;
          }
  
          public boolean pop() {
              if (m_dataLength == 0) {
                  return false;
              }
              int offset = m_dataLength - 1;
              int count = m_data[offset];
              if (count == 0) {
                  return false;
              }
              count -= 1;
              offset -= 2;
              m_data[offset] = count;
              offset -= (1 + count * 2);
              m_data[offset] = count;
              m_dataLength -= 2;
              m_count -= 1;
              return true;
          }
  
          public int getPrefix(int index) {
              return get(index, true);
          }
  
          public int getUri(int index) {
              return get(index, false);
          }
  
          public int findPrefix(int uri) {
              return find(uri, false);
          }
  
          public int findUri(int prefix) {
              return find(prefix, true);
          }
  
          public int getDepth() {
              return m_depth;
          }
  
          public void increaseDepth() {
              ensureDataCapacity(2);
              int offset = m_dataLength;
              m_data[offset] = 0;
              m_data[offset + 1] = 0;
              m_dataLength += 2;
              m_depth += 1;
          }
  
          public void decreaseDepth() {
              if (m_dataLength == 0) {
                  return;
              }
              int offset = m_dataLength - 1;
              int count = m_data[offset];
              if ((offset - 1 - count * 2) == 0) {
                  return;
              }
              m_dataLength -= 2 + count * 2;
              m_count -= count;
              m_depth -= 1;
          }
  
          private void ensureDataCapacity(int capacity) {
              int available = (m_data.length - m_dataLength);
              if (available > capacity) {
                  return;
              }
              int newLength = (m_data.length + available) * 2;
              int[] newData = new int[newLength];
              System.arraycopy(m_data, 0, newData, 0, m_dataLength);
              m_data = newData;
          }
  
          private int find(int prefixOrUri, boolean prefix) {
              if (m_dataLength == 0) {
                  return -1;
              }
              int offset = m_dataLength - 1;
              for (int i = m_depth; i != 0; --i) {
                  int count = m_data[offset];
                  offset -= 2;
                  for (; count != 0; --count) {
                      if (prefix) {
                          if (m_data[offset] == prefixOrUri) {
                              return m_data[offset + 1];
                          }
                      } else {
                          if (m_data[offset + 1] == prefixOrUri) {
                              return m_data[offset];
                          }
                      }
                      offset -= 2;
                  }
              }
              return -1;
          }
  
          private int get(int index, boolean prefix) {
              if (m_dataLength == 0 || index < 0) {
                  return -1;
              }
              int offset = 0;
              for (int i = m_depth; i != 0; --i) {
                  int count = m_data[offset];
                  if (index >= count) {
                      index -= count;
                      offset += (2 + count * 2);
                      continue;
                  }
                  offset += (1 + index * 2);
                  if (!prefix) {
                      offset += 1;
                  }
                  return m_data[offset];
              }
              return -1;
          }
          private int[] m_data;
          private int m_dataLength;
          private int m_count;
          private int m_depth;
      }
  
      /////////////////////////////////// package-visible
  //	final void fetchAttributes(int[] styleableIDs,TypedArray result) {
  //		result.resetIndices();
  //		if (m_attributes==null || m_resourceIDs==null) {
  //			return;
  //		}
  //		boolean needStrings=false;
  //		for (int i=0,e=styleableIDs.length;i!=e;++i) {
  //			int id=styleableIDs[i];
  //			for (int o=0;o!=m_attributes.length;o+=ATTRIBUTE_LENGHT) {
  //				int name=m_attributes[o+ATTRIBUTE_IX_NAME];
  //				if (name>=m_resourceIDs.length ||
  //					m_resourceIDs[name]!=id)
  //				{
  //					continue;
  //				}
  //				int valueType=m_attributes[o+ATTRIBUTE_IX_VALUE_TYPE];
  //				int valueData;
  //				int assetCookie;
  //				if (valueType==TypedValue.TYPE_STRING) {
  //					valueData=m_attributes[o+ATTRIBUTE_IX_VALUE_STRING];
  //					assetCookie=-1;
  //					needStrings=true;
  //				} else {
  //					valueData=m_attributes[o+ATTRIBUTE_IX_VALUE_DATA];
  //					assetCookie=0;
  //				}
  //				result.addValue(i,valueType,valueData,assetCookie,id,0);
  //			}
  //		}
  //		if (needStrings) {
  //			result.setStrings(m_strings);
  //		}
  //	}
      final StringBlock getStrings() {
          return m_strings;
      }
  
      ///////////////////////////////////
      private int getAttributeOffset(int index) {
          if (m_event != START_TAG) {
              throw new IndexOutOfBoundsException("Current event is not START_TAG.");
          }
          int offset = index * 5;
          if (offset >= m_attributes.length) {
              throw new IndexOutOfBoundsException("Invalid attribute index (" + index + ").");
          }
          return offset;
      }
  
      private int findAttribute(String namespace, String attribute) {
          if (m_strings == null || attribute == null) {
              return -1;
          }
          int name = m_strings.find(attribute);
          if (name == -1) {
              return -1;
          }
          int uri = (namespace != null)
                  ? m_strings.find(namespace)
                  : -1;
          for (int o = 0; o != m_attributes.length; ++o) {
              if (name == m_attributes[o + ATTRIBUTE_IX_NAME]
                      && (uri == -1 || uri == m_attributes[o + ATTRIBUTE_IX_NAMESPACE_URI])) {
                  return o / ATTRIBUTE_LENGHT;
              }
          }
          return -1;
      }
  
      private void resetEventInfo() {
          m_event = -1;
          m_lineNumber = -1;
          m_name = -1;
          m_namespaceUri = -1;
          m_attributes = null;
          m_idAttribute = -1;
          m_classAttribute = -1;
          m_styleAttribute = -1;
      }
  
      private void doNext() throws IOException {
          // Delayed initialization.
          if (m_strings == null) {
              ChunkUtil.readCheckType(m_reader, CHUNK_AXML_FILE);
              /*chunkSize*/            m_reader.skipInt();
              m_strings = StringBlock.read(m_reader);
              m_namespaces.increaseDepth();
              m_operational = true;
          }
  
          if (m_event == END_DOCUMENT) {
              return;
          }
  
          int event = m_event;
          resetEventInfo();
  
          while (true) {
              if (m_decreaseDepth) {
                  m_decreaseDepth = false;
                  m_namespaces.decreaseDepth();
              }
  
              // Fake END_DOCUMENT event.
              if (event == END_TAG
                      && m_namespaces.getDepth() == 1
                      && m_namespaces.getCurrentCount() == 0) {
                  m_event = END_DOCUMENT;
                  break;
              }
  
              int chunkType;
              if (event == START_DOCUMENT) {
                  // Fake event, see CHUNK_XML_START_TAG handler.
                  chunkType = CHUNK_XML_START_TAG;
              } else {
                  chunkType = m_reader.readInt();
              }
  
              if (chunkType == CHUNK_RESOURCEIDS) {
                  int chunkSize = m_reader.readInt();
                  if (chunkSize < 8 || (chunkSize % 4) != 0) {
                      throw new IOException("Invalid resource ids size (" + chunkSize + ").");
                  }
                  m_resourceIDs = m_reader.readIntArray(chunkSize / 4 - 2);
                  continue;
              }
  
              if (chunkType < CHUNK_XML_FIRST || chunkType > CHUNK_XML_LAST) {
                  throw new IOException("Invalid chunk type (" + chunkType + ").");
              }
  
              // Fake START_DOCUMENT event.
              if (chunkType == CHUNK_XML_START_TAG && event == -1) {
                  m_event = START_DOCUMENT;
                  break;
              }
  
              // Common header.
  			/*chunkSize*/            m_reader.skipInt();
              int lineNumber = m_reader.readInt();
              /*0xFFFFFFFF*/            m_reader.skipInt();
  
              if (chunkType == CHUNK_XML_START_NAMESPACE
                      || chunkType == CHUNK_XML_END_NAMESPACE) {
                  if (chunkType == CHUNK_XML_START_NAMESPACE) {
                      int prefix = m_reader.readInt();
                      int uri = m_reader.readInt();
                      m_namespaces.push(prefix, uri);
                  } else {
                      /*prefix*/                    m_reader.skipInt();
                      /*uri*/                    m_reader.skipInt();
                      m_namespaces.pop();
                  }
                  continue;
              }
  
              m_lineNumber = lineNumber;
  
              if (chunkType == CHUNK_XML_START_TAG) {
                  m_namespaceUri = m_reader.readInt();
                  m_name = m_reader.readInt();
                  /*flags?*/                m_reader.skipInt();
                  int attributeCount = m_reader.readInt();
                  m_idAttribute = (attributeCount >>> 16) - 1;
                  attributeCount &= 0xFFFF;
                  m_classAttribute = m_reader.readInt();
                  m_styleAttribute = (m_classAttribute >>> 16) - 1;
                  m_classAttribute = (m_classAttribute & 0xFFFF) - 1;
                  m_attributes = m_reader.readIntArray(attributeCount * ATTRIBUTE_LENGHT);
                  for (int i = ATTRIBUTE_IX_VALUE_TYPE; i < m_attributes.length;) {
                      m_attributes[i] = (m_attributes[i] >>> 24);
                      i += ATTRIBUTE_LENGHT;
                  }
                  m_namespaces.increaseDepth();
                  m_event = START_TAG;
                  break;
              }
  
              if (chunkType == CHUNK_XML_END_TAG) {
                  m_namespaceUri = m_reader.readInt();
                  m_name = m_reader.readInt();
                  m_event = END_TAG;
                  m_decreaseDepth = true;
                  break;
              }
  
              if (chunkType == CHUNK_XML_TEXT) {
                  m_name = m_reader.readInt();
                  /*?*/                m_reader.skipInt();
                  /*?*/                m_reader.skipInt();
                  m_event = TEXT;
                  break;
              }
          }
      }
      /////////////////////////////////// data
      /*
       * All values are essentially indices, e.g. m_name is
       * an index of name in m_strings.
       */
      private IntReader m_reader;
      private boolean m_operational = false;
      private StringBlock m_strings;
      private int[] m_resourceIDs;
      private NamespaceStack m_namespaces = new NamespaceStack();
      private boolean m_decreaseDepth;
      private int m_event;
      private int m_lineNumber;
      private int m_name;
      private int m_namespaceUri;
      private int[] m_attributes;
      private int m_idAttribute;
      private int m_classAttribute;
      private int m_styleAttribute;
      private static final String E_NOT_SUPPORTED = "Method is not supported.";
      private static final int ATTRIBUTE_IX_NAMESPACE_URI = 0,
              ATTRIBUTE_IX_NAME = 1,
              ATTRIBUTE_IX_VALUE_STRING = 2,
              ATTRIBUTE_IX_VALUE_TYPE = 3,
              ATTRIBUTE_IX_VALUE_DATA = 4,
              ATTRIBUTE_LENGHT = 5;
      private static final int CHUNK_AXML_FILE = 0x00080003,
              CHUNK_RESOURCEIDS = 0x00080180,
              CHUNK_XML_FIRST = 0x00100100,
              CHUNK_XML_START_NAMESPACE = 0x00100100,
              CHUNK_XML_END_NAMESPACE = 0x00100101,
              CHUNK_XML_START_TAG = 0x00100102,
              CHUNK_XML_END_TAG = 0x00100103,
              CHUNK_XML_TEXT = 0x00100104,
              CHUNK_XML_LAST = 0x00100104;
  }
  