using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Perforce.P4 { /// <summary> /// Describes fields and comments in a Perforce specification. /// </summary> public class FormBase :Dictionary<string, object> { public Dictionary<string, bool> IsFieldMultiLine { get; internal set; } public String Comments { get; set; } public FormBase() { IsFieldMultiLine = new Dictionary<string,bool>(); } #region Tagged Form Data /// <summary> /// Set the Values Dictionary from tagged output of a Perforce command. /// </summary> /// <remarks> /// Needed when the object's data dictionary is set after the object /// is created using the default constructer. /// </remarks> /// <param name="data">Object data</param> internal void SetValues(TaggedObject data) { //if (data.ContainsKey("specdef")) //{ // specDescription = new SpecificationMetaData(data["specdef"]); //} // map of base key names to max index (so far) Dictionary<string, int> baseKeys = new Dictionary<string,int>(); foreach (String key in data.Keys) { try { if (char.IsNumber(key, key.Length - 1)) { // value is part of a list string baseKey = key.TrimEnd('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); string idxStr = key.Substring(baseKey.Length); int idx = -1; int.TryParse(idxStr, out idx); IsFieldMultiLine[baseKey] = true; if (ContainsKey(baseKey) == false) { this[baseKey] = new List<string>(idx + 1); } List<string> strList = this[baseKey] as List<string>; while (strList.Count <= idx) { strList.Add(null); } strList[idx] = data[key]; } else { this[key] = data[key]; IsFieldMultiLine[key] = false; } } catch { }; //Extra tag included with TaggedInfoItem data can be ignored } } #endregion #region From string data (a spec form) /// <summary> /// Parse a string specification in the server format into an object. /// </summary> /// <remarks> /// The base implementation parses the generic specification tag::value /// format into the underlying dictionary /// </remarks> /// <param name="spec">String specification</param> /// <returns>Success/Failure</returns> virtual public bool Parse(String spec) { String currentTag = String.Empty; IList<string> currentValueList = null; String[] lines = spec.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int idx = 0; idx < lines.Length; idx++) { if (lines[idx][0] == '#') // # comment { if (Comments == null) { Comments = lines[idx]; } else { Comments += "\r\n"; Comments += lines[idx]; } continue; } else if (lines[idx][0] == '\t') // tab char so this is part of a value field { currentValueList.Add(lines[idx].TrimStart('\t')); } else { //new tag line String line = lines[idx].Trim(); int colonPos = line.IndexOf(':'); if (colonPos <= 0) //bad line continue; // start of a tag currentValueList = null; currentTag = line.Substring(0, colonPos); if (colonPos < line.Length - 1) { // right of colon is the value this[currentTag] = line.Substring(colonPos + 1).Trim(); IsFieldMultiLine[currentTag] = false; } else { IsFieldMultiLine[currentTag] = true; currentValueList = new List<string>(); this[currentTag] = currentValueList; } } } return true; } #endregion /// <summary> /// Create a form specification from the fields that make up a form /// </summary> /// <returns></returns> public override string ToString() { StringBuilder buff = new StringBuilder(2048); if (Comments != null) { buff.AppendLine(Comments); } foreach (string key in Keys) { if ((IsFieldMultiLine.ContainsKey(key)) && (IsFieldMultiLine[key])) { buff.AppendFormat("{0}:\r\n", key); if (this[key] is string) { buff.AppendFormat("\t{0}\r\n", this[key] as string); } else { IList<string> lines = this[key] as IList<string>; for (int idx = 0; idx < lines.Count; idx++) { buff.AppendFormat("\t{0}\r\n", lines[idx]); } } } else { buff.AppendFormat("{0}:\t{1}\r\n", key, this[key] as string); } } return buff.ToString(); } /// <summary> /// Utility function to format a DateTime in the format expected in a spec /// </summary> /// <param name="dt"></param> /// <returns></returns> public static String FormatDateTime(DateTime dt) { if ((dt != null) && (DateTime.MinValue != dt)) return dt.ToString("yyyy/MM/dd HH:mm:ss"); return string.Empty; } /// <summary> /// Utility to convert a Unix time (Seconds past midnight 1/1/1970) to a DateTime /// </summary> /// <param name="unixTime"></param> /// <returns></returns> public static DateTime ConvertUnixTime(long unixTime) { return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(unixTime); } /// <summary> /// Utility to convert a Unix time (Seconds past midnight 1/1/1970) to a DateTime /// </summary> /// <param name="unixTimeStr">Unix time as a string</param> /// <returns></returns> public static DateTime ConvertUnixTime(string unixTimeStr) { long unixTime = 0; if (long.TryParse(unixTimeStr, out unixTime)) { return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(unixTime); } return new DateTime(1970, 1, 1, 0, 0, 0, 0); } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 16210 | Norman Morse | Remove files from old locations | ||
#2 | 12135 | Norman Morse |
Integrate dev branch changes into main. This code is the basiis of the 2.7 BETA release which provides Unity 5 compatibility |
||
#1 | 10940 | Norman Morse |
Inital Workshop release of P4Connect. Released under BSD-2 license |