All Downloads are FREE. Search and download functionalities are using the official Maven repository.

brut.androlib.res.data.axml.NamespaceStack Maven / Gradle / Ivy

/*
 *  Copyright (C) 2010 Ryszard Wiśniewski 
 *  Copyright (C) 2010 Connor Tumbleson 
 *
 *  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
 *
 *       https://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 brut.androlib.res.data.axml;

/**
 * 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' !! */ public final class NamespaceStack { private int[] m_data; private int m_dataLength; private int m_depth; public NamespaceStack() { m_data = new int[32]; } public void reset() { m_dataLength = 0; m_depth = 0; } 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; } 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; 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 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_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; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy