001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *   http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 * 
017 */
018
019package org.apache.commons.compress.utils;
020
021import java.io.UnsupportedEncodingException;
022
023import org.apache.commons.compress.archivers.ArchiveEntry;
024
025/**
026 * Generic Archive utilities
027 */
028public class ArchiveUtils {
029
030    /** Private constructor to prevent instantiation of this utility class. */
031    private ArchiveUtils(){
032    }
033
034    /**
035     * Generates a string containing the name, isDirectory setting and size of an entry.
036     * <p>
037     * For example:
038     * <pre>
039     * -    2000 main.c
040     * d     100 testfiles
041     * </pre>
042     * 
043     * @return the representation of the entry
044     */
045    public static String toString(ArchiveEntry entry){
046        StringBuilder sb = new StringBuilder();
047        sb.append(entry.isDirectory()? 'd' : '-');// c.f. "ls -l" output
048        String size = Long.toString(entry.getSize());
049        sb.append(' ');
050        // Pad output to 7 places, leading spaces
051        for(int i=7; i > size.length(); i--){
052            sb.append(' ');
053        }
054        sb.append(size);
055        sb.append(' ').append(entry.getName());
056        return sb.toString();
057    }
058
059    /**
060     * Check if buffer contents matches Ascii String.
061     * 
062     * @param expected
063     * @param buffer
064     * @param offset
065     * @param length
066     * @return {@code true} if buffer is the same as the expected string
067     */
068    public static boolean matchAsciiBuffer(
069            String expected, byte[] buffer, int offset, int length){
070        byte[] buffer1;
071        try {
072            buffer1 = expected.getBytes(CharsetNames.US_ASCII);
073        } catch (UnsupportedEncodingException e) {
074            throw new RuntimeException(e); // Should not happen
075        }
076        return isEqual(buffer1, 0, buffer1.length, buffer, offset, length, false);
077    }
078
079    /**
080     * Check if buffer contents matches Ascii String.
081     * 
082     * @param expected
083     * @param buffer
084     * @return {@code true} if buffer is the same as the expected string
085     */
086    public static boolean matchAsciiBuffer(String expected, byte[] buffer){
087        return matchAsciiBuffer(expected, buffer, 0, buffer.length);
088    }
089
090    /**
091     * Convert a string to Ascii bytes.
092     * Used for comparing "magic" strings which need to be independent of the default Locale.
093     * 
094     * @param inputString
095     * @return the bytes
096     */
097    public static byte[] toAsciiBytes(String inputString){
098        try {
099            return inputString.getBytes(CharsetNames.US_ASCII);
100        } catch (UnsupportedEncodingException e) {
101           throw new RuntimeException(e); // Should never happen
102        }
103    }
104
105    /**
106     * Convert an input byte array to a String using the ASCII character set.
107     * 
108     * @param inputBytes
109     * @return the bytes, interpreted as an Ascii string
110     */
111    public static String toAsciiString(final byte[] inputBytes){
112        try {
113            return new String(inputBytes, CharsetNames.US_ASCII);
114        } catch (UnsupportedEncodingException e) {
115            throw new RuntimeException(e); // Should never happen
116        }
117    }
118
119    /**
120     * Convert an input byte array to a String using the ASCII character set.
121     * 
122     * @param inputBytes input byte array
123     * @param offset offset within array
124     * @param length length of array
125     * @return the bytes, interpreted as an Ascii string
126     */
127    public static String toAsciiString(final byte[] inputBytes, int offset, int length){
128        try {
129            return new String(inputBytes, offset, length, CharsetNames.US_ASCII);
130        } catch (UnsupportedEncodingException e) {
131            throw new RuntimeException(e); // Should never happen
132        }
133    }
134
135    /**
136     * Compare byte buffers, optionally ignoring trailing nulls
137     * 
138     * @param buffer1
139     * @param offset1
140     * @param length1
141     * @param buffer2
142     * @param offset2
143     * @param length2
144     * @param ignoreTrailingNulls
145     * @return {@code true} if buffer1 and buffer2 have same contents, having regard to trailing nulls
146     */
147    public static boolean isEqual(
148            final byte[] buffer1, final int offset1, final int length1,
149            final byte[] buffer2, final int offset2, final int length2,
150            boolean ignoreTrailingNulls){
151        int minLen=length1 < length2 ? length1 : length2;
152        for (int i=0; i < minLen; i++){
153            if (buffer1[offset1+i] != buffer2[offset2+i]){
154                return false;
155            }
156        }
157        if (length1 == length2){
158            return true;
159        }
160        if (ignoreTrailingNulls){
161            if (length1 > length2){
162                for(int i = length2; i < length1; i++){
163                    if (buffer1[offset1+i] != 0){
164                        return false;
165                    }
166                }
167            } else {
168                for(int i = length1; i < length2; i++){
169                    if (buffer2[offset2+i] != 0){
170                        return false;
171                    }
172                }
173            }
174            return true;
175        }
176        return false;
177    }
178
179    /**
180     * Compare byte buffers
181     * 
182     * @param buffer1
183     * @param offset1
184     * @param length1
185     * @param buffer2
186     * @param offset2
187     * @param length2
188     * @return {@code true} if buffer1 and buffer2 have same contents
189     */
190    public static boolean isEqual(
191            final byte[] buffer1, final int offset1, final int length1,
192            final byte[] buffer2, final int offset2, final int length2){
193        return isEqual(buffer1, offset1, length1, buffer2, offset2, length2, false);
194    }
195
196    /**
197     * Compare byte buffers
198     * 
199     * @param buffer1
200     * @param buffer2
201     * @return {@code true} if buffer1 and buffer2 have same contents
202     */
203    public static boolean isEqual(final byte[] buffer1, final byte[] buffer2 ){
204        return isEqual(buffer1, 0, buffer1.length, buffer2, 0, buffer2.length, false);
205    }
206
207    /**
208     * Compare byte buffers, optionally ignoring trailing nulls
209     * 
210     * @param buffer1
211     * @param buffer2
212     * @param ignoreTrailingNulls
213     * @return {@code true} if buffer1 and buffer2 have same contents
214     */
215    public static boolean isEqual(final byte[] buffer1, final byte[] buffer2, boolean ignoreTrailingNulls){
216        return isEqual(buffer1, 0, buffer1.length, buffer2, 0, buffer2.length, ignoreTrailingNulls);
217    }
218
219    /**
220     * Compare byte buffers, ignoring trailing nulls
221     * 
222     * @param buffer1
223     * @param offset1
224     * @param length1
225     * @param buffer2
226     * @param offset2
227     * @param length2
228     * @return {@code true} if buffer1 and buffer2 have same contents, having regard to trailing nulls
229     */
230    public static boolean isEqualWithNull(
231            final byte[] buffer1, final int offset1, final int length1,
232            final byte[] buffer2, final int offset2, final int length2){
233        return isEqual(buffer1, offset1, length1, buffer2, offset2, length2, true);
234    }
235    
236    /**
237     * Returns true if the first N bytes of an array are all zero
238     * 
239     * @param a
240     *            The array to check
241     * @param size
242     *            The number of characters to check (not the size of the array)
243     * @return true if the first N bytes are zero
244     */
245    public static boolean isArrayZero(byte[] a, int size) {
246        for (int i = 0; i < size; i++) {
247            if (a[i] != 0) {
248                return false;
249            }
250        }
251        return true;
252    }
253}