using System;
using System.ComponentModel; // for Win32Exception
using System.Diagnostics; // for ProcessWindowStyle
using System.IO; // for File class
using System.Reflection; // for GetExecutingAssembly
using System.Windows.Forms; // for MessageBox
using System.Xml; // for XmlDocument
///
/// Utility-type code that can be included in other projects with
/// no external dependencies.
///
public class Util
{
#region Directory functions
///
/// Get the folder where the application is stored on disk.
///
///
/// The full path of the folder ending in "\" of where the application
/// is stored.
///
public static string DirGetStartup()
{
string strDrive = ""; string strDir = ""; string strFname = ""; string strExt = "";
Splitpath(Application.ExecutablePath, ref strDrive, ref strDir, ref strFname, ref strExt);
return strDrive + strDir;
}
///
/// Count the number of files matching a given search path.
///
///
/// String containing the file path and the search pattern used.
/// For example "c:\\mydir\\*.txt" counts the number of text files
/// in the "mydir" folder.
///
///
/// The number of matching files.
///
public static int DirCountTotal(string strPattern)
{
string[] arrFiles = FileGetList(strPattern);
return (arrFiles.Length);
}
#endregion
#region Error functions
///
/// Show an error summary in a message box.
///
///
/// The exception being shown.
///
public void ErrorShow(Exception e)
{
string strLastStackLine = e.StackTrace.Substring(e.StackTrace.LastIndexOf("\\")+1);
string strError = "Error = " + e.Message + "\r\n" +
"Location = " + strLastStackLine + "\r\n";
MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private static string cls_strError = "";
private static int cls_iMaxError = 1;
///
/// Add a line number and an error description to the error list.
///
///
/// Line number in the input of where the error occurred.
///
///
/// Text of the error. If this is null or an empty string, the error is not added.
///
public static void ErrorAdd(int iLineNumber, string strError)
{
if (strError != null && strError.Length > 0 && ErrorGetCount() < cls_iMaxError)
{
cls_strError = cls_strError + iLineNumber.ToString() + " " + strError + "\r\n";
}
}
///
/// Return the number of errors in the error list.
///
///
/// The number of errors so far.
///
public static int ErrorGetCount()
{
int iReturn = 0;
for (int i=0; i
/// Initialize the error list and reset the error count.
///
///
/// The maximum number of errors that will be reported. Any errors
/// in excess of this limit added with ErrorAdd are ignored.
///
public static void ErrorInit(int iMaxError)
{
cls_strError = ""; cls_iMaxError = iMaxError;
}
///
/// Return the errors in the error list.
///
///
/// The list of errors, formatted as a string.
///
public static string ErrorGetList()
{
return cls_strError;
}
#endregion
#region File functions
///
/// Read in a text file.
///
///
/// File name of the text file being read in.
///
///
/// The contents of the text file, or an empty string if the text file does not exist.
///
public static string FileReadText(string strFilename)
{
string strFileText = "";
string strInput = "";
if (strFilename != null && strFilename != "" && File.Exists(strFilename))
{
StreamReader sr = File.OpenText(strFilename);
while ((strInput = sr.ReadLine()) != null)
strFileText = strFileText + strInput + "\n";
sr.Close();
}
return strFileText;
}
///
/// Write a text file to disk.
///
///
/// File name of the text file being written. Any existing file of
/// the same name is overwritten.
///
///
/// String that gets written to the text file. If this is an empty
/// string, an empty text file is created.
///
public static void FileWriteText(string strFilename, string strFileText)
{
if (strFilename != null && strFilename != "")
{
StreamWriter sw = File.CreateText(strFilename);
if (strFileText != null)
sw.Write(strFileText);
sw.Close();
}
}
///
/// Append some text to a text file.
///
///
/// File name of the text file being appended to. This file is created
/// if it does not exist.
///
///
/// String that gets appended to the text file.
///
///
/// This routine is useful for error logging, as it can be called
/// repeatedly to append text strings to the log file.
///
public static void FileAppendText(string strFilename, string strText)
{
if (strFilename != null && strFilename != "" && strText != null && strText != "")
{
if (!File.Exists(strFilename))
{
StreamWriter f = new StreamWriter(strFilename);
f.Write(strText);
f.Close();
}
else
{
StreamWriter f = new StreamWriter(strFilename, true);
f.Write(strText);
f.Close();
}
}
}
///
/// Count the number of lines in a text file.
///
///
/// File name of the text file having its lines counted.
///
///
/// The number of lines in the file. Lines are defined as being
/// terminated with the "\n" character. If the last line in the
/// file does not end with "\n" it is not counted.
///
public static int FileCountLines(string strFilename)
{
char[] buffer = new char[32 * 1024];
int total = 0;
StreamReader sr = null;
int charCount = 0;
if (strFilename != null && strFilename != "" && File.Exists(strFilename))
{
sr = new StreamReader(strFilename);
while ((charCount = sr.Read(buffer, 0, buffer.Length)) > 0)
{
for (int i = 0; i < charCount; i++)
if (buffer[i] == '\n')
total++;
}
sr.Close();
}
return total;
}
///
/// Get the list of file names matching a given search path.
///
///
/// String containing the file path and the search pattern used.
/// For example "c:\\mydir\\*.txt" returns the names of the text files
/// in the "mydir" folder.
///
///
/// A string array containing the full paths of the files that match.
/// If there are no matching files, this returns an empty array.
/// It does not return null.
///
public static string[] FileGetList(string strPattern)
{
string[] arrFiles = null;
string strDriveDir = FileGetdrive(strPattern) + FileGetdir(strPattern);
string strFnameExt = FileGetfname(strPattern) + FileGetext(strPattern);
if (Directory.Exists(strDriveDir))
arrFiles = Directory.GetFiles(strDriveDir, strFnameExt);
if (arrFiles != null)
return (arrFiles);
else
return (new string[] { });
}
///
/// Delete one or more files in a single folder, matching a given pattern.
///
///
/// String containing the file path and the search pattern used.
/// For example "c:\\mydir\\*.txt" deletes the text files in the "mydir" folder.
///
///
/// The number of files deleted.
///
public static int FileDelete(string strPattern)
{
string[] arrFiles = FileGetList(strPattern);
for (int i = 0; i < arrFiles.Length; i++)
{
File.Delete(arrFiles[i]);
}
return (arrFiles.Length);
}
///
/// Return the Drive element of a file path.
///
///
/// A partial or complete file path. The path is processed as a string
/// and the drives, folders and files in the path do not have to exist.
///
///
/// The Drive element of the path, for example "C:".
/// An empty string is returned if this element does not exist.
///
public static string FileGetdrive(string path)
{
string drive = ""; string dir = ""; string fname = ""; string ext = "";
Splitpath(path, ref drive, ref dir, ref fname, ref ext);
return (drive);
}
///
/// Return the Directory element of a file path.
///
///
/// A partial or complete file path. The path is processed as a string
/// and the drives, folders and files in the path do not have to exist.
///
///
/// The Directory element of the path, for example "\mydir\myfiles\".
/// If the Directory element exists, it always ends in "\" or "/".
/// An empty string is returned if this element does not exist.
///
public static string FileGetdir(string path)
{
string drive = ""; string dir = ""; string fname = ""; string ext = "";
Splitpath(path, ref drive, ref dir, ref fname, ref ext);
return (dir);
}
///
/// Return the Filename element of a file path.
///
///
/// A partial or complete file path. The path is processed as a string
/// and the drives, folders and files in the path do not have to exist.
///
///
/// The Filename element of the path, for example "myfile".
/// If the Filename element exists, it never contains "\", "/" or ".".
/// An empty string is returned if this element does not exist.
///
public static string FileGetfname(string path)
{
string drive = ""; string dir = ""; string fname = ""; string ext = "";
Splitpath(path, ref drive, ref dir, ref fname, ref ext);
return (fname);
}
///
/// Return the Extension element of a file path.
///
///
/// A partial or complete file path. The path is processed as a string
/// and the drives, folders and files in the path do not have to exist.
///
///
/// The Extension element of the path, for example ".ext".
/// If the Extension element exists, it always starts with
/// "." and never contains "\" or "/".
/// An empty string is returned if this element does not exist.
///
public static string FileGetext(string path)
{
string drive = ""; string dir = ""; string fname = ""; string ext = "";
Splitpath(path, ref drive, ref dir, ref fname, ref ext);
return (ext);
}
///
/// Split a file path up into Drive, Directory, Filename and Extension elements.
///
///
/// A partial or complete file path. The path is processed as a string
/// and the drives, folders and files in the path do not have to exist.
///
///
/// This returns the Drive element of the path, for example "C:".
/// An empty string is returned if this element does not exist.
///
///
/// The Directory element of the path, for example "\mydir\myfiles\".
/// If the Directory element exists, it always ends in "\" or "/".
/// An empty string is returned if this element does not exist.
///
///
/// The Filename element of the path, for example "myfile".
/// If the Filename element exists, it never contains "\", "/" or ".".
/// An empty string is returned if this element does not exist.
///
///
/// The Extension element of the path, for example ".ext".
/// If the Extension element exists, it always starts with
/// "." and never contains "\" or "/".
/// An empty string is returned if this element does not exist.
///
public static void Splitpath(string path, ref string drive, ref string dir, ref string fname, ref string ext)
{
int idxDrive, lenDrive;
int idxDir, lenDir;
int idxFname, lenFname;
int idxExt, lenExt;
// Initialize return values, this is OK even if the inouts are null.
drive = dir = fname = ext = "";
if (path != null && path.Length > 0)
{
// Get the drive.
idxDrive = lenDrive = 0;
if (path.Length >= 2 && Char.IsLetter(path[0]) && path[1] == ':')
{
idxDrive = 0; lenDrive = 2;
}
// Get the ext.
idxExt = path.Length - 1;
lenExt = 0;
while (idxExt >= lenDrive && path[idxExt] != '.' && path[idxExt] != '\\' && path[idxExt] != '/')
{
idxExt--; lenExt++;
}
if (idxExt >= lenDrive && path[idxExt] == '.')
lenExt++;
else
idxExt = lenExt = 0;
// Get the fname.
if (lenExt > 0)
idxFname = idxExt - 1;
else
idxFname = path.Length - 1;
lenFname = 0;
while (idxFname >= lenDrive && path[idxFname] != '\\' && path[idxFname] != '/')
{
idxFname--; lenFname++;
}
if (lenFname > 0)
idxFname++;
else
idxFname = lenFname = 0;
// Get the dir.
idxDir = lenDrive;
if (lenFname > 0)
lenDir = idxFname - idxDir;
else if (lenExt > 0)
lenDir = idxExt - idxDir;
else
lenDir = path.Length - idxDir;
if (lenDir == 0)
idxDir = lenDir = 0;
// Return values.
drive = path.Substring(idxDrive, lenDrive);
dir = path.Substring(idxDir, lenDir);
fname = path.Substring(idxFname, lenFname);
ext = path.Substring(idxExt, lenExt);
}
}
///
/// Load the content of named elements from an XML formatted initialization
/// file. The file should exist in the application startup folder.
///
///
/// String array with the names of the XML elements being loaded.
///
///
/// Returns a string array of values obtained from the XML elements
/// requested. This parameter will contain the same number of elements
/// as the element paths array, and elements that were not found return
/// an empty string. If the initialization file was not found, this
/// returns an empty array. It does not return null.
///
///
/// The XML formatted initialization file is assumed to have the same
/// name as the application and should exist in the application startup
/// directory. For example the initialization file for "c:\mydir\myapp.exe"
/// should be "c:\mydir\myapp.xml". The XML should be in the following format:
///
/// <root>
/// <inner1>Value1</inner1>
/// <inner2>Value2</inner2>
/// ...
/// </root>
///
public static void LoadIniFile(string[] aElementPaths, ref string[] aElementValues)
{
if (aElementPaths != null && aElementPaths.Length > 0)
{
aElementValues = new string[aElementPaths.Length];
XmlDocument xmldoc = new XmlDocument();
string strExeFile = Application.ExecutablePath;
string strXmlIniFile = strExeFile.Substring(0, strExeFile.LastIndexOf('.')) + ".ini";
if (File.Exists(strXmlIniFile))
{
xmldoc.Load(strXmlIniFile);
for (int i = 0; i < aElementPaths.Length; i++)
{
if (xmldoc.SelectSingleNode(aElementPaths[i]) != null)
aElementValues[i] = xmldoc.SelectSingleNode(aElementPaths[i]).InnerText;
else
aElementValues[i] = "";
}
}
else
{
for (int i = 0; i < aElementValues.Length; i++)
aElementValues[i] = "";
}
}
else
{
aElementValues = new string[] { };
}
}
///
/// Save the content of named elements back to an XML formatted initialization file.
/// The file is created in the application startup folder, and any pre-existing
/// XML file of the same name is overwritten.
///
///
/// String array with names of XML elements to create.
///
///
/// String array with values of the XML elements. This array should have
/// the same number of elements as the Paths array.
///
public static void SaveIniFile(string[] aElementPaths, string[] aElementValues)
{
if (aElementPaths != null && aElementPaths.Length > 0 &&
aElementValues != null && aElementValues.Length > 0)
{
// Create an empty XmlDocument with the outer elements only.
XmlDocument xmldoc = new XmlDocument();
string strRootNode = FileGetdir(aElementPaths[0]).Replace("/", "").Replace("\\", "");
string strOuterXml = "<" + strRootNode + ">" + "\r\n" + "" + strRootNode + ">" + "\r\n";
xmldoc.LoadXml(strOuterXml);
// Add nested elements for all elements in aElementPaths[].
XmlElement newElement = null;
for (int i = 0; i < aElementPaths.Length; i++)
{
newElement = xmldoc.CreateElement(FileGetfname(aElementPaths[i]));
newElement.InnerText = ((i < aElementValues.Length) ? aElementValues[i] : "");
xmldoc.DocumentElement.AppendChild(newElement);
}
// Save the XmlDocument back to the ini file.
string strExeFile = Application.ExecutablePath;
string strXmlIniFile = strExeFile.Substring(0, strExeFile.LastIndexOf('.')) + ".ini";
xmldoc.Save(strXmlIniFile);
}
}
#endregion
#region Information functions
///
/// Count the number of computers on the local network on which the
/// specified path is available [not finished yet!].
///
///
/// A directory path checked for availability on the available
/// networked computers. A networked computer is counted as being
/// available if this folder exists with read/write access.
///
///
/// Currently this routine returns the value 1, indicating the
/// local computer is the only one available.
///
///
/// This routine helps multi processing on a network. If a program
/// is installed onto multiple networked computers, it can create
/// a shared folder on each networked computer and can run itself
/// on startup. It can periodically monitor the shared folder for
/// work items and put the completed work back in the same folder.
/// A master program is responsible for creating the work items,
/// copying them to the shared folders on the networked computers,
/// and collecting the results.
///
public static int CountNetworkedComputers(string strTestPath)
{
return 1;
}
///
/// Return a program version string.
///
///
/// The program version in the form X.Y (yyyy.mm.dd) where X and Y are
/// the major and minor version number, and yyyy, mm and dd are the
/// date the EXE file was built.
///
public string GetProgramVersion()
{
// v1.2.3.4 as entered in application properties.
int iVersionMajor = Assembly.GetExecutingAssembly().GetName().Version.Major;
int iVersionMinor = Assembly.GetExecutingAssembly().GetName().Version.Minor;
int iBuildMajor = Assembly.GetExecutingAssembly().GetName().Version.Build;
int iBuildMinor = Assembly.GetExecutingAssembly().GetName().Version.Revision;
DateTime dt = GetLinkerTimestamp();
return (iVersionMajor.ToString() + "." +
iVersionMinor.ToString() + " (" +
dt.Year.ToString() + "." + dt.Month.ToString() + "." +
dt.Day.ToString() + ")");
}
///
/// Return some useful information about the running program.
///
///
/// A multi line string containing program information.
///
public string GetProgramInfo()
{
return "Build date = " + GetLinkerTimestamp() + CRLF +
"Computer name = " + Environment.MachineName + CRLF +
"Current folder = " + Environment.CurrentDirectory + CRLF +
"Domain name = " + Environment.UserDomainName + CRLF +
"Framework version = " + Environment.Version + CRLF +
"User name = " + Environment.UserName + CRLF +
"Windows version = " + Environment.OSVersion + CRLF;
}
private DateTime GetLinkerTimestamp()
{
string strFilepath = System.Reflection.Assembly.GetCallingAssembly().Location;
const int c_PeHeaderOffset = 60;
const int c_LinkerTimestampOffset = 8;
byte[] b = new byte[2048];
Stream s = null;
try
{
s = new FileStream(strFilepath, FileMode.Open, FileAccess.Read);
s.Read(b, 0, 2048);
}
finally
{
if (s != null)
s.Close();
}
int i = BitConverter.ToInt32(b, c_PeHeaderOffset);
int iSecsSince1970 = BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0);
dt = dt.AddSeconds(iSecsSince1970);
dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
return dt;
}
#endregion
#region Process control functions
// Some common error codes, from "winerror.h" and "winnt.h".
private const int ERROR_FILE_NOT_FOUND = 2;
private const int ERROR_ACCESS_DENIED = 5;
/// Control+C was pressed in a command prompt window.
public const uint STATUS_CONTROL_C_EXIT = 0xC000013A;
private const string CRLF = "\r\n";
///
/// Run a program, optionally waiting for it to finish.
///
///
/// Name of the EXE file to run.
///
///
/// Optional arguments passed to the EXE file.
///
///
/// True to wait for the EXE file to finish running, False otherwise.
///
///
/// Values such as Normal, Hidden, Minimized, Maximized.
///
///
/// If the EXE file was run using the Wait option, this parameter is
/// the EXE file's return code. Otherwise this returns zero.
///
public static void Exec(string strPath, string strArgs, bool fWait, ProcessWindowStyle eStyle,
ref int iReturnCode)
{
Process objProcess = new Process();
iReturnCode = 0;
try
{
objProcess.StartInfo.FileName = strPath;
objProcess.StartInfo.Arguments = strArgs;
objProcess.StartInfo.WindowStyle = eStyle;
objProcess.Start();
if (fWait)
{
objProcess.WaitForExit();
iReturnCode = objProcess.ExitCode;
}
}
catch (Win32Exception e)
{
if (e.NativeErrorCode == ERROR_FILE_NOT_FOUND)
MessageBox.Show(e.Message + ". Check the path.\r\n", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
else if (e.NativeErrorCode == ERROR_ACCESS_DENIED)
MessageBox.Show(e.Message + ". No permission to run file.\r\n", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
else
MessageBox.Show(e.Message + ".\r\n", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#endregion
#region String functions
///
/// Test if a character is alphanumeric.
///
///
/// The character being tested which should be: A-Z, a-z, 0-9
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsAlnumChar(char ch)
{
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'))
return true;
else
return false;
}
///
/// Test if a character is alphabetic.
///
///
/// The character being tested which should be: A-Z, a-z
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsAlphaChar(char ch)
{
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' || ch <= 'z'))
return true;
else
return false;
}
///
/// Test if a character is an ASCII control character.
///
///
/// The character being tested which should be: 0x00-0x1F, 0x7F.
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsCntrlChar(char ch)
{
if ((ch >= 0x00 && ch <= 0x1F) || (ch == 0x7F))
return true;
else
return false;
}
///
/// Test if a character can occur in an identifier other than as the first character.
///
///
/// The character being tested which should be: A-Z, a-z, 0-9, _
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsCsymChar(char ch)
{
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '_'))
return true;
else
return false;
}
///
/// Test if a character can occur as the first character of an identifier.
///
///
/// The character being tested which should be: A-Z, a-z, _
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsCsymfChar(char ch)
{
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch == '_'))
return true;
else
return false;
}
///
/// Test if a character is a numeric digit.
///
///
/// The character being tested which should be: 0-9
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsDigitChar(char ch)
{
if (ch >= '0' && ch <= '9')
return true;
else
return false;
}
///
/// Test if a character is printable ASCII (a space to a tilde).
///
///
/// The character being tested which should be: 0x20-0x7e.
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsPrintChar(char ch)
{
if (ch >= 0x20 && ch <= 0x7e)
return true;
else
return false;
}
///
/// Test if a character is a space.
///
///
/// The character being tested which should be: 0x09-0x0D, 0x20
/// 0x09 is a Tab, 0x0A is LF, 0x0B is a Vertical tab, 0x0C is a page feed,
/// 0x0D is CR, 0x20 is a space. Only the normal tab, LF, CR and space are
/// common in text files.
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsSpaceChar(char ch)
{
if ((ch >= 0x09 && ch <= 0x0D) || (ch == 0x20))
return true;
else
return false;
}
///
/// Test if a character is a tab or a space.
///
///
/// The character being tested which should be: 0x09, 0x20
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsWhitespaceChar(char ch)
{
if (ch == 0x09 || ch == 0x20)
return true;
else
return false;
}
///
/// Test if a character is hexadecimal.
///
///
/// The character being tested which should be: A-F, a-f, 0-9
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsXdigitChar(char ch)
{
if ((ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f') || (ch >= '0' && ch <= '9'))
return true;
else
return false;
}
///
/// Test if a character can occur in an XML identifier other than as the first character.
///
///
/// The character being tested which should be: A-Z, a-z, 0-9, _, :, -, .
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsXmlsymChar(char ch)
{
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '_') || (ch == ':') || (ch == '-') || (ch == '.'))
return true;
else
return false;
}
///
/// Test if a character can occur as the first character of an XML identifier.
///
///
/// The character being tested which should be: A-Z, a-z, _, :
///
///
/// True if the character passed the test, False otherwise.
///
public static bool IsXmlsymfChar(char ch)
{
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch == '_') || (ch == ':'))
return true;
else
return false;
}
///
/// Test if a string is a valid identifier.
///
///
/// The string being tested which should be in the form: [A-Za-z_] [A-Za-z_0-9]*
///
///
/// True if the string is a valid identifier, False otherwise.
///
public static bool IsCsymString(string s)
{
bool fReturn = false;
if (s != null && s != "")
{
fReturn = IsCsymfChar(s[0]);
for (int i=1; i
/// If a string contains identifiers enclosed with the specified characters,
/// replace any spaces in the identifier with underscores.
///
///
/// This parameter may contain fragments of program text, such as identifiers
/// enclosed in brackets containing spaces, and internal strings.
///
///
/// Left bracket character, usually this will be '[' or similar.
///
///
/// Right bracket character, usually this will be ']' or similar.
///
///
/// The input text with underscores instead of spaces in any bracketed
/// identifiers. For example:
/// "[my id] = 'array a[1 2]' + b c"
/// becomes
/// "[my_id] = 'array a[1 2]' + b c"
/// Note the contents of internal strings in the input text are unchanged.
///
public static string StringFixDelimitedId(string strIn, char chLeft, char chRight)
{
char[] aOut = null;
bool fInSqString = false;
bool fInDqString = false;
bool fInIdent = false;
if (strIn != null && strIn.Length > 0)
{
aOut = new char[strIn.Length];
for (int i=0; i
/// Unwrap a string from any enclosing brackets.
///
///
/// String being tested.
///
///
/// This is compared to the string's leftmost character.
///
///
/// This is compared to the string's rightmost character.
///
///
/// If a string starts and ends with the specified characters,
/// return it without these characters. Otherwise return the
/// string unchanged. For example "[my id]" is returned as "my id".
///
public static string StringUnwrap(string strIn, char chLeft, char chRight)
{
string strOut = "";
if (strIn != null && strIn.Length > 0)
{
int len = strIn.Length;
if (len >= 2 && strIn[0] == chLeft && strIn[len-1] == chRight)
strOut = strIn.Substring(1, len-2);
else
strOut = strIn;
}
return strOut;
}
///
/// Convert a two dimensional array into a string representation.
///
///
/// A two dimensional array of integers, indexed as a[rows,cols]. The array
/// is converted by using each integer as an index in aDescriptions, and building
/// up the returned string from the descriptions.
///
///
/// String array containing the descriptions used for the conversion.
/// If the integers in aIn[] are within the bounds of the descriptions array,
/// they index the description from the descriptions array. If the integers
/// are outside the bounds, the description and separator are not added.
///
///
/// String array containing separators used after applying the descriptions.
///
///
/// A multi line string produced by converting aIn[]. Each row in aIn[]
/// produces a line in the returned string.
///
public static string ArrayToString(int[,] aIn, string[] aDescriptions, string[] aSeparators)
{
string strReturn = "";
string strDescription = "";
if (aIn != null && aDescriptions != null && aSeparators != null)
{
for (int r=aIn.GetLowerBound(0); r<=aIn.GetUpperBound(0); r++)
{
for (int c=aIn.GetLowerBound(1); c<=aIn.GetUpperBound(1); c++)
{
if (aIn[r,c] >= aDescriptions.GetLowerBound(0) && aIn[r,c] <= aDescriptions.GetUpperBound(0))
{
strDescription = aDescriptions[aIn[r,c]];
strReturn = strReturn + strDescription;
if (c >= aSeparators.GetLowerBound(0) && c <= aSeparators.GetUpperBound(0))
strReturn = strReturn + aSeparators[c];
else if (aSeparators.GetUpperBound(0) >= aSeparators.GetLowerBound(0))
strReturn = strReturn + aSeparators[aSeparators.GetUpperBound(0)];
}
}
strReturn = strReturn.TrimEnd() + "\r\n";
}
}
return strReturn;
}
#endregion
}