Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Build / Microsoft / Build / Tasks / Windows / UidManager.cs / 2 / UidManager.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // // Adds, updates or checks validity of Uids (Unique identifiers) // on all XAML elements in XAML files. // // History: // 07/24/2003 : [....] - Created // 04/02/2004 : [....] - preserved format using XmlTextWriter + StreamWriter // 11/17/2004 : [....] - rework UidManager. Preserve source file format // using only stream writer. //--------------------------------------------------------------------------- using System; using System.Xml; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Reflection; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; using MS.Internal.Markup; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using MS.Utility; // For SR using MS.Internal.Tasks; // Since we disable PreSharp warnings in this file, we first need to disable warnings about unknown message numbers and unknown pragmas. #pragma warning disable 1634, 1691 namespace Microsoft.Build.Tasks.Windows { ////// An MSBuild task that checks or corrects unique identifiers in /// XAML markup. /// public sealed class UidManager : Task { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors ////// Create a UidManager object. /// public UidManager() : base(SR.ResourceManager) { _backupPath = Directory.GetCurrentDirectory(); } #endregion //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods ////// The method invoked by MSBuild to check or correct Uids. /// public override bool Execute() { TaskHelper.DisplayLogo(Log, SR.Get(SRID.UidManagerTask)); if (MarkupFiles == null || MarkupFiles.Length == 0) { Log.LogErrorWithCodeFromResources(SRID.SourceFileNameNeeded.String); return false; } try { _task = (UidTask)Enum.Parse(typeof(UidTask), _taskAsString); } catch (ArgumentException) { Log.LogErrorWithCodeFromResources(SRID.BadUidTask.String, _taskAsString); return false; } bool allFilesOk; try { allFilesOk = ManageUids(); } catch (Exception e) { // PreSharp Complaint 6500 - do not handle null-ref or SEH exceptions. if (e is NullReferenceException || e is SEHException) { throw; } else { string message; string errorId; errorId = Log.ExtractMessageCode(e.Message, out message); if (String.IsNullOrEmpty(errorId)) { errorId = UnknownErrorID; message = SR.Get(SRID.UnknownBuildError, message); } Log.LogError(null, errorId, null, null, 0, 0, 0, 0, message, null); allFilesOk = false; } } #pragma warning disable 6500 catch // Non-CLS compliant errors { Log.LogErrorWithCodeFromResources(SRID.NonClsError.String); allFilesOk = false; } #pragma warning restore 6500 return allFilesOk; } #endregion //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ #region Public Properties ////// The markup file(s) to be checked or updated. /// [Required] public ITaskItem[] MarkupFiles { get { return _markupFiles; } set { _markupFiles = value; } } ////// The directory for intermedia files /// ////// public string IntermediateDirectory { get { return _backupPath; } set { string sourceDir = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar; _backupPath = TaskHelper.CreateFullFilePath(value, sourceDir); } } ////// Enum to determine which Uid management task to undertake /// private enum UidTask { ////// Uid managment task to check validity of Uids /// Check = 0, ////// Uid managment task to Update Uids to a valid state /// Update = 1, ////// Uid managment task to remove all Uids /// Remove = 2, } ////// Uid management task required /// [Required] public string Task { get { return _taskAsString; } set { _taskAsString = value; } } #endregion //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ private bool ManageUids() { int countGoodFiles = 0; // enumerate through each file foreach (ITaskItem inputFile in _markupFiles) { Log.LogMessageFromResources(SRID.CheckingUids.String, inputFile.ItemSpec); switch (_task) { case UidTask.Check: { UidCollector collector = ParseFile(inputFile.ItemSpec); bool success = VerifyUid( collector, // uid collector true // log error ); if (success) countGoodFiles++; break; } case UidTask.Update: { UidCollector collector = ParseFile(inputFile.ItemSpec); bool success = VerifyUid( collector, // uid collector false // log error ); if (!success) { if (SetupBackupDirectory()) { // resolve errors collector.ResolveUidErrors(); // temp file to write to string tempFile = GetTempFileName(inputFile.ItemSpec); // backup file of the source file before it is overwritten. string backupFile = GetBackupFileName(inputFile.ItemSpec); using (Stream uidStream = new FileStream(tempFile, FileMode.Create)) { using (Stream source = File.OpenRead(inputFile.ItemSpec)) { UidWriter writer = new UidWriter(collector, source, uidStream); writer.UpdateUidWrite(); } } // backup source file by renaming it. Expect to be (close to) atomic op. RenameFile(inputFile.ItemSpec, backupFile); // rename the uid output onto the source file. Expect to be (close to) atomic op. RenameFile(tempFile, inputFile.ItemSpec); // remove the temp files RemoveFile(tempFile); RemoveFile(backupFile); countGoodFiles++; } } else { // all uids are good. No-op countGoodFiles++; } break; } case UidTask.Remove: { UidCollector collector = ParseFile(inputFile.ItemSpec); bool hasUid = false; for (int i = 0; i < collector.Count; i++) { if (collector[i].Status != UidStatus.Absent) { hasUid = true; break; } } if (hasUid) { if (SetupBackupDirectory()) { // temp file to write to string tempFile = GetTempFileName(inputFile.ItemSpec); // backup file of the source file before it is overwritten. string backupFile = GetBackupFileName(inputFile.ItemSpec); using (Stream uidStream = new FileStream(tempFile, FileMode.Create)) { using (Stream source = File.OpenRead(inputFile.ItemSpec)) { UidWriter writer = new UidWriter(collector, source, uidStream); writer.RemoveUidWrite(); } } // rename the source file to the backup file name. Expect to be (close to) atomic op. RenameFile(inputFile.ItemSpec, backupFile); // rename the output file over to the source file. Expect to be (close to) atomic op. RenameFile(tempFile, inputFile.ItemSpec); // remove the temp files RemoveFile(tempFile); RemoveFile(backupFile); countGoodFiles++; } } else { // There is no Uid in the file. No need to do remove. countGoodFiles++; } break; } } } // spew out the overral log info for the task switch (_task) { case UidTask.Remove: Log.LogMessageFromResources(SRID.FilesRemovedUid.String, countGoodFiles); break; case UidTask.Update: Log.LogMessageFromResources(SRID.FilesUpdatedUid.String, countGoodFiles); break; case UidTask.Check: Log.LogMessageFromResources(SRID.FilesPassedUidCheck.String, countGoodFiles); if (_markupFiles.Length > countGoodFiles) { Log.LogErrorWithCodeFromResources(SRID.FilesFailedUidCheck.String, _markupFiles.Length - countGoodFiles); } break; } return _markupFiles.Length == countGoodFiles; } private string GetTempFileName(string fileName) { return Path.Combine(_backupPath, Path.ChangeExtension(Path.GetFileName(fileName), "uidtemp")); } private string GetBackupFileName (string fileName) { return Path.Combine(_backupPath, Path.ChangeExtension(Path.GetFileName(fileName), "uidbackup")); } private void RenameFile(string src, string dest) { RemoveFile(dest); File.Move(src, dest); } private void RemoveFile(string fileName) { if (File.Exists(fileName)) { File.Delete(fileName); } } private bool SetupBackupDirectory() { try { if (!Directory.Exists(_backupPath)) { Directory.CreateDirectory(_backupPath); } return true; } catch (Exception e) { // PreSharp Complaint 6500 - do not handle null-ref or SEH exceptions. if (e is NullReferenceException || e is SEHException) { throw; } else { Log.LogErrorWithCodeFromResources(SRID.IntermediateDirectoryError.String, _backupPath); return false; } } #pragma warning disable 6500 catch // Non-cls compliant errors { Log.LogErrorWithCodeFromResources(SRID.IntermediateDirectoryError.String, _backupPath); return false; } #pragma warning restore 6500 } ////// Verify the Uids in the file /// /// UidCollector containing all Uid instances /// true to log errors while verifying ///true indicates no errors private bool VerifyUid( UidCollector collector, bool logError ) { bool errorFound = false; for (int i = 0; i < collector.Count; i++) { Uid currentUid = collector[i]; if (currentUid.Status == UidStatus.Absent) { // Uid missing if (logError) { Log.LogErrorWithCodeFromResources( null, collector.FileName, currentUid.LineNumber, currentUid.LinePosition, 0, 0, SRID.UidMissing.String, currentUid.ElementName ); } errorFound = true; } else if (currentUid.Status == UidStatus.Duplicate) { // Uid duplicates if (logError) { Log.LogErrorWithCodeFromResources( null, collector.FileName, currentUid.LineNumber, currentUid.LinePosition, 0, 0, SRID.MultipleUidUse.String, currentUid.Value, currentUid.ElementName ); } errorFound = true; } } return !errorFound; } ////// Parse the input file and get all the information of Uids /// /// input file ///UidCollector containing all the information for the Uids in the file private UidCollector ParseFile(string fileName) { UidCollector collector = new UidCollector(fileName ); using (Stream xamlStream = File.OpenRead(fileName)) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext( null, // nametable nsmgr, // namespace manager null, // xml:Lang scope XmlSpace.Default // XmlSpace ); XmlTextReader reader = new XmlTextReader( xamlStream, // xml stream XmlNodeType.Document, // parsing document context // parser context ); while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element : { if (collector.RootElementLineNumber < 0) { collector.RootElementLineNumber = reader.LineNumber; collector.RootElementLinePosition = reader.LinePosition; } if (reader.Name.IndexOf('.') >= 0) { // the name has a dot, which suggests it is a property tag. // we will ignore adding uid continue; } Uid currentUid = new Uid( reader.LineNumber, reader.LinePosition + reader.Name.Length, reader.Name, SpaceInsertion.BeforeUid // insert space before the Uid ); ; if (reader.HasAttributes) { reader.MoveToNextAttribute(); // As a heuristic to better preserve the source file, add uid to the place of the // first attribute currentUid.LineNumber = reader.LineNumber; currentUid.LinePosition = reader.LinePosition; currentUid.Space = SpaceInsertion.AfterUid; do { string namespaceUri = nsmgr.LookupNamespace(reader.Prefix); if (reader.LocalName == XamlReaderHelper.DefinitionUid && namespaceUri == XamlReaderHelper.DefinitionNamespaceURI) { // found x:Uid attribute, store the actual value and position currentUid.Value = reader.Value; currentUid.LineNumber = reader.LineNumber; currentUid.LinePosition = reader.LinePosition; } else if (reader.LocalName == "Name" && namespaceUri == XamlReaderHelper.DefaultNamespaceURI) { // found Name attribute, store the Name value currentUid.FrameworkElementName = reader.Value; } else if (reader.LocalName == "Name" && namespaceUri == XamlReaderHelper.DefinitionNamespaceURI) { // found x:Name attribute, store the Name value currentUid.FrameworkElementName = reader.Value; } else if (reader.Prefix == "xmlns") { // found a namespace declaration, store the namespace prefix // so that when we need to add a new namespace declaration later // we won't reuse the namespace prefix. collector.AddNamespacePrefix(reader.LocalName); } } while (reader.MoveToNextAttribute()); } if (currentUid.Value == null) { // there is no x:Uid found on this element, we need to resolve the // namespace prefix in order to add the Uid string prefix = nsmgr.LookupPrefix(XamlReaderHelper.DefinitionNamespaceURI); if (prefix != string.Empty) currentUid.NamespacePrefix = prefix; } collector.AddUid(currentUid); break; } } } } return collector; } //----------------------------------- // Private members //----------------------------------- private UidTask _task; // task private ITaskItem[] _markupFiles; // input Xaml files private string _taskAsString; // task string private string _backupPath; // path to store to backup source Xaml files internal static readonly CultureInfo EnglishUSCulture = CultureInfo.GetCultureInfo("en-us"); private const string UnknownErrorID = "UM1000"; } // represent all the information about a Uid // The uid may be valid, absent, or duplicate internal sealed class Uid { internal Uid( int lineNumber, int linePosition, string elementName, SpaceInsertion spaceInsertion ) { LineNumber = lineNumber; LinePosition = linePosition; ElementName = elementName; Value = null; NamespacePrefix = null; FrameworkElementName = null; Status = UidStatus.Valid; Space = spaceInsertion; } internal int LineNumber; // Referenced line number of the original document internal int LinePosition; // Reference line position of the original document internal string ElementName; // name of the element that needs this uid internal SpaceInsertion Space; // Insert a space before/after the Uid internal string Value; // value of the uid internal string NamespacePrefix; // namespace prefix for the uid internal string FrameworkElementName; // the FrameworkElement.Name of element internal UidStatus Status; // the status of the this uid } internal enum UidStatus : byte { Valid = 0, // uid is valid Absent = 1, // uid is absent Duplicate = 2, // uid is duplicated } internal enum SpaceInsertion : byte { BeforeUid, // Insert a space before the Uid AfterUid // Insert a space after the Uid } // a class collects all the information about Uids per file internal sealed class UidCollector { public UidCollector(string fileName) { _uids = new List(32); _namespacePrefixes = new List (2); _uidTable = new Hashtable(); _fileName = fileName; _sequenceMaxIds = new Hashtable(); } // remembering all the namespace prefixes in the file // in case we need to add a new definition namespace declaration public void AddNamespacePrefix(string prefix) { _namespacePrefixes.Add(prefix); } // add the uid to the collector public void AddUid(Uid uid) { _uids.Add(uid); // set the uid status according to the raw data if (uid.Value == null) { uid.Status = UidStatus.Absent; } else if (_uidTable.Contains(uid.Value)) { uid.Status = UidStatus.Duplicate; } else { // valid uid, store it StoreUid(uid.Value); } } public void ResolveUidErrors() { for (int i = 0; i < _uids.Count; i++) { Uid currentUid = _uids[i]; if ( currentUid.Status == UidStatus.Absent && currentUid.NamespacePrefix == null && _namespacePrefixForMissingUid == null) { // there is Uid not in scope of any definition namespace // we will need to generate a new namespace prefix for them _namespacePrefixForMissingUid = GeneratePrefix(); } if (currentUid.Status != UidStatus.Valid) { // resolve invalid uids currentUid.Value = GetAvailableUid(currentUid); } } } public int RootElementLineNumber { get { return _rootElementLineNumber; } set { _rootElementLineNumber = value; } } public int RootElementLinePosition { get { return _rootElementLinePosition; } set { _rootElementLinePosition = value; } } public string FileName { get { return _fileName; } } public Uid this[int index] { get { return _uids[index]; } } public int Count { get { return _uids.Count; } } public string NamespaceAddedForMissingUid { get { return _namespacePrefixForMissingUid; } } //------------------------------------- // Private methods //------------------------------------- private void StoreUid(string value) { // we just want to check for existence, so storing a null _uidTable[value] = null; string uidSequence; Int64 index; ParseUid(value, out uidSequence, out index); if (uidSequence != null) { if (_sequenceMaxIds.Contains(uidSequence)) { Int64 maxIndex = (Int64)_sequenceMaxIds[uidSequence]; if (maxIndex < index) { _sequenceMaxIds[uidSequence] = index; } } else { _sequenceMaxIds[uidSequence] = index; } } } private string GetAvailableUid(Uid uid) { string availableUid; // copy the ID if available if (uid.FrameworkElementName != null && (!_uidTable.Contains(uid.FrameworkElementName)) ) { availableUid = uid.FrameworkElementName; } else { // generate a new id string sequence = GetElementLocalName(uid.ElementName); Int64 index; if (_sequenceMaxIds.Contains(sequence)) { index = (Int64) _sequenceMaxIds[sequence]; if (index == Int64.MaxValue) { // this sequence reaches the max // we fallback to create a new sequence index = -1; while (index < 0) { sequence = (_uidSequenceFallbackCount == 0) ? UidFallbackSequence : UidFallbackSequence + _uidSequenceFallbackCount; if (_sequenceMaxIds.Contains(sequence)) { index = (Int64) _sequenceMaxIds[sequence]; if (index < Int64.MaxValue) { // found the fallback sequence with valid index index ++; break; } } else { // create a new sequence from 1 index = 1; break; } _uidSequenceFallbackCount ++; } } else { index ++; } } else { // a new sequence index = 1; } availableUid = sequence + UidSeparator + index; } // store the uid so that it won't be used again StoreUid(availableUid); return availableUid; } private void ParseUid(string uid, out string prefix, out Int64 index) { // set prefix and index to invalid values prefix = null; index = -1; if (uid == null) return; int separatorIndex = uid.LastIndexOf(UidSeparator); if (separatorIndex > 0) { string suffix = uid.Substring(separatorIndex + 1); // Disable Presharp warning 6502 : catch block shouldn't have empty body #pragma warning disable 6502 try { index = Int64.Parse(suffix, UidManager.EnglishUSCulture); prefix = uid.Substring(0, separatorIndex); } catch (FormatException) { // wrong format } catch (OverflowException) { // not acceptable uid } #pragma warning restore 6502 } } private string GetElementLocalName(string typeFullName) { int index = typeFullName.LastIndexOf('.'); if (index > 0) { return typeFullName.Substring(index + 1); } else { return typeFullName; } } private string GeneratePrefix() { Int64 ext = 1; string prefix = UidNamespaceAbbreviation.ToString(UidManager.EnglishUSCulture); // Disable Presharp warning 6502 : catch block shouldn't have empty body #pragma warning disable 6502 try { // find a prefix that is not used in the Xaml // from x1, x2, ... x[n] while (_namespacePrefixes.Contains(prefix)) { prefix = UidNamespaceAbbreviation + ext.ToString(UidManager.EnglishUSCulture); ext++; } return prefix; } catch (OverflowException) { } #pragma warning restore 6502 // if overflows, (extreamly imposible), we will return a guid as the prefix return Guid.NewGuid().ToString(); } private List _uids; private Hashtable _uidTable; private string _fileName; private Hashtable _sequenceMaxIds; private List _namespacePrefixes; private int _rootElementLineNumber = -1; private int _rootElementLinePosition = -1; private string _namespacePrefixForMissingUid = null; private int _uidSequenceFallbackCount = 0; private const char UidNamespaceAbbreviation = 'x'; private const char UidSeparator = '_'; private const string UidFallbackSequence = "_Uid"; } // writing to a file, removing or updating uid internal sealed class UidWriter { internal UidWriter(UidCollector collector, Stream source, Stream target) { _collector = collector; _sourceReader = new StreamReader(source); UTF8Encoding encoding = new UTF8Encoding(true); _targetWriter = new StreamWriter(target, encoding); _lineBuffer = new LineBuffer(_sourceReader.ReadLine()); } // write to target stream and update uids internal bool UpdateUidWrite() { try { // we need to add a new namespace if (_collector.NamespaceAddedForMissingUid != null) { // write to the beginning of the root element WriteTillSourcePosition( _collector.RootElementLineNumber, _collector.RootElementLinePosition ); WriteElementTag(); WriteSpace(); WriteNewNamespace(); } for (int i = 0; i < _collector.Count; i++) { Uid currentUid = _collector[i]; WriteTillSourcePosition(currentUid.LineNumber, currentUid.LinePosition); if (currentUid.Status == UidStatus.Absent) { if (currentUid.Space == SpaceInsertion.BeforeUid) { WriteSpace(); } WriteNewUid(currentUid); if (currentUid.Space == SpaceInsertion.AfterUid) { WriteSpace(); } } else if (currentUid.Status == UidStatus.Duplicate) { ProcessAttributeStart(WriterAction.Write); SkipSourceAttributeValue(); WriteNewAttributeValue(currentUid.Value); } } WriteTillEof(); return true; } catch (Exception e) { // PreSharp Complaint 6500 - do not handle null-ref or SEH exceptions. if (e is NullReferenceException || e is SEHException) { throw; } return false; } #pragma warning disable 6500 catch { return false; } #pragma warning restore 6500 } // writing to the target stream removing uids internal bool RemoveUidWrite() { try { for (int i = 0; i < _collector.Count; i++) { Uid currentUid = _collector[i]; // skipping valid and duplicate uids. if ( currentUid.Status == UidStatus.Duplicate || currentUid.Status == UidStatus.Valid) { // write till the space in front of the Uid WriteTillSourcePosition(currentUid.LineNumber, currentUid.LinePosition - 1); // skip the uid ProcessAttributeStart(WriterAction.Skip); SkipSourceAttributeValue(); } } WriteTillEof(); return true; } catch (Exception e) { // PreSharp Complaint 6500 - do not handle null-ref or SEH exceptions. if (e is NullReferenceException || e is SEHException) { throw; } return false; } #pragma warning disable 6500 catch { return false; } #pragma warning restore 6500 } private void WriteTillSourcePosition(int lineNumber, int linePosition) { // write to the correct line while (_currentLineNumber < lineNumber) { // write out the line buffer _targetWriter.WriteLine(_lineBuffer.ReadToEnd()); _currentLineNumber++; _currentLinePosition = 1; // read one more line _lineBuffer.SetLine(_sourceReader.ReadLine()); } // write to the correct line position while (_currentLinePosition < linePosition) { _targetWriter.Write(_lineBuffer.Read()); _currentLinePosition++; } } private void WriteElementTag() { if (_lineBuffer.EOL) { // advance to the non-empty line AdvanceTillNextNonEmptyLine(WriterAction.Write); } char ch = _lineBuffer.Peek(); // stop when we see space, "/" or ">". That is the end of the // element name while (!Char.IsWhiteSpace(ch) && ch != '/' && ch != '>' ) { _targetWriter.Write(ch); _currentLinePosition++; _lineBuffer.Read(); if (_lineBuffer.EOL) { AdvanceTillNextNonEmptyLine(WriterAction.Write); } ch = _lineBuffer.Peek(); } } private void WriteNewUid(Uid uid) { // construct the attribute name, e.g. x:Uid // "x" will be the resolved namespace prefix for the definition namespace string attributeName = (uid.NamespacePrefix == null) ? _collector.NamespaceAddedForMissingUid + ":" + XamlReaderHelper.DefinitionUid : uid.NamespacePrefix + ":" + XamlReaderHelper.DefinitionUid; // escape all the Xml entities in the value string attributeValue = EscapedXmlEntities.Replace( uid.Value, EscapeMatchEvaluator ); string clause = string.Format( UidManager.EnglishUSCulture, "{0}=\"{1}\"", attributeName, attributeValue ); _targetWriter.Write(clause); } private void WriteNewNamespace() { string clause = string.Format( UidManager.EnglishUSCulture, "xmlns:{0}=\"{1}\"", _collector.NamespaceAddedForMissingUid, XamlReaderHelper.DefinitionNamespaceURI ); _targetWriter.Write(clause); } private void WriteNewAttributeValue(string value) { string attributeValue = EscapedXmlEntities.Replace( value, EscapeMatchEvaluator ); _targetWriter.Write( string.Format( UidManager.EnglishUSCulture, "\"{0}\"", value ) ); } private void WriteSpace() { // insert a space _targetWriter.Write(" "); } private void WriteTillEof() { _targetWriter.WriteLine(_lineBuffer.ReadToEnd()); _targetWriter.Write(_sourceReader.ReadToEnd()); _targetWriter.Flush(); } private void SkipSourceAttributeValue() { char ch = (char) 0; // read to the start quote of the attribute value while (ch != '\"' && ch != '\'') { if (_lineBuffer.EOL) { AdvanceTillNextNonEmptyLine(WriterAction.Skip); } ch = _lineBuffer.Read(); _currentLinePosition ++; } char attributeValueStart = ch; // read to the end quote of the attribute value ch = (char) 0; while (ch != attributeValueStart) { if (_lineBuffer.EOL) { AdvanceTillNextNonEmptyLine(WriterAction.Skip); } ch = _lineBuffer.Read(); _currentLinePosition ++; } } private void AdvanceTillNextNonEmptyLine(WriterAction action) { do { if (action == WriterAction.Write) { _targetWriter.WriteLine(); } _lineBuffer.SetLine(_sourceReader.ReadLine()); _currentLineNumber++; _currentLinePosition = 1; } while (_lineBuffer.EOL); } private void ProcessAttributeStart(WriterAction action) { if (_lineBuffer.EOL) { AdvanceTillNextNonEmptyLine(action); } char ch; do { ch = _lineBuffer.Read(); if (action == WriterAction.Write) { _targetWriter.Write(ch); } _currentLinePosition++; if (_lineBuffer.EOL) { AdvanceTillNextNonEmptyLine(action); } } while (ch != '='); } // // source position in a file starts from (1,1) // private int _currentLineNumber = 1; // current line number in the source stream private int _currentLinePosition = 1; // current line position in the source stream private LineBuffer _lineBuffer; // buffer for one line's content private UidCollector _collector; private StreamReader _sourceReader; private StreamWriter _targetWriter; // // buffer for the content of a line // The UidWriter always reads one line at a time from the source // and store the line in this buffer. // private sealed class LineBuffer { private int Index; private string Content; public LineBuffer(string line) { SetLine(line); } public void SetLine(string line) { Content = (line == null) ? string.Empty : line; Index = 0; } public bool EOL { get { return (Index == Content.Length); } } public char Read() { if (!EOL) { return Content[Index++]; } throw new InvalidOperationException(); } public char Peek() { if (!EOL) { return Content[Index]; } throw new InvalidOperationException(); } public string ReadToEnd() { if (!EOL) { int temp = Index; Index = Content.Length; return Content.Substring(temp); } return string.Empty; } } private enum WriterAction { Write = 0, // write the content Skip = 1, // skip the content } private static Regex EscapedXmlEntities = new Regex("(<|>|\"|'|&)", RegexOptions.CultureInvariant | RegexOptions.Compiled); private static MatchEvaluator EscapeMatchEvaluator = new MatchEvaluator(EscapeMatch); /// /// the delegate to escape the matched pattern /// private static string EscapeMatch(Match match) { switch (match.Value) { case "<": return "<"; case ">": return ">"; case "&": return "&"; case "\"": return """; case "'": return "'"; default: return match.Value; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ObjectListDesigner.cs
- HttpCacheVary.cs
- XmlEnumAttribute.cs
- CheckBoxBaseAdapter.cs
- SelectionPatternIdentifiers.cs
- IItemContainerGenerator.cs
- WebBrowserContainer.cs
- DataServiceHost.cs
- SecurityPolicySection.cs
- ServiceObjectContainer.cs
- DataSetMappper.cs
- XamlFigureLengthSerializer.cs
- DuplexChannelFactory.cs
- _NetRes.cs
- FormViewRow.cs
- Literal.cs
- Model3D.cs
- PartialArray.cs
- DesignerCalendarAdapter.cs
- LinkLabelLinkClickedEvent.cs
- BinHexDecoder.cs
- ToolStripProgressBar.cs
- GeneratedContractType.cs
- HMAC.cs
- Transform.cs
- InternalTypeHelper.cs
- CellParagraph.cs
- HttpContextServiceHost.cs
- BindingsCollection.cs
- XPathConvert.cs
- TableLayoutStyleCollection.cs
- TimelineClockCollection.cs
- LinearKeyFrames.cs
- DataControlFieldCell.cs
- ClientSideProviderDescription.cs
- SQLSingleStorage.cs
- InteropExecutor.cs
- DataKeyCollection.cs
- Base64Stream.cs
- ChildTable.cs
- OleDbConnectionFactory.cs
- DispatcherExceptionEventArgs.cs
- VisualBrush.cs
- SqlDataRecord.cs
- QueryTaskGroupState.cs
- CallbackException.cs
- ConfigurationElementProperty.cs
- InfoCardRSAPKCS1SignatureDeformatter.cs
- DrawingState.cs
- ControlLocalizer.cs
- CompilerHelpers.cs
- PostBackOptions.cs
- EncodingDataItem.cs
- SqlProcedureAttribute.cs
- HttpWebRequest.cs
- Stream.cs
- SkewTransform.cs
- SiteMapDataSource.cs
- XPathPatternParser.cs
- _WebProxyDataBuilder.cs
- XPathPatternParser.cs
- TextElementEditingBehaviorAttribute.cs
- CorrelationKey.cs
- CodeNamespace.cs
- AspNetRouteServiceHttpHandler.cs
- RequiredAttributeAttribute.cs
- TraceHandler.cs
- FlowDocumentReader.cs
- SizeChangedEventArgs.cs
- WinEventQueueItem.cs
- Literal.cs
- TableCellAutomationPeer.cs
- CommandEventArgs.cs
- Light.cs
- HandledMouseEvent.cs
- UnsafeNativeMethods.cs
- GcSettings.cs
- xsdvalidator.cs
- AdapterDictionary.cs
- XmlSchemaImporter.cs
- SqlCachedBuffer.cs
- GeometryModel3D.cs
- PointCollection.cs
- SecurityHeaderLayout.cs
- InvokePatternIdentifiers.cs
- AuthenticationConfig.cs
- DotExpr.cs
- PcmConverter.cs
- DataSourceXmlElementAttribute.cs
- TrackingServices.cs
- ComponentFactoryHelpers.cs
- AssemblyInfo.cs
- InvalidDataException.cs
- FlowLayoutPanelDesigner.cs
- NetTcpSection.cs
- WebPartConnectionsCancelVerb.cs
- CheckoutException.cs
- Composition.cs
- GeneralTransform3DGroup.cs
- BaseTemplateBuildProvider.cs