/* * Copyright (C) 2007, 2009, 2010 IsmAvatar <IsmAvatar@gmail.com> * Copyright (C) 2006, 2007 Clam <clamisgood@gmail.com> * * This file is part of LibMaker. * LibMaker is free software and comes with ABSOLUTELY NO WARRANTY. * See LICENSE for details. */ package org.lateralgm.libmaker.file; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import org.lateralgm.libmaker.Messages; import org.lateralgm.libmaker.backend.PropertyMap; public class GmStreamDecoder extends StreamDecoder { public GmStreamDecoder(InputStream in) { super(in); } public GmStreamDecoder(String path) throws FileNotFoundException { super(path); } public GmStreamDecoder(File f) throws FileNotFoundException { super(f); } public int read(byte b[]) throws IOException { return read(b,0,b.length); } public int read(byte b[], int off, int len) throws IOException { int total = 0; while (true) { int n = in.read(b,off + total,len - total); if (n <= 0) { if (total == 0) total = n; break; } total += n; if (total == len) break; } if (total != len) { String error = Messages.format("StreamDecoder.UNEXPECTED_EOF",getPosString()); //$NON-NLS-1$ throw new IOException(error); } pos += len; return total; } public int read() throws IOException { int t = in.read(); if (t == -1) { String error = Messages.format("StreamDecoder.UNEXPECTED_EOF",getPosString()); //$NON-NLS-1$ throw new IOException(error); } pos++; return t; } /** * ISO-8859-1 was the fixed charset in earlier LGM versions, so those parts of the code which * have not been updated to set the charset explicitly should continue to use it to avoid * regressions. */ private Charset charset = Charset.forName("ISO-8859-1"); //$NON-NLS-1$ public Charset getCharset() { return charset; } public void setCharset(Charset charset) { this.charset = charset; } public String readStr() throws IOException { byte data[] = new byte[read4()]; read(data); return new String(data,charset); } public String readStr1() throws IOException { byte data[] = new byte[read()]; read(data); return new String(data,charset); } public boolean readBool() throws IOException { int val = read4(); if (val != 0 && val != 1) { String error = Messages.format("GmStreamDecoder.INVALID_BOOLEAN",val,getPosString()); //$NON-NLS-1$ throw new IOException(error); } return val == 0 ? false : true; } public <P extends Enum<P>>void read4(PropertyMap<P> map, P...keys) throws IOException { for (P key : keys) map.put(key,read4()); } public <P extends Enum<P>>void readStr(PropertyMap<P> map, P...keys) throws IOException { for (P key : keys) map.put(key,readStr()); } public <P extends Enum<P>>void readBool(PropertyMap<P> map, P...keys) throws IOException { for (P key : keys) map.put(key,readBool()); } public <P extends Enum<P>>void readD(PropertyMap<P> map, P...keys) throws IOException { for (P key : keys) map.put(key,readD()); } /** * Convenience method to retrieve whether the given bit is masked in bits, * That is, if given flag is set. * E.g.: to find out if the 3rd flag from right is set in 00011*0*10, use mask(26,4); * @param bits - A cluster of flags/bits * @param bit - The desired (and already shifted) bit or bits to mask * @return Whether bit is masked in bits */ public static boolean mask(int bits, int bit) { return (bits & bit) == bit; } /** * If the stream is currently reading zlib data, * this returns a string in the format: * <code><file offset>[<decompressed data offset>]</code><br/> * Otherwise just the file offset is returned. */ protected String getPosString() { return Integer.toString(pos); } }