content: /* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
   * file except in compliance with the License. You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software distributed under
   * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
   * OF ANY KIND, either express or implied. See the License for the specific language
   * governing permissions and limitations under the License.
   */
  
  package net.csdn.modules.compress.lzf;
  
  import java.io.IOException;
  
  /**
   * Encoder that handles splitting of input into chunks to encode,
   * calls {@link ChunkEncoder} to compress individual chunks and
   * combines resulting chunks into contiguous output byte array.
   *
   * @author tatu@ning.com
   */
  public class LZFEncoder {
      // Static methods only, no point in instantiating
      private LZFEncoder() {
      }
  
      public static byte[] encode(byte[] data) throws IOException {
          return encode(data, data.length);
      }
  
      /**
       * Method for compressing given input data using LZF encoding and
       * block structure (compatible with lzf command line utility).
       * Result consists of a sequence of chunks.
       */
      public static byte[] encode(byte[] data, int length) throws IOException {
          ChunkEncoder enc = new ChunkEncoder(length, BufferRecycler.instance());
          byte[] result = encode(enc, data, length);
          // important: may be able to reuse buffers
          enc.close();
          return result;
      }
  
      public static byte[] encode(ChunkEncoder enc, byte[] data, int length)
              throws IOException {
          int left = length;
          int chunkLen = Math.min(LZFChunk.MAX_CHUNK_LEN, left);
          LZFChunk first = enc.encodeChunk(data, 0, chunkLen);
          left -= chunkLen;
          // shortcut: if it all fit in, no need to coalesce:
          if (left < 1) {
              return first.getData();
          }
          // otherwise need to get other chunks:
          int resultBytes = first.length();
          int inputOffset = chunkLen;
          LZFChunk last = first;
  
          do {
              chunkLen = Math.min(left, LZFChunk.MAX_CHUNK_LEN);
              LZFChunk chunk = enc.encodeChunk(data, inputOffset, chunkLen);
              inputOffset += chunkLen;
              left -= chunkLen;
              resultBytes += chunk.length();
              last.setNext(chunk);
              last = chunk;
          } while (left > 0);
          // and then coalesce returns into single contiguous byte array
          byte[] result = new byte[resultBytes];
          int ptr = 0;
          for (; first != null; first = first.next()) {
              ptr = first.copyTo(result, ptr);
          }
          return result;
      }
  }
  