using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
namespace Sdaleo.Internal
{
///
/// Interface of Versioning, to check if the passed in version is supported by the Versioning Object
///
internal interface IVersionSupported
{
bool IsSupported(string Version);
bool IsSupported(Versioning Version);
}
///
/// Allows us to easily wrap Versioning Functionallity,
/// into Objects.
/// [Major version].[Minor version].[Build number]
/// ---------------------------------------------------
/// Major version can be any valid uint as well as *
/// Minor version can be any valid uint as well as *
/// Build number can be any valid uint as well as *
///
internal class Versioning : ICloneable, IComparable, IVersionSupported
{
#region Internal consts
internal const int STAR_ALL = -1;
#endregion
#region Private Members
private int _MajorVersion = STAR_ALL;
private int _MinorVersion = STAR_ALL;
private int _BuildNumber = STAR_ALL;
#endregion
#region Construction
///
/// Use this to initialize the class with a version string, can not contain multiple versions seperated by ";"
///
/// any version string in the format [Major].[Minor].[Build], like 5.3.3 or 5.4.*
internal Versioning(string strVersion)
{
if (!IsValidVersionStr(strVersion) || strVersion.Contains(";"))
throw new ArgumentException("Invalid Version String");
ParseVersion(strVersion, out this._MajorVersion, out this._MinorVersion, out this._BuildNumber);
}
///
/// Initialize Versioning with a single MajorVersion and MinorVersion.
///
/// Major Version
/// Minor Version
internal Versioning(int MajorVersion, int MinorVersion)
{
if (MajorVersion >= STAR_ALL && MinorVersion >= STAR_ALL)
{
_MajorVersion = MajorVersion;
_MinorVersion = MinorVersion;
}
else
throw new ArgumentException("MajorVersion or MinorVersion is invalid");
}
///
/// Initialize Versioning with a single MajorVersion,MinorVersion, and BuildNumber.
///
/// Major Version
/// Minor Version
/// Build Number
internal Versioning(int MajorVersion, int MinorVersion, int BuildNumber)
{
if (MajorVersion >= STAR_ALL && MinorVersion >= STAR_ALL && _BuildNumber >= STAR_ALL)
{
_MajorVersion = MajorVersion;
_MinorVersion = MinorVersion;
_BuildNumber = BuildNumber;
}
else
throw new ArgumentException("MajorVersion,MinorVersion, or BuildNumber is invalid");
}
#endregion
#region Versioning Getter/Setter
///
/// Set/Retrieve Version
///
internal String Version
{
get
{
return VersionToVersionString(_MajorVersion, _MinorVersion, _BuildNumber);
}
set
{
if (IsValidVersionStr(value) && !value.Contains(";"))
ParseVersion(value, out this._MajorVersion, out this._MinorVersion, out this._BuildNumber);
else
throw new ArgumentException("Invalid Version String");
}
}
#endregion
#region internal Static Helpers
///
/// Gets a Versioning object for the Version Information of a File
///
/// Full File Name and Path
/// returns a new Versioning Object for a File, or null if error occured
internal static Versioning GetFileVersioning(string FileNameNPath)
{
if (!string.IsNullOrEmpty(FileNameNPath) && File.Exists(FileNameNPath))
{
try
{
FileVersionInfo info = FileVersionInfo.GetVersionInfo(FileNameNPath);
return new Versioning(info.FileMajorPart, info.FileMinorPart, info.FileBuildPart);
}
catch (Exception) { /* ignore */ }
}
return null;
}
///
/// Parses out a single Version from a string
///
/// pass in a Version format [Major].[Minor].[Build], like 5.3.3 or 5.4.*
/// returns an int or STAR_ALL, or UNINITIALIZED, if error occured
/// returns an int or STAR_ALL, or UNINITIALIZED, if error occured
/// returns an int or STAR_ALL, or UNINITIALIZED, if error occured
internal static void ParseVersion(string strVersion, out int MajorVersion, out int MinorVersion, out int BuildNumber)
{
if (!IsValidVersionStr(strVersion) || strVersion.Contains(";"))
throw new ArgumentException("Invalid Version String");
MajorVersion = STAR_ALL;
MinorVersion = STAR_ALL;
BuildNumber = STAR_ALL;
string[] MajorMinorPossBuildVersion = strVersion.Split('.');
try
{
for (int i = 0; i < MajorMinorPossBuildVersion.Length; ++i)
{
if (i == 0)
{
if (MajorMinorPossBuildVersion[0] != "*")
MajorVersion = int.Parse(MajorMinorPossBuildVersion[0]);
}
else if (i == 1)
{
if (MajorMinorPossBuildVersion[1] != "*")
MinorVersion = int.Parse(MajorMinorPossBuildVersion[1]);
}
else if (i == 2)
{
if (MajorMinorPossBuildVersion[2] != "*")
BuildNumber = int.Parse(MajorMinorPossBuildVersion[2]);
}
}
}
catch (Exception) { /* Ignore */ }
}
///
/// Turns Version Numbers into a Version String
///
/// Major Version
/// Minor Version, can be *
/// Build Number, can be * or UNINITIALIZED
/// the Version String
internal static string VersionToVersionString(int MajorVersion, int MinorVersion = STAR_ALL, int BuildNumber = STAR_ALL)
{
string strRetVal = String.Empty;
if (MajorVersion >= STAR_ALL)
{
// Major Version
if (MajorVersion == STAR_ALL)
strRetVal += "*";
else
strRetVal += MajorVersion.ToString();
// Minor Version
if (MinorVersion >= STAR_ALL)
{
strRetVal += ".";
if (MinorVersion == STAR_ALL)
strRetVal += "*";
else
strRetVal += MinorVersion.ToString();
}
// Build Number
if (BuildNumber >= STAR_ALL)
{
strRetVal += ".";
if (BuildNumber == STAR_ALL)
strRetVal += "*";
else
strRetVal += BuildNumber.ToString();
}
}
return strRetVal;
}
#endregion
#region Validation
private const string CharSet_AllowedNumeric = "0123456789";
private const string CharSet_AllowedVersionChars = CharSet_AllowedNumeric + "*;.";
///
/// Generic Function to use with Allowed Character Sets above
///
/// string to evaluate
/// Pass in one of the legal character consts declared above
/// true if valid, false otherwise
private static bool ContainsOnlyLegalChars(string TextToEvaluate, string TextToEvaluateWith)
{
foreach (char c in TextToEvaluate.ToCharArray())
{
bool bFound = (TextToEvaluateWith.IndexOf(c) >= 0);
if (!bFound)
return false;
}
return true;
}
///
/// Used to Validate a Version string of format 12.1.12;12.2.*;12.2.1
///
/// a Version String
/// true if valid, false otherwise
public static bool IsValidVersionStr(string VersionStr)
{
if (String.IsNullOrEmpty(VersionStr))
{
return false;
}
else if (VersionStr.Length < 1 && VersionStr.Length > 50) // restrice Version String Length
{
return false;
}
else if (!ContainsOnlyLegalChars(VersionStr, CharSet_AllowedVersionChars))
{
return false;
}
else
{
return true;
}
}
#endregion
#region ICloneable Members
public object Clone()
{
Versioning versioning = new Versioning(this._MajorVersion, this._MinorVersion, this._BuildNumber);
return versioning;
}
#endregion
#region IComparable Members
public int CompareTo(object obj)
{
if (obj is Versioning)
{
Versioning v = (Versioning)obj;
//*.*.*
//*.2.*
//1.*.*
//1.1.*
//1.1.1
//2.2.2
//2.2.*
int nCompare = 0;
nCompare = this._MajorVersion.CompareTo(v._MajorVersion);
if (nCompare == 0)
nCompare = this._MinorVersion.CompareTo(v._MinorVersion);
if (nCompare == 0)
nCompare = this._BuildNumber.CompareTo(v._BuildNumber);
return nCompare;
}
else
{
throw new ArgumentException("object is not a Versioning");
}
}
#endregion
#region IVersionSupported Members
///
/// Returns true if the Version String passed in is supported/matches Versioning for this object
///
/// a Version string to validate against
/// true if supported, false otherwise
public bool IsSupported(string Version)
{
Versioning version = new Versioning(Version);
return IsSupported(version);
}
///
/// Returns true if the Version passed in is supported/matches Versioning for this object
///
/// a Version Object to validate against
/// true if supported, false otherwise
public bool IsSupported(Versioning Version)
{
if (Version != null)
{
int nCompare = this.CompareTo(Version);
if (nCompare == 0)
{
return true;
}
else if (nCompare == 1)
{
return false;
}
else if (nCompare == -1)
{
if (((this._MajorVersion == STAR_ALL) || (this._MajorVersion == Version._MajorVersion)) &&
((this._MinorVersion == STAR_ALL) || (this._MinorVersion == Version._MinorVersion)) &&
((this._BuildNumber == STAR_ALL) || (this._BuildNumber == Version._BuildNumber))
)
{
return true;
}
else
{
return false;
}
}
}
return false;
}
#endregion
}
///
/// Allows us to easily parse/sort/search multiple versioning classes
///
internal static class Versionings
{
///
/// Used to parse multiple ";" seperated versions from a string
///
/// single/multiple version strings, seperated by ";", in the format [Major].[Minor].[Build], like 5.3.3 or 5.4.*
/// a sorted array of versionings or null if error occured
internal static Versioning[] ParseVersions(string strVersions)
{
if (!Versioning.IsValidVersionStr(strVersions))
return null;
List RetValueVersions = new List();
string[] Versions = strVersions.Split(';');
foreach (string Version in Versions)
RetValueVersions.Add(new Versioning(Version));
RetValueVersions.Sort();
return RetValueVersions.ToArray();
}
#region IsSupportedFile
///
/// Use this to find out if a File Version is supported by the passed in Versions string
///
/// single/multiple version strings, seperated by ";", in the format [Major].[Minor].[Build], like 5.3.3 or 5.4.*
/// Full File Name and Path
/// true if the File Version is supported by the Versions string
internal static bool IsSupportedFile(string strVersions, string FileNameNPath)
{
return IsSupported(ParseVersions(strVersions), Versioning.GetFileVersioning(FileNameNPath));
}
///
/// Use this to find out if a File Version is supported by the passed in Versions []
///
/// single/multiple versioning objects
/// Full File Name and Path
/// true if the File Version is supported by the Versions string
internal static bool IsSupportedFile(Versioning[] Versions, string FileNameNPath)
{
return IsSupported(Versions, Versioning.GetFileVersioning(FileNameNPath));
}
#endregion
#region IsSupported
///
/// Pass in a Versions string, and a Version to check against. Returns true, if the Version is IVersionSupported by
/// the passed in Versions string.
///
/// single/multiple version strings, seperated by ";", in the format [Major].[Minor].[Build], like 5.3.3 or 5.4.*
/// any version string in the format [Major].[Minor].[Build], like 5.3.3 or 5.4.*
/// true, if a Versioning Object in the Versions returns true for IVersionSupported, false otherwise
internal static bool IsSupported(string strVersions, string strVersion)
{
return IsSupported(ParseVersions(strVersions), new Versioning(strVersion));
}
///
/// Pass in a single/multipe Versions object, and a Version object to check against. Returns true, if the Version is IVersionSupported by
/// the passed in Versions Objects.
///
/// single/multiple versioning objects
/// single versioning object
/// true, if a Versioning Object in the Versions returns true for IVersionSupported, false otherwise
internal static bool IsSupported(Versioning[] Versions, Versioning Version)
{
// Let IVersionSupported do all the work
foreach (Versioning _version in Versions)
{
if (_version.IsSupported(Version))
return true;
}
return false;
}
#endregion
}
}