Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Base / MS / Internal / IO / Packaging / PieceNameHelper.cs / 1 / PieceNameHelper.cs
//------------------------------------------------------------------------------ // Microsoft Avalon // Copyright (c) Microsoft Corporation, 2005 // // File: PieceNameHelper.cs // // Description: The static class PieceNameHelper contains utilities to parse // and create piece names in an adaptor-independent way. // This file also contains PieceNameInfo, a structured representation // of a piece name, and its subclass PieceInfo, which provides // piece name and zip file info for a piece. // // History: 05/15/05 - [....] - initial implementation //----------------------------------------------------------------------------- using System; using System.IO; using System.IO.Packaging; // For ZipPackagePart, etc. using System.Windows; // for ExceptionStringTable using System.Globalization; // For CultureInfo using System.Collections.Generic; // IEqualityComparer using MS.Internal; // For Invariant using MS.Internal.IO.Zip; // For ZipFileInfo using System.Diagnostics; // For Debug.Assert namespace MS.Internal.IO.Packaging { #region class PieceInfo ////// A piece descriptor, made up of a ZipFileInfo and a PieceNameInfo. /// ////// PieceNameHelper implements IComparable in such a way as to enforce /// case-insensitive lexicographical order on <name, number, isLast> triples. /// internal class PieceInfo { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors internal PieceInfo(ZipFileInfo zipFileInfo, PackUriHelper.ValidatedPartUri partUri, string prefixName, int pieceNumber, bool isLastPiece) { Debug.Assert(zipFileInfo != null); Debug.Assert(prefixName != null && prefixName != String.Empty); Debug.Assert(pieceNumber >= 0); _zipFileInfo = zipFileInfo; // partUri can be null to indicate that the prefixname is not a valid part name _partUri = partUri; _prefixName = prefixName; _pieceNumber = pieceNumber; _isLastPiece = isLastPiece; // Currently as per the book, the prefix names/ logical names should be // compared in a case-insensitive manner. _normalizedPieceNamePrefix = _prefixName.ToUpperInvariant(); } #endregion Constructors //------------------------------------------------------ // // public methods // //----------------------------------------------------- // None //------------------------------------------------------ // // Internal properties // //------------------------------------------------------ #region Internal properties internal string NormalizedPrefixName { get { return _normalizedPieceNamePrefix; } } internal string PrefixName { get { return _prefixName; } } internal int PieceNumber { get { return _pieceNumber; } } internal bool IsLastPiece { get { return _isLastPiece; } } internal PackUriHelper.ValidatedPartUri PartUri { get { return _partUri; } } internal ZipFileInfo ZipFileInfo { get { return _zipFileInfo; } } #endregion Internal properties //----------------------------------------------------- // // Private members // //------------------------------------------------------ #region Private members private PackUriHelper.ValidatedPartUri _partUri; private string _prefixName; private int _pieceNumber; private bool _isLastPiece; private ZipFileInfo _zipFileInfo; private string _normalizedPieceNamePrefix; #endregion Private members } #endregion class PieceInfo #region class PieceNameHelper ////// The static class PieceNameHelper contains utilities to parse and create piece names /// in an adaptor-independent way. /// internal static class PieceNameHelper { #region Internal Properties internal static PieceNameComparer PieceNameComparer { get { return _pieceNameComparer; } } #endregion Internal Properties #region Internal Methods ////// Build a piece name from its constituents: part name, piece number /// and terminal status. /// The linearized result obeys the piece name syntax: /// piece_name = prefix_name "/" "[" 1*digit "]" [".last"] ".piece" /// /// A part name or the zip item name corresponding to a part name. /// The 0-based order number of the piece. /// Whether the piece is last in the part. ///A Metro piece name. ///If partName is a piece uri. ///If pieceNumber is negative. internal static string CreatePieceName(string partName, int pieceNumber, bool isLastPiece) { Invariant.Assert(pieceNumber >= 0, "Negative piece number."); return string.Format(CultureInfo.InvariantCulture, "{0}/[{1:D}]{2}.piece", partName, pieceNumber, isLastPiece ? ".last" : ""); } ////// Return true and create a PieceInfo if the name in the input ZipFileInfo parses /// as a piece name. /// ////// No Uri validation is carried out at this level. All that is checked is valid piece /// syntax. So the _prefixName returned as part of the PieceInfo will not necessarily /// a part name. For example, it could be the name of the content type stream. /// internal static bool TryCreatePieceInfo(ZipFileInfo zipFileInfo, out PieceInfo pieceInfo) { Invariant.Assert(zipFileInfo != null); pieceInfo = null; // Try to parse as a piece name. PieceNameInfo pieceNameConstituents; bool result = PieceNameHelper.TryParseAsPieceName(zipFileInfo.Name, out pieceNameConstituents); // Return the result and the output parameter. if(result) pieceInfo = new PieceInfo(zipFileInfo, pieceNameConstituents.PartUri, pieceNameConstituents.PrefixName, pieceNameConstituents.PieceNumber, pieceNameConstituents.IsLastPiece); return result; } #endregion Internal Methods #region Private Methods //----------------------------------------------------- // // Private Methods // //----------------------------------------------------- #region Scan Steps // The functions in this region conform to the delegate type ScanStepDelegate // and implement the following automaton for scanning a piece name from right to left: // state transition new state // ----- ---------- --------- // FindPieceExtension ".piece" FindIsLast // FindIsLast "].last" FindPieceNumber // FindIsLast "]" FindPieceNumber // FindPieceNumber "/[" 1*digit FindPartName (terminal state) // On entering the step, position is at the beginning of the last portion that was recognized. // So left-to-right scanning starts at position - 1 in each step. private delegate bool ScanStepDelegate( string path, ref int position, ref ScanStepDelegate nextStep, ref PieceNameInfo parseResults); // Look for ".piece". private static bool FindPieceExtension(string path, ref int position, ref ScanStepDelegate nextStep, ref PieceNameInfo parseResults) { if (!FindString(path, ref position, ".piece")) return false; nextStep = FindIsLast; return true; } // Look for "]" or "].last". private static bool FindIsLast(string path, ref int position, ref ScanStepDelegate nextStep, ref PieceNameInfo parseResults) { // Case of no ".last" member: if (path[position - 1] == ']') { parseResults.IsLastPiece = false; --position; nextStep = FindPieceNumber; return true; } // There has to be "].last". if (!FindString(path, ref position, "].last")) return false; parseResults.IsLastPiece = true; nextStep = FindPieceNumber; return true; } // Look for "/[" followed by decimal digits. private static bool FindPieceNumber(string path, ref int position, ref ScanStepDelegate nextStep, ref PieceNameInfo parseResults) { if (!char.IsDigit(path[position - 1])) return false; int pieceNumber = 0; int multiplier = 1; // rightmost digit is for units --position; do { pieceNumber += multiplier * (int)char.GetNumericValue(path[position]); multiplier *= 10; } while (char.IsDigit(path[--position])); // Point to the last digit found. ++position; //If we have a leading 0, then its not correct piecename syntax if (multiplier > 10 && (int)char.GetNumericValue(path[position]) == 0) return false; if (!FindString(path, ref position, "/[")) return false; parseResults.PieceNumber = pieceNumber; nextStep = FindPartName; return true; } // Retrieve part name. The position points to the slash past the part name. // So simply return the prefix up to that slash. private static bool FindPartName(string path, ref int position, ref ScanStepDelegate nextStep, ref PieceNameInfo parseResults) { parseResults.PrefixName = path.Substring(0, position); // Subtract the length of the part name from position. position = 0; if (parseResults.PrefixName.Length == 0) return false; Uri partUri = new Uri(ZipPackage.GetOpcNameFromZipItemName(parseResults.PrefixName), UriKind.Relative); PackUriHelper.TryValidatePartUri(partUri, out parseResults.PartUri); return true; } #endregion Scan Steps ////// Attempts to parse a name as a piece name. Returns true and places the /// output in pieceNameConstituents. Otherwise, returns false and returns /// the default constituent values pieceName, 0, and false. /// /// The input string. /// An object containing the prefix name (i.e. generally the part name), the 0-based order number of the piece, and whether the piece is last in the part. ///True for parse success. ////// Syntax of a piece name: /// piece_name = part_name "/" "[" 1*digit "]" [".last"] ".piece" /// private static bool TryParseAsPieceName(string path, out PieceNameInfo parseResults) { parseResults = new PieceNameInfo(); // initialize to CLR default values // Start from the end and look for ".piece". int position = path.Length; ScanStepDelegate nextStep = new ScanStepDelegate(FindPieceExtension); // Scan backward until the whole path has been scanned. while (position > 0) { if (!nextStep.Invoke(path, ref position, ref nextStep, ref parseResults)) { // Scan step failed. Return false. parseResults.IsLastPiece = false; parseResults.PieceNumber = 0; parseResults.PrefixName = path; parseResults.PartUri = null; return false; } } return true; } ////// Look for 'query' backward in 'input' starting at 'position'. /// private static bool FindString(string input, ref int position, string query) { int queryPosition = query.Length; //The input string should have length that is greater than or equal to the //length of the query string. if (position < queryPosition) return false; while (--queryPosition >= 0) { --position; if (Char.ToUpperInvariant(input[position]) != Char.ToUpperInvariant(query[queryPosition])) return false; } return true; } #endregion Private Methods #region Private Member Variables //----------------------------------------------------- // // Private Variables // //------------------------------------------------------ private static PieceNameComparer _pieceNameComparer = new PieceNameComparer(); #endregion Private Member Variables #region Private Struct : PieceNameInfo ////// The result of parsing a piece name as returned by the parsing methods of PieceNameHelper. /// ////// private struct PieceNameInfo { internal PackUriHelper.ValidatedPartUri PartUri; internal string PrefixName; internal int PieceNumber; internal bool IsLastPiece; } #endregion Private Struct : PieceNameInfo } #endregion class PieceNameHelper #region class PieceNameComparer internal sealed class PieceNameComparer : IComparer/// The first member, _prefixName, will be a part name if the input to parse begins with /// a part name, and a zip item name if it starts with a zip item name. /// ////// In other words, all that precedes the suffixes is returned unanalyzed as an "prefix name" /// by the parse functions of the PieceNameHelper. /// ///{ //For comparing the piece names we consider the prefix name and piece numbers //Pieces that are terminal and non terminal with the same number and same prefix //number will be treated as equivalent. //For example - /partA/[number].piece and /partA[number].last.piece will be treated //to be equivalent, as in a well-formed package either one of them can be present, //not both. int IComparer .Compare(PieceInfo pieceInfoA, PieceInfo pieceInfoB) { //Even though most comparers allow for comparisons with null, we assert here, as //this is an internal class and we are sure that pieceInfoA and pieceInfoB passed //in here should be non-null, else it would be a logical error. Invariant.Assert(pieceInfoA != null); Invariant.Assert(pieceInfoB != null); int result = string.Compare( pieceInfoA.NormalizedPrefixName, pieceInfoB.NormalizedPrefixName, StringComparison.Ordinal); if (result != 0) return result; result = pieceInfoA.PieceNumber - pieceInfoB.PieceNumber; return result; } } #endregion class PieceNameComparer } // 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
- Propagator.JoinPropagator.JoinPredicateVisitor.cs
- ColumnMapVisitor.cs
- AppDomainAttributes.cs
- CompositeControl.cs
- SetState.cs
- CommonRemoteMemoryBlock.cs
- PriorityItem.cs
- BezierSegment.cs
- XmlDocumentType.cs
- mediapermission.cs
- FontStretch.cs
- CompilerGeneratedAttribute.cs
- AccessDataSourceView.cs
- PrinterResolution.cs
- DbConnectionPoolOptions.cs
- ProfileService.cs
- FrameDimension.cs
- ThreadExceptionEvent.cs
- SchemaObjectWriter.cs
- JpegBitmapEncoder.cs
- Pair.cs
- View.cs
- ProxyManager.cs
- Drawing.cs
- DBAsyncResult.cs
- XmlDataDocument.cs
- Events.cs
- AstTree.cs
- GotoExpression.cs
- InputReport.cs
- DynamicMethod.cs
- ButtonDesigner.cs
- DnsPermission.cs
- SystemIPGlobalStatistics.cs
- CharAnimationUsingKeyFrames.cs
- DataGridAutomationPeer.cs
- InputReferenceExpression.cs
- ErrorWrapper.cs
- RoutedPropertyChangedEventArgs.cs
- Type.cs
- CounterSampleCalculator.cs
- Operators.cs
- IisTraceWebEventProvider.cs
- _NestedSingleAsyncResult.cs
- FixedSOMTableRow.cs
- WebPartConnectionsConnectVerb.cs
- DotExpr.cs
- DodSequenceMerge.cs
- ByteAnimationUsingKeyFrames.cs
- FilteredDataSetHelper.cs
- ColumnHeader.cs
- PrintDialogDesigner.cs
- StylusTip.cs
- ElementNotAvailableException.cs
- TitleStyle.cs
- ToolboxItemAttribute.cs
- SymbolDocumentGenerator.cs
- EditingCoordinator.cs
- WindowsGraphicsCacheManager.cs
- Converter.cs
- AbsoluteQuery.cs
- MimeObjectFactory.cs
- AnnouncementInnerClient11.cs
- arc.cs
- XsltSettings.cs
- PerformanceCounterPermissionEntry.cs
- XPathDocumentIterator.cs
- AffineTransform3D.cs
- TextSpanModifier.cs
- SqlEnums.cs
- EntityDataSourceContainerNameConverter.cs
- DataContract.cs
- COMException.cs
- ReadWriteObjectLock.cs
- PropertyGridEditorPart.cs
- FixedStringLookup.cs
- SmtpNegotiateAuthenticationModule.cs
- XmlElement.cs
- SessionEndedEventArgs.cs
- ServicePointManagerElement.cs
- SqlClientWrapperSmiStreamChars.cs
- CustomErrorsSection.cs
- RightsDocument.cs
- SchemaNames.cs
- Parallel.cs
- ObsoleteAttribute.cs
- RunInstallerAttribute.cs
- ListenerSessionConnection.cs
- SqlXmlStorage.cs
- Size.cs
- DesignerAdRotatorAdapter.cs
- MembershipSection.cs
- AppSettingsReader.cs
- StringReader.cs
- _TransmitFileOverlappedAsyncResult.cs
- MarshalDirectiveException.cs
- WorkflowDefinitionDispenser.cs
- GradientPanel.cs
- StyleSheetComponentEditor.cs
- XmlElementList.cs