/* InFile.java
 *
 * Ace Kanji Workout
 * Copyright (C) 2006 Alex Quinn <aquinn@cs.washington.edu>
 * Licensed under GPL v2, http://www.gnu.org/licenses/gpl.html
 *
 * Convenience class to simplify file access.  Handles exceptions
 * like runtime exceptions, provides a much simpler constructor,
 * handles non-default encodings gracefully, and provides a few
 * Python-style methods.  A companion OutFile is also provided.
 *
 * The downside of these classes (and OutFile) is that they
 * usually catch many exceptions and just dump the whole application
 * via System.exit(..) instead of passing them up the chain.
 * The only exception to that is readFileSafe(..) which does pass
 * the exception up.
 *
 * Author:  Alex Quinn
 * Created: 6/11/2006
 */

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.net.URI;
import java.io.File;
import java.net.URISyntaxException;
import java.io.InputStream;

class InFile {
	protected BufferedReader breader;
	protected InFile() {}
	public InFile(String name){
		try {
			breader = new BufferedReader(new FileReader(name));
		}
		catch( IOException e ) {
			e.printStackTrace();
			System.exit(-1);
		}
	}
	public InFile(String name, String encoding) {
		try {
			breader = new BufferedReader(new InputStreamReader(new FileInputStream(name),encoding));
		}
		catch( IOException e ) {
			e.printStackTrace();
			System.exit(-1);
		}
	}
	public static String readFileSafe(String name, String encoding) throws IOException {
		BufferedReader breader = new BufferedReader(
				new InputStreamReader(new FileInputStream(name),encoding));
		final int chunkSize = 10*1024;   // read in 10K chunks
		final int limit = 10*1024*1024;  // don't allow anything over 10 MB
		char[] cbuf = new char[chunkSize];
		String asString = "";
		int charsRead = 0;
		charsRead = breader.read(cbuf,0,chunkSize);
		while( charsRead >= 0 ) {
			if( charsRead + asString.length() > limit ) {
				throw new RuntimeException("This file is too big.  It must be less than "+String.valueOf(limit)+".");
			}
			asString += String.valueOf(cbuf,0,charsRead);
			charsRead = breader.read(cbuf,0,chunkSize);
		}
		breader.close();
		return asString;
	}
	public String readAll() {
		final int chunkSize = 10*1024;   // read in 10K chunks
		final int limit = 10*1024*1024;  // don't allow anything over 10 MB
		char[] cbuf = new char[chunkSize];
		String asString = "";
		try {
			int charsRead = 0;
			charsRead = breader.read(cbuf,0,chunkSize);
			while( charsRead >= 0 ) {
				if( charsRead + asString.length() > limit ) {
					throw new RuntimeException("This file is too big.  It must be less than "+String.valueOf(limit)+".");
				}
				asString += String.valueOf(cbuf,0,charsRead);
				charsRead = breader.read(cbuf,0,chunkSize);
			}
		}
		catch( IOException e ) {
			e.printStackTrace();
			System.exit(-1);
		}
		return asString;
	}
	public String[] readLines() {
		LinkedList<String> list = new LinkedList<String>();
		String line = null;
		String[] lineArray = null;
		try {
			line = breader.readLine();
			while(line!=null) {
				list.add(line);
				line = breader.readLine();
			}
		}
		catch( IOException e ) {
			e.printStackTrace();
			System.exit(-1);
		}
		lineArray = list.toArray(new String[list.size()]);
		return lineArray;
	}
	public String readLine() {
		// Note: Result does NOT include the newline at the end.
		String line = null;
		try {
			line = breader.readLine();
		}
		catch( IOException e ) {
			e.printStackTrace();
			System.exit(-1);
		}
		return line;
	}
	public void close() {
		try {
			breader.close();
		}
		catch( IOException e ) {
			e.printStackTrace();
			System.exit(-1);
		}
	}
}

class JarInFile extends InFile {
// A companion class which is able to look inside a jar file.  Actually,
// it will look wherever the running code (in particular, this class)
// is being loaded from.
	private File getFile(String name) {
		File file = null;
		try {
			URI uri = getClass().getResource(name).toURI();
			file = new File(uri);
		}
		catch( URISyntaxException e ) {
			System.err.println("URISyntaxException");
			e.printStackTrace();
			System.exit(1);
		}
		return file;
	}
	public JarInFile(String name){
		InputStream is = getClass().getClassLoader().getResourceAsStream(name);
		breader = new BufferedReader(new InputStreamReader(is));
	}
	public static String readFileQuick(String name, String encoding) {
		JarInFile infile = new JarInFile(name, encoding);
		String contents = infile.readAll();
		return contents;
	}
	public JarInFile(String name, String encoding) {
		try {
			InputStream is = getClass().getClassLoader().getResourceAsStream(name);
			assert is!=null;
			try {
				breader = new BufferedReader(new InputStreamReader(is,encoding));
			}
			catch( NullPointerException e ) {
				e.printStackTrace();
				System.err.println(name);
				System.err.println(is);
				System.err.println(encoding.toString());
				System.exit(1);
			}
		}
		catch( IOException e ) {
			e.printStackTrace();
			System.exit(-1);
		}
	}
}
