CompoundFileReference.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Packaging / CompoundFile / CompoundFileReference.cs / 1305600 / CompoundFileReference.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//   Implementation of the CompoundFileReference base class. 
//
// History: 
//  03/31/2003: BruceMac: Created (from ContainerReference.cs)
//  04/08/2003: BruceMac: Made into abstract base class.
//  05/20/2003: RogerCh:  Ported to WCP tree. Split CompoundFileSubStreamReference.cs
//                          (2 classes) into individual files for ByteRange and Index 
//                          reference.
//  08/11/2003: LGolding: Fix Bug 864168 (some of BruceMac's bug fixes were lost 
//                          in port to WCP tree). 
//
// Notes: 
//  Persistence of specific classes is mostly hard-coded in this base class because
//  the persistence must follow a shared binary implementation with Office.  It is
//  also intentionally not polymorphic because we don't allow arbitrary subclasses
//  to participate. 
//-----------------------------------------------------------------------------
 
using System; 
using System.Collections.Specialized;       // for StringCollection class
using System.IO; 
using System.Diagnostics;                   // for Debug.Assert
using System.Windows;                       // for SR error message lookup

using MS.Internal.WindowsBase; 

namespace MS.Internal.IO.Packaging.CompoundFile 
{ 

    ///  
    /// Logical reference to a portion of a container
    /// 
    /// 
    /// Use this class to represent a logical reference to a portion of a container such as a stream 
    /// Note that a CompoundFileReference is not natively tied to any specific container.  This lack of context allows
    /// the developer freedom to create the reference in the absence of the container, or to have the reference 
    /// refer to any one of multiple containers having a similar format. 
    /// 
    internal abstract class CompoundFileReference: IComparable 
    {
        #region Enums
        /// 
        /// Reference component types 
        /// 
        ///  
        /// These are only used for serialization 
        /// 
        private enum RefComponentType : int 
        {
            /// 
            /// Stream component
            ///  
            Stream = 0,
            ///  
            /// Storage component 
            /// 
            Storage = 1, 
        };
        #endregion

        #region Abstracts 

        ///  
        /// Full name of the stream or storage this reference refers to (see StreamInfo and StorageInfo) 
        /// 
        abstract public string FullName {get;} 

        #endregion

        #region IComparable 
        /// 
        /// This is not implemented - it exists as a reminder to authors of subclasses that they must implement this interface 
        ///  
        /// ignored
        int IComparable.CompareTo(object ob) 
        {
            // this must be implemented by our inheritors
            Debug.Assert(false, "subclasses must override this method");
            return 0; 
        }
        #endregion 
 
        #region Operators
        /// Compare for equality 
        /// the CompoundFileReference to compare to
        public override bool Equals(object o)
        {
            // this must be implemented by our inheritors 
            Debug.Assert(false, "subclasses must override this method");
            return false; 
        } 

        /// Returns an integer suitable for including this object in a hash table 
        public override int GetHashCode()
        {
            // this must be implemented by our inheritors
            Debug.Assert(false, "subclasses must override this method"); 
            return 0;
        } 
        #endregion 

        #region Persistence 

