aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCarsten Weisse <[email protected]>2004-10-19 17:23:20 +0000
committerCarsten Weisse <[email protected]>2004-10-19 17:23:20 +0000
commitd058eb9ddaf1a99277a387dbdee92ea898e3b84b (patch)
tree3291af08f4a63cc5cd2ad7d1213656b39ff36b20 /src
parent755c881683aea8ad95ce6957515895703974fbf5 (diff)
new method: LoadMappedFile (memory mapped io);
and code cleanup
Diffstat (limited to 'src')
-rw-r--r--src/jake2/qcommon/FS.java229
1 files changed, 161 insertions, 68 deletions
diff --git a/src/jake2/qcommon/FS.java b/src/jake2/qcommon/FS.java
index 9081cd3..2eb591c 100644
--- a/src/jake2/qcommon/FS.java
+++ b/src/jake2/qcommon/FS.java
@@ -2,12 +2,12 @@
* FS.java
* Copyright (C) 2003
*
- * $Id: FS.java,v 1.8 2004-10-18 19:45:54 cawe Exp $
+ * $Id: FS.java,v 1.9 2004-10-19 17:23:20 cawe Exp $
*/
/*
Copyright (C) 1997-2001 Id Software, Inc.
-This program is free software; you can redistribute it and/or
+ This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
@@ -31,7 +31,9 @@ import jake2.game.cvar_t;
import jake2.sys.Sys;
import java.io.*;
+import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
import java.util.*;
import javax.imageio.stream.FileImageInputStream;
@@ -44,11 +46,11 @@ import javax.imageio.stream.FileImageInputStream;
public final class FS extends Globals {
/*
- * =============================================================================
+ * ==================================================
*
* QUAKE FILESYSTEM
*
- * =============================================================================
+ * ==================================================
*/
public static class packfile_t {
@@ -93,25 +95,23 @@ public final class FS extends Globals {
String to;
}
- public static List fs_links = new LinkedList(); // with
- // filelink_t
- // entries
+ // with filelink_t entries
+ public static List fs_links = new LinkedList();
public static class searchpath_t {
String filename;
- pack_t pack; // only one of filename / pack will be used
+ pack_t pack; // only one of filename or pack will be used
searchpath_t next;
}
public static searchpath_t fs_searchpaths;
- public static searchpath_t fs_base_searchpaths; // without
- // gamedirs
+ // without gamedirs
+ public static searchpath_t fs_base_searchpaths;
/*
- *
* All of Quake's data access is through a hierchal file system, but the
* contents of the file system can be transparently merged from several
* sources.
@@ -132,9 +132,9 @@ public final class FS extends Globals {
*/
/*
- * ============ FS_CreatePath
+ * CreatePath
*
- * Creates any directories needed to store the given filename ============
+ * Creates any directories needed to store the given filename.
*/
public static void CreatePath(String path) {
int index = path.lastIndexOf('/');
@@ -148,10 +148,10 @@ public final class FS extends Globals {
}
/*
- * ============== FS_FCloseFile
+ * FCloseFile
*
* For some reason, other dll's can't just call fclose() on files returned
- * by FS_FOpenFile... ==============
+ * by FS_FOpenFile...
*/
public static void FCloseFile(RandomAccessFile file) throws IOException {
file.close();
@@ -185,7 +185,7 @@ public final class FS extends Globals {
}
}
- // search through the path, one element at a time
+ // search through the path, one element at a time
for (search = fs_searchpaths; search != null; search = search.next) {
// is the element a pak file?
@@ -225,16 +225,14 @@ public final class FS extends Globals {
return -1;
}
+ public static int file_from_pak = 0;
+
/*
- * =========== FS_FOpenFile
+ * FOpenFile
*
- * Finds the file in the search path. returns filesize and an open FILE *
- * Used for streaming data out of either a pak file or a seperate file.
- * ===========
+ * Finds the file in the search path. returns a RadomAccesFile. Used for
+ * streaming data out of either a pak file or a seperate file.
*/
-
- public static int file_from_pak = 0;
-
public static RandomAccessFile FOpenFile(String filename)
throws IOException {
searchpath_t search;
@@ -263,7 +261,7 @@ public final class FS extends Globals {
}
//
- // search through the path, one element at a time
+ // search through the path, one element at a time
//
for (search = fs_searchpaths; search != null; search = search.next) {
// is the element a pak file?
@@ -310,15 +308,14 @@ public final class FS extends Globals {
return null;
}
- /*
- * ================= FS_ReadFile
+ // read in blocks of 64k
+ public static final int MAX_READ = 0x10000;
+
+ /**
+ * Read
*
- * Properly handles partial reads =================
+ * Properly handles partial reads
*/
- public static final int MAX_READ = 0x10000; // read in
- // blocks of
- // 64k
-
public static void Read(byte[] buffer, int len, RandomAccessFile f) {
int block, remaining;
@@ -343,7 +340,7 @@ public final class FS extends Globals {
Com.Error(Globals.ERR_FATAL, "FS_Read: -1 bytes read");
}
//
- // do some progress bar thing here...
+ // do some progress bar thing here...
//
remaining -= read;
offset += read;
@@ -351,10 +348,10 @@ public final class FS extends Globals {
}
/*
- * ============ FS_LoadFile
+ * LoadFile
*
* Filename are reletive to the quake search path a null buffer will just
- * return the file length without loading ============
+ * return the file content as byte[]
*/
public static byte[] LoadFile(String path) {
RandomAccessFile file;
@@ -362,7 +359,7 @@ public final class FS extends Globals {
byte[] buf = null;
int len = 0;
- // TODO bughack for bad strings (fuck \0)
+ // TODO hack for bad strings (fuck \0)
int index = path.indexOf('\0');
if (index != -1)
path = path.substring(0, index);
@@ -386,7 +383,111 @@ public final class FS extends Globals {
}
/*
- * ============= FS_FreeFile =============
+ * LoadMappedFile
+ *
+ * Filename are reletive to the quake search path a null buffer will just
+ * return the file content as ByteBuffer (memory mapped)
+ */
+ public static ByteBuffer LoadMappedFile(String filename) {
+ searchpath_t search;
+ String netpath;
+ pack_t pak;
+ int i;
+ filelink_t link;
+ File file = null;
+
+ int fileLength = 0;
+ FileChannel channel = null;
+ FileInputStream input = null;
+ ByteBuffer buffer = null;
+
+ file_from_pak = 0;
+
+ try {
+ // check for links first
+ for (Iterator it = fs_links.iterator(); it.hasNext();) {
+ link = (filelink_t) it.next();
+
+ if (filename.regionMatches(0, link.from, 0, link.fromlength)) {
+ netpath = link.to + filename.substring(link.fromlength);
+ file = new File(netpath);
+ if (file.canRead()) {
+ input = new FileInputStream(file);
+ channel = input.getChannel();
+ fileLength = (int) channel.size();
+ buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0,
+ fileLength);
+ input.close();
+ return buffer;
+ }
+ return null;
+ }
+ }
+
+ //
+ // search through the path, one element at a time
+ //
+ for (search = fs_searchpaths; search != null; search = search.next) {
+ // is the element a pak file?
+ if (search.pack != null) {
+ // look through all the pak file elements
+ pak = search.pack;
+ filename = filename.toLowerCase();
+ packfile_t entry = (packfile_t) pak.files.get(filename);
+
+ if (entry != null) {
+ // found it!
+ file_from_pak = 1;
+ //Com.DPrintf ("PackFile: " + pak.filename + " : " +
+ // filename + '\n');
+ file = new File(pak.filename);
+ if (!file.canRead())
+ Com.Error(Globals.ERR_FATAL, "Couldn't reopen "
+ + pak.filename);
+ if (pak.handle == null || !pak.handle.getFD().valid()) {
+ // hold the pakfile handle open
+ pak.handle = new RandomAccessFile(pak.filename, "r");
+ }
+ // open a new file on the pakfile
+
+ channel = pak.handle.getChannel();
+ buffer = channel.map(FileChannel.MapMode.READ_ONLY,
+ entry.filepos, entry.filelen);
+ channel.close();
+ return buffer;
+ }
+ } else {
+ // check a file in the directory tree
+ netpath = search.filename + '/' + filename;
+
+ file = new File(netpath);
+ if (!file.canRead())
+ continue;
+
+ //Com.DPrintf("FindFile: " + netpath +'\n');
+ input = new FileInputStream(file);
+ channel = input.getChannel();
+ fileLength = (int) channel.size();
+ buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0,
+ fileLength);
+ input.close();
+ return buffer;
+ }
+ }
+ } catch (Exception e) {
+ }
+ try {
+ if (input != null)
+ input.close();
+ else if (channel != null && channel.isOpen())
+ channel.close();
+ } catch (IOException ioe) {
+ }
+ return null;
+ }
+
+ /*
+ * FreeFile
*/
public static void FreeFile(byte[] buffer) {
buffer = null;
@@ -395,7 +496,7 @@ public final class FS extends Globals {
static final int IDPAKHEADER = (('K' << 24) + ('C' << 16) + ('A' << 8) + 'P');
static class dpackheader_t {
- int ident; // == IDPAKHEADER
+ int ident; // IDPAKHEADER
int dirofs;
@@ -404,13 +505,16 @@ public final class FS extends Globals {
static final int MAX_FILES_IN_PACK = 4096;
+ // buffer for C-Strings char[56]
+ static byte[] tmpText = new byte[packfile_t.NAME_SIZE];
+
/*
- * ================= FS_LoadPackFile
+ * LoadPackFile
*
* Takes an explicit (not game tree related) path to a pak file.
*
* Loads the header and directory, adding the files at the beginning of the
- * list so they override previous pack files. =================
+ * list so they override previous pack files.
*/
static pack_t LoadPackFile(String packfile) {
@@ -448,26 +552,22 @@ public final class FS extends Globals {
packhandle.seek(header.dirofs);
- // buffer for C-Strings char[56]
- byte[] text = new byte[packfile_t.NAME_SIZE];
// parse the directory
packfile_t entry = null;
for (int i = 0; i < numpackfiles; i++) {
- packhandle.readFully(text);
+ packhandle.readFully(tmpText);
entry = new packfile_t();
- entry.name = new String(text).trim();
+ entry.name = new String(tmpText).trim();
entry.filepos = packhandle.readInt();
entry.filelen = packhandle.readInt();
newfiles.put(entry.name.toLowerCase(), entry);
-
- //logger.log(Level.FINEST, i + ".\t" + entry);
}
} catch (IOException e) {
- //logger.log(Level.WARNING, e.toString());
+ Com.DPrintf(e.getMessage() + '\n');
return null;
}
@@ -484,10 +584,10 @@ public final class FS extends Globals {
}
/*
- * ================ FS_AddGameDirectory
+ * AddGameDirectory
*
* Sets fs_gamedir, adds the directory to the head of the path, then loads
- * and adds pak1.pak pak2.pak ... ================
+ * and adds pak1.pak pak2.pak ...
*/
static void AddGameDirectory(String dir) {
int i;
@@ -530,18 +630,17 @@ public final class FS extends Globals {
}
/*
- * ============ FS_Gamedir
+ * Gamedir
*
- * Called to find where to write a file (demos, savegames, etc) ============
+ * Called to find where to write a file (demos, savegames, etc)
*/
public static String Gamedir() {
return (fs_userdir != null) ? fs_userdir : Globals.BASEDIRNAME;
}
/*
- * ============= FS_ExecAutoexec =============
+ * ExecAutoexec
*/
-
public static void ExecAutoexec() {
String dir;
@@ -565,16 +664,13 @@ public final class FS extends Globals {
}
/*
- * ================ FS_SetGamedir
+ * SetGamedir
*
- * Sets the gamedir and path to a different directory. ================
+ * Sets the gamedir and path to a different directory.
*/
public static void SetGamedir(String dir) {
searchpath_t next;
- // if (strstr(dir, "..") || strstr(dir, "/")
- // || strstr(dir, "\\") || strstr(dir, ":") )
-
if (dir.indexOf("..") != -1 || dir.indexOf("/") != -1
|| dir.indexOf("\\") != -1 || dir.indexOf(":") != -1) {
Com.Printf("Gamedir should be a single filename, not a path\n");
@@ -589,7 +685,7 @@ public final class FS extends Globals {
try {
fs_searchpaths.pack.handle.close();
} catch (IOException e) {
- //logger.log(Level.WARNING, e.toString());
+ Com.DPrintf(e.getMessage() + '\n');
}
// clear the hashtable
fs_searchpaths.pack.files.clear();
@@ -622,9 +718,9 @@ public final class FS extends Globals {
}
/*
- * ================ FS_Link_f
+ * Link_f
*
- * Creates a filelink_t ================
+ * Creates a filelink_t
*/
public static void Link_f() {
filelink_t entry = null;
@@ -660,7 +756,7 @@ public final class FS extends Globals {
}
/*
- * * FS_ListFiles
+ * ListFiles
*/
public static String[] ListFiles(String findname, int musthave, int canthave) {
String[] list = null;
@@ -678,7 +774,7 @@ public final class FS extends Globals {
}
/*
- * * FS_Dir_f
+ * Dir_f
*/
public static void Dir_f() {
String path = null;
@@ -720,9 +816,7 @@ public final class FS extends Globals {
}
/*
- * ============ FS_Path_f
- *
- * ============
+ * Path_f
*/
public static void Path_f() {
@@ -748,10 +842,9 @@ public final class FS extends Globals {
}
/*
- * ================ FS_NextPath
+ * NextPath
*
* Allows enumerating all of the directories in the search path
- * ================
*/
public static String NextPath(String prevpath) {
searchpath_t s;
@@ -775,7 +868,7 @@ public final class FS extends Globals {
}
/*
- * ================ FS_InitFilesystem ================
+ * InitFilesystem
*/
public static void InitFilesystem() {
Cmd.AddCommand("path", new xcommand_t() {