/// <summary>
        /// Create a new LocalFileHeader
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="encoding"></param>
        /// <param name="compressionMethod"></param>
        /// <param name="deflateOption"></param>
        /// <param name="streaming">true if in streaming mode</param>
        /// <returns></returns>
        internal static ZipIOLocalFileHeader CreateNew(string fileName, Encoding encoding,
                                                       CompressionMethodEnum compressionMethod, DeflateOptionEnum deflateOption, bool streaming)
        {
            //this should be ensured by the higher levels
            Debug.Assert(Enum.IsDefined(typeof(CompressionMethodEnum), compressionMethod));
            Debug.Assert(Enum.IsDefined(typeof(DeflateOptionEnum), deflateOption));

            byte[] asciiName = encoding.GetBytes(fileName);
            if (asciiName.Length > ZipIOBlockManager.MaxFileNameSize)
            {
                throw new ArgumentOutOfRangeException("fileName");
            }

            ZipIOLocalFileHeader header = new ZipIOLocalFileHeader();

            header._signature         = ZipIOLocalFileHeader._signatureConstant;
            header._compressionMethod = (ushort)compressionMethod;

            if (streaming)
            {
                header._versionNeededToExtract = (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat;
            }
            else
            {
                header._versionNeededToExtract = (UInt16)ZipIOBlockManager.CalcVersionNeededToExtractFromCompression(
                    compressionMethod);
            }

            if (compressionMethod != CompressionMethodEnum.Stored)
            {
                Debug.Assert(deflateOption != DeflateOptionEnum.None); //this should be ensured by the higher levels
                header.DeflateOption = deflateOption;
            }

            if (streaming)
            {
                // set bit 3
                header.StreamingCreationFlag = true;
            }

            header._lastModFileDateTime = ZipIOBlockManager.ToMsDosDateTime(DateTime.Now);

            header._fileNameLength = (UInt16)asciiName.Length;

            header._fileName         = asciiName;
            header._extraField       = ZipIOExtraField.CreateNew(!streaming /* creating padding if it is not in streaming creation mode */);
            header._extraFieldLength = header._extraField.Size;

            //populate frequently used field with user friendly data representations
            header._stringFileName = fileName;

            return(header);
        }
        // this function is sets the sizes into the either 64 or 32 bit structures based on values of the fields
        // It used in 2 places by the MoveReference and by the UpdateFromLocalFileBlock
        private void UpdateZip64Structures
            (long compressedSize, long uncompressedSize, long offset)
        {
            Debug.Assert((compressedSize >= 0) && (uncompressedSize >= 0) && (offset >= 0));

            // according to the appnote central directory extra field might be a mix of any values based on escaping
            // we will fully (without disk number) use it every time we are building a ZIP 64 arhichive
            // we also trying to stay on the safe side and treeat the boundary case of 32 escape values
            // as a zip 64 scenrio
            if ((compressedSize >= UInt32.MaxValue) ||
                (uncompressedSize >= UInt32.MaxValue) ||
                (offset >= UInt32.MaxValue))
            {
                // Zip 64 case
                _extraField.CompressedSize      = compressedSize;
                _extraField.UncompressedSize    = uncompressedSize;
                _extraField.OffsetOfLocalHeader = offset;

                //set proper escape values
                _compressedSize              = UInt32.MaxValue;
                _uncompressedSize            = UInt32.MaxValue;
                _relativeOffsetOfLocalHeader = UInt32.MaxValue;

                // update version needed to extract to 4.5
                _versionNeededToExtract = (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat;
            }
            else
            {
                // 32 bit case
                _compressedSize              = checked ((UInt32)compressedSize);
                _uncompressedSize            = checked ((UInt32)uncompressedSize);
                _relativeOffsetOfLocalHeader = checked ((UInt32)offset);

                // reset the extra ZIP 64 field to empty
                _extraField.Zip64ExtraFieldUsage = ZipIOZip64ExtraFieldUsage.None;

                // version needed to extract needs to be recalculated from scratch based on compression
                _versionNeededToExtract = (UInt16)ZipIOBlockManager.CalcVersionNeededToExtractFromCompression
                                              ((CompressionMethodEnum)_compressionMethod);
            }
        }
        internal void UpdateZip64Structures(long compressedSize,
                                            long uncompressedSize,
                                            long offset)
        {
            // according to the appnote local file header ZIP 64 extra field if used must contain both
            // compressed and uncompressed size
            // we also trying to stay on the safe side and treeat the boundary case of 32 escape values
            // as a zip 64 scenario
            // we will also make this ZIP64 file if it is small but positioned beyond Uint32.MaxValue offset
            if ((compressedSize >= UInt32.MaxValue) ||
                (uncompressedSize >= UInt32.MaxValue) ||
                (offset >= UInt32.MaxValue))
            {
                // Zip 64 case
                _extraField.CompressedSize   = compressedSize;
                _extraField.UncompressedSize = uncompressedSize;

                //set proper escape values
                _compressedSize   = UInt32.MaxValue;
                _uncompressedSize = UInt32.MaxValue;

                // update version needed to extract to 4.5
                _versionNeededToExtract = (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat;
            }
            else
            {
                // 32 bit case
                _compressedSize   = (UInt32)compressedSize; // checked{} isn't required because of the checks above
                _uncompressedSize = (UInt32)uncompressedSize;

                // reset the extra ZIP 64 field to empty
                _extraField.Zip64ExtraFieldUsage = ZipIOZip64ExtraFieldUsage.None;

                // version needed to extract needs to be recalculated from scratch based on compression
                _versionNeededToExtract =
                    (UInt16)ZipIOBlockManager.CalcVersionNeededToExtractFromCompression(CompressionMethod);
            }
        }