/* * Copyright (C) 2021 Thomas Wolf and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at * https://www.eclipse.org/org/documents/edl-v10.php. * * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.util.io; import java.io.IOException; import java.io.OutputStream; import org.eclipse.jgit.util.Base85; /** * An {@link OutputStream} that encodes data for a git binary patch. * * @since 5.12 */ public class BinaryHunkOutputStream extends OutputStream { private static final int MAX_BYTES = 52; private final OutputStream out; private final byte[] buffer = new byte[MAX_BYTES]; private int pos; /** * Creates a new {@link BinaryHunkOutputStream}. * * @param out * {@link OutputStream} to write the encoded data to */ public BinaryHunkOutputStream(OutputStream out) { this.out = out; } /** * Flushes and closes this stream, and closes the underlying * {@link OutputStream}. */ @Override public void close() throws IOException { flush(); out.close(); } /** * Writes any buffered output as a binary patch line to the underlying * {@link OutputStream} and flushes that stream, too. */ @Override public void flush() throws IOException { if (pos > 0) { encode(buffer, 0, pos); pos = 0; } out.flush(); } @Override public void write(int b) throws IOException { buffer[pos++] = (byte) b; if (pos == buffer.length) { encode(buffer, 0, pos); pos = 0; } } @Override public void write(byte[] b, int off, int len) throws IOException { if (len == 0) { return; } int toCopy = len; int in = off; if (pos > 0) { // Fill the buffer int chunk = Math.min(toCopy, buffer.length - pos); System.arraycopy(b, in, buffer, pos, chunk); in += chunk; pos += chunk; toCopy -= chunk; if (pos == buffer.length) { encode(buffer, 0, pos); pos = 0; } if (toCopy == 0) { return; } } while (toCopy >= MAX_BYTES) { encode(b, in, MAX_BYTES); toCopy -= MAX_BYTES; in += MAX_BYTES; } if (toCopy > 0) { System.arraycopy(b, in, buffer, 0, toCopy); pos = toCopy; } } private void encode(byte[] data, int off, int length) throws IOException { if (length <= 26) { out.write('A' + length - 1); } else { out.write('a' + length - 27); } out.write(Base85.encode(data, off, length)); out.write('\n'); } }