Java tutorial
//package com.java2s; /* * Copyright (C) 2014 The Android Open Source Project * * 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. */ import java.util.Arrays; public class Main { private static final Object scratchEscapePositionsLock = new Object(); /** * Temporary store for positions of escape codes in {@link #unescapeStream(byte[], int)}. Guarded * by {@link #scratchEscapePositionsLock}. */ private static int[] scratchEscapePositions = new int[10]; /** * Unescapes {@code data} up to the specified limit, replacing occurrences of [0, 0, 3] with * [0, 0]. The unescaped data is returned in-place, with the return value indicating its length. * <p> * Executions of this method are mutually exclusive, so it should not be called with very large * buffers. * * @param data The data to unescape. * @param limit The limit (exclusive) of the data to unescape. * @return The length of the unescaped data. */ public static int unescapeStream(byte[] data, int limit) { synchronized (scratchEscapePositionsLock) { int position = 0; int scratchEscapeCount = 0; while (position < limit) { position = findNextUnescapeIndex(data, position, limit); if (position < limit) { if (scratchEscapePositions.length <= scratchEscapeCount) { // Grow scratchEscapePositions to hold a larger number of positions. scratchEscapePositions = Arrays.copyOf(scratchEscapePositions, scratchEscapePositions.length * 2); } scratchEscapePositions[scratchEscapeCount++] = position; position += 3; } } int unescapedLength = limit - scratchEscapeCount; int escapedPosition = 0; // The position being read from. int unescapedPosition = 0; // The position being written to. for (int i = 0; i < scratchEscapeCount; i++) { int nextEscapePosition = scratchEscapePositions[i]; int copyLength = nextEscapePosition - escapedPosition; System.arraycopy(data, escapedPosition, data, unescapedPosition, copyLength); unescapedPosition += copyLength; data[unescapedPosition++] = 0; data[unescapedPosition++] = 0; escapedPosition += copyLength + 3; } int remainingLength = unescapedLength - unescapedPosition; System.arraycopy(data, escapedPosition, data, unescapedPosition, remainingLength); return unescapedLength; } } private static int findNextUnescapeIndex(byte[] bytes, int offset, int limit) { for (int i = offset; i < limit - 2; i++) { if (bytes[i] == 0x00 && bytes[i + 1] == 0x00 && bytes[i + 2] == 0x03) { return i; } } return limit; } }