        /// Save to a stream
        /// reference to save
        /// The BinaryWriter to persist this object to. 
        /// This method will alter the stream pointer of the underlying stream as a side effect.
        /// Passing null simply calculates how many bytes would be written. 
        /// number of bytes written including any padding 
        static internal int Save(CompoundFileReference reference, BinaryWriter writer)
        { 
            int bytes = 0;

            // NOTE: Our RefComponentType must be written by our caller
            bool calcOnly = (writer == null); 

            // what are we dealing with here? 
            CompoundFileStreamReference streamReference = reference as CompoundFileStreamReference; 
            if ((streamReference == null) && (!(reference is CompoundFileStorageReference)))
                throw new ArgumentException(SR.Get(SRID.UnknownReferenceSerialize), "reference"); 

            // first parse the path into strings
            string[] segments = ContainerUtilities.ConvertBackSlashPathToStringArrayPath(reference.FullName);
            int entries = segments.Length; 

            // write the count 
            if (!calcOnly) 
                writer.Write( entries );
 
            bytes += ContainerUtilities.Int32Size;

            // write the segments - if we are dealing with a stream entry, don't write the last "segment"
            // because it is in fact a stream name 
            for (int i = 0; i < segments.Length - (streamReference == null ? 0 : 1); i++)
            { 
                if (!calcOnly) 
                {
                    writer.Write( (Int32)RefComponentType.Storage ); 
                }
                bytes += ContainerUtilities.Int32Size;
                bytes += ContainerUtilities.WriteByteLengthPrefixedDWordPaddedUnicodeString(writer, segments[i]);
            } 

            if (streamReference != null) 
            { 
                // we are responsible for the prefix
                if (!calcOnly) 
                {
                    writer.Write( (Int32)RefComponentType.Stream );
                }
                bytes += ContainerUtilities.Int32Size; 

                // write the stream name 
                bytes += ContainerUtilities.WriteByteLengthPrefixedDWordPaddedUnicodeString(writer, segments[segments.Length - 1]); 
            }
 
            return bytes;
        }

        ///  
        /// Deserialize from the given stream
        ///  
        /// the BinaryReader to deserialize from with the seek pointer at the beginning of the container reference 
        /// bytes consumed from the stream
        ///  
        /// Side effect of change the stream pointer
        /// 
        /// Throws a FileFormatException if any formatting errors are encountered
        internal static CompoundFileReference Load(BinaryReader reader, out int bytesRead) 
        {
            ContainerUtilities.CheckAgainstNull( reader, "reader" ); 
 
            bytesRead = 0;  // running count of how much we've read - sanity check
 
            // create the TypeMap
            // reconstitute ourselves from the given BinaryReader

            // in this version, the next Int32 is the number of entries 
            Int32 entryCount = reader.ReadInt32();
            bytesRead += ContainerUtilities.Int32Size; 
            // EntryCount of zero indicates the root storage. 
            if (entryCount < 0)
                throw new FileFormatException( 
                    SR.Get(SRID.CFRCorrupt));

            // need a temp collection because we don't know what we're dealing with until a non-storage component
            // type is encountered 
            StringCollection storageList = null;
            String streamName = null; 
 
            // loop through the entries - accumulating strings until we know what kind of object
            // we ultimately need 
            int byteLength;     // reusable
            while (entryCount > 0)
            {
                // first Int32 tells us what kind of component this entry represents 
                RefComponentType refType = (RefComponentType)reader.ReadInt32();
                bytesRead += ContainerUtilities.Int32Size; 
 
                switch (refType)
                { 
                    case RefComponentType.Storage:
                    {
                        if (streamName != null)
                            throw new FileFormatException( 
                                SR.Get(SRID.CFRCorruptStgFollowStm));
 
                        if (storageList == null) 
                            storageList = new StringCollection();
 
                        String str = ContainerUtilities.ReadByteLengthPrefixedDWordPaddedUnicodeString(reader, out byteLength);
                        bytesRead += byteLength;
                        storageList.Add(str);
 
                    } break;
                    case RefComponentType.Stream: 
                    { 
                        if (streamName != null)
                            throw new FileFormatException( 
                                SR.Get(SRID.CFRCorruptMultiStream));

                        streamName = ContainerUtilities.ReadByteLengthPrefixedDWordPaddedUnicodeString(reader, out byteLength);
                        bytesRead += byteLength; 
                    } break;
 
                    // we don't handle these types yet 
                    default:
                        throw new FileFormatException( 
                            SR.Get(SRID.UnknownReferenceComponentType));
                }

                --entryCount; 
            }
 
            CompoundFileReference newRef = null; 

            // stream or storage? 
            if (streamName == null)
            {
                newRef = new CompoundFileStorageReference(
                    ContainerUtilities.ConvertStringArrayPathToBackSlashPath(storageList)); 
            }
            else 
                newRef = new CompoundFileStreamReference( 
                    ContainerUtilities.ConvertStringArrayPathToBackSlashPath(storageList, streamName));
 
            return newRef;
        }
        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//   Implementation of the CompoundFileReference base class. 
//
// History: 
//  03/31/2003: BruceMac: Created (from ContainerReference.cs)
//  04/08/2003: BruceMac: Made into abstract base class.
//  05/20/2003: RogerCh:  Ported to WCP tree. Split CompoundFileSubStreamReference.cs
//                          (2 classes) into individual files for ByteRange and Index 
//                          reference.
//  08/11/2003: LGolding: Fix Bug 864168 (some of BruceMac's bug fixes were lost 
//                          in port to WCP tree). 
//
// Notes: 
//  Persistence of specific classes is mostly hard-coded in this base class because
//  the persistence must follow a shared binary implementation with Office.  It is
//  also intentionally not polymorphic because we don't allow arbitrary subclasses
//  to participate. 
//-----------------------------------------------------------------------------
 
using System; 
using System.Collections.Specialized;       // for StringCollection class
using System.IO; 
using System.Diagnostics;                   // for Debug.Assert
using System.Windows;                       // for SR error message lookup

using MS.Internal.WindowsBase; 

namespace MS.Internal.IO.Packaging.CompoundFile 
{ 

