ComponentAce.Compression.Libs.ZLib.Deflate.deflate C# (CSharp) Method

deflate() private method

Performs data compression with the deflate algorithm
private deflate ( ZStream strm, FlushStrategy f ) : int
strm ZStream
f FlushStrategy
return int
        internal int deflate(ZStream strm, FlushStrategy f)
        {
            int old_flush;

            int internalFlush = (int)f;

            if (internalFlush > (int)FlushStrategy.Z_FINISH || internalFlush < 0)
            {
                return (int)ZLibResultCode.Z_STREAM_ERROR;
            }

            if (strm.next_out == null || (strm.next_in == null && strm.avail_in != 0) || (status == DeflateState.FINISH_STATE && internalFlush != (int)FlushStrategy.Z_FINISH))
            {
                strm.msg = ZLibUtil.z_errmsg[(int)ZLibResultCode.Z_NEED_DICT - ((int)ZLibResultCode.Z_STREAM_ERROR)];
                return (int)ZLibResultCode.Z_STREAM_ERROR;
            }
            if (strm.avail_out == 0)
            {
                strm.msg = ZLibUtil.z_errmsg[(int)ZLibResultCode.Z_NEED_DICT - ((int)ZLibResultCode.Z_BUF_ERROR)];
                return (int)ZLibResultCode.Z_DATA_ERROR;
            }

            this.strm = strm; // just in case
            old_flush = last_flush;
            last_flush = internalFlush;

            // Write the zlib header
            if (status == DeflateState.INIT_STATE)
            {
                int header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
                int level_flags = ((level - 1) & 0xff) >> 1;

                if (level_flags > 3)
                    level_flags = 3;
                header |= (level_flags << 6);
                if (strstart != 0)
                    header |= PRESET_DICT;
                header += 31 - (header % 31);

                status = DeflateState.BUSY_STATE;
                putShortMSB(header);


                // Save the adler32 of the preset dictionary:
                if (strstart != 0)
                {
                    putShortMSB((int)(ZLibUtil.URShift(strm.adler, 16)));
                    putShortMSB((int)(strm.adler & 0xffff));
                }
                strm.adler = Adler32.GetAdler32Checksum(0, null, 0, 0);
            }

            // Flush as much pending output as possible
            if (pending != 0)
            {
                strm.flush_pending();
                if (strm.avail_out == 0)
                {
                    //System.out.println("  _avail_out==0");
                    // Since _avail_out is 0, deflate will be called again with
                    // more output space, but possibly with both pending and
                    // _avail_in equal to zero. There won't be anything to do,
                    // but this is not an error situation so make sure we
                    // return OK instead of BUF_ERROR at next call of deflate:
                    last_flush = -1;
                    return (int)ZLibResultCode.Z_OK;
                }

                // Make sure there is something to do and avoid duplicate consecutive
                // flushes. For repeated and useless calls with Z_FINISH, we keep
                // returning (int)ZLibResultCode.Z_STREAM_END instead of Z_BUFF_ERROR.
            }
            else if (strm.avail_in == 0 && internalFlush <= old_flush && internalFlush != (int)FlushStrategy.Z_FINISH)
            {
                strm.msg = ZLibUtil.z_errmsg[(int)ZLibResultCode.Z_NEED_DICT - ((int)ZLibResultCode.Z_BUF_ERROR)];
                return (int)ZLibResultCode.Z_DATA_ERROR;
            }

            // User must not provide more input after the first FINISH:
            if (status == DeflateState.FINISH_STATE && strm.avail_in != 0)
            {
                strm.msg = ZLibUtil.z_errmsg[(int)ZLibResultCode.Z_NEED_DICT - ((int)ZLibResultCode.Z_BUF_ERROR)];
				return (int)ZLibResultCode.Z_DATA_ERROR;
			}
			
			// Start a new block or continue the current one.
			if (strm.avail_in != 0 || lookahead != 0 || (internalFlush != (int)FlushStrategy.Z_NO_FLUSH && status != DeflateState.FINISH_STATE))
			{
				int bstate = - 1;
				switch (config_table[level].func)
				{
					
					case STORED: 
						bstate = deflate_stored(internalFlush);
						break;
					
					case FAST: 
						bstate = deflate_fast(internalFlush);
						break;
					
					case SLOW: 
						bstate = deflate_slow(internalFlush);
						break;
					
					default: 
						break;
					
				}
				
				if (bstate == FinishStarted || bstate == FinishDone)
				{
					status = DeflateState.FINISH_STATE;
				}
				if (bstate == NeedMore || bstate == FinishStarted)
				{
					if (strm.avail_out == 0)
					{
						last_flush = -1; // avoid BUF_ERROR next call, see above
					}
					return (int)ZLibResultCode.Z_OK;
					// If internalFlush != Z_NO_FLUSH && _avail_out == 0, the next call
					// of deflate should use the same internalFlush parameter to make sure
					// that the internalFlush is complete. So we don't have to output an
					// empty block here, this will be done at next call. This also
					// ensures that for a very small output buffer, we emit at most
					// one empty block.
				}
				
				if (bstate == BlockDone)
				{
					if (internalFlush == (int)FlushStrategy.Z_PARTIAL_FLUSH)
					{
						_tr_align();
					}
					else
					{
						// FULL_FLUSH or SYNC_FLUSH
						_tr_stored_block(0, 0, false);
						// For a full internalFlush, this empty block will be recognized
						// as a special marker by inflate_sync().
                        if (internalFlush == (int)FlushStrategy.Z_FULL_FLUSH)
						{
							for (int i = 0; i < hash_size; i++)
							// forget history
								head[i] = 0;
						}
					}
					strm.flush_pending();
					if (strm.avail_out == 0)
					{
						last_flush = -1; // avoid BUF_ERROR at next call, see above
						return (int)ZLibResultCode.Z_OK;
					}
				}
			}
			
			if (internalFlush != (int)FlushStrategy.Z_FINISH)
				return (int)ZLibResultCode.Z_OK;
			if (NoHeader != 0)
				return (int)ZLibResultCode.Z_STREAM_END;
			
			// Write the zlib trailer (adler32)
			putShortMSB((int) (ZLibUtil.URShift(strm.adler, 16)));
			putShortMSB((int) (strm.adler & 0xffff));
			strm.flush_pending();
			
			// If _avail_out is zero, the application will call deflate again
			// to internalFlush the rest.
			NoHeader = - 1; // WritePos the trailer only once!
            return pending != 0 ? (int)ZLibResultCode.Z_OK : (int)ZLibResultCode.Z_STREAM_END;
        }