346 lines
10 KiB
C#
346 lines
10 KiB
C#
/******************************************************
|
|
* ROMVault2 is written by Gordon J. *
|
|
* Contact gordon@romvault.com *
|
|
* Copyright 2014 *
|
|
******************************************************/
|
|
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using ROMVault2.Properties;
|
|
using ROMVault2.SupportedFiles;
|
|
using ROMVault2.Utils;
|
|
|
|
namespace ROMVault2.RvDB
|
|
{
|
|
public class RvDir : RvBase
|
|
{
|
|
|
|
public RvTreeRow Tree;
|
|
public RvGame Game;
|
|
private readonly List<RvDat> _dirDats = new List<RvDat>();
|
|
private readonly List<RvBase> _children = new List<RvBase>();
|
|
public readonly ReportStatus DirStatus = new ReportStatus();
|
|
|
|
public ZipStatus ZipStatus;
|
|
|
|
public RvDir(FileType type)
|
|
: base(type)
|
|
{
|
|
if (type != FileType.Dir && type != FileType.Zip)
|
|
ReportError.SendAndShow("Trying to set Dir type to " + type);
|
|
}
|
|
|
|
|
|
|
|
public override void Write(BinaryWriter bw)
|
|
{
|
|
base.Write(bw);
|
|
if (Tree == null)
|
|
bw.Write(false);
|
|
else
|
|
{
|
|
bw.Write(true);
|
|
Tree.Write(bw);
|
|
}
|
|
|
|
if (Game == null)
|
|
bw.Write(false);
|
|
else
|
|
{
|
|
bw.Write(true);
|
|
Game.Write(bw);
|
|
}
|
|
|
|
int count = _dirDats.Count;
|
|
bw.Write(count);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
_dirDats[i].Write(bw);
|
|
}
|
|
|
|
count = _children.Count;
|
|
bw.Write(count);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
FileType type = _children[i].FileType;
|
|
bw.Write((byte)type);
|
|
_children[i].Write(bw);
|
|
}
|
|
|
|
if (DBTypeGet.isCompressedDir(FileType))
|
|
bw.Write((byte)ZipStatus);
|
|
|
|
}
|
|
public override void Read(BinaryReader br, List<RvDat> parentDirDats)
|
|
{
|
|
base.Read(br, parentDirDats);
|
|
bool foundTree = br.ReadBoolean();
|
|
if (foundTree)
|
|
{
|
|
Tree = new RvTreeRow();
|
|
Tree.Read(br);
|
|
}
|
|
else
|
|
Tree = null;
|
|
|
|
bool foundGame = br.ReadBoolean();
|
|
if (foundGame)
|
|
{
|
|
Game = new RvGame();
|
|
Game.Read(br);
|
|
}
|
|
else
|
|
Game = null;
|
|
|
|
int count = br.ReadInt32();
|
|
_dirDats.Clear();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
RvDat dat = new RvDat { DatIndex = i };
|
|
dat.Read(br);
|
|
_dirDats.Add(dat);
|
|
|
|
string datname = TreeFullName + @"\" + dat.GetData(RvDat.DatData.DatName);
|
|
if (datname.Length >= 9 && datname.Substring(0, 9) == @"RomVault\")
|
|
datname = datname.Substring(9);
|
|
|
|
DB.Bgw.ReportProgress(0, new bgwText("Loading: " + datname));
|
|
DB.Bgw.ReportProgress((int)br.BaseStream.Position);
|
|
|
|
}
|
|
if (_dirDats.Count > 0)
|
|
parentDirDats = _dirDats;
|
|
|
|
count = br.ReadInt32();
|
|
_children.Clear();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
RvBase tChild = DBTypeGet.GetRvType((FileType)br.ReadByte());
|
|
|
|
tChild.Parent = this;
|
|
tChild.Read(br, parentDirDats);
|
|
_children.Add(tChild);
|
|
}
|
|
|
|
if (DBTypeGet.isCompressedDir(FileType))
|
|
ZipStatus = (ZipStatus)br.ReadByte();
|
|
|
|
}
|
|
|
|
|
|
public override EFile DatRemove()
|
|
{
|
|
Tree = null;
|
|
Game = null;
|
|
_dirDats.Clear();
|
|
return base.DatRemove();
|
|
}
|
|
public override void DatAdd(RvBase b)
|
|
{
|
|
Tree = ((RvDir)b).Tree;
|
|
Game = ((RvDir)b).Game;
|
|
if (_dirDats.Count > 0)
|
|
ReportError.SendAndShow(Resources.RvDir_SetDat_Setting_Dir_with_a_dat_list);
|
|
base.DatAdd(b);
|
|
}
|
|
|
|
|
|
public override EFile FileRemove()
|
|
{
|
|
ZipStatus = ZipStatus.None;
|
|
return base.FileRemove();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public int DirDatCount
|
|
{
|
|
get
|
|
{
|
|
return _dirDats.Count;
|
|
}
|
|
}
|
|
public RvDat DirDat(int index)
|
|
{
|
|
return _dirDats[index];
|
|
}
|
|
public void DirDatAdd(RvDat dat)
|
|
{
|
|
int index;
|
|
DirDatSearch(dat, out index);
|
|
_dirDats.Insert(index, dat);
|
|
for (int i = 0; i < _dirDats.Count; i++)
|
|
_dirDats[i].DatIndex = i;
|
|
}
|
|
public void DirDatRemove(int index)
|
|
{
|
|
_dirDats.RemoveAt(index);
|
|
for (int i = 0; i < _dirDats.Count; i++)
|
|
_dirDats[i].DatIndex = i;
|
|
}
|
|
|
|
private void DirDatSearch(RvDat dat, out int index)
|
|
{
|
|
int intBottom = 0;
|
|
int intTop = _dirDats.Count;
|
|
int intMid = 0;
|
|
int intRes = -1;
|
|
|
|
//Binary chop to find the closest match
|
|
while (intBottom < intTop && intRes != 0)
|
|
{
|
|
intMid = (intBottom + intTop) / 2;
|
|
|
|
intRes = DBHelper.DatCompare(dat, _dirDats[intMid]);
|
|
if (intRes < 0)
|
|
intTop = intMid;
|
|
else if (intRes > 0)
|
|
intBottom = intMid + 1;
|
|
}
|
|
index = intMid;
|
|
|
|
// if match was found check up the list for the first match
|
|
if (intRes == 0)
|
|
{
|
|
int intRes1 = 0;
|
|
while (index > 0 && intRes1 == 0)
|
|
{
|
|
intRes1 = DBHelper.DatCompare(dat, _dirDats[index - 1]);
|
|
if (intRes1 == 0)
|
|
index--;
|
|
}
|
|
}
|
|
// if the search is greater than the closest match move one up the list
|
|
else if (intRes > 0)
|
|
index++;
|
|
}
|
|
|
|
|
|
|
|
public int ChildCount
|
|
{
|
|
get
|
|
{
|
|
return _children.Count;
|
|
}
|
|
}
|
|
public RvBase Child(int index)
|
|
{
|
|
return _children[index];
|
|
}
|
|
|
|
public int ChildAdd(RvBase child)
|
|
{
|
|
int index;
|
|
ChildNameSearch(child, out index);
|
|
ChildAdd(child, index);
|
|
return index;
|
|
}
|
|
public void ChildAdd(RvBase child, int index)
|
|
{
|
|
if (
|
|
(FileType == FileType.Dir && child.FileType == FileType.ZipFile) ||
|
|
(FileType == FileType.Zip && child.FileType != FileType.ZipFile)
|
|
)
|
|
ReportError.SendAndShow("Typing to add a " + child.FileType + " to a " + FileType);
|
|
|
|
_children.Insert(index, child);
|
|
child.Parent = this;
|
|
UpdateRepStatusArrUpTree(child, 1);
|
|
}
|
|
|
|
public void ChildRemove(int index)
|
|
{
|
|
UpdateRepStatusArrUpTree(_children[index], -1);
|
|
if (_children[index].Parent == this)
|
|
_children[index].Parent = null;
|
|
_children.RemoveAt(index);
|
|
}
|
|
|
|
public int ChildNameSearch(RvBase lName, out int index)
|
|
{
|
|
int intBottom = 0;
|
|
int intTop = _children.Count;
|
|
int intMid = 0;
|
|
int intRes = -1;
|
|
|
|
//Binary chop to find the closest match
|
|
while (intBottom < intTop && intRes != 0)
|
|
{
|
|
intMid = (intBottom + intTop) / 2;
|
|
|
|
intRes = DBHelper.CompareName(lName, _children[intMid]);
|
|
if (intRes < 0)
|
|
intTop = intMid;
|
|
else if (intRes > 0)
|
|
intBottom = intMid + 1;
|
|
}
|
|
index = intMid;
|
|
|
|
// if match was found check up the list for the first match
|
|
if (intRes == 0)
|
|
{
|
|
int intRes1 = 0;
|
|
while (index > 0 && intRes1 == 0)
|
|
{
|
|
intRes1 = DBHelper.CompareName(lName, _children[index - 1]);
|
|
if (intRes1 == 0)
|
|
index--;
|
|
}
|
|
}
|
|
// if the search is greater than the closest match move one up the list
|
|
else if (intRes > 0)
|
|
index++;
|
|
|
|
return intRes;
|
|
}
|
|
|
|
|
|
public bool FindChild(RvBase lName, out int index)
|
|
{
|
|
if (ChildNameSearch(lName, out index) != 0)
|
|
{
|
|
ReportError.UnhandledExceptionHandler("Could not find self in Parent " + FullName);
|
|
return false;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (_children[index] == lName)
|
|
return true;
|
|
index++;
|
|
|
|
} while (index < _children.Count && DBHelper.CompareName(lName, _children[index]) == 0);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
public void UpdateRepStatusUpTree(RepStatus rStat, int dir)
|
|
{
|
|
DirStatus.UpdateRepStatus(rStat, dir);
|
|
if (Parent != null)
|
|
Parent.UpdateRepStatusUpTree(rStat, dir);
|
|
}
|
|
|
|
private void UpdateRepStatusArrUpTree(RvBase child, int dir)
|
|
{
|
|
DirStatus.UpdateRepStatus(child.RepStatus, dir);
|
|
RvDir rvDir = child as RvDir;
|
|
if (rvDir != null)
|
|
DirStatus.UpdateRepStatus(rvDir.DirStatus, dir);
|
|
|
|
if (Parent != null)
|
|
Parent.UpdateRepStatusArrUpTree(child, dir);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|