CompoundFileReference.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Base / MS / Internal / IO / Packaging / CompoundFile / CompoundFileReference.cs / 1 / 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

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

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