com.squareup.spoon.axmlparser.StringBlock Maven / Gradle / Ivy
The newest version!
/*
* 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.squareup.spoon.axmlparser;
import java.io.IOException;
/**
* @author Dmitry Skiba
*
* Block of strings, used in binary xml and arsc.
*
* TODO:
* - implement get()
*
*/
public class StringBlock {
/**
* Reads whole (including chunk type) string block from stream.
* Stream must be at the chunk type.
*/
public static StringBlock read(IntReader reader) throws IOException {
ReadUtil.readCheckType(reader,CHUNK_TYPE);
int chunkSize=reader.readInt();
int stringCount=reader.readInt();
int styleOffsetCount=reader.readInt();
/*?*/reader.readInt();
int stringsOffset=reader.readInt();
int stylesOffset=reader.readInt();
StringBlock block=new StringBlock();
block.m_stringOffsets=reader.readIntArray(stringCount);
if (styleOffsetCount!=0) {
block.m_styleOffsets=reader.readIntArray(styleOffsetCount);
}
{
int size=((stylesOffset==0)?chunkSize:stylesOffset)-stringsOffset;
if ((size%4)!=0) {
throw new IOException("String data size is not multiple of 4 ("+size+").");
}
block.m_strings=reader.readIntArray(size/4);
}
if (stylesOffset!=0) {
int size=(chunkSize-stylesOffset);
if ((size%4)!=0) {
throw new IOException("Style data size is not multiple of 4 ("+size+").");
}
block.m_styles=reader.readIntArray(size/4);
}
block.s=new String[block.getCount()];
for (int i=0;i!=block.getCount();++i) {
block.s[i]=block.getRaw(i);
}
return block;
}
public String[] s;
/**
* Returns number of strings in block.
*/
public int getCount() {
return m_stringOffsets!=null?
m_stringOffsets.length:
0;
}
/**
* Returns raw string (without any styling information) at specified index.
* Returns null if index is invalid or object was not initialized.
*/
public String getRaw(int index) {
if (index<0 ||
m_stringOffsets==null ||
index>=m_stringOffsets.length)
{
return null;
}
int offset=m_stringOffsets[index];
int length=getShort(m_strings,offset);
StringBuilder result=new StringBuilder(length);
for (;length!=0;length-=1) {
offset+=2;
result.append((char)getShort(m_strings,offset));
}
return result.toString();
}
/**
* Not yet implemented.
*
* Returns string with style information (if any).
* Returns null if index is invalid or object was not initialized.
*/
public CharSequence get(int index) {
return Cast.toCharSequence(getRaw(index));
}
/**
* Returns string with style tags (html-like).
*/
public String getHTML(int index) {
String raw=getRaw(index);
if (raw==null) {
return raw;
}
int[] style=getStyle(index);
if (style==null) {
return raw;
}
StringBuilder html=new StringBuilder(raw.length()+32);
int offset=0;
while (true) {
int i=-1;
for (int j=0;j!=style.length;j+=3) {
if (style[j+1]==-1) {
continue;
}
if (i==-1 || style[i+1]>style[j+1]) {
i=j;
}
}
int start=((i!=-1)?style[i+1]:raw.length());
for (int j=0;j!=style.length;j+=3) {
int end=style[j+2];
if (end==-1 || end>=start) {
continue;
}
if (offset<=end) {
html.append(raw,offset,end+1);
offset=end+1;
}
style[j+2]=-1;
html.append('<');
html.append('/');
html.append(getRaw(style[j]));
html.append('>');
}
if (offset');
style[i+1]=-1;
}
return html.toString();
}
/**
* Finds index of the string.
* Returns -1 if the string was not found.
*/
public int find(String string) {
if (string==null) {
return -1;
}
for (int i=0;i!=m_stringOffsets.length;++i) {
int offset=m_stringOffsets[i];
int length=getShort(m_strings,offset);
if (length!=string.length()) {
continue;
}
int j=0;
for (;j!=length;++j) {
offset+=2;
if (string.charAt(j)!=getShort(m_strings,offset)) {
break;
}
}
if (j==length) {
return i;
}
}
return -1;
}
///////////////////////////////////////////// implementation
private StringBlock() {
}
/**
* Returns style information - array of int triplets,
* where in each triplet:
* * first int is index of tag name ('b','i', etc.)
* * second int is tag start index in string
* * third int is tag end index in string
*/
private int[] getStyle(int index) {
if (m_styleOffsets==null || m_styles==null ||
index>=m_styleOffsets.length)
{
return null;
}
int offset=m_styleOffsets[index]/4;
int style[];
{
int count=0;
for (int i=offset;i>> 16);
}
}
private int[] m_stringOffsets;
private int[] m_strings;
private int[] m_styleOffsets;
private int[] m_styles;
private static final int CHUNK_TYPE=0x001C0001;
}