    ///  
    /// Logical reference to a portion of a container
    /// 
    /// 
    /// Use this class to represent a logical reference to a portion of a container such as a stream 
    /// Note that a CompoundFileReference is not natively tied to any specific container.  This lack of context allows
    /// the developer freedom to create the reference in the absence of the container, or to have the reference 
    /// refer to any one of multiple containers having a similar format. 
    /// 
    internal abstract class CompoundFileReference: IComparable 
    {
        #region Enums
        /// 
        /// Reference component types 
        /// 
        ///  
        /// These are only used for serialization 
        /// 
        private enum RefComponentType : int 
        {
            /// 
            /// Stream component
            ///  
            Stream = 0,
            ///  
            /// Storage component 
            /// 
            Storage = 1, 
        };
        #endregion

        #region Abstracts 

        ///  
        /// Full name of the stream or storage this reference refers to (see StreamInfo and StorageInfo) 
        /// 
        abstract public string FullName {get;} 

        #endregion

        #region IComparable 
        /// 
        /// This is not implemented - it exists as a reminder to authors of subclasses that they must implement this interface 
        ///  
        /// ignored
        int IComparable.CompareTo(object ob) 
        {
            // this must be implemented by our inheritors
            Debug.Assert(false, "subclasses must override this method");
            return 0; 
        }
        #endregion 
 
        #region Operators
        /// Compare for equality 
        /// the CompoundFileReference to compare to
        public override bool Equals(object o)
        {
            // this must be implemented by our inheritors 
            Debug.Assert(false, "subclasses must override this method");
            return false; 
        } 

        /// Returns an integer suitable for including this object in a hash table 
        public override int GetHashCode()
        {
            // this must be implemented by our inheritors
            Debug.Assert(false, "subclasses must override this method"); 
            return 0;
        } 
        #endregion 

        #region Persistence 

