//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ /// <summary> /// Assign the fullName /// </summary> /// <param name="fullName">name</param> /// <remarks>cache a duplicate copy of the storage name to save having to do this for /// every call to get_Name</remarks> /// <exception cref="ArgumentException">if leading or trailing path delimiter</exception> private void SetFullName(string fullName) { if (fullName == null || fullName.Length == 0) { _fullName = String.Empty; } else { // fail on leading path separator to match functionality across the board // Although we need to do ToUpperInvariant before we do string comparison, in this case // it is not necessary since PathSeparatorAsString is a path symbol if (fullName.StartsWith(ContainerUtilities.PathSeparatorAsString, StringComparison.Ordinal)) { throw new ArgumentException( SR.Get(SRID.DelimiterLeading), "fullName"); } _fullName = fullName; // ensure that the string is a legal whack-path string[] strings = ContainerUtilities.ConvertBackSlashPathToStringArrayPath(_fullName); if (strings.Length == 0) { throw new ArgumentException( SR.Get(SRID.CompoundFilePathNullEmpty), "fullName"); } } }
/// <summary>Save to a stream</summary> /// <param name="reference">reference to save</param> /// <param name="writer">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.</param> /// <returns>number of bytes written including any padding</returns> 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); }
/// <summary> /// Creates a new instance relative to the given parent /// </summary> /// <param name="parent">The parent storage</param> /// <param name="streamName">Path to stream under parent storage</param> /// <param name="compressionOption">CompressionOption</param> /// <param name="encryptionOption">EncryptionOption</param> internal StreamInfo(StorageInfo parent, string streamName, CompressionOption compressionOption, EncryptionOption encryptionOption) { // Parameter validation CU.CheckAgainstNull(parent, "parent"); CU.CheckStringAgainstNullAndEmpty(streamName, "streamName"); // Parse path relative to given parent. BuildStreamInfoRelativeToStorage(parent, streamName); _compressionOption = compressionOption; _encryptionOption = encryptionOption; _streamReference = new CompoundFileStreamReference(this.parentStorage.FullNameInternal, this.core.streamName); }
/// <summary> /// Full featured constructor /// </summary> /// <param name="storageName">optional string describing the storage name - may be null if stream exists in the root storage</param> /// <param name="streamName">stream name</param> /// <exception cref="ArgumentException">streamName cannot be null or empty</exception> public CompoundFileStreamReference(string storageName, string streamName) { ContainerUtilities.CheckStringAgainstNullAndEmpty(streamName, "streamName"); if ((storageName == null) || (storageName.Length == 0)) { _fullName = streamName; } else { // preallocate space for the stream we are building StringBuilder sb = new StringBuilder(storageName, storageName.Length + 1 + streamName.Length); sb.Append(ContainerUtilities.PathSeparator); sb.Append(streamName); _fullName = sb.ToString(); } }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ /// <summary> /// Initialize _fullName /// </summary> /// <remarks>this should only be called from constructors as references are immutable</remarks> /// <param name="fullName">string to parse</param> /// <exception cref="ArgumentException">if leading or trailing path delimiter</exception> private void SetFullName(string fullName) { ContainerUtilities.CheckStringAgainstNullAndEmpty(fullName, "fullName"); // fail on leading path separator to match functionality across the board // Although we need to do ToUpperInvariant before we do string comparison, in this case // it is not necessary since PathSeparatorAsString is a path symbol if (fullName.StartsWith(ContainerUtilities.PathSeparatorAsString, StringComparison.Ordinal)) { throw new ArgumentException( SR.DelimiterLeading, "fullName"); } _fullName = fullName; string[] strings = ContainerUtilities.ConvertBackSlashPathToStringArrayPath(fullName); if (strings.Length == 0) { throw new ArgumentException( SR.CompoundFilePathNullEmpty, "fullName"); } }
/// <summary> /// Deserialize from the given stream /// </summary> /// <param name="reader">the BinaryReader to deserialize from with the seek pointer at the beginning of the container reference</param> /// <param name="bytesRead">bytes consumed from the stream</param> /// <remarks> /// Side effect of change the stream pointer /// </remarks> /// <exception cref="FileFormatException">Throws a FileFormatException if any formatting errors are encountered</exception> 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); }
//------------------------------------------------------ // // Public Events // //------------------------------------------------------ // None //------------------------------------------------------ // // Internal Constructors // //------------------------------------------------------ // None //------------------------------------------------------ // // Internal Properties // //------------------------------------------------------ // None //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #if !PBTCOMPILER /// <summary> /// Constructor for FormatVersion with information read from the given BinaryReader /// </summary> /// <param name="reader">BinaryReader where version information is read from</param> /// <param name="bytesRead">number of bytes read including padding</param> /// <returns>FormatVersion object</returns> /// <remarks> /// This operation will change the stream pointer. This function is preferred over the /// LoadFromStream as it doesn't leave around Undisposed BinaryReader, which /// LoadFromStream will /// </remarks> private static FormatVersion LoadFromBinaryReader(BinaryReader reader, out Int32 bytesRead) { checked { if (reader == null) { throw new ArgumentNullException("reader"); } FormatVersion ver = new FormatVersion(); bytesRead = 0; // Initialize the number of bytes read // ************** // feature ID // ************** Int32 strBytes; ver._featureIdentifier = ContainerUtilities.ReadByteLengthPrefixedDWordPaddedUnicodeString(reader, out strBytes); bytesRead += strBytes; Int16 major; Int16 minor; // **************** // Reader Version // **************** major = reader.ReadInt16(); // Major number bytesRead += ContainerUtilities.Int16Size; minor = reader.ReadInt16(); // Minor number bytesRead += ContainerUtilities.Int16Size; ver.ReaderVersion = new VersionPair(major, minor); // ***************** // Updater Version // ***************** major = reader.ReadInt16(); // Major number bytesRead += ContainerUtilities.Int16Size; minor = reader.ReadInt16(); // Minor number bytesRead += ContainerUtilities.Int16Size; ver.UpdaterVersion = new VersionPair(major, minor); // **************** // Writer Version // **************** major = reader.ReadInt16(); // Major number bytesRead += ContainerUtilities.Int16Size; minor = reader.ReadInt16(); // Minor number bytesRead += ContainerUtilities.Int16Size; ver.WriterVersion = new VersionPair(major, minor); return(ver); } }
/// <summary> /// Persist format version to the given stream /// </summary> /// <param name="stream">the stream to be written</param> /// <remarks> /// This operation will change the stream pointer /// stream can be null and will still return the number of bytes to be written /// </remarks> public int SaveToStream(Stream stream) { checked { // Suppress 56518 Local IDisposable object not disposed: // Reason: The stream is not owned by the BlockManager, therefore we can // close the BinaryWriter as it will Close the stream underneath. #pragma warning disable 6518 int len = 0; BinaryWriter binarywriter = null; #pragma warning restore 6518 if (stream != null) { binarywriter = new BinaryWriter(stream, System.Text.Encoding.Unicode); } // ************ // feature ID // ************ len += ContainerUtilities.WriteByteLengthPrefixedDWordPaddedUnicodeString(binarywriter, _featureIdentifier); // **************** // Reader Version // **************** if (stream != null) { binarywriter.Write(_reader.Major); // Major number binarywriter.Write(_reader.Minor); // Minor number } len += ContainerUtilities.Int16Size; len += ContainerUtilities.Int16Size; // ***************** // Updater Version // ***************** if (stream != null) { binarywriter.Write(_updater.Major); // Major number binarywriter.Write(_updater.Minor); // Minor number } len += ContainerUtilities.Int16Size; len += ContainerUtilities.Int16Size; // **************** // Writer Version // **************** if (stream != null) { binarywriter.Write(_writer.Major); // Major number binarywriter.Write(_writer.Minor); // Minor number } len += ContainerUtilities.Int16Size; len += ContainerUtilities.Int16Size; return(len); } }