Filter:   InfoImg
download Mpq.cs
Language: C#
Copyright: (C) 2006 The Hungry Programmers (http://www.hungry.com/)
LOC: 191
Project Info
mpqtool - Blizzard MPQ Archive Tool(mpqtool)
Server: Google
Type: svn
...\trunk\MpqTool\SCSharp.Mpq\
   BitStream.cs
   Mpq.cs
   MpqArchive.cs
   MpqHuffman.cs
   MpqParserException.cs
   MpqStream.cs
   MpqStructs.cs
   MpqWavCompression.cs
   PKLibDecompress.cs

//
// SCSharp.Mpq.Mpq
//
// Authors:
//	Chris Toshok (toshok@hungry.com)
//
// (C) 2006 The Hungry Programmers (http://www.hungry.com/)
//

//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;

namespace SCSharp
{
	public interface MpqResource
	{
		void ReadFromStream (Stream stream);
	}

	public abstract class Mpq : IDisposable
	{
		Dictionary<string,object> cached_resources;

		protected Mpq ()
		{
			cached_resources = new Dictionary <string,object>();
		}

		public abstract Stream GetStreamForResource (string path);

#if false	    
		protected Type GetTypeFromResourcePath (string path)
		{
			string ext = Path.GetExtension (path);
			if (ext.ToLower() == ".tbl") {
				return typeof (Tbl);
			}
			else if (ext.ToLower () == ".fnt") {
				return typeof (Fnt);
			}
			else if (ext.ToLower () == ".got") {
				return typeof (Got);
			}
			else if (ext.ToLower () == ".grp") {
				return typeof (Grp);
			}
			else if (ext.ToLower () == ".bin") {
				if (path.ToLower().EndsWith ("aiscript.bin")) /* must come before iscript.bin */
					return null;
				else if (path.ToLower().EndsWith ("iscript.bin"))
					return typeof (IScriptBin);
				else
					return typeof (Bin);
			}
			else if (ext.ToLower () == ".chk") {
				return typeof (Chk);
			}
			else if (ext.ToLower () == ".dat") {
				if (path.ToLower().EndsWith ("flingy.dat"))
					return typeof (FlingyDat);
				else if (path.ToLower().EndsWith ("images.dat"))
					return typeof (ImagesDat);
				else if (path.ToLower().EndsWith ("sfxdata.dat"))
					return typeof (SfxDataDat);
				else if (path.ToLower().EndsWith ("sprites.dat"))
					return typeof (SpritesDat);
				else if (path.ToLower().EndsWith ("units.dat"))
					return typeof (UnitsDat);
				else if (path.ToLower().EndsWith ("mapdata.dat"))
					return typeof (MapDataDat);
				else if (path.ToLower().EndsWith ("portdata.dat"))
					return typeof (PortDataDat);
			}
			else if (ext.ToLower () == ".spk") {
				return typeof (Spk);
			}

			return null;
		}

		public object GetResource (string path)
		{
			if (cached_resources.ContainsKey (path))
				return cached_resources[path];

			Stream stream = GetStreamForResource (path);
			if (stream == null)
				return null;

			Type t = GetTypeFromResourcePath (path);
			if (t == null)
				return stream;

			MpqResource res = Activator.CreateInstance (t) as MpqResource;

			if (res == null) return null;

			res.ReadFromStream (stream);

			/* don't cache .smk files */
			if (!path.ToLower().EndsWith (".smk"))
				cached_resources [path] = res;

			return res;
		}
#endif
		public virtual void Dispose ()
		{
		}
	}

	public class MpqContainer : Mpq
	{
		List<Mpq> mpqs;

		public MpqContainer ()
		{
			mpqs = new List<Mpq>();
		}

		public void Add (Mpq mpq)
		{
			if (mpq == null)
				return;
			mpqs.Add (mpq);
		}

		public void Remove (Mpq mpq)
		{
			if (mpq == null)
				return;
			mpqs.Remove (mpq);
		}

		public void Clear ()
		{
			mpqs.Clear ();
		}

		public override void Dispose ()
		{
			foreach (Mpq mpq in mpqs)
				mpq.Dispose ();
		}

		public override Stream GetStreamForResource (string path)
		{
			foreach (Mpq mpq in mpqs) {
				Stream s = mpq.GetStreamForResource (path);
				if (s != null)
					return s;
			}

			Console.WriteLine ("returning null stream for resource: {0}", path);
			return null;
		}
	}

	public class MpqDirectory : Mpq
	{
		Dictionary<string,string> file_hash;
		string mpq_dir_path;

		public MpqDirectory (string path)
		{
			mpq_dir_path = path;
			file_hash = new Dictionary<string,string> ();

			RecurseDirectoryTree (mpq_dir_path);
		}

		string ConvertBackSlashes (string path)
		{
			while (path.IndexOf ('\\') != -1)
				path = path.Replace ('\\', Path.DirectorySeparatorChar);

			return path;
		}

		public override Stream GetStreamForResource (string path)
		{
			string rebased_path = ConvertBackSlashes (Path.Combine (mpq_dir_path, path));

			if (file_hash.ContainsKey (rebased_path.ToLower ())) {
				string real_path = file_hash[rebased_path.ToLower ()];
				if (real_path != null) {
					Console.WriteLine ("using {0}", real_path);
					return File.OpenRead (real_path);
				}
			}
			return null;
		}

		void RecurseDirectoryTree (string path)
		{
			string[] files = Directory.GetFiles (path);
			foreach (string f in files) {
				string platform_path = ConvertBackSlashes (f);
				file_hash.Add (f.ToLower(), platform_path);
			}

			string[] directories = Directory.GetDirectories (path);
			foreach (string d in directories) {
				RecurseDirectoryTree (d);
			}
		}
	}

	public class MpqArchive : Mpq
	{
		MpqReader.MpqArchive mpq;

		public MpqArchive (string path)
		{
			mpq = new MpqReader.MpqArchive (path);
		}

		public override Stream GetStreamForResource (string path)
		{
			try {
				return mpq.OpenFile (path);
			}
			catch (FileNotFoundException) {
				return null;
			}
		}

		public override void Dispose ()
		{
			mpq.Dispose ();
		}
	}
}