        /// Save to a stream
        /// reference to save
        /// The BinaryWriter to persist this object to. 
        /// This method will alter the stream pointer of the underlying stream as a side effect.
        /// Passing null simply calculates how many bytes would be written. 
        /// number of bytes written including any padding 
        static internal int Save(CompoundFileReference reference, BinaryWriter writer)
        { 
            int bytes = 0;

            // NOTE: Our RefComponentType must be written by our caller
            bool calcOnly = (writer == null); 

            // what are we dealing with here? 
            CompoundFileStreamReference streamReference = reference as CompoundFileStreamReference; 
            if ((streamReference == null) && (!(reference is CompoundFileStorageReference)))
                throw new ArgumentException(SR.Get(SRID.UnknownReferenceSerialize), "reference"); 

            // first parse the path into strings
            string[] segments = ContainerUtilities.ConvertBackSlashPathToStringArrayPath(reference.FullName);
            int entries = segments.Length; 

            // write the count 
            if (!calcOnly) 
                writer.Write( entries );
 
            bytes += ContainerUtilities.Int32Size;

            // write the segments - if we are dealing with a stream entry, don't write the last "segment"
            // because it is in fact a stream name 
            for (int i = 0; i < segments.Length - (streamReference == null ? 0 : 1); i++)
            { 
                if (!calcOnly) 
                {
                    writer.Write( (Int32)RefComponentType.Storage ); 
                }
                bytes += ContainerUtilities.Int32Size;
                bytes += ContainerUtilities.WriteByteLengthPrefixedDWordPaddedUnicodeString(writer, segments[i]);
            } 

            if (streamReference != null) 
            { 
                // we are responsible for the prefix
                if (!calcOnly) 
                {
                    writer.Write( (Int32)RefComponentType.Stream );
                }
                bytes += ContainerUtilities.Int32Size; 

                // write the stream name 
                bytes += ContainerUtilities.WriteByteLengthPrefixedDWordPaddedUnicodeString(writer, segments[segments.Length - 1]); 
            }
 
            return bytes;
        }

        ///  
        /// Deserialize from the given stream
        ///  
        /// the BinaryReader to deserialize from with the seek pointer at the beginning of the container reference 
        /// bytes consumed from the stream
        ///  
        /// Side effect of change the stream pointer
        /// 
        /// Throws a FileFormatException if any formatting errors are encountered
        internal static CompoundFileReference Load(BinaryReader reader, out int bytesRead) 
        {
            ContainerUtilities.CheckAgainstNull( reader, "reader" ); 
 
            bytesRead = 0;  // running count of how much we've read - sanity check
 
            // create the TypeMap
            // reconstitute ourselves from the given BinaryReader

            // in this version, the next Int32 is the number of entries 
            Int32 entryCount = reader.ReadInt32();
            bytesRead += ContainerUtilities.Int32Size; 
            // EntryCount of zero indicates the root storage. 
            if (entryCount < 0)
                throw new FileFormatException( 
                    SR.Get(SRID.CFRCorrupt));

            // need a temp collection because we don't know what we're dealing with until a non-storage component
            // type is encountered 
            StringCollection storageList = null;
            String streamName = null; 
 
            // loop through the entries - accumulating strings until we know what kind of object
            // we ultimately need 
            int byteLength;     // reusable
            while (entryCount > 0)
            {
                // first Int32 tells us what kind of component this entry represents 
                RefComponentType refType = (RefComponentType)reader.ReadInt32();
                bytesRead += ContainerUtilities.Int32Size; 
 
                switch (refType)
                { 
                    case RefComponentType.Storage:
                    {
                        if (streamName != null)
                            throw new FileFormatException( 
                                SR.Get(SRID.CFRCorruptStgFollowStm));
 
                        if (storageList == null) 
                            storageList = new StringCollection();
 
                        String str = ContainerUtilities.ReadByteLengthPrefixedDWordPaddedUnicodeString(reader, out byteLength);
                        bytesRead += byteLength;
                        storageList.Add(str);
 
                    } break;
                    case RefComponentType.Stream: 
                    { 
                        if (streamName != null)
                            throw new FileFormatException( 
                                SR.Get(SRID.CFRCorruptMultiStream));

                        streamName = ContainerUtilities.ReadByteLengthPrefixedDWordPaddedUnicodeString(reader, out byteLength);
                        bytesRead += byteLength; 
                    } break;
 
                    // we don't handle these types yet 
                    default:
                        throw new FileFormatException( 
                            SR.Get(SRID.UnknownReferenceComponentType));
                }

                --entryCount; 
            }
 
            CompoundFileReference newRef = null; 

            // stream or storage? 
            if (streamName == null)
            {
                newRef = new CompoundFileStorageReference(
                    ContainerUtilities.ConvertStringArrayPathToBackSlashPath(storageList)); 
            }
            else 
                newRef = new CompoundFileStreamReference( 
                    ContainerUtilities.ConvertStringArrayPathToBackSlashPath(storageList, streamName));
 
            return newRef;
        }
